D触发器仿真没有打一拍

目录
    本文上次更新于 525 天前,其内容可能已经过时,如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!

    vcs:2016.06_Full64
    verdi: verdi3_L-2016.06-1

    具体代码如下

    `timescale 1ns/1ps
    module exp1(
            input        clk   ,
    	input        rst_n ,
    	input        a     ,
    	output [3:0] a_cnt
    );
    
    wire a_risedge ;
    
    reg a_risedge_q;
    reg a_q        ;
    
    reg [3:0] a_cnt;
    
    assign a_risedge = ( a_q ^ a) & a; 
    
    always@(posedge clk or negedge rst_n) begin
    	if(!rst_n) begin 
                a_cnt <= 1'b0;
    	end
    	else begin
                a_q <= a;
    	end
    end
      
    always@(posedge clk or negedge rst_n) begin
    	if(!rst_n) begin
    		a_cnt <= 1'b0;
    	end
    	else begin
    		a_risedge_q <= a_risedge;
    	end
    end
    
    always@(posedge clk or negedge rst_n) begin
    	if(!rst_n) begin
    		a_cnt <= 1'b0;
    	end
    	else if(a_risedge_q == 1'b1)  begin
    		a_cnt = a_cnt + 1'b1;
    	end
    	else begin
    		a_cnt <= a_cnt;
    	end
    end
    
    endmodule
    
    module test;
    	wire clk  ;
    	wire rst_n;
    	wire a    ;
    	
    	reg [3:0] a_cnt;
    
    	parameter cycle = 2;
    	exp1 u_exp1(
    							.clk   (clk  ),
    							.rst_n (rst_n),
    							.a     (a    ),
    							.a_cnt (a_cnt)
    	);
    
    	initial begin
    		clk = 0;
    		forever #(cycle/2) clk <= ~clk;
    	end
    	initial begin
    		$fsdbDumpfile("dut.fsdb");
    		$fsdbDumpvars(0,u_exp1);
    		$fsdbDumpon();
    		rst_n = 1'b0;
    		a 		= 4'b0;
    		#1;
    		rst_n = 1'b1;
    		#1;
    		a = 1'b1;
    		#7;
    		a = 1'b0;
    		#2;
    		a = 1'b1;
    		#4;
    		a = 1'b0;
    		#4;
    		a = 1'b1;
    		#2;
    		a = 1'b0;
    		$fsdbDumpoff();
    		$finish();
    	end
    endmodule

    用 vcs 编译并仿真,在仿真时需要加上 -fsdb 和 -region,在仿真时需要加上 +fsdb+delta 才能从verdi上看到Delta cycle


    2024.1.30 更新, -fsdb 在高版本(比如vcs2023)已经弃用, 可以用 -debug_access 替代, +fsdb+delta中间没有空格,有空格的话后面用verdi打开时相应的是灰色的

    vcs -full64 -cpp g++-4.4 -cc gcc-4.4 -sverilog -debug_access exp1.v && ./simv +fsdb+delta

    vcs -full64 -cpp g++-4.4 -cc gcc-4.4 -sverilog -fsdb -region exp1.v && ./simv +fsdb+delta

    vcs -full64 -cpp g++-4.4 -cc gcc-4.4 -sverilog -fsdb -region exp1.v && ./simv +fsdb+delta

    用 verdi 打开 dut.fsdb 文件,将波形全部加载进来

    verdi -ssf dut.fsdb & 

    鼠标左键单击时钟上升沿,在按键盘小写的 w ( nWave–>View –> Expand Delta –> Expand/Collapse Time at Cursor )即可显示出Delta cycle。可以看到在时钟上升沿,采到的值为0,这是因为verilog中存在仿真调度的问题,虽然都是在同一时刻,但是毕竟是用来软件来模拟硬件的行为,软件执行始终是有先后顺序的,具体的顺序可以参考这里,active 区是要在 NBA区之前执行的,在 active 区域会执行阻塞赋值的内容,在 NBA 区域会执行非阻塞赋值的东西。因此,在 9ns 的时候,a 的值是先变为0,然后时钟上升沿才到来,因此在时钟上升沿采样到的就是0,也就不会有打一拍。

    当我们把 tb 中的阻塞赋值改为非阻塞赋值后,把时钟的非阻塞改为阻塞后,该现象就没了,下图是改为非阻塞后的结果。

    如果在这个过程中遇到了其它问题,欢迎在评论区留言,或者Google一下,也欢迎把具体的解决方法留在评论区,以供后来者参考

    参考

    如果在这个过程中遇到了其它问题,欢迎在评论区留言,如果你已解决,也欢迎把具体的解决方法留在评论区,以供后来者参考
    ×

    感谢您的支持,请扫码打赏

    微信打赏 支付宝打赏
    guest
    0 评论
    内联反馈
    查看所有评论