FPGA 状态机(FSM)的三段式推荐写法

用一段式建模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
原文地址:https://www.cnblogs.com/sky1991/p/2583612.html