Verilog:甚至在时钟上设置恒定值

发布于 2024-12-21 00:35:30 字数 764 浏览 0 评论 0原文

我是 Verilog 新手,所以这个问题可能很愚蠢。

我正在尝试:我有一个具有 clk、8 位输入和 8 位输出的组件。它应该做的是:

如果时钟事件是下降沿,则应将输出设置为 0 如果时钟事件是正边沿,则应将输出设置为边沿事件此时的输入。在时钟的高电平阶段,无论输入发生变化,输出都不应改变。

到目前为止我尝试过的:

always @(negedge clk)
    _ledOut <= 0;

always @(posedge clk)
    _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];

这告诉我,它无法解析 net _ledOut 的多个常量驱动程序。

然而,将其放在始终 @(negedge clk, posege clk) 中告诉我,它无法测试这两种条件。

所以我尝试只制作一个always @(clk) 块,然后使用if 语句:

always @(clk) begin
    if(clk == 0)
        _ledOut <= 0;
    else if(clk == 1)
        _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end

但这不仅仅是打开clk 事件。在时钟的高电平阶段,它将 _ledOut 与 ledIn 链接起来,因此 ledIn 上的更改也会对 _ledOut 产生影响。我在这里做错了什么?

此致, 迈克尔

I am new to Verilog, so this question might be quite dumb.

What I am trying: I have a component that has a clk, an 8 bit input and an 8 bit output. What it should do, is:

If the clock event is negative edge, it should set the output to 0
If the clock event is positive edge, it should set the output to whatever input is at this moment of the edge event. During the high phase of the clock, the output should NOT change, regardless changes on the input.

What I tried so far:

always @(negedge clk)
    _ledOut <= 0;

always @(posedge clk)
    _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];

This tells my, that it can't resolve multiple constant drivers for net _ledOut.

However, putting this together in an always @(negedge clk, posedge clk) tells me, it can't test for both conditions.

So I tried to make just one always @(clk) block and then used an if statement:

always @(clk) begin
    if(clk == 0)
        _ledOut <= 0;
    else if(clk == 1)
        _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end

But this didn't just switch on a clk event. During the high phase of the clock, it links _ledOut with ledIn, so that changes on ledIn do also have effect on _ledOut. What am I doing wrong here?

Best regards,
Michael

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风追烟花雨 2024-12-28 00:35:30

这告诉我,它无法解析网络的多个常量驱动程序
_ledOut。

对于综合,您不能从多个always块分配reg类型。

但是,将其放在始终 @(negedge clk, posege
clk) 告诉我,它无法测试这两种情况。

这实质上描述了 DDR 寄存器。虽然许多 FPGA 器件都具有这些特性,但它们通常无法综合。如果您确实需要此功能,Xilinx 可以使用 ODDR2 和 IDDR2 原语。

如果时钟事件为下降沿,则应将输出设置为 0 如果
时钟事件是上升沿,它应该将输出设置为任何值
输入是在边缘事件的此时。在高位阶段期间
时钟,输出不应该改变,无论改变
输入。

如果这就是您所需要的,那么您可以使用输出端带有与门的 D 触发器。触发器将在 clk 的每个上升沿对 ledIn 进行采样,并且只要时钟为零,与门就会屏蔽输出。这并不理想,因为您通常不希望时钟接触非顺序逻辑,但避免这种情况可能意味着改变您的要求。

正如 toolic 所示,您发布的代码将起作用,但您应该了解该代码将合成到由 clk 控制的多路复用器。

This tells my, that it can't resolve multiple constant drivers for net
_ledOut.

For synthesis you cannot assign reg types from multiple always blocks.

However, putting this together in an always @(negedge clk, posedge
clk) tells me, it can't test for both conditions.

This essentially describes a DDR register. While many FPGA devices have these they typically cannot be synthesized. Xilinx uses ODDR2 and IDDR2 primitives if you really need this functionality.

If the clock event is negative edge, it should set the output to 0 If
the clock event is positive edge, it should set the output to whatever
input is at this moment of the edge event. During the high phase of
the clock, the output should NOT change, regardless changes on the
input.

If this is all you need then you can use a D flip flop with an AND gate on the output. The flip-flop will sample ledIn on each rising edge of clk and the AND gate will mask the output whenever the clock is zero. This is not ideal as you generally do not want clocks to touch non-sequential logic but avoiding this would likely mean changing your requirements.

As toolic indicated, the code you posted will work but you should understand that code will synthesize to a multiplexer controlled by clk.

说好的呢 2024-12-28 00:35:30

好的,现在这是我的工作解决方案。也许这不是您见过的最好的 verilog 代码。 ;)然而,这是我用它做的第一件事,作为我大学的一个项目。所以只要它做了我想让它做的事,这对我来说就是巨大的成功! ;)

这是我现在使用的代码,感谢 Adam12:

parameter RowSize = 8;

input clk;
input [RowSize-1:0] ledIn;
output [RowSize-1:0] ledOut;

reg[RowSize-1:0] _ledOut;
assign ledOut = _ledOut & {RowSize{clk}};

always @(posedge clk) begin
    _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end

Ok, here is my working solution now. Maybe it's not the best verilog code you have seen out there. ;) This is, however, my first thing I do with it, as a project at my university. So as long as it does what I want it to do, this is a great success to me! ;)

