十一、状态机

状态机简写为FSM,也称为同步有限状态机,一般简称为状态机。分类:Moore型状态机、Mealy型状态机。 关于状态机的详细知识点参照另一位博主的,讲的很详细:状态机

实战演练一

可乐机每次只能投入一枚一元硬币,每瓶可乐卖3元钱,投入3个硬币就可以让可乐机出可乐,如果投币不够3元想放弃投币,则需要按复位键,否则之前投入的硬币不能退回。

一、画图

模块图:

波形图:

二、代码

module simple_fsm(
input wire sys_clk,
input wire sys_rst_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;
//二段式状态机代码
//状态跳转
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_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
                
//输出信号
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_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

综合器综合出的状态转移图:

三、仿真

仿真代码:

`timescale 1ns/1ns
module tb_simple_fsm();
reg sys_clk;
reg sys_rst_n;
reg pi_money;
wire po_cola;

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)
        pi_money <= 1'b0;
    else
        pi_money <= {$random}%2;
        

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(
.sys_clk  (sys_clk),
.sys_rst_n(sys_rst_n),
.pi_money (pi_money),
.po_cola  (po_cola)
);
endmodule

打印信息:

实战演练二

前面实现的可乐机比较简单,只能投一元的硬币,但是生活中还有0.5元的硬币,所以我们在这个实验中将可乐机设置得较为复杂一些,做成既可以投1元的硬币,也可以投0.5元的硬币,然后把可乐定价改为2.5元。此处因增加了可乐机的复杂度吧而引入了新的问题:投币后可乐机不仅需要放出可乐,还有可能出现需要找零钱的情况。

实验目标:可乐定价为2.5元一瓶,可投入0.5元、1元硬币,投币不够2.5元时按复位键可退回钱款,投币超过2.5元则需要找零。

一、画图

二、代码

module complex_fsm(
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_money
);
parameter IDLE = 5'b00001;
parameter HALF = 5'b00010;
parameter ONE = 5'b00100;
parameter ONE_HALF = 5'b01000;
parameter TWO = 5'b10000;
wire [1:0] pi_money;
reg [4:0] state;//有几个状态就要有几个位宽的状态变量

assign pi_money ={pi_money_one,pi_mo ney_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 == 2'b01)
                state <= HALF;
              else if(pi_money == 2'b10)
                state <= ONE;
              else
                state <= IDLE;
        HALF: if(pi_money == 2'b01)
                state <= ONE;
              else if(pi_money == 2'b10)
                state <= ONE_HALF;
              else
                state <= HALF;
        ONE: if(pi_money == 2'b01)
                state <= ONE_HALF;
              else if(pi_money == 2'b10)
                state <= TWO;
              else
                state <= ONE;
        ONE_HALF: if(pi_money == 2'b01)
                state <= TWO;
              else if(pi_money == 2'b10)
                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
//输出信号_可乐
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 == 2'b10)||(state == TWO && pi_money == 2'b01) || (state == TWO && pi_money == 2'b10))
        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 == 2'b10)
        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_half;
reg pi_money_one;
wire po_cola;
wire po_money;
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)
        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;
wire [1:0] pi_money=complex_fsm_inst.pi_money;
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_money=%b",$time,pi_money_half,pi_money_one,pi_money,state,po_cola,po_money);
    end         
complex_fsm complex_fsm_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_money     (po_money     )
);
endmodule

仿真波形:

打印结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值