RTL if语句逻辑与仿真结果不匹配,输出异常闪烁问题求解
问题根本原因分析
1. 核心为Testbench采样竞争问题
你遇到的闪烁现象本质是Testbench生成的激励与时钟沿对齐导致的仿真调度竞争,符合SystemVerilog标准的调度规则,并非RTL逻辑错误:
- 你当前的激励生成逻辑中,
in置高的时间点和时钟上升沿完全重合 - 时序逻辑在时钟上升沿采样输入信号时,若输入信号与时钟沿同时变化,采样到的是变化前还是变化后的值不存在强制约束,由仿真器的调度顺序决定,本身具有随机性
- 闪烁的成因是部分时钟沿采样到
in=0,进入out <= out + 1'b1分支让out加1变为1,下一个时钟沿又采样到in=1,检测到|out=1就清零为0,循环往复就出现0和1交替跳动的现象 - 更换位宽后问题消失是因为不同位宽的代码在仿真器中的调度优先级发生了变化,刚好每次都采样到
in=1,本质还是依赖随机性,没有解决根本问题。
2. 修复方案
方案1:调整激励生成时序
将激励信号的变化对齐到时钟下降沿,完全避开采样竞争,示例修改如下:
initial begin clk = 0; rst = 1; in = 0 ; #30 rst = 0; @(negedge clk); // 等待时钟下降沿再修改输入 in = 1; #500; rst=1; #100ns; $stop(); end
方案2:采用标准时钟生成逻辑
你当前使用的always@(clk) #10ns clk <= !clk属于非规范时钟生成写法,修改为通用写法可减少不必要的调度异常:
initial clk = 0; always #10 clk = ~clk;
方案3:激励使用非阻塞赋值
Testbench给DUT的输入信号统一使用非阻塞赋值,符合仿真调度规则,从根源避免采样竞争:
in <= 1;
3. RTL代码逻辑说明
你的RTL代码本身逻辑没有问题:当时钟沿采样到in=1且out=3'b000时,归约或|out结果为0,不会进入清零分支,时序逻辑中未被赋值的寄存器默认保持原值,out会恒定为0,完全符合设计预期。
内容的提问来源于stack exchange,提问作者Mahmoud Maarouf
相关产品推荐
相关产品推荐

