Verilog中always块事件控制赋值的疑问及仿真差异咨询
Verilog时序控制语句的理解与仿真差异问题
我正在学习Verilog,遇到了如下代码的理解疑问:
always @(posedge clock) begin reg1 <= #25 in_1; reg2 <= @(negedge clock) in_2 ^ in_3; reg3 <= in_1; end
我对reg2的执行逻辑理解如下:
- 在clock上升沿计算
in_2 ^ in_3的值 - 在clock下降沿将计算结果存入reg2
请问这个理解是否正确?
为验证该想法,我用ModelSim 6.6d和Vivado 2019.1对同一代码仿真,却得到了不同波形,这是为什么?
测试代码
test.v
`timescale 1ns / 1ps module test( input wire clock, input wire [2:0] in_1, in_2, in_3, output reg [2:0] reg1, reg2, reg3 ); always @(posedge clock) begin reg1 <= #25 in_1; reg2 <= @(negedge clock) in_2 ^ in_3; reg3 <= in_1; end endmodule
tb_test.v
`timescale 1ns / 1ps module tb_test(); reg clock = 1'b0; reg [2:0] in_1 = 3'b001; reg [2:0] in_2 = 3'b010; reg [2:0] in_3 = 3'b100; wire [2:0] reg1; wire [2:0] reg2; wire [2:0] reg3; always #5 clock = ~clock; test uut( .clock (clock), .in_1 (in_1), .in_2 (in_2), .in_3 (in_3), .reg1 (reg1), .reg2 (reg2), .reg3 (reg3) ); endmodule
仿真波形
- ModelSim仿真波形:

- Vivado仿真波形:

问题解答
1. 关于reg2执行逻辑的理解
你的理解不完全正确。Verilog中,@(negedge clock)属于事件控制延迟赋值,其执行逻辑是:
- 在
always @(posedge clock)触发时,仅调度该赋值操作,不会立即计算in_2 ^ in_3的值; - 直到下一个clock下降沿到来时,才会计算
in_2 ^ in_3的当前值,并将其赋给reg2。
简言之:计算与赋值动作都发生在下降沿,而非上升沿计算、下降沿赋值。
2. 仿真工具波形差异的原因
这种差异源于不同仿真工具对Verilog非标准/非可综合语法的实现细节差异:
@(事件)作为非阻塞赋值的延迟控制属于行为级仿真语法,并非可综合语法,IEEE Verilog标准对这类语法的执行顺序细节未做强制统一规定;- ModelSim与Vivado(基于XSIM仿真器)的事件调度机制不同:两者在处理这类事件延迟赋值时,对信号采样时机、事件队列优先级的处理逻辑存在区别,导致波形表现不一致;
- 另外,
#25这类固定延迟在不同工具中的时间精度处理也可能存在细微差别,进一步放大了波形差异。
注意事项
这类行为级语法仅适用于仿真验证,无法被综合成硬件电路。如果需要实现“上升沿采样、下降沿赋值”的逻辑,建议使用标准可综合写法,例如:
reg [2:0] temp; always @(posedge clock) begin temp <= in_2 ^ in_3; // 上升沿采样输入值 end always @(negedge clock) begin reg2 <= temp; // 下降沿将采样值赋值给reg2 end
内容的提问来源于stack exchange,提问作者moonjy1120
相关产品推荐
相关产品推荐

