FPGA,verilog程序技巧之狀態機與穩定性,高速


             關於FPGA的verilog語言的書,已經有很多很多了,甚至程序的寫作標准也很完善了。本人FPGA入行兩年,對很多的小問題,還有百度上很容易能想到,能看到的,我就不在描述,必定意義不大。對剛入門的FPGA的朋友,你們暫時還涉及不到穩定性問題。關於小白們,我能給你們的意見是,多百度,上面可以幫你解決,前2年遇到的所有問題。

           狀態機的重要性,寫過一兩年程序的人都知道,不用多說了吧。直接上重點。

           第一個:輸出信號填寫問題,下面是我轉載的一些能百度的到的東西。好像都比較正常。這里我還要強調的是,每個狀態機的輸出信號都需要全面。

舉例:

always @ (posedge clk or negedge rst_n)              這里的狀態機簡單的描述,其實還有很多狀態。

...//初始化                                              out3在s1  s2輸出都是一樣的,在狀態跳轉從s1跳到s2的

 case(next_state)                                                    時候out3會在s1處所存,所以就算在s2的地方不寫一次out3 <= 1'b0 ;情況S1:                                                                         也是是輸出0.對狀態機要求高的話,需要這么寫。

  out1 <= 1'b1;  

 out2 <= 1'b0;  

out3 <= 1'b0;       //看這里    

S2:

  out2 <= 1'b0;

 out2 <= 1'b1;

out3 <= 1'b0 ;            //看這里    

default:...    

endcase

end

                     第二個:程序輸出結構。看程序應該能懂,不需要太多解釋吧。

舉例:

always @ (posedge clk or negedge rst_n)        

case (next_state)                                                                                           

S1:                                                                                                                      

out1 <= 1'b1;                 //看這里                                          所有的不受if控制的輸出都要寫到if的外面。

 out2 <= 1'b0;                  

if (x)                  

   out3 <= 1'b0;

else

   out3 <=1'b1;

S2:

  out2 <= 1'b0;       //看這里   

 out2 <= 1'b1;

if (y)

   out3 <= 1'b0;

else

   out3 <=1'b1;

 

default:...    

endcase

end

                                    第三個。三段式(多段式)。簡單描述就是將第三段的輸出,在分為多段。

舉例:(我不知道我這么寫例子是否恰當,只能表達一個意思吧)

always @ (posedge clk or negedge rst_n)        

case (next_state)                                                                                           

S1:                                                                                                                      

out1 <= 1'b1;            

 out2 <= 1'b0;                  

S2:

  out2 <= 1'b0;      

 out2 <= 1'b1; 

default:...    

endcase

end

-------------------------------------------------------------------

always @ (posedge clk or negedge rst_n)        

case (next_state)                                                                                           

S1:                                                                                                                                     

if (x)                  

   out3 <= 1'b0;

else

   out3 <=1'b1;

S2:

if (y)

   out3 <= 1'b0;

else

   out3 <=1'b1;

 

default:...    

endcase

end

                                         第四個。狀態機的拆分,講連續變化的狀態機,從大的狀態機里面拿出來。我只能這么說,沒辦法舉例子了。這里涉及的編程思想也比較多了,沒法描述但是要有這個思想。

                                          第五個。獨熱碼好像有時候也不夠穩定。你可以使用fifo來做狀態緩存。當然這里只是理論概念,因為我還沒寫過,三段式,獨熱碼,程序拆分后,還是不穩定的程序。但是如果以上內容你都做了,速度和穩定性還不夠,你可以考慮的。主要的想法是這樣的,fifo在多時鍾域都可以良好的切換,就說明它的亞穩態現象很低,為什么狀態機不穩定,就是對狀態采樣的時候,出現的問題。所以,它應該能做到更好的效果。

 

 

微笑本人能力有限,但努力奉獻我的知識,希望各位朋友可以快速成長。

 

 

-----------------------------------百度上截取--------------------------------------------------------------

Verilog有限狀態機三段式描述方法

PART1

1、好的狀態機標准

好的狀態機的標准很多,最重要的幾個方面如下:

第一,狀態機要安全,是指FSM不會進入死循環,特別是不會進入非預知的狀態,而且由於某些擾動進入非設計狀態,也能很快的恢復到正常的狀態循環中來。這里面有兩層含義:其一要求該FSM的綜合實現結果無毛刺等異常擾動;其二要求FSM要完備,即使受到異常擾動進入非設計狀態,也能很快恢復到正常狀態。

第二,狀態機的設計要滿足設計的面積和速度的要求。

第三,狀態機的設計要清晰易懂、易維護。


2、狀態機描述方法

