上一章中,可乐的定价为3元,且只能投一元的硬币,不可以找零,实现了简单版本的状态机,本章,将可乐定价为2.5元,可以投1元,0.5元的硬币,可以找零;
绘制模块框图如下:
pi_money_half :投币0.5元;
pi_money_one:投币1元;
po_cola:出可乐;
po_money:找零;
输入:0.5、1;
输出:不出可乐/不找零(编码:00)、出可乐/不找零(编码:10)、出可乐/找零(编码:11);
状态:0(编码:00)、0.5(编码:01)、1(编码:10)、1.5、2、2.5、3;
状态转移图如下:
可乐状态机的波形图如下图所示:
对照波形图编写Verilog HDL文件如下:
`timescale 1ns/1ns
module complex_fsm
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire pi_money_half ,
input wire pi_money_one ,
output reg po_cola ,
output reg po_money
);
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};
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) || (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 == 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;
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_half;
reg pi_money_one;
reg random_data;
wire po_cola ;
wire po_money;
initial
begin
sys_clk= 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1
end
always #10 sys_clk = ~sys_clk;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_clk == 1'b0)
random_data <= 1'b0;
else
random_data <= {$random} % 2;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_clk == 1'b0)
pi_money_half <= 1'b0;
else
pi_money_half <= random_data;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_clk == 1'b0)
pi_money_one <= 1'b0;
else
pi_money_one <= ~random_data;
wire [1:0] pi_money = complex_fsm_inst.pi_money;
wire [4:0] state = complex_fsm_inst.state;
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
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
通过仿真,得到仿真波形图如下: