赞
踩
一、有限状态机
- 基本概念
有限状态机(Finite State Machine, FSM)是电路设计的经典方法,通常可以认为是组合逻辑和寄存器逻辑的组合,其中组合逻辑用于状态译码和产生输出信号,寄存器用于存储状态。
- Moore和Mealy型状态机
摩尔型(Moore)状态机: 输出只是当前状态的函数
米利型(Mealy)状态机: 输出是当前状态和当前输入的函数
似乎不太好理解,我们结合状态机模型来看一下
可以看出,Moore型状态机输出只与当前状态(现态CS)有关
图中可以看出,Mealy型状态机相较于Moore型状态机,其输出逻辑多了一个输入端,即上述定义所说的Mealy型状态机输出由当前状态(现态CS)和当前输入决定。
- 两种状态机的区别
由于两者模型的差别,不难看出,Mealy型状态机当输入改变时输出也会立即改变,不依赖时钟,而Moore型状态机输入状态改变时,需要经过时钟同步后输出才会改变,即Moore型状态机比Mealy型状态机输出要多一个时钟周期。实用的状态机一般都设计成同步时序模式。
二、有限状态机的Verilog描述
-状态机的设计中主要包含以下3个对象:
-Verilog描述方式
-举例(可乐机:2.5¥出可乐,可以投入0.5¥、1¥)
1.先画出状态转移图,比较丑,但大概是这样,简单起见,不考虑找零,不投硬币也不算输入。
2.Verilog描述
2.1三段式描述
//三段式描述(CS、NS、OL) module Coke_Machine //模块名 ( input wire sys_clk , //输入时钟 input wire sys_rst_n , //输入复位 input wire pi_money_half , //输入0.5 input wire pi_money_one , //输入1.0 output reg po_cola ); parameter IDLE = 5'b00001, //状态编码,独热码 HALF = 5'b00010, ONE = 5'b00100, ONE_HALF = 5'b01000, TWO = 5'b10000; wire [1:0] pi_money; reg [4:0] state,next_state; assign pi_money = {pi_money_one,pi_money_half}; //合并输入,即输入0.5为01,输入1为10 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) state <= IDLE; //定义起始状态 else state <= next_state; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) state <= IDLE; //定义起始状态 else case(state) IDLE: if(pi_money == 2'b01) next_state <= HALF; else if(pi_money == 2'b10) next_state <= ONE; else next_state <= IDLE; HALF: if(pi_money == 2'b01) next_state <= ONE; else if(pi_money == 2'b10) next_state <= ONE_HALF; else next_state <= HALF; ONE: if(pi_money == 2'b01) next_state <= ONE_HALF; else if(pi_money == 2'b10) next_state <= TWO; else next_state <= ONE; ONE_HALF: if(pi_money == 2'b01) next_state <= TWO; else if(pi_money == 2'b10) next_state <= IDLE; else next_state <= ONE_HALF; TWO: if(pi_money == 2'b01) next_state <= IDLE; else if(pi_money == 2'b10) next_state <= HALF; else next_state <= TWO; default: next_state <= IDLE; endcase always@(posedge sys_clk or negedge sys_rst_n) //输出逻辑 if(sys_rst_n == 1'b0) po_cola <= 1'b0; else if(((state == ONE_HALF) && (pi_money == 2'b10)) || ((state == TWO) && (pi_money == 2'b01)) || ((state == TWO) && (pi_money == 2'b10))) po_cola <= 1'b1; else po_cola <= 1'b0; endmodule
2.2两段式描述(CS+NS、OL)
//两段式描述(CS+NS、OL) module Coke_Machine //模块名 ( input wire sys_clk , //输入时钟 input wire sys_rst_n , //输入复位 input wire pi_money_half , //输入01 input wire pi_money_one , //输入10 output reg po_cola ); parameter IDLE = 5'b00001, //状态编码,独热码 HALF = 5'b00010, ONE = 5'b00100, ONE_HALF = 5'b01000, TWO = 5'b10000; wire [1:0] pi_money; reg [4:0] state; assign pi_money = {pi_money_one,pi_money_half}; //合并输入,即输入0.5为01,输入1为10 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) state <= IDLE; //定义起始状态 else case(state) IDLE: if(pi_money == 2'b01) state <= HALF; else if(pi_money == 2'b10) state <= ONE; else state <= IDLE; HALF: if(pi_money == 2'b01) state <= ONE; else if(pi_money == 2'b10) state <= ONE_HALF; else state <= HALF; ONE: if(pi_money == 2'b01) state <= ONE_HALF; else if(pi_money == 2'b10) state <= TWO; else state <= ONE; ONE_HALF: if(pi_money == 2'b01) state <= TWO; else if(pi_money == 2'b10) state <= IDLE; else state <= ONE_HALF; TWO: if(pi_money == 2'b01) state <= IDLE; else if(pi_money == 2'b10) state <= HALF; else state <= TWO; default: state <= IDLE; endcase always@(posedge sys_clk or negedge sys_rst_n) //输出逻辑 if(sys_rst_n == 1'b0) po_cola <= 1'b0; else if(((state == ONE_HALF) && (pi_money == 2'b10)) || ((state == TWO) && (pi_money == 2'b01)) || ((state == TWO) && (pi_money == 2'b10))) po_cola <= 1'b1; else po_cola <= 1'b0; endmodule
2.3单过程描述
//单段式描述 module Coke_Machine //模块名 ( input wire sys_clk , //输入时钟 input wire sys_rst_n , //输入复位 input wire pi_money_half , //输入01 input wire pi_money_one , //输入10 output reg po_cola ); parameter IDLE = 5'b00001, //状态编码,独热码 HALF = 5'b00010, ONE = 5'b00100, ONE_HALF = 5'b01000, TWO = 5'b10000; wire [1:0] pi_money; reg [4:0] state; assign pi_money = {pi_money_one,pi_money_half}; //合并输入,即输入0.5为01,输入1为10 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) state <= IDLE; //定义起始状态 else case(state) IDLE: if(pi_money == 2'b01) begin state <= HALF; po_cola <= 1'b0; end else if(pi_money == 2'b10) begin state <= ONE; po_cola <= 1'b0; end else begin state <= IDLE; po_cola <= 1'b0; end HALF: if(pi_money == 2'b01) begin state <= ONE; po_cola <= 1'b0; end else if(pi_money == 2'b10) begin state <= ONE_HALF; po_cola <= 1'b0; end else begin state <= HALF; po_cola <= 1'b0; end ONE: if(pi_money == 2'b01) begin state <= ONE_HALF; po_cola <= 1'b0; end else if(pi_money == 2'b10) begin state <= TWO; po_cola <= 1'b0; end else begin state <= ONE; po_cola <= 1'b0; end ONE_HALF: if(pi_money == 2'b01) begin state <= TWO; po_cola <= 1'b0; end else if(pi_money == 2'b10) begin state <= IDLE; po_cola <= 1'b1; end else begin state <= ONE_HALF; po_cola <= 1'b0; end TWO: if(pi_money == 2'b01) begin state <= IDLE; po_cola <= 1'b1; end else if(pi_money == 2'b10) begin state <= HALF; po_cola <= 1'b1; end else begin state <= TWO; po_cola <= 1'b0; end default: begin state <= IDLE; po_cola <= 1'b0; end endcase endmodule
三、状态编码
常用编码方式:
**参考资料:
王金明.《FPGA设计与Verilog HDL实现》.北京:电子工业出版社,2021.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。