狀態機描述時關鍵是要描述清楚幾個狀態機的要素,即如何進行狀態轉移每個狀態的輸出是什么狀態轉移的條件等。具體描述時方法各種各樣,最常見的有三種描述方式:

(1)一段式:整個狀態機寫到一個always模塊里面,在該模塊中既描述狀態轉移,又描述狀態的輸入和輸出;

(2)二段式:用兩個always模塊來描述狀態機,其中一個always模塊采用同步時序描述狀態轉移;另一個模塊采用組合邏輯判斷狀態轉移條件描述狀態轉移規律以及輸出

(3)三段式:在兩個always模塊描述方法基礎上,使用三個always模塊,一個always模塊采用同步時序描述狀態轉移,一個always采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律,另一個always模塊描述狀態輸出(可以用組合電路輸出,也可以時序電路輸出)


一般而言,推薦的FSM  描述方法是后兩種。這是因為:FSM和其他設計一樣,最好使用同步時序方式設計,以提高設計的穩定性,消除毛刺。狀態機實現后,一般來說,狀態轉移部分同步時序電路狀態的轉移條件的判斷組合邏輯


第二種描述方法同第一種描述方法相比,將同步時序和組合邏輯分別放到不同的always模塊中實現,這樣做的好處不僅僅是便於閱讀、理解、維護,更重要的是利於綜合器優化代碼,利於用戶添加合適的時序約束條件,利於布局布線器實現設計。

在第二種方式的描述中,描述當前狀態的輸出用組合邏輯實現,組合邏輯很容易產生毛刺,而且不利於約束,不利於綜合器和布局布線器實現高性能的設計。

第三種描述方式與第二種相比,關鍵在於根據狀態轉移規律,在上一狀態根據輸入條件判斷出當前狀態的輸出,從而在不插入額外時鍾節拍的前提下,實現了寄存器輸出。


PART2

時序電路的狀態是一個狀態變量集合,這些狀態變量在任意時刻的值都包含了為確定電路的未來行為而必需考慮的所有歷史信息。

狀態機采用VerilogHDL語言編碼,建議分為三個always段完成。


三段式建模描述FSM的狀態機輸出時,只需指定case敏感表為次態寄存器,然后直接在每個次態的case分支中描述該狀態的輸出即可,不用考慮狀態轉移條件。

三段式描述方法雖然代碼結構復雜了一些,但是換來的優勢是:使FSM做到了同步寄存器輸出,消除了組合邏輯輸出的不穩定與毛刺的隱患,而且更利於時序路徑分組,一般來說在FPGA/CPLD等可編程邏輯器件上的綜合與布局布線效果更佳。

示列如下:

 

//第一個進程,同步時序always模塊,格式化描述次態寄存器遷移到現態寄存器

always @ (posedge clk or negedge rst_n)   //異步復位

 if(!rst_n)

  current_state <= IDLE;

 else

  current_state <= next_state;  //注意,使用的是非阻塞賦值

 

//第二個進程,組合邏輯always模塊,描述狀態轉移條件判斷

always @ (current_state)       //電平觸發

 begin

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

   case(current_state)

   S1: if(...)

      next_state = S2;          //阻塞賦值

   ...

   endcase

end

 

//第三個進程,同步時序always模塊,格式化描述次態寄存器輸出

always @ (posedge clk or negedge rst_n)

...//初始化

 case(next_state)

S1:

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

S2:

  out2 <= 1'b1;

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

endcase

end

 

 

兩段式有限狀態機與三段式有限狀態機的區別

FSM將時序部分(狀態轉移部分)和組合部分(判斷狀態轉移條件和產生輸出)分開,寫為兩個always語句,即為兩段式有限狀態機。
將組合部分中的判斷狀態轉移條件和產生輸入再分開寫,則為三段式有限狀態機。
區別:
二段式在組合邏輯特別復雜時適用,但要注意需在后面加一個觸發器以消除組合邏輯對輸出產生的毛刺。三段式沒有這個問題,由於第三個always會生成觸發器。
設計時注意方面:
1.編碼原則

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

2.FSM初始化問題:
GSR(Gobal Set/Reset)只是在加電時清零所有的reg和片內ram,並不保證FSM能進入初始化狀態,要利用GSR,方案是適用one-hot code with zero idle,即初始狀態編碼為全零。已可以適用異步復位rst
3.FSM輸出可以適用task
4FSM中的case最好加上default,默認態可以設為初始態
5.尤其注意
第二段的always(組合部分,賦值用=)里面判斷條件一定要包含所有情況!可以用else保證包含完全。
6第二段always,組合邏輯電平要維持超過一個clock,仿真時注意。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

 


免責聲明!

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



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