在 Verilog的江湖里,流傳著一段,兩段,三段式狀態(tài)機(jī)的傳說(shuō)。它們各有優(yōu)劣,本文就書(shū)寫三段式狀態(tài)機(jī)的錯(cuò)誤原因進(jìn)行探尋。
本文會(huì)涉及到Verilog的基本語(yǔ)法,需要一定的Verilog基礎(chǔ),包括對(duì)reg,always,狀態(tài)機(jī)的一些認(rèn)識(shí),數(shù)字電路基礎(chǔ)。
三段式狀態(tài)機(jī),將狀態(tài)機(jī)分為三段,功能為狀態(tài)轉(zhuǎn)移,狀態(tài)轉(zhuǎn)移條件判斷,輸出邏輯等。
存在問(wèn)題的“三段式狀態(tài)機(jī)”代碼如下:
程序比較簡(jiǎn)單,于是直接上板驗(yàn)證。
經(jīng)過(guò)上板調(diào)試,發(fā)現(xiàn)問(wèn)題存在于當(dāng)empty為低時(shí),rd_en并沒(méi)有拉高。于是,我首先懷疑整個(gè)系統(tǒng)是不是一直處于復(fù)位狀態(tài)。
經(jīng)過(guò)查找,發(fā)現(xiàn)rst一直保持低電平,整個(gè)程序不在復(fù)位狀態(tài)。這就很神奇了。
后來(lái),經(jīng)過(guò)提醒和仔細(xì)查找原因,才發(fā)現(xiàn)這個(gè)狀態(tài)機(jī)寫的其實(shí)存在問(wèn)題。狀態(tài)轉(zhuǎn)移條件判斷和狀態(tài)轉(zhuǎn)移都使用時(shí)序邏輯,兩者并行運(yùn)行,問(wèn)題就凸顯出來(lái)了。
舉例說(shuō)明,假設(shè)當(dāng)前狀態(tài)state
, next_state
都處于IDLE
狀態(tài);
事實(shí)上,這么寫,造成的問(wèn)題是state相對(duì)其他信號(hào)可能會(huì)晚一節(jié)拍。狀態(tài)機(jī)晚一節(jié)拍,可能會(huì)導(dǎo)致時(shí)序錯(cuò)亂。
而事實(shí)上,三段式狀態(tài)機(jī)當(dāng)然不是這么寫的。
首先,三段式狀態(tài)機(jī)由三部分(段)組成,前面也提到了,是狀態(tài)轉(zhuǎn)移,狀態(tài)轉(zhuǎn)移條件判斷,輸出邏輯等。
首先談到狀態(tài)轉(zhuǎn)移,三段式狀態(tài)機(jī)有state, next_state信號(hào)作為指示。兩者在位寬,信號(hào)類型上一模一樣,都是reg型變量。
狀態(tài)轉(zhuǎn)移很簡(jiǎn)單,大致如下:
其中,IDLE
是預(yù)先定義的常量,使用localparam
,parameter
定義即可,或者可以使用`define定義宏變量參數(shù),然后放在一個(gè)通用的參數(shù)模塊文件里,供項(xiàng)目里所有文件調(diào)用,后續(xù)再詳細(xì)講解這塊吧。
這塊的內(nèi)容,僅僅是將next_state的值打一拍,通過(guò)了一個(gè)寄存器,意義何在呢,要結(jié)合狀態(tài)轉(zhuǎn)移條件判斷一起看。
狀態(tài)轉(zhuǎn)移條件判斷代碼大致如下:
這塊的內(nèi)容主要是做next_state值變更的條件判斷,結(jié)合功能來(lái)說(shuō),就是做狀態(tài)值的更新。
那可能有人會(huì)問(wèn):
- always @ (*) 是什么意思
簡(jiǎn)單來(lái)說(shuō),always @ ( ) 意為每時(shí)每刻都在運(yùn)行,也就是組合邏輯,你也可以使用always @ (state, a, b)方式來(lái)代替always @ ( )。但是,假如always列表里的信號(hào)不全,可能造成的影響又是什么呢?
- reg類型為什么放在組合邏輯里面做
reg型變量最后綜合的電路也可能是組合邏輯,也不是說(shuō)always塊一定綜合出時(shí)序邏輯,主要還是跟敏感列表有關(guān),其次always里只能使用reg型變量
- 為什么你的if沒(méi)有補(bǔ)全else
對(duì)于時(shí)序邏輯來(lái)說(shuō),沒(méi)有補(bǔ)全else,default等不會(huì)生成鎖存器;對(duì)于組合邏輯來(lái)說(shuō),沒(méi)有else,default確實(shí)可能生成鎖存器,但是鎖存器生成的原因是因?yàn)樵O(shè)計(jì)代碼中要求組合邏輯去保持或者說(shuō)記憶住某個(gè)值,這本該是時(shí)序邏輯該干的事,組合邏輯干不了,所以生成鎖存器;而本段代碼,第一行代碼就相當(dāng)于已經(jīng)為所有無(wú)法進(jìn)入if條件的情況增加了默認(rèn)情況,就是賦值為state的狀態(tài)。
這兩塊內(nèi)容都跟狀態(tài)轉(zhuǎn)移有關(guān),第二塊進(jìn)行條件判斷,而判斷不僅要根據(jù)外部信號(hào),也要根據(jù)自身所在的狀態(tài),所以第一塊進(jìn)行狀態(tài)值的更新。
那么這么做的好處是什么呢?跟一段式狀態(tài)機(jī)相比,將狀態(tài)轉(zhuǎn)移與判斷和輸出邏輯分開(kāi)寫,方便后續(xù)的調(diào)試。
因?yàn)樵谡{(diào)試階段,查找問(wèn)題時(shí)會(huì)去查找問(wèn)題所在的狀態(tài),然后再比對(duì)代碼中該狀態(tài)的判斷條件,沒(méi)有錯(cuò)誤再比對(duì)該條件下問(wèn)題信號(hào)的輸出邏輯,調(diào)試更為方便。
那么第三段的輸出邏輯,代碼大致如下:
首先,輸出邏輯這段并不是要求只用一個(gè)always寫完所有的輸出邏輯;其次,使用時(shí)序邏輯輸出,更利于信號(hào)的時(shí)序分析和時(shí)序收斂。
當(dāng)然,一段式狀態(tài)機(jī)也并不是一無(wú)是處,很多時(shí)候,在一些邏輯簡(jiǎn)單,功能簡(jiǎn)單的場(chǎng)景下,我也愿意使用一段式狀態(tài)機(jī)。兩段式狀態(tài)機(jī)用的比較少,感覺(jué)像是一段式和三段式狀態(tài)機(jī)的過(guò)渡狀態(tài),有點(diǎn)雞肋的感覺(jué)。
-
鎖存器
+關(guān)注
關(guān)注
8文章
906瀏覽量
41509 -
時(shí)序邏輯電路
+關(guān)注
關(guān)注
2文章
94瀏覽量
16546 -
狀態(tài)機(jī)
+關(guān)注
關(guān)注
2文章
492瀏覽量
27541 -
Verilog語(yǔ)言
+關(guān)注
關(guān)注
0文章
113瀏覽量
8235
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論