事故現(xiàn)場
先貼一下代碼的簡版:
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
狀態(tài)機本身很簡單,default也寫了,然后進行仿真時看到了這樣的波形:

nx_status仿真初始的值為4'hb,而后導致status的值也為4'hb,始終無法回到IDLE狀態(tài),整個電路的功能也無法正常開展。
事故分析
這個問題得以暴露要感謝在驗證環(huán)境中打開了initreg功能:
CMP_OPTIONS += +vcs+initreg+random
RUN_OPTIONS += +vcs+initreg+$(SEED)
通過這樣的配置使得reg型的數(shù)值在仿真開始時被賦值為隨機數(shù)。該bug就是由于nx_status被賦值為狀態(tài)之外的隨機數(shù)而發(fā)現(xiàn)的。
在代碼中,nx_status沒有任何位置被進行“復位”,當然了因為nx_status本身不是寄存器也就不存在復位的問題,不過狀態(tài)機的alway@*中的處理是有問題的,這導致nx_status一旦跑“飛”了,status下一拍會更新為nx_status的值,那么整個狀態(tài)機將不可恢復。
事故解決
修改狀態(tài)機的寫法為:
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
重新仿真后波形正確:

-
寄存器
+關注
關注
31文章
5587瀏覽量
128993 -
仿真器
+關注
關注
14文章
1048瀏覽量
86730 -
狀態(tài)機
+關注
關注
2文章
497瀏覽量
28827
發(fā)布評論請先 登錄
Verilog狀態(tài)機+設計實例
玩轉Spring狀態(tài)機
什么是狀態(tài)機?狀態(tài)機的三種實現(xiàn)方法
如何寫好狀態(tài)機
狀態(tài)機舉例
什么是狀態(tài)機 狀態(tài)機的描述三種方法
什么是狀態(tài)機?狀態(tài)機5要素
狀態(tài)模式(狀態(tài)機)

狀態(tài)機怎么上來就錯了?怎么解決?
評論