Verilog中的状态机(野火-复杂)

简单的可乐贩卖机,实现找零


代码中注意的点:
实现不同时投入1元和0.5元先定义一个随机数,再赋值给 pi_money_half,而pi_money_one取反
只能实现01,10

pi_money_half  <= random_data;
pi_money_one  <= ~random_data;

或者,可以实现10,01,00

random_data <= {$random} % 3;
{pi_money_one,pi_money_half} = random_data;

1. 状态机

在这里插入图片描述

2. 时序图

在这里插入图片描述

3. 代码

complex_fsm_fire.v文件

module  complex_fsm_fire
(
    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_half
);

parameter   IDEL       =   5'b0_0001,
            HALF       =   5'b0_0010,
            ONE        =   5'b0_0100,
            ONE_HALF   =   5'b0_1000,
            TWO        =   5'b1_0000;

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 <= IDEL;
    else    case(state)
        IDEL:   case(pi_money)
                2'b00:  state <= IDEL;
                2'b01:  state <= HALF;
                2'b10:  state <= ONE;
                2'b11:  state <= IDEL;
                endcase
        HALF:   case(pi_money)
                2'b00:  state <= HALF;
                2'b01:  state <= ONE;
                2'b10:  state <= ONE_HALF;
                2'b11:  state <= IDEL;
                endcase
        ONE:    case(pi_money)
                2'b00:  state <= ONE;
                2'b01:  state <= ONE_HALF;
                2'b10:  state <= TWO;
                2'b11:  state <= IDEL;
                endcase
        ONE_HALF:  case(pi_money)
                2'b00:  state <= ONE_HALF;
                2'b01:  state <= TWO;
                2'b10:  state <= IDEL;
                2'b11:  state <= IDEL;
                endcase
        TWO:    case(pi_money)
                2'b00:  state <= TWO;
                2'b01:  state <= IDEL;
                2'b10:  state <= IDEL;
                2'b11:  state <= IDEL;
                endcase
    endcase

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0) begin
        po_cola <= 1'b0;
        po_half <= 1'b0;
    end
    else    if((state == ONE_HALF) && (pi_money == 2'b10))
        po_cola <= 1'b1;
    else    if((state == TWO) && (pi_money == 2'b01))
        po_cola <= 1'b1;
    else    if((state == TWO) && (pi_money == 2'b10)) begin
        po_cola <= 1'b1;
        po_half <= 1'b1;
    end
    else begin
        po_cola <= 1'b0;
        po_half <= 1'b0;
    end


endmodule

tb_complex_fsm_fire.v文件

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

//声明变量
reg     sys_clk;
reg     sys_rst_n;
reg     pi_money_half;
reg     pi_money_one;
reg     random_data;

wire    po_cola;
wire    po_half;

//初始化
initial
    begin
        sys_clk = 1'b0;
        sys_rst_n <= 1'b0;
        #20
        sys_rst_n <= 1'b1;
    end

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) 
        pi_money_half  <= 1'b0;
    else
        pi_money_half  <= random_data;


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0) 
        pi_money_one  <= 1'b0;
    else
        pi_money_one  <= ~random_data;

//系统时钟初始化,周期为20ns
always #10 sys_clk = ~sys_clk;

wire    [1:0]   pi_money = complex_fsm_fire_inst.pi_money;
wire    [4:0]   state = complex_fsm_fire_inst.state;

//初始化显示
initial
    begin
        $timeformat(-9,0,"ns",6);
        $monitor("$time %t:pi_money_half=%b,pi_money_one=%b,pi_money=%b,state=%b,po_cola=%b,po_half=%b",$time,pi_money_half,pi_money_one,pi_money,state,po_cola,po_half);
    end

//实例化
complex_fsm_fire    complex_fsm_fire_inst
(
    .sys_clk       (sys_clk),
    .sys_rst_n     (sys_rst_n),
    .pi_money_half (pi_money_half),
    .pi_money_one  (pi_money_one),

    .po_cola       (po_cola),
    .po_half       (po_half)
);
endmodule

4.vivado时序图

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值