FSM设计之一
FSM的设计是数字FPGA设计的一个主要课题之一,是Verilog必须掌握的设计手段。状态机FSM的设计一般分成三个部分,即三个always设计。
三段式风格:其中一个always块用于状态转移,一个always块用于状态译码逻辑,另一个always块用于状态输出的寄存;但它并不一定指整个状态机只能包括三个always块,在满足输出寄存的前提下,可以使用三个及以上的always块,甚至在某些特殊情况,用两个always块的状态机也可以认为是三段式的写法。
第一个always(同步时序)格式化的描述次态寄存器到现态寄存器的转移(CS<=NS);
always @ (posedge clk,negedge rst_n)
begin
if(!rst_n)
cs <= idle;
else
cs <= ns;
end
第二个always (纯组合逻辑)描述状态转移的条件判断,描述状态转移的规律;
always @ (cs,a)
begin
case(cs)
idle :
begin
if(a) ns = start;
else ns = idle;
end
start:
begin
if(!a) ns = stop;
else ns = start;
end
stop:
begin
if(a) ns = clear;
else ns = stop;
end
clear:
begin
if(!a) ns = idle;
else ns = clear;
end
default: ns ='bx;
endcase
end
第三个always块群,分别用always块来描述每个输出的组合逻辑
//--------------------------------------
always @ (cs,rst_n,a)
begin
if(!rst_n)
k1 = 1'b0;
else
if(cs == clear && !a) k1 = 1'b1;
else k1 = 1'b0;
end
//--------------------------------------
always @ (cs,rst_n,a)
begin
if(!rst_n)
k2 = 1'b0;
else
if(cs==stop && a) k2=1'b1;
else k2 = 1'b0;
end
整个FSM的程序结构如下:
1 module fsm
2 (
3 input clk,
4 input rst_n,
5 input a,
6 output reg k1,
7 output reg k2
8 );
9 //-----------------------------------
10 reg [1:0] cs,ns;
11 //-----------------------------------
12 parameter
13 idle = 2'b00,
14 start = 2'b01,
15 stop = 2'b11,
16 clear = 2'b10;
17 //-----------------------------------
18 always @ (posedge clk,negedge rst_n)
19 begin
20 if(!rst_n)
21 cs <= idle;
22 else
23 cs <= ns;
24 end
25 //-----------------------------------
26 always @ (cs,a)
27 begin
28 case(cs)
29 idle :
30 begin
31 if(a) ns = start;
32 else ns = idle;
33 end
34 start:
35 begin
36 if(!a) ns = stop;
37 else ns = start;
38 end
39 stop:
40 begin
41 if(a) ns = clear;
42 else ns = stop;
43 end
44 clear:
45 begin
46 if(!a) ns = idle;
47 else ns = clear;
48 end
49 default: ns = idle;
50 endcase
51 end
52 //--------------------------------------
53 always @ (cs,rst_n,a)
54 begin
55 if(!rst_n)
56 k1 = 1'b0;
57 else
58 if(cs == clear && !a) k1 = 1'b1;
59 else k1 = 1'b0;
60 end
61 //--------------------------------------
62 always @ (cs,rst_n,a)
63 begin
64 if(!rst_n)
65 k2 = 1'b0;
66 else
67 if(cs==stop && a) k2=1'b1;
68 else k2 = 1'b0;
69 end
70 //----------------------------------------
71 endmodule
---------------------------------------------------------------------
在第三个always块也可以写出时序输出形式
always @ (posedge clk,negedge rst_n)
if(!rst_n)
{out1,out2,out3} <= 3'b000;
else
case(NS)
idle : {out1,out2,out3} <= 3'b001;
.......
endcase
路漫漫其修远兮,吾将上下而求索