1.实验目标
可乐定价为 2.5 元一瓶,可投入 0.5 元、1 元硬币,投币不够 2.5 元需要按复位键退回钱款,投币超过 2.5 元需找零。
2.程序设计
2.1可乐机模块框图
2.2复杂可乐机状态转移图
2.3状态机波形图
3代码编写
module complex_fsm2(
input wire clk ,
input wire reset_n ,
input wire pi_money_one ,
input wire pi_money_half ,
output reg po_cola ,
output reg po_money
);
//只有五种状态,使用独热码
parameter IDLE = 5'd00001;
parameter HALF = 5'd00010;
parameter ONE = 5'd00100;
parameter ONE_HALF = 5'd01000;
parameter TWO = 5'd10000;
reg [4:0] state;
wire [1:0] pi_money;
//pi_money:为了减少变量的个数,我们用位拼接把输入的两个 1bit 信号拼接成 1 个 2bit 信号
//投币方式可以为:不投币(00)、投 0.5 元(01)、投 1 元(10),每次只投一个币
assign pi_money = {pi_money_one,pi_money_half};
//第一段状态机,描述当前状态 state 如何根据输入跳转到下一状态
always@(posedge clk or negedge reset_n)
if (reset_n == 1'b0)
state <= IDLE; //任何情况下只要按复位就回到初始状态
else case(state)
IDLE: if(pi_money == 2'b01) //投0.5元
state <= HALF;
else if(pi_money == 2'b10) //投1元
state <= ONE;
else
state <= IDLE;
HALF: if(pi_money == 2'b01) //投0.5元
state <= ONE;
else if(pi_money == 2'b10) //投1元
state <= ONE_HALF;
else
state <= HALF;
ONE: if(pi_money == 2'b01) //投0.5元
state <= ONE_HALF;
else if(pi_money == 2'b10) //投1元
state <= TWO;
else
state <= ONE;
ONE_HALF: if(pi_money == 2'b01) //投0.5元
state <= TWO;
else if(pi_money == 2'b10) //投1元
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
//第二段状态机,描述当前状态 state 和输入 pi_money 如何影响 po_cola 输出
always@(posedge clk or negedge reset_n)
if (reset_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;
//第二段状态机,描述当前状态 state 和输入 pi_money 如何影响 po_money 输出
always@(posedge clk or negedge reset_n)
if (reset_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
4.仿真验证
`timescale 1ns/1ns
module tb_complex_fsm();
reg clk;
reg reset_n;
reg pi_money_one;
reg pi_money_half;
reg random_date; //赋值一个随机数
wire po_cola;
wire po_money;
//初始化系统时钟、全局复位
initial
begin
clk = 1'b1;
reset_n <= 1'b0;
#20
reset_n <= 1'b1;
end
//clk:模拟系统时钟,每 10ns 电平翻转一次,周期为 20ns,频率为 50MHz
always #10 clk = ~clk;
//random_date:产生非负随机数0、1
always @(posedge clk or negedge reset_n)
if (reset_n == 1'b0)
random_date <= 1'b0;
else
random_date <= {$random} % 2;
//pi_money_half:模拟投入 0.5 元的情况
always @(posedge clk or negedge reset_n)
if (reset_n == 1'b0)
pi_money_half <= 1'b0;
else
pi_money_half <= random_date;
//pi_money_one:模拟投入 1 元的情况
always @(posedge clk or negedge reset_n)
if (reset_n == 1'b0)
pi_money_one <= 1'b0;
else
pi_money_one <= ~random_date;
//例化
complex_fsm complex_fsm_inst(
. clk (clk) ,
. reset_n (reset_n) ,
. pi_money_one (pi_money_one) ,
. pi_money_half(pi_money_half) ,
. po_cola (po_cola) ,
. po_money (po_money)
);
endmodule
5.仿真波形
以上就是这两天磨磨唧唧写出来的复杂可乐机代码........