Verilog 为什么我的D触发器不等待时钟的正边缘?

Verilog 为什么我的D触发器不等待时钟的正边缘?,verilog,Verilog,正如我所知,D触发器在每个正边缘对其输入值进行采样 时钟的方向 因此,它将产生1个周期的延迟。对吧? 但是为什么我的D触发器不产生1个周期的延迟呢 module flipflop( input clk, input rstn, input [7:0] i_data, output reg [7:0] o_data ); alway

正如我所知,D触发器在每个正边缘对其输入值进行采样 时钟的方向

因此,它将产生1个周期的延迟。对吧?

但是为什么我的D触发器不产生1个周期的延迟呢

         module flipflop(
             input clk,
             input rstn,
             input [7:0] i_data,
             output reg [7:0] o_data
         );

             always @(posedge clk) begin
                     if (~rstn) begin
                             o_data <= 0;
                     end
                     else begin
                             o_data <= i_data;
                     end
             end
         endmodule

       module test;
           reg clk;
           reg [7:0] i_data;
           reg rstn;
           wire [7:0] o_data;

           initial begin
                   clk = 0;
                   rstn = 1;
                   i_data = 0;
                   #20;
                   rstn = 0;

                   #30;
                   rstn = 1;
                   #20;
                   i_data = 8'hFA;
                   #20;
                   i_data = 8'hF0;
                   #20
                   i_data = 8'hF1;
                   #20
                   #10 $finish;
           end

           always #10 clk = !clk;

           flipflop flipflop(
                   .clk (clk),
                   .rstn(rstn),
                   .i_data(i_data),
                   .o_data(o_data)
           );

           initial begin
                   $dumpfile("flipflop.vcd");
                   $dumpvars();
           end
       endmodule
模块触发器(
输入时钟,
输入rstn,
输入[7:0]i_数据,
输出reg[7:0]o_数据
);
始终@(posedge clk)开始
如果(~rstn)开始

o_data您遇到了Verilog模拟器事件调度的微妙之处!将数据分配更改为使用非阻塞分配可能是最简单的修复方法

#20;
i_data <= 8'hFA;
#20;
i_data <= 8'hF0;
#20
i_data <= 8'hF1;
#20

模拟器可能正在执行以下操作:

       initial begin
               clk = 0;
               rstn = 1;
               i_data = 0;
               #10;
               clk = !clk;
               #10;
               rstn = 0;
               clk = !clk;

               #10;
               clk = !clk;
               #10;
               clk = !clk;
               #10;
               rstn = 1;
               clk = !clk;
               #10;
               clk = !clk;
               #10
               i_data = 8'hFA; //Input updated
               clk = !clk;     //Clock event
                               //o_data assigned here
               #10;
               clk = !clk;
               #10;
               i_data = 8'hF0;
               clk = !clk;
               #20
               i_data = 8'hF1;
               #20
               #10 $finish;
       end
由于时钟事件在测试台的每个时间步中都是最后一个发生的,所以看起来触发器是立即分配的。你可能想让你的测试台完全脱离时间,所以Marty建议使用@(posedge…)就可以实现这一点。你也可以简单地在一开始就推迟一次作业:

       initial begin
               clk = 0;
               #1;
               rstn = 1;
               i_data = 0;
               #20;
               rstn = 0;

               #30;
               rstn = 1;
               #20;
               i_data = 8'hFA;
               #20;
               i_data = 8'hF0;
               #20
               i_data = 8'hF1;
               #20
               #10 $finish;
       end

这是一个很好的解释问题的方法。马蒂,你能回顾一下你最后的建议吗?它认为应该是
@(posedge clk)i_数据
       initial begin
               clk = 0;
               #1;
               rstn = 1;
               i_data = 0;
               #20;
               rstn = 0;

               #30;
               rstn = 1;
               #20;
               i_data = 8'hFA;
               #20;
               i_data = 8'hF0;
               #20
               i_data = 8'hF1;
               #20
               #10 $finish;
       end