一、实现的功能
实现可乐机
能够投入5毛和1块的硬币
2.5元吐出可乐
3元的时候吐出可乐并且进行找零
二、实现
1、状态图
2、波形图
3、rtl视图
4.程序
模块程序
module complex_fsm
(
input wire sys_clk,
input wire sys_rst_n,
input wire pi_money_one,
input wire pi_money_half,
output reg po_cola,
output reg po_money
);
wire [1:0] pi_money;
reg [4:0] state;
/* parameter IDLE = 5'b00001;
parameter HALF = 5'b00010;
parameter ONE = 5'b00100;
parameter ONE_HALF= 5'b01000;
parameter TWO = 5'b10000; */
parameter IDLE = 5'b00001,
HALF = 5'b00010,
ONE = 5'b00100,
ONE_HALF= 5'b01000,
TWO = 5'b10000;
assign pi_money = {pi_money_one,pi_money_half};
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 <= IDLE;
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 == TWO)
po_cola <= 1'b1;
else
po_cola <= 1'b0;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n ==1'b0)
po_money <= 1'b0;
else if((state == TWO)&&(pi_money == 2'b10))
po_money <= 1'b1;
else
po_money <= 1'b0;
endmodule
其中下面两种方式是一样的,后面的方式比较简单
仿真程序
`timescale 1ns/1ns
module tb_complex_fsm ();
reg sys_clk;
reg sys_rst_n;
reg pi_money_one;
reg pi_money_half;
reg random_data_gen;
wire po_cola;
wire po_money;
always #10 sys_clk = ~sys_clk;
initial
begin
sys_clk = 1'b0;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
random_data_gen <= 1'b0;
else
random_data_gen <= {$random} %2;
always@(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
pi_money_half <= 1'b0;
else
pi_money_half <= random_data_gen;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
pi_money_one <= 1'b0;
else
pi_money_one <= ~random_data_gen;
/*只有一个投币口,避免5毛和1块同时产生数据对其取反就避免了*/
initial
begin
$timeformat (-9,0,"ns",6);
$monitor ("@time %t:pi_money_one=%b pi_money_half=%b pi_money=%b state=%b po_cola=%b po_money=%b",$time, pi_money_one, pi_money_half, pi_money, state, po_cola, po_money);
end
/*连接出来,可以对状态机内部进行观察*/
wire [1:0] pi_money = complex_fsm_inst.pi_money;
wire [4:0] state = complex_fsm_inst.state;
complex_fsm complex_fsm_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ) ,
.pi_money_one (pi_money_one ) ,
.pi_money_half (pi_money_half) ,
.po_cola (po_cola ) ,
.po_money (po_money )
);
endmodule