电子说
先贴一下代码的简版:
localparam S_IDLE = 4'd0;
localparam S_HEAD = 4'd1;
localparam S_PAYLOAD = 4'd2;
localparam S_TAIL = 4'd3;
localparam S_ERROR = 4'd4;
reg [3:0]status, nx_status;
always @(posedge clk_100m or negedge rst_spt_n)begin
if(!rst_spt_n) status <= S_IDLE;
else status <= nx_status;
end
always @* begin
case(status)
S_IDLE: ...
S_HEAD: ...
S_PAYLOAD: ...
S_TAIL: ...
S_ERROR: ...
default: nx_status = status;
endcase
end
状态机本身很简单,default也写了,然后进行仿真时看到了这样的波形:
nx_status仿真初始的值为4'hb,而后导致status的值也为4'hb,始终无法回到IDLE状态,整个电路的功能也无法正常开展。
这个问题得以暴露要感谢在验证环境中打开了initreg功能:
CMP_OPTIONS += +vcs+initreg+random
RUN_OPTIONS += +vcs+initreg+$(SEED)
通过这样的配置使得reg型的数值在仿真开始时被赋值为随机数。该bug就是由于nx_status被赋值为状态之外的随机数而发现的。
在代码中,nx_status没有任何位置被进行“复位”,当然了因为nx_status本身不是寄存器也就不存在复位的问题,不过状态机的alway@*中的处理是有问题的,这导致nx_status一旦跑“飞”了,status下一拍会更新为nx_status的值,那么整个状态机将不可恢复。
修改状态机的写法为:
always @* begin
case(status)
S_IDLE: ...
S_HEAD: ...
S_PAYLOAD: ...
S_TAIL: ...
S_ERROR: ...
default: nx_status = S_IDLE;
endcase
end
或者
always @* begin
nx_status = S_IDLE;
case(status)
S_IDLE: ...
S_HEAD: ...
S_PAYLOAD: ...
S_TAIL: ...
S_ERROR: ...
default: nx_status = status;
endcase
end
重新仿真后波形正确:
全部0条评论
快来发表一下你的评论吧 !