Here is the code I used now, thanks to Adam12:

parameter RowSize = 8;

input clk;
input [RowSize-1:0] ledIn;
output [RowSize-1:0] ledOut;

reg[RowSize-1:0] _ledOut;
assign ledOut = _ledOut & {RowSize{clk}};

always @(posedge clk) begin
    _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end
安静被遗忘 2024-12-28 00:35:30

考虑以下激励:

module tb;

parameter RowSize = 8;
reg clk;
reg [7:0] ledIn, _ledOut;

always @(clk) begin
    if(clk == 0)
        _ledOut <= 0;
    else if(clk == 1)
        _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end

initial begin
    $monitor($time, " clk=%b ledIn=%h _ledOut=%h", clk, ledIn, _ledOut);
    ledIn = 0;
    #22 ledIn = 8'h55;
    #20 $finish;
end

always begin
    #5 clk <= 0;
    #5 clk <= 1;
end

endmodule

它产生以下输出:

               0 clk=x ledIn=00 _ledOut=xx
               5 clk=0 ledIn=00 _ledOut=00
              10 clk=1 ledIn=00 _ledOut=00
              15 clk=0 ledIn=00 _ledOut=00
              20 clk=1 ledIn=00 _ledOut=00
              22 clk=1 ledIn=55 _ledOut=00
              25 clk=0 ledIn=55 _ledOut=00
              30 clk=1 ledIn=55 _ledOut=55
              35 clk=0 ledIn=55 _ledOut=00
              40 clk=1 ledIn=55 _ledOut=55

请注意,在时间 22 处,当 ledIn 发生变化时,_ledOut 输出不会发生变化。 _ledOut 仅在时间 30 处 clk 的下一个 posege 处发生变化。因此,always @(clk) 解决方案正在执行您想要的操作:正如您所指定的,输出仅在时钟沿发生变化。

Consider the following stimulus:

module tb;

parameter RowSize = 8;
reg clk;
reg [7:0] ledIn, _ledOut;

always @(clk) begin
    if(clk == 0)
        _ledOut <= 0;
    else if(clk == 1)
        _ledOut[RowSize-1:0] <= ledIn[RowSize-1:0];
end

initial begin
    $monitor($time, " clk=%b ledIn=%h _ledOut=%h", clk, ledIn, _ledOut);
    ledIn = 0;
    #22 ledIn = 8'h55;
    #20 $finish;
end

always begin
    #5 clk <= 0;
    #5 clk <= 1;
end

endmodule

It produces this output:

               0 clk=x ledIn=00 _ledOut=xx
               5 clk=0 ledIn=00 _ledOut=00
              10 clk=1 ledIn=00 _ledOut=00
              15 clk=0 ledIn=00 _ledOut=00
              20 clk=1 ledIn=00 _ledOut=00
              22 clk=1 ledIn=55 _ledOut=00
              25 clk=0 ledIn=55 _ledOut=00
              30 clk=1 ledIn=55 _ledOut=55
              35 clk=0 ledIn=55 _ledOut=00
              40 clk=1 ledIn=55 _ledOut=55

Notice at time 22, when ledIn changes, the _ledOut output does not change. _ledOut only changes at the next posedge of clk at time 30. Therefore, the always @(clk) solution is doing what you want: the output only changes at the clock edge, as you specified.

萌逼全场 2024-12-28 00:35:30

这是一个非常不寻常的问题,它让我建议您需要提供更多有关您实际想要实现的目标的信息,因为如果这是针对 FPGA,它很可能会影响时序性能和时钟约束。已经提到了综合,但是您将把时钟门控输出输入什么?如果它是引脚焊盘,那么您应该阅读设备规范中的 DDR 焊盘缓冲区,并推断能够驱动 DDR 信号的特定原语。

如果您将此信号保留在芯片内,那么这是一个非常奇怪的请求。如果我需要生成该波形,我可能会使用 PLL 生成两倍于基频的锁相时钟,并将门控数据放入该域,并通过切换来应用桅杆,以便工具能够正确分析时钟交叉,并且生成的数据路径仍然在单个边沿有效转换。

上面推断在输出上强制使用组合多路复用器的寄存器的答案很有趣,但是无论您将其输入什么,都必须处理尴尬的设置/保持条件,并且如果在片上,则无论如何都只会采样一个边缘,所以这有点多余。

This is a pretty unusual question, and it makes me advise you need to give more information about what you are actually trying to achieve, since it may well impact the timing performance and clock constraints if this is targeting an FPGA. Synthesis has been mentioned, but what will you be feeding the clock-gated output into? If it's a pin-pad, then you should read the DDR pad buffers in the device specifications and infer the specific primitive to be able to drive a DDR signal.

If you are keeping this signal within the chip then this is a very bizarre request. If I needed to generate that waveform, I would probably use a PLL to generate a phase-locked clock at twice the base frequency and put the gated data into that domain, with a toggle to apply the mast, so that the tooling will be able to properly analyse the clock crossings and the resulting data path is still effectively transitioning on a single edge.

The answers above to infer a register with a combinatorial multiplexer forced on the output is interesting, but whatever you feed this into will have to deal with awkward setup/hold conditions, and if on-chip, would only be sampling one edge anyway, so this is kind of redundant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文