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
相关产品推荐
相关产品推荐

