verilog 三段式狀態機的技巧


三段式代碼多,但是有時鍾同步,延時少,組合邏輯跟時序邏輯分開並行出錯少。

(1)同步狀態轉移 (2)當前狀態判斷接下來的狀態 (3)動作輸出

如果程序復雜可以不止三個always   。always 后常接case  case必須有default   ,對於FPGA常用  狀態數較少,獨熱碼編碼 ,或者格雷碼

//獨熱碼編碼

parameter NO_KEY_PRESSED = 6'b000_001; // 沒有按鍵按下
parameter SCAN_row0 = 6'b000_010; // 掃描第0行
parameter SCAN_row1 = 6'b000_100; // 掃描第1行
parameter SCAN_row2 = 6'b001_000; // 掃描第2行
parameter SCAN_row3 = 6'b010_000; // 掃描第3行
parameter KEY_PRESSED = 6'b100_000; // 有按鍵按下

reg [5:0] current_state, next_state; // 現態、次態

(1)第一個always模塊,格式化描述次態寄存器遷移到現態寄存器

always @ (posedge key_clk, negedge rst_n) //異步復位
if (!rst_n)
current_state <= NO_KEY_PRESSED;//初始化按鍵沒按下 //默認狀態
else
current_state <= next_state;    //注意,使用的是非阻塞賦值

(2)第二個進程,組合邏輯always模塊,描述狀態轉移條件判斷用current_state

always @ (current_state) //電平觸發      或者always @ *

begin

next_state = x; //要初始化,使得系統復位后能進入正確的狀態

case(current_state)

S1: if(...)

next_state = S2;     //阻塞賦值

...

endcase

end

 

(3)第三個進程,同步時序always模塊,描述次態寄存器輸出

always @ (posedge clk or negedge rst_n)

...//初始化

case(next_state)

S1:

out1 <= 1'b1; //注意是非阻塞邏輯

S2:

out2 <= 1'b1;

default:... //default的作用是免除綜合工具綜合出鎖存器。

endcase

end

 

三段式並不是一定要寫為3個always塊,如果狀態機更復雜,就不止3段了。

1. 三段always模塊中,第一個和第三個always模塊是同步時序always模塊,用非阻塞賦值( <= );第二個always模塊是組合邏輯always模塊,用阻塞賦值( = )

2. 第二部分為組合邏輯always模塊,為了抑制warning信息,對於always的敏感列表建議采用always@*)的方式。

3. 第二部分,組合邏輯always模塊,里面判斷條件一定要包含所有情況!可以用else保證包含完全。

4. 第二部分,組合邏輯電平要維持超過一個clock,仿真時注意。

5. 需要注意:第二部分case中的條件應該為當前態(current_state)。

6. 第三部分case中的條件應該為次態(next_state)。

7. 編碼原則,binary和gray-code適用於觸發器資源較少,組合電路資源豐富的情況(CPLD),對於FPGA,適用one-hot code。這樣不但充分利用FPGA豐富的觸發器資源,還因為只需比較一個bit,速度快,組合電路簡單。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM