野火—复杂可乐机状态机学习笔记

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.仿真波形

以上就是这两天磨磨唧唧写出来的复杂可乐机代码........ 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值