Verilog代码报阻塞与非阻塞赋值混用错误,求解决及新手问题指正
问题排查与修复方案
1 报错核心原因:state变量混用阻塞/非阻塞赋值
你收到的报错是因为寄存器state在代码中同时使用了两种赋值方式:
- initial初始化块中用了阻塞赋值:
state=0; - 时钟沿触发的时序逻辑块中,对
state的赋值混用了阻塞state = #50 x和非阻塞state <= x两种写法,违反了Verilog编码规范。
修复方式:
- 所有时序逻辑(时钟沿触发的always块)中对寄存器的赋值统一使用非阻塞赋值
<= - initial块中对state的初始化也统一改为非阻塞:
state <= 0; - 删掉所有时序逻辑中的
#50手动延迟,该语法仅用于仿真,不可综合,要实现状态跳转直接每个时钟沿更新一次state即可。
2 其他编码错误
2.1 组合逻辑错误使用非阻塞赋值
mux8模块的always @(*)是组合逻辑块,当前对data_bus用了非阻塞赋值<=,需全部改为阻塞赋值=add_8_10_10模块的always块敏感列表不全,仅写了@(ctrl),会导致a、b变化时输出不更新,需改为always @(*),且该块是组合逻辑,对out_hold的赋值需改为阻塞赋值=,或者直接简化为纯组合逻辑写法assign out = a + b,不需要额外寄存器。
2.2 功能逻辑错误
- 你定义了
next_state、b、c三个变量但完全没有使用,属于冗余代码可直接删除 - 滑动平均的求和逻辑缺失:
temp_sum变量仅做了初始化,没有在状态跳转时更新值,会导致最终计算的平均值错误,需要在每次加法后更新temp_sum,8个数据累加完成后右移3位即可得到8个数的平均值 add_8_10_10模块功能冗余,不需要单独封装,直接在需要加法的位置写求和逻辑即可。
修复后的核心代码片段示例
// mux8组合逻辑修改 always @ (*) begin case (select) 0: data_bus = data0 ; 1: data_bus = data1 ; // 其余case同理全部改为= endcase end // avg_small的initial块修改 initial begin next_state <= 3'd0; temp_sum <= 11'd0; output_register <= 7'd0; registers[0] <= 0; registers[1] <= 0; registers[2] <= 0; registers[3] <= 0; registers[4] <= 0; registers[5] <= 0; registers[6] <= 0; registers[7] <= 0; state <= 0; // 改为非阻塞 end // 时序逻辑state赋值修改示例 always@(posedge clk) begin if(rs) begin state <= 0; temp_sum <= 0; // 复位时补充寄存器清零逻辑 end else begin case(state) 0:begin registers[0] <= registers[1]; temp_sum <= temp_sum + registers[1]; // 补充求和逻辑 state <= 1; // 去掉#50,统一用非阻塞 end // 其余状态同理修改 7:begin registers[7] <= num_in; temp_sum <= temp_sum + num_in; output_register <= temp_sum[10:3]; // 右移3位即除以8得到平均值 state <= 0; end endcase end end
内容的提问来源于stack exchange,提问作者bitbytten
相关产品推荐
相关产品推荐

