饮料售卖机FSM
状态机的类型
mealy
输出与当前状态及输入有关
本状态机应该就属于mealy状态机
moore
输出只与当前状态有关
目前还没遇到这种状态机,我认为应该就是只有状态的转换吧,不考虑输入。
状态编码
我们知道有三种编吗方式;
1.binary编码:状态描述简洁,占用较少寄存器资源,是比较常用的状态机编码方式;
2.gray编码
3.one hot编码:占用更多寄存器资源,时序性能更好,适用于逻辑复杂的状态机设计:
要求
请设计一个状态机模拟饮料售卖机,接受1元, 2元, 5元的零钱,饮料为5元,并可以找零。
状态图
代码
\\top.v
`timescale 1ns / 1ps
module fsm(
input wire sclk,
input wire rst_n,
input wire [2:0]pi_money,
output reg [2:0]po_cola,
output reg [2:0]po_money
);
reg [5:0] state;
parameter IDLE =6'b000001;
parameter S1 =6'b000010;
parameter S2 =6'b000100;
parameter S3 =6'b001000;
parameter S4 =6'b010000;
parameter S5 =6'b100000;
[email protected](posedge sclk or negedge rst_n)
if(!rst_n)
state<=IDLE;
else case(state)
IDLE: if(pi_money == 2'b01)
state <= S1;
else if(pi_money == 2'b10)
state<=S2;
else if(pi_money == 3'b101)
state<=S5;
else state <= IDLE;
S1: if(pi_money == 2'b01)
state<=S2;
else if(pi_money == 2'b10)
state<=S3;
else if(pi_money == 3'b101)
state<=S5;
else state <= S1;
S2: if(pi_money == 2'b01)
state <= S3;
else if(pi_money == 2'b10)
state<=S4;
else if(pi_money == 3'b101)
state<=S5;
else state <= S2;
S3: if(pi_money == 2'b00)
state<=S3;
else if(pi_money == 2'b01)
state<=S4;
else state <= S5;
S4: if(pi_money == 2'b00)
state<=S4;
else state <= S5;
S5: if(pi_money == 2'b01)
state<=S1;
else if(pi_money == 2'b10)
state<=S2;
else if(pi_money == 3'b101)
state<=S5;
else state <= IDLE;
default:state<=IDLE;
endcase
[email protected](posedge sclk or negedge rst_n)
if(!rst_n)
po_cola<=1'b0;
else if((state == S3&&pi_money==2'b10)||(pi_money== 3'b101))
po_cola<=1'b1;
//else if(state == S5 && pi_money == 3'b101)
// po_cola=2'b10;
else
po_cola<=1'b0; //
[email protected](posedge sclk or negedge rst_n)
if(!rst_n)
po_money<=1'b0;
else if((state == S1&&pi_money == 3'b101)||(state == S4&&pi_money == 3'b10))
po_money<=1'b1;
else if((state == S2&&pi_money == 3'b101))
po_money<=2'b10;
else if(state == S3&&pi_money == 3'b101)
po_money<=2'b11;
else if(state == S4&&pi_money == 3'b101)
po_money<=3'b100;
else po_money<=1'b0;
endmodule
\\testbench
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2019/03/29 20:46:57
// Design Name:
// Module Name: tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ns
module tb();
reg sclk;
reg rst_n;
reg [2:0]pi_money;
wire [2:0]po_cola;
wire [2:0]po_money;
initial
begin
sclk=0;
rst_n=1;
pi_money=0;
#20
rst_n=0;
#20
rst_n=1;
#20
pi_money=0;
#20
pi_money=1;
#20
pi_money=2;
#20
pi_money=2;
#20
pi_money=5;
#20
pi_money=1;
#20
pi_money=5;
#20
pi_money=2;
#20
pi_money=5;
#20
pi_money=0;
end
always # 10 sclk=~sclk;
//always # 50 pi_money={$random}%8;
fsm fsm_cola_ctrl_inst(
.sclk (sclk ),
.rst_n (rst_n ),
.pi_money (pi_money ),
.po_cola (po_cola ),
. po_money ( po_money )
);
endmodule
仿真结果
仿真是正确的
总结
虽然我这里写了三个always,但我觉得这仍然是两段式,一个描述状态转移及转移条件,一个描述输出结果,也就是逻辑组合。
但我总觉得自己的写法很繁琐,本来S5的状态转移是
S5<=IDLE;
但是仿真结果显示,不能在S5的状态下判断付的钱,从而不能正确输出,所以改成了上面的代码
如果错误,希望大家批评指正。
多多交流哦~