仿真时寄存器究竟在时钟沿的什么时刻赋值?

 1 现象:

  仿真在140ns位置处,时钟clk上升沿一来,data_in和data_in_reg同步变化? 但是,data_in_reg为寄存器,它与数据源data_in同时变化,这与寄存器赋值会有一拍延时相矛盾。例如:cnt与data_out两个信号,data_out比cnt延时一拍。

2 原因

        由于data_in不是由寄存器驱动的,而是在testbench中直接赋值,modelsim在分析时,认为此时data_in的值已经更新为1,故将data_in直接赋值给data_in_reg,在理想仿真情况下,寄存器的输入与输出没有延时,data_in_reg更新为1。

3 解决:

(1)在testbench中错开时钟沿赋值;

 (2)在RTL中加入#1延迟;

 

 4 相关程序

(1)设计程序

 1 module register_test(
 2     input        wire            clk,
 3     input     wire            rst_n,
 4     input     wire     [7:0]    data_in,
 5     output     reg     [7:0]    data_in_reg,
 6     output     reg     [7:0]    data_out
 7 );
 8 
 9     reg        [7:0]        cnt;
10     
11     always@(posedge clk or negedge rst_n)begin
12         if(!rst_n)
13             data_in_reg <= 8'd0;
14         else
15             data_in_reg <= data_in;
16     end
17     
18     always@(posedge clk or negedge rst_n)begin
19         if(!rst_n)
20             cnt <= 8'd0;
21         else
22             cnt <= cnt + 1'b1;
23     end
24     
25     always@(posedge clk or negedge rst_n)begin
26         if(!rst_n)
27             data_out <= 8'd0;
28         else
29             data_out <= cnt;
30     end
31 
32 endmodule 

(2)仿真程序

 1 `timescale 1ns/1ns
 2 
 3 module register_test_tb();
 4 
 5     reg                        clk;
 6     reg                        rst_n;
 7     reg                 [7:0]    data_in;
 8     wire                 [7:0]    data_in_reg;
 9     wire                 [7:0]    data_out;
10 
11     integer             i;
12     
13     register_test register_test_inst(
14         .clk                    (clk),
15         .rst_n                (rst_n),
16         .data_in                (data_in    ),
17         .data_in_reg        (data_in_reg),
18         .data_out            (data_out)
19     );
20 
21     initial clk = 1;
22     always #10 clk = ~clk;
23     
24     initial begin
25         rst_n = 0; data_in = 0;
26         #100; rst_n = 1;
27         #20;
28         for(i=0;i<15;i=i+1)begin
29             data_in = i;
30             #20;
31         end
32         #20;
33         $stop;
34     end
35 
36 endmodule

 

参考资料:

(1)小梅哥Verilog语法常见知识讲解_哔哩哔哩_bilibili

posted @ 2021-10-10 17:06  豌豆茶  阅读(332)  评论(0编辑  收藏  举报