有限状态机英文名字,Finite State Machine,简称状态机,缩写为FSM。
有限状态机是指输出取决于过去输入部分和当前输入部分的时序逻辑电路。 有限状态机又可以认为是组合逻辑和寄存器逻辑的一种组合。状态机特别适合描 述那些发生有先后顺序或者有逻辑规律的事情,其实这就是状态机的本质。
状态机就是对具有逻辑顺序或时序规律的事件进行描述的一种方法 根据状态机的输出是否与输入条件相关,可将状态机分为两大类,即摩尔 (Moore) 型状态机和米勒 (Mealy) 型状态机。
根据实际写法,状态机还可以分为一段式、二段式和三段式状态机。
说明: 实际应用中三段式使用最多,也最为可靠,避免了状态和输入输出的干 扰,推荐大家使用第三种写法,我们实际项目中基本全部是第三种写法。 本文也着重讲解三段式。
Mealy 状态机
下一个状态 = F(当前状态,输入信号); 输出信号 = G(当前状态,输入信号);
三段式状态机
两段式直接采用组合逻辑输出,而三段式则通过在组合逻辑后再增加一级寄 存器来实现时序逻辑输出。这样做的好处是可以有效地滤去各个逻辑输出的毛刺, 同时可以有效地进行时序计算与约束,另外对于总线形式的输出信号来说,容易 使总线数据对齐,从而减小总线数据间的偏移,减小接收端数据采样出错的频率。
三段式状态机的基本格式是:
第一个always语句实现同步状态跳转;
第二个always语句实现组合逻辑;
第三个always语句实现同步输出。
Verilog描述状态机需要注意的事项:
一个三段式状态机例子:
module divider7_fsm (
//input
input sys_clk, // system clock;
input sys_rst_n, // system reset, low is active;
//output
output reg clk_divide_7 // output divide 7 clk
);
//reg define
reg [6:0] curr_st ; // FSM current state
reg [6:0] next_st ; // FSM next state reg
clk_divide_7 ; // generated clock,divide by 7
//wire define
//parameter define
//one hot code design
parameter S0 = 7'b0000000;
parameter S1 = 7'b0000001;
parameter S2 = 7'b0000010;
parameter S3 = 7'b0000100;
parameter S4 = 7'b0001000;
parameter S5 = 7'b0010000;
parameter S6 = 7'b0100000;
/******************************** Main Program ***********************************/
//generate FSM next state
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n ==1'b0) begin
curr_st <= 7'b0;
end
else begin
curr_st <= next_st;
end end
//FSM state logic
always @(*) begin
case (curr_st)
S0: begin
next_st = S1;
end
S1: begin
next_st = S2;
end
S2: begin
next_st = S3;
end
S3: begin
next_st = S4;
end
S4: begin
next_st = S5;
end
S5: begin
next_st = S6;
end
S6: begin
next_st = S0;
end
default: next_st = S0;
endcase
end
//control divide clock offset
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n ==1'b0) begin
clk_divide_7 <= 1'b0;
end
else if ((curr_st == S0) | (curr_st == S1) | (curr_st == S2) | (curr_st == S3))
clk_divide_7 <= 1'b0;
else if ((curr_st == S4) | (curr_st == S5) | (curr_st == S6))
clk_divide_7 <= 1'b1;
else
;
end
endmodule
//end of RTL code
说明:
1、 本状态机采用独热码设计,简称one-hot code,独热码编码的最大 优势在于状态比较时仅仅需要比较一个位,从而一定程度上简化了译码逻辑。
2、 一般状态机状态编码使用二进制编码、格雷码、独热码。
各种编码比较:
二进制编码、格雷码编码使用最少的触发器,消耗较多的组合逻辑, 而独热码编码反之。独热码编码的最大优势在于状态比较时仅仅需 要比较一个位,从而一定程度上简化了译码逻辑。虽然在需要表示 同样的状态数时,独热编码占用较多的位,也就是消耗较多的触发 器,但这些额外触发器占用的面积可与译码电路省下来的面积相抵 消。
Binary(二进制编码)、gray-code(格雷码)编码使用最少的触 发器,较多的组合逻辑,而 one-hot(独热码)编码反之。one-hot 编码的最大优势在于状态比较时仅仅需要比较一个 bit,一定程度 上从而简化了比较逻辑,减少了毛刺产生的概率。另一方面,对于 小型设计使用 gray-code 和 binary 编码更有效,而大型状态机使 用 one-hot 更高效。
以上面的LED流水灯为例,采用行为建模方法。
module LED (
//input
input sys_clk , //system clock;
input sys_rst_n , //system reset, low is active;
//output
output reg [7:0] LED
);
//Parameter define
parameter WIDTH = 8 ;
parameter SIZE = 8 ;
parameter WIDTH2 = 18 ;
parameter Para = 100000;
//Reg define
reg [SIZE-1:0] counter ;
reg [WIDTH2-1:0] coun ;
//Wire define
//*****************************************************
//** Main Program
//**
//************************************************
// count for add counter
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n ==1'b0)
count <= 18'b0;
else
count <= count + 18'b1;
end
// counter for delay time to LED display
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n ==1'b0)
counter <= 8'b0;
else if ( count == Para)
counter <= counter + 8'b1;
else ;
end
// ctrl LED pipeline display when counter is equal 10 or 20 ....
always @(posedge sys_clk or negedge sys_rst_n) begin
if (sys_rst_n ==1'b0)
LED <= 8'b0;
else begin
case (counter)
8'd10 : LED <= 8'b10000000 ;
8'd20 : LED <= 8'b01000000 ;
8'd30 : LED <= 8'b00100000 ;
8'd40 : LED <= 8'b00010000 ;
8'd50 : LED <= 8'b00001000 ;
8'd60 : LED <= 8'b00000100 ;
8'd70 : LED <= 8'b00000010 ;
8'd80 : LED <= 8'b00000001 ;
default : LED <= 8'b00000000 ;
endcase
end
end