事故現(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)機(jī)本身很簡單,default也寫了,然后進(jìn)行仿真時(shí)看到了這樣的波形:
nx_status仿真初始的值為4'hb,而后導(dǎo)致status的值也為4'hb,始終無法回到IDLE狀態(tài),整個(gè)電路的功能也無法正常開展。
事故分析
這個(gè)問題得以暴露要感謝在驗(yàn)證環(huán)境中打開了initreg功能:
CMP_OPTIONS += +vcs+initreg+random
RUN_OPTIONS += +vcs+initreg+$(SEED)
通過這樣的配置使得reg型的數(shù)值在仿真開始時(shí)被賦值為隨機(jī)數(shù)。該bug就是由于nx_status被賦值為狀態(tài)之外的隨機(jī)數(shù)而發(fā)現(xiàn)的。
在代碼中,nx_status沒有任何位置被進(jìn)行“復(fù)位”,當(dāng)然了因?yàn)閚x_status本身不是寄存器也就不存在復(fù)位的問題,不過狀態(tài)機(jī)的alway@*中的處理是有問題的,這導(dǎo)致nx_status一旦跑“飛”了,status下一拍會更新為nx_status的值,那么整個(gè)狀態(tài)機(jī)將不可恢復(fù)。
事故解決
修改狀態(tài)機(jī)的寫法為:
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
重新仿真后波形正確:
-
寄存器
+關(guān)注
關(guān)注
31文章
5343瀏覽量
120443 -
仿真器
+關(guān)注
關(guān)注
14文章
1018瀏覽量
83765 -
狀態(tài)機(jī)
+關(guān)注
關(guān)注
2文章
492瀏覽量
27548
發(fā)布評論請先 登錄
相關(guān)推薦
評論