Verilog:在时钟偶数上设置常量值

Verilog:在时钟偶数上设置常量值,verilog,Verilog,我是Verilog新手,所以这个问题可能相当愚蠢 我正在尝试的是:我有一个组件,它有一个clk、一个8位输入和一个8位输出。它应该做的是: 如果时钟事件为负边缘,则应将输出设置为0 如果时钟事件为正边缘,则应将输出设置为边缘事件此时的任何输入。在时钟的高相位期间,无论输入发生变化,输出都不应改变 到目前为止,我尝试的是: always @(negedge clk) _ledOut <= 0; always @(posedge clk) _ledOut[RowSize-1:

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

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

如果时钟事件为负边缘,则应将输出设置为0 如果时钟事件为正边缘,则应将输出设置为边缘事件此时的任何输入。在时钟的高相位期间,无论输入发生变化,输出都不应改变

到目前为止,我尝试的是:

always @(negedge clk)
    _ledOut <= 0;

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

_ledOut考虑以下刺激:

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
请注意,在时间22,当
发光二极管
改变时,
\u发光二极管
输出不会改变<代码>\u指示灯
仅在时间30的下一个posedge
clk
处更改。因此,
always@(clk)
解决方案正在做您想要做的事情:按照您的指定,输出只在时钟边缘变化

这告诉我,它不能为net解析多个常量驱动程序 _领头羊

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

然而,把这些放在一起总是@(negedge clk,posedge clk)告诉我,它不能同时测试这两种情况

这基本上描述了DDR寄存器。虽然许多FPGA设备具有这些特性,但它们通常无法合成。如果确实需要此功能,Xilinx将使用ODDR2和IDDR2原语

如果时钟事件为负边缘,则应将输出设置为0 时钟事件是正边缘,它应该将输出设置为任意值 输入是在边缘事件的这个时刻。在经济高速发展时期 时钟,输出不应改变,无论上的变化 输入

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


正如toolic所指出的,您发布的代码可以工作,但是您应该理解代码将合成为clk控制的多路复用器

好的,这是我现在的工作方案。也许这不是你见过的最好的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
参数RowSize=8;
输入时钟;
输入[RowSize-1:0]ledIn;
输出[RowSize-1:0]发光二极管;
reg[RowSize-1:0]\u列示灯;
分配列线输出=_列线输出&{RowSize{clk}};
始终@(posedge clk)开始

_ledOut[RowSize-1:0]这是一个非常不寻常的问题,我建议您需要提供更多关于您实际尝试实现的信息,因为如果这是针对FPGA,它可能会影响时序性能和时钟约束。已经提到了合成,但是您将把时钟选通输出馈送到什么?如果是pin焊盘,则应阅读设备规范中的DDR焊盘缓冲区,并推断出能够驱动DDR信号的特定原语

如果你将这个信号保存在芯片中,那么这是一个非常奇怪的请求。如果我需要生成该波形,我可能会使用一个PLL以两倍于基频的频率生成一个锁相时钟,并将选通数据放入该域,用一个开关应用mast,因此,工具将能够正确地分析时钟交叉,并且生成的数据路径仍然有效地在单个边缘上转换


上面的答案可以推断出一个寄存器,该寄存器的输出上强制有一个组合多路复用器,这很有趣,但无论你将其输入到什么地方,都必须处理尴尬的设置/保持条件,如果是在芯片上,无论如何只会对一条边进行采样,因此这是一种冗余

然而,在模拟中这是有效的,在合成中似乎不起作用。always块似乎在不断地分配给_ledOut。你应该在问题中规定你需要合成代码。为什么你需要离开时钟的两个边缘?这是你的问题的根源,一个时钟以两倍的速度运行,带有单边逻辑,可能是一个更好的解决方案。
               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
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