有限狀態機編碼技巧

admin @ 2014-03-26 , reply:0

 狀態機的編碼
a、狀態機的編碼。Biary、gray-code 編碼使用最少的觸發器,較多的組合邏輯。而one-hot編碼反之。由於CPLD 更多的提供組合邏輯資源,而FPGA 更多的提供觸發器資源,所以CPLD多使用gray-code,而FPGA多使用one-hot 編碼。另一方面,對於小型設計使用gray-code和binary 編碼更有效,而大型狀態機使用one-hot 更高效。

b、在代碼中添加綜合器的綜合約束屬性或者在圖形界面下設置綜合約束屬性可以比較方便地改變狀態的編碼。

VHDL 的示例:
Synplicity:
attribute syn_encoding : string;
attribute syn_encoding of <signal_name> : type is "value ";
The syn_encoding attribute has 4 values : sequential, onehot, gray and safe.
Exemplar:
-- Declare TYPE_ENCODING_style attribute
-- Not needed if the exemplar_1164 package is used
type encoding_style is (BINARY, ONEHOT, GRAY, RANDOM, AUTO);
attribute TYPE_ENCODING_style : encoding_style;
...
attribute TYPE_ENCODING_style of <typename> : type is ONEHOT;
Verilog 示例:
Synplicity:
Reg[2:0] state; /* synthesis syn_encoding = "value" */;
// The syn_encoding attribute has 4 values : sequential, onehot, gray and safe.
Exemplar:
Parameter /* exemplar enum <type_name> */ s0 = 0, s1 = 1, s2 = 2, s3 = 3, S4 = 4;
Reg [2:0] /* exemplar enum <type_name> */ present_state, next_state

狀態機的編碼風格
a、關於FSM 的編碼方法。FSM 分兩大類:米勒型和摩爾型。組成要素有輸入(包括複位),狀態(包括當前狀態的操作),狀態轉移條件,狀態的輸出條件。 設計FSM 的方法和技巧多種多樣,但是總結起來有兩大類:第一種,將狀態轉移和狀態的操作和判斷等寫到一個模塊(process、block)中。另一種是將狀態轉移單獨寫成一個模塊,將狀態的操作和判斷等寫到另一個模塊中(在Verilog 代碼中,相當於使用兩個“always” block)。其中較好的方式是後者。其原因如下。 首先FSM 和其他設計一樣,最好使用同步時序方式設計,好處不再贅述。而狀態機實現后,狀態轉移是用寄存器實現的,是同步時序部分。狀態的轉移條件的判斷是通過組合邏輯判斷實現的,之所以第二種比第一種編碼方式合理,就在於第二種編碼將同步時序和組合邏輯分別放到不同的程序塊(process,block)中實現。這樣做的好處不僅僅是便於閱讀、理解、維護,更重要的是利於綜合器優化代碼,利於用戶添加合適的時序約束條件,利於布局布線器實現設計。

b、初始化狀態和默認狀態。 一個完備的狀態機(健壯性強)應該具備初始化狀態和默認狀態。當晶元加電或者複位后,狀態機應該能夠自動將所有判斷條件複位,並進入初始化狀態。需要註明的一點是,大多數FPGA 有GSR(Global Set/Reset)信號,當FPGA 加電后,GSR 信號拉高,對所有的寄存器,RAM 等單元複位/置位,這是配置於FPGA 的邏輯並未生效,所以不能保證正確的進入初始化狀態。所以使用GSR 企圖進入FPGA 的初始化狀態,常常會產生種種不必要的麻煩。一般的方法是採用非同步複位信號,當然也可以使用同步複位,但是要注意同步複位的邏輯設計。解決這個問題的另一種方法是將默認的初始狀態的編碼設為全零,這樣GSR 複位后,狀態機自動進入初始狀態。 令一方面狀態機也應該有一個默認(default)狀態,當轉移條件不滿足,或者狀態發生了突變時,要能保證邏輯不會陷入“死循環”。這是對狀態機健壯性的一個重要要求,也就是常說的要具備“自恢復”功能。對應於編碼就是對case,if-else 語句要特別注意,要寫完備的條件判斷語句。VHDL 中,當使用CASE 語句的時候,要使用“When Others”建立默認狀態。使用“IF...THEN...ELSE”語句的時候,要用“ELSE”指定默認狀態。Verilog 中,使用“case”語句的時候要用“default”建立默認狀態,使用“if...else”語句的注意事項相似。 另外提一個技巧:大多數綜合器都支持Verilog 編碼狀態機的完備狀態屬性--“full case”。這個屬性用於指定將狀態機綜合成完備的狀態,如Synplicity 的綜合工具(Synplify/Synplify Pro,Amplify,etc)支持的命令格式如下:
case (current_state) // synthesis full_case
2’b00 : next_state <= 2’b01;
2’b01 : next_state <= 2’b11;
2’b11 : next_state <= 2’b00;
//這兩段代碼等效
case (current_state)
2’b00 : next_state <= 2’b01;
2’b01 : next_state <= 2’b11;
2’b11 : next_state <= 2’b00;
default : next_state <= 2bx;
    Synplicity 還有一個關於狀態機的綜合屬性,叫“// synthesis parallel_case”其功能是檢查所有的狀態是“并行的”(parallel),也就是說在同一時間只有一個狀態能夠成立。

c、使用完備的“if...else”還有一個重要的好處,就是可以避免生成非目的性的“鎖存器”(Latch)。

d、狀態機的定義可以用parameter 定義,但是不推薦使用`define 宏定義的方式,因為‘define 宏定義在編譯時自動替換整個設計中所定義的宏,而parameter 僅僅定義模塊內部的參數,定義的參數不會與模塊外的其他狀態機混淆。




[admin via 研發互助社區 ] 有限狀態機編碼技巧已經有1901次圍觀

http://cocdig.com/docs/show-post-42997.html