可乐机每次只能投入 1 枚 1 元硬币,且每瓶可乐卖 3 元钱,即投入 3 个硬币就可以让可乐机出可乐,如果投币不够 3 元想放弃投币需要按复位键,否则之前投入的钱不能退回。
1.程序设计
1.1模块框图
pi_money------投币1元的输入
po_cola------可乐的输出
1.2状态机波形图
1.3代码编写
module simple_fsm(
input wire clk,
input wire reset_n,
input wire pi_money,
output reg po_cola
);
parameter IDLE = 3'b001;
parameter ONE = 3'b010;
parameter TWO = 3'b100;
reg [2:0] state;
//第一段状态机,描述当前状态 state 如何根据输入跳转到下一状态
always@(posedge clk or negedge reset_n)
if(reset_n == 1'b0)
state <= IDLE; //任何情况下只要按复位就回到初始状态
else case(state)
IDLE: if(pi_money == 1'b1)
state <= ONE;
else
state <= IDLE;
ONE: if(pi_money == 1'b1)
state <= TWO;
else
state <= ONE;
TWO: if(pi_money == 1'b1)
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 == TWO)&&(pi_money == 1'b1))
po_cola <= 1'b1;
else
po_cola <= 1'b0;
endmodule
1.4仿真验证
`timescale 1ns/1ns
module tb_simple_fsm();
reg clk;
reg reset_n;
reg pi_money;
wire po_cola;
//初始化系统时钟、全局复位
initial
begin
clk = 1'b1;
reset_n <= 1'b0;
#20
reset_n <= 1'b1;
end
//clk:模拟系统时钟,每 10ns 电平翻转一次,周期为 20ns,频率为 50MHz
always #10 clk = ~clk;
//产生输入随机数,模拟投币 1 元的情况
always @(posedge clk or negedge reset_n)
if(reset_n == 1'b0)
pi_money <= 1'b0;
else
pi_money <= {$random}%2; //取模求余数,产生非负随机数 0、1
//将 RTL 模块中的内部信号引入到 Testbench 模块中进行观察
wire [2:0] state = simple_fsm_inst.state;
//使用两个系统函数,方便验证
initial
begin
$timeformat(-9,0,"ns",6);
$monitor("@time %t: pi_money = %b,state = %b,po_cola = %b",$time,pi_money,state,po_cola);
end
//例化
simple_fsm simple_fsm_inst(
. clk (clk),
. reset_n (reset_n),
. pi_money(pi_money),
. po_cola (po_cola)
);
endmodule
2.仿真波形
2.1打印信息
以上是今天的学习笔记......