状态机FSM:2.5元一瓶可乐例


前言

实验目标:可乐定价为2.5元一瓶,可以投0.5元和1元的硬币。投币不足2.5元,不会出可乐;超过2.5元,需要找零。
以下为状态转移图:
在这里插入图片描述红色线条表示回到IDLE的三种情况。

画出波形图:
在这里插入图片描述注意组合逻辑和时序逻辑。这里的money是同一时刻5毛和1块的组合逻辑,不是积累的含义。时序逻辑包含积累的含义。


一、rtl代码

module fsm2
(
input wire sys_clk,
input wire sys_rst_n,
input wire  money_half,
input wire  money_one,
output reg  cola,
output reg  money_return
);

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语句进行赋值,变量类型wire型
wire [1:0] money;
reg [4:0] state;
//位拼接对money进行赋值
assign money={money_one,money_half};
//数据跳转
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
         state<=IDLE;
    else case(state)
        IDLE    :if(money==2'b01)
                     state<=HALF;
                 else if(money==2'b10)
                     state<=ONE;
                 else
                     state<=IDLE;
        HALF    :if(money==2'b01)
                     state<=ONE;
                 else if(money==2'b10)
                     state<=ONE_HALF;
                 else
                     state<=HALF;
        ONE     :if(money==2'b01)
                     state<=ONE_HALF;
                 else if(money==2'b10)
                     state<=TWO;
                 else
                     state<=ONE;
        ONE_HALF:if(money==2'b01)
                     state<=TWO;
                 else if(money==2'b10)
                     state<=IDLE;
                 else
                     state<=ONE_HALF;
        TWO     :if((money==2'b01)||(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)
        cola<=1'b0;
    else if((state==ONE_HALF && money==2'b10)
             ||(state==TWO && money==2'b01)
             ||(state==TWO && money==2'b10))
        cola<=1'b1;
    else
        cola<=1'b0;
//找零信号的赋值
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        money_return<=1'b0;
    else if(state==TWO && money==2'b10)
        money_return<=1'b1;
    else
        money_return<=1'b0;      

endmodule

二、状态机视图

在这里插入图片描述综合器综合出的状态转移图与绘制波形图一致。

三、测试代码

`timescale 1ns/1ns
module tb_fsm2();

reg sys_clk;
reg sys_rst_n;
reg money_half;
reg money_one;
wire cola;
wire money_return;
reg random_data;

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_rst_n==1'b0)
        random_data<=1'b0;
    else
        random_data<={$random}%2;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        money_half<=1'b0;
    else
        money_half<=random_data;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        money_one<=1'b0;
    else
        money_one<=~random_data;
 
wire [1:0] money=fsm2_inst.money;
wire [4:0] state=fsm2_inst.state;
 
initial
    begin
        $timeformat(-9,0,"ns",6);
        $monitor("@time %t:money_half=%b,money_one=%b,money=%b,state=%b,cola=%b,money_return=%b",$time,money_half,money_one,money,state,cola,money_return);
    end        

fsm2 fsm2_inst
(
. sys_clk     (sys_clk     ),
. sys_rst_n   (sys_rst_n   ),
. money_half  (money_half  ),
. money_one   (money_one   ),
. cola        (cola        ),
. money_return(money_return)
); 

endmodule

四、仿真结果

在这里插入图片描述
左边的红框是出可乐不找零的情况,右边的红框是出可乐找零(找5毛)的情况。
在这里插入图片描述打印的信息中,输出与输入延迟一个时钟周期,可以参考红色方框。红色方框为买到一瓶可乐的完整过程。
其中初始状态位红色横线00001,即IDLE;输入橙色横线1元,对应状态为00100,即1元;输入黄色横线5毛,对应状态为01000,即1.5元;输入绿色横线5毛,对应状态为10000,即2元;输入蓝色横线5毛,对应状态为IDLE,此时累积为2.5元,不找零。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小年痴槑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值