verilog 自动售货机状态机实现_Verilog语法简介(5)

状态机

有限状态机英文名字,Finite State Machine,简称状态机,缩写为FSM。

有限状态机是指输出取决于过去输入部分和当前输入部分的时序逻辑电路。 有限状态机又可以认为是组合逻辑和寄存器逻辑的一种组合。状态机特别适合描 述那些发生有先后顺序或者有逻辑规律的事情,其实这就是状态机的本质。

状态机就是对具有逻辑顺序或时序规律的事件进行描述的一种方法 根据状态机的输出是否与输入条件相关,可将状态机分为两大类,即摩尔 (Moore) 型状态机和米勒 (Mealy) 型状态机。 

  • Mealy 状态机:时序逻辑的输出不仅取决于当前状态,还取决于输入。 
  • Moore 状态机:时序逻辑的输出只取决于当前状态。

根据实际写法,状态机还可以分为一段式、二段式和三段式状态机。

  1. 一段式:把整个状态机写在一个 always 模块中,并且这个模块既包含状态转移, 又含有组合逻辑输入/输出。 
  2. 二段式: 状态切换用时序逻辑,次态输出和信号输出用组合逻辑。
  3. 三段式: 状态切换用时序逻辑,次态输出用组合逻辑,信号输出用时序逻辑。

说明: 实际应用中三段式使用最多,也最为可靠,避免了状态和输入输出的干 扰,推荐大家使用第三种写法,我们实际项目中基本全部是第三种写法。 本文也着重讲解三段式。

Mealy 状态机

下一个状态 = F(当前状态,输入信号); 输出信号 = G(当前状态,输入信号);

verilog 自动售货机状态机实现_Verilog语法简介(5)_第1张图片

三段式状态机

两段式直接采用组合逻辑输出,而三段式则通过在组合逻辑后再增加一级寄 存器来实现时序逻辑输出。这样做的好处是可以有效地滤去各个逻辑输出的毛刺, 同时可以有效地进行时序计算与约束,另外对于总线形式的输出信号来说,容易 使总线数据对齐,从而减小总线数据间的偏移,减小接收端数据采样出错的频率。

三段式状态机的基本格式是:

第一个always语句实现同步状态跳转;

第二个always语句实现组合逻辑;

第三个always语句实现同步输出。

Verilog描述状态机需要注意的事项: 

  • 定义模块名和输入输出端口; 
  • 定义输入、输出变量或寄存器; 
  • 定义时钟和复位信号; 
  • 定义状态变量和状态寄存器; 
  • 用时钟沿触发的 always 块表示状态转移过程; 
  • 在复位信号有效时给状态寄存器赋初始值; 
  • 描述状态的转换过程:符合条件,从一个状态到另外一个状态,否则留在原状态;
  • 验证状态转移的正确性,必须完整和全面。

一个三段式状态机例子:

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

你可能感兴趣的:(verilog,自动售货机状态机实现)