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

Verilog posedge寄存器级联异常问题咨询及FPGA适配疑问

Verilog模块级联测试异常问题解答

问题背景

编写了一个同步寄存器模块test,功能是在时钟上升沿将输入left传递到输出right,代码如下:

`timescale 1ns / 1ps

module test (
    input clk,
    input left,
    output right
);
    reg right_ = 0;
    assign right = right_;
    always @(posedge clk) begin
        right_ <= left;
    end
endmodule

测试台中级联两个test模块,代码如下:

`include "test.v"

`timescale 1ns / 1ps

module test_tb;

// Inputs
reg clk = 1;
reg left = 0;

// Outputs
wire right;
wire out;

// Clock gen
always  begin
    #1;
    clk = ~clk;
end

// Instantiate modules
test t1(
    .clk(clk),
    .left(left),
    .right(right)
);

test t2(
    .clk(clk),
    .left(right),
    .right(out)
);

initial begin
    $dumpfile(`VCD_FILE);
    $dumpvars(0, test_tb);
    #10;
    left = 1;
    #11;
    $finish;
end

endmodule

通过gtkWave观察到:t1的right似乎随left立即变化,而t2的out需要等待一个时钟周期。


问题1:原因与解决方案

异常原因

这是测试台时序巧合导致的视觉误解:

  • 时钟周期为2ns(每1ns翻转一次),#10对应的10ns时刻恰好是时钟上升沿(从0翻到1)。
  • 此时执行left=1(阻塞赋值,立即生效),同时t1的always @(posedge clk)块触发,执行非阻塞赋值right_ <= left。非阻塞赋值会在当前时间步所有阻塞操作完成后更新寄存器值,因此right会在10ns时刻同步更新,看起来像是“立即传递”。
  • 而t2在同一个时钟上升沿触发时,读取的是t1寄存器更新前的旧值(非阻塞赋值的更新在采样之后),因此需要等到下一个时钟上升沿才能完成传递。

解决方案

调整测试台中left的赋值时间,避开时钟上升沿,比如将:

#10;
left = 1;

修改为:

#9;
left = 1;

此时left在9ns(时钟为0的时刻)变为1,下一个时钟上升沿(10ns)到来时,t1才会触发并更新right,这样t1和t2的传递都会显示为延迟一个时钟周期,符合预期的同步寄存器行为。


问题2:FPGA硬件适用性

完全适用。

  • 模块中的非阻塞赋值<=会被综合为FPGA中的触发器(寄存器),严格按照时钟上升沿采样输入、更新输出,与仿真行为完全一致。
  • 调整测试台时序只是为了更准确地观察硬件的实际工作状态,硬件本身的逻辑设计符合同步电路规范,只要输入信号满足FPGA的建立/保持时间要求,就能稳定工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:41:01