You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Modelsim仿真中寄存器未出现单周期延迟问题求助

问题:4位寄存器输出与输入同步变化,仿真未观测到单周期延迟

我设计的4位寄存器工作异常,输出与输入同步变化,本应存在单周期延迟,但在Modelsim仿真中未观测到该现象,请问原因是什么?

寄存器代码

module register_4bit (
    input wire clk,           // Clock signal
    input wire rst_n,         // Active-low asynchronous reset
    input wire [3:0] d,       // 4-bit data input
    output reg [3:0] q        // 4-bit data output
);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            q <= 4'b0000;     // Reset to 0 when rst_n is low
        else
            q <= d;           // Load data on clock edge
    end

endmodule

测试平台代码

module tb_register_4bit;
    reg clk, rst_n;
    reg [3:0] d;
    wire [3:0] q;
    
    register_4bit dut (
        .clk(clk),
        .rst_n(rst_n),
        .d(d),
        .q(q)
    );
    
    // Clock generation
    initial clk = 0;
    always #5 clk = ~clk;  // 10ns period
    
    initial begin
        // Initialize
        rst_n = 0;
        d = 4'b0000;
        #15 rst_n = 1;
        
        // Test sequence - watch the delay!
        #10 d = 4'b0001;  // Change at t=25ns
        #10 d = 4'b0010;  // Change at t=35ns
        #10 d = 4'b0100;  // Change at t=45ns
        #10 d = 4'b1000;  // Change at t=55ns
        #10 d = 4'b1111;  // Change at t=65ns
        
        #20 $finish;
    end
    
    // Monitor to see delay clearly
    initial begin
        $monitor("Time=%0t | d=%b | q=%b", $time, d, q);
    end
endmodule

仿真结果说明

仿真过程中观测到输入d变化时,输出q立即同步更新,未出现预期的单周期延迟。


原因分析及解决方法

1. 输入信号变化时机与时钟上升沿完全对齐

测试平台中时钟周期为10ns(每#5ns翻转一次),而输入d的更新间隔是#10ns,导致d的变化时刻(25ns、35ns、45ns等)完全和时钟上升沿重合。

在Verilog仿真的事件队列机制中,时钟上升沿触发的寄存器非阻塞赋值(<=)与输入d的阻塞赋值(=)会在同一时间步执行。虽然非阻塞赋值的逻辑是“先计算右侧值,再更新左侧”,但当d的变化与时钟沿同步时,仿真器会直接使用更新后的d值驱动寄存器输出,造成无延迟的错觉。

2. $monitor的打印机制放大了同步错觉

$monitor会在任何信号发生变化时立即触发打印。当d和时钟沿同时变化时,寄存器的q会在同一时间步完成更新,因此$monitor会一次性打印出更新后的d和q,让你误以为两者没有延迟。

解决方法

  • 错开输入变化与时钟沿的时机:将测试平台中d的更新延迟改为非10ns的倍数,比如#7,确保d在时钟沿之间变化,这样就能看到q在下一个时钟上升沿才跟随d变化。修改后的测试序列示例:
    // Test sequence - 错开时钟沿
    #7 d = 4'b0001;  // 变化在t=22ns,介于t=20ns和t=30ns时钟沿之间
    #10 d = 4'b0010; // 变化在t=32ns
    #10 d = 4'b0100; // 变化在t=42ns
    #10 d = 4'b1000; // 变化在t=52ns
    #10 d = 4'b1111; // 变化在t=62ns
    
  • 改用$strobe打印:$strobe会在当前时间步所有事件执行完成后打印,能准确反映寄存器在时钟沿后的输出状态,避免同步错觉。修改监控语句:
    initial begin
        $strobe("Time=%0t | d=%b | q=%b", $time, d, q);
    end
    
  • 查看波形图:直接在Modelsim中查看clk、d、q的波形,能直观看到q是在时钟上升沿之后才变化的,不受打印机制的干扰。

内容的提问来源于stack exchange,提问作者user22714606

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 01:40:24