FPGA学习日志——复杂状态机complex_fsm

复杂状态机complex_fsm

实验目的

在之前的简易的可乐机的基础上实现一个功能更复杂也更合理的可乐机器。

将可乐定价为2.5元,可以投入1元与0.5元的硬币,小于2.5元不出可乐,大于2.5元实现找零。

实验框图、状态图

根据上述实验条件可以分析得到输入除了时钟和复位信号,还有输入的两种钱币信号,输出就是找零和可乐。
在这里插入图片描述

接下来分析状态图的情况:

输入有三种情况:0元,0.5元,1元,分别对应输入状态:00,01,10
输出有三种情况:不出可乐/不找零,出可乐/不找零,出可乐/找零,分别对应输出状态:00,10,11
而状态机的状态有:0,0.5,1,1.5,2,2.5,3,设置分别对应 IDLE、HALF…
在这里插入图片描述

米利/穆尔型时序电路

米利型时序电路的输出信号O是状态变量S和输入信号I二者的函数,即O=h(I,S),这种时序电路在时钟脉冲的两个触发沿之间,输出信号随时可能受到非时钟同步的输入信号作用而发生变化,从而影响电路输出的同步性。

穆尔型时序电路是米利型时序电路的一种特例,它的输出信号O仅仅是状态变量S的函数,即O=h(S)穆尔型时序电路的输出信号只取决于与时钟同步的各触发器的状态,在时钟脉冲触发沿的间隔期间,不受非同步的输入信号影响

在现代高速时序电路设计中,一般尽量采用穆尔型时序电路结构,以利于后线高速电路的同步。在米利时序电路的输出端增加一级存储电路,构成“流水线输出“形式,是将其转化为穆尔电路的最简单的方法。需要注意的是,流水线存储电路将把输出号延迟一个时钟周期。虽然流水线输出电路增加了一些逻辑元件,但它的输出信号同步特性好,具有更好的稳定性和抗干扰性能。在大规模集成电路技术成熟的今天,节省逻辑元件的数量经常不再是逻辑电路设计者追求的唯一目标,电路工作的稳定性和可靠性,以及工作速度的提才是更重要的要求。

即在上图的第一个状态图中状态THREE和TWO_HALF的下一个状态和输入无关了,所以可以节约元器件省略。得到下面的米利型电路

波形图

在这里插入图片描述

图中的输入为随意设定

实验代码

module  complex_fsm
(
    input   wire    sys_clk         ,
    input   wire    sys_rst_n       ,
    input   wire    pi_money_one    ,
    input   wire    pi_money_half   ,
    
    output  reg     po_cola         ,
    output  reg     po_money
);
/*     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;
reg     [4:0]   state;
/* //也可以增加这个中间量,方便后期调试更改数据
wire    [1:0]   pi_money;
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<=IDLE;
        else    case(state)
        IDLE      : if(pi_money_half==1'b1)
                    state<=HALF;
                    else    if(pi_money_one==1'b1)
                            state<=ONE;
                            else    state<=IDLE;
        HALF      : if(pi_money_half==1'b1)
                    state<=ONE;
                    else    if(pi_money_one==1'b1)
                            state<=ONE_HALF;
                            else    state<=HALF;
        ONE       : if(pi_money_half==1'b1)
                    state<=ONE_HALF;
                    else    if(pi_money_one==1'b1)
                            state<=TWO;
                            else    state<=ONE;    
        ONE_HALF  : if(pi_money_half==1'b1)
                    state<=TWO;
                    else    if(pi_money_one==1'b1)
                            state<=IDLE;
                            else    state<=ONE_HALF;   
        TWO       : if(pi_money_half==1'b1)
                    state<=IDLE;
                    else    if(pi_money_one==1'b1)
                            state<=IDLE;
                            else    state<=TWO;  
        default   : state<=IDLE;
endcase                    
always@(posedge sys_clk or  negedge sys_rst_n)
        if(sys_rst_n==1'b0)   
            po_cola<=1'b0;
        else    if((state==ONE_HALF)&&(pi_money_one==1'b1)||
                   (state==TWO)&&(pi_money_half==1'b1)||
                   (state==TWO)&&(pi_money_one==1'b1))
                    po_cola=1'b1;
                else    po_cola<=1'b0;
always@(posedge sys_clk or  negedge sys_rst_n)
        if(sys_rst_n==1'b0)   
            po_money<=1'b0;
        else    if((state==TWO)&&(pi_money_one==1'b1))
                    po_money=1'b1;
                else    po_money<=1'b0;               

endmodule   

仿真代码

`timescale  1ns/1ns
module  tb_complex_fsm();
reg      sys_clk       ;
reg      sys_rst_n     ;
reg      pi_money_one  ;
reg      pi_money_half ;

wire     po_cola       ;
wire     po_money      ;

reg     random_data;//随机数,两个输入不能同时取1,一个输入为随机数,另一个取反即可避免

initial 
    begin
        sys_clk=1'b0;
        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)
        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;   

wire    [4:0]   state=complex_fsm_inst.state;

initial
    begin
        $timeformat(-9,0,"ns",6);
        $monitor("@time %t:pi_money_half:%b,pi_money_one:%b,state:%b,po_cola:%b,po_money:%b",$time,pi_money_half,pi_money_one,state,po_cola,po_money);    
    end   
complex_fsm complex_fsm_inst
(
   .sys_clk       (sys_clk),
   .sys_rst_n     (sys_rst_n ),
   .pi_money_one  (pi_money_one),
   .pi_money_half (pi_money_half),
                  
   .po_cola       (po_cola ),
   .po_money      (po_money )
);
endmodule

值得注意的是,在仿真中由于投入0.5元硬币和1元硬币不能同时投入即不能同时为1,实验中设置random_data进行限制。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Chendy_00

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

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

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

打赏作者

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

抵扣说明:

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

余额充值