用一段式建模FSM 的寄存器輸出的時候,必須要綜合考慮現態在何種狀態轉移條件下會進入哪些次態,然后在每個現態的case 分支下分別描述每個次態的輸出,這顯然不符合思維習慣;而三段式建模描述FSM 的狀態機輸出時,只需指定case 敏感表為次態寄存器,然后直接在每個次態的case 分支中描述該狀態的輸出即可,根本不用考慮狀態轉移條件。本例的FSM 很簡單,如果設計的FSM 相對復雜,三段式的描述優勢就會凸顯出來。
另一方面,三段式描述方法與兩段式描述相比,雖然代碼結構復雜了一些,但是換來的優勢是使FSM 做到了同步寄存器輸出,消除了組合邏輯輸出的不穩定與毛刺的隱患,而且更利於時序路徑分組,一般來說在FPGA/CPLD 等可編程邏輯器件上的綜合與布局布線效果更佳。
下面以‘101’序列檢測器的FSM來說明三段式FSM的寫法:
1 `timescale 1ns / 1ps 2 3 ///////////////////////////////////////////////////////////////// 4 5 // Company: csic 6 7 // Engineer: shengyi 8 9 // Create Date: 15:24:44 09/16/2010 10 11 // Design Name: seqcheck_fsm3 12 13 // Module Name: seqcheck_101 14 15 // Project Name: seqcheck_fsm3 16 17 // Target Devices: V5 220t 18 19 // Tool versions: ise 10.1 20 21 // Description: 借'101'序列檢測器程序說明FSM的三段式寫法 22 23 // Dependencies: 24 25 // Revision: 26 27 // Revision 0.01 - File Created 28 29 // Additional Comments: 30 31 ///////////////////////////////////////////////////////////////// 32 33 //3-paragraph method to describe FSM 34 35 //Describe sequential state transition in the 1st sequential always block 36 37 //State transition conditions in the 2nd combinational always block 38 39 //Describe the FSM out in the 3rd sequential always block 40 41 module seqcheck_101( 42 43 clk, 44 45 rst, 46 47 din, 48 49 dout 50 51 ); 52 53 parameter IDLE=4'b0001,S1=4'b0010,S2=4'b0100,S3=4'b1000; 54 55 input clk; 56 57 input rst; 58 59 input din; 60 61 output dout; 62 63 reg dout; 64 65 reg [3:0] current_state,next_state; 66 67 68 69 //第一部分說明初始狀態,和current_state<=next_state 70 71 //每一個時鍾沿產生一次可能的狀態變化 72 73 always @(posedge clk) 74 75 begin 76 77 if(rst) 78 79 current_state<=IDLE; 80 81 else 82 83 current_state<=next_state; 84 85 end 86 87 88 89 //第二部分,狀態轉移,產生下一狀態的整合邏輯 90 91 always @(din or current_state) 92 93 begin 94 95 next_state<=4'bx; 96 97 case(current_state) 98 99 IDLE: 100 101 begin 102 103 if(din==1'b1) 104 105 next_state<=S1; 106 107 else 108 109 next_state<=IDLE; 110 111 end 112 113 S1: 114 115 begin 116 117 if(din==1'b1) 118 119 next_state<=S1; 120 121 else 122 123 next_state<=S2; 124 125 end 126 127 S2: 128 129 begin 130 131 if(din==1'b1) 132 133 next_state<=S3; 134 135 else 136 137 next_state<=IDLE; 138 139 end 140 141 S3: 142 143 begin 144 145 if(din==1'b1) 146 147 next_state<=S1; 148 149 else 150 151 next_state<=S2; 152 153 end 154 155 default: 156 157 next_state<=4'bx; 158 159 endcase 160 161 end 162 163 164 165 //第三段,產生輸出 166 167 always @(posedge clk) 168 169 begin 170 171 if(rst) 172 173 dout<=1'b0; 174 175 else 176 177 begin 178 179 case(next_state) 180 181 IDLE:dout<=1'b0; 182 183 S1:dout<=1'b0; 184 185 S2:dout<=1'b0; 186 187 S3:dout<=1'b1; 188 189 default:dout<=1'bx; 190 191 endcase 192 193 end 194 195 end 196 197 endmodule