事故現(xiàn)場(chǎng)
先貼一下代碼的簡(jiǎ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ī)本身很簡(jiǎn)單,default也寫了,然后進(jìn)行仿真時(shí)看到了這樣的波形:

nx_status仿真初始的值為4'hb,而后導(dǎo)致status的值也為4'hb,始終無(wú)法回到IDLE狀態(tài),整個(gè)電路的功能也無(wú)法正常開展。
事故分析
這個(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下一拍會(huì)更新為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文章
5590瀏覽量
129248 -
仿真器
+關(guān)注
關(guān)注
14文章
1049瀏覽量
86821 -
狀態(tài)機(jī)
+關(guān)注
關(guān)注
2文章
498瀏覽量
28903
發(fā)布評(píng)論請(qǐng)先 登錄
Verilog狀態(tài)機(jī)+設(shè)計(jì)實(shí)例
玩轉(zhuǎn)Spring狀態(tài)機(jī)
什么是狀態(tài)機(jī)?狀態(tài)機(jī)的三種實(shí)現(xiàn)方法
如何寫好狀態(tài)機(jī)
狀態(tài)機(jī)舉例
狀態(tài)機(jī)代碼生成工具
簡(jiǎn)述使用QII狀態(tài)機(jī)向?qū)绾蝿?chuàng)建一個(gè)狀態(tài)機(jī)
什么是狀態(tài)機(jī) 狀態(tài)機(jī)的描述三種方法
FPGA:狀態(tài)機(jī)簡(jiǎn)述
什么是狀態(tài)機(jī)?狀態(tài)機(jī)5要素
狀態(tài)模式(狀態(tài)機(jī))

狀態(tài)機(jī)怎么上來(lái)就錯(cuò)了?怎么解決?
評(píng)論