FPGA学习日记第二天

文章介绍了状态机的概念,包括同步有限状态机的定义,以及Moore型和Mealy型的区别。通过两个示例——简单的3元可乐贩卖机和复杂的2.5元可乐贩卖机,展示了状态机如何建模和编程,并讨论了在FPGA设计中状态编码的选择,如独热码、二进制码和格雷码的适用场景。
摘要由CSDN通过智能技术生成

状态机:描述时序系统的状态,简称为FSM(Finite State Machine),全称同步有限状态机。同 步指状态的变化只发生在时钟的上升沿或下降沿,有限指状态的数量有限。

分类:Moore型、Mealy型。

Moore型:输出只与状态有关,与输入无关。

Mealy型:输出既与状态有关,又与输入有关。


一个简单的例子:自助可乐贩卖机

一台贩卖售价为3元的可乐贩卖机,每次可投入1元硬币,投入三枚时出一瓶可乐。

首先分析它的输入输出和状态

输入:是否投入1元硬币(0表示没投,1表示投了)

输出:是否出可乐(0表示不出,1表示出)

状态:初始状态、有1元、有2元、有3元(等效于初始状态)

然后分析状态转换条件(画出状态转换图)

最后根据状态转换图编程、调试

程序及仿真代码


module simple_fsm (
    input   wire    sys_clk     ,
    input   wire    sys_rst_n   ,
    input   wire    pi_one      ,
 
    output  reg     po_cola     
);
 
parameter   IDLE    =   3'b001,
            ONE     =   3'b010,
            TWO     =   3'b100;
reg     [2:0]   state;
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(sys_rst_n == 1'b0)
        state <= IDLE;
    else    case (state)
        IDLE    :   state <= (pi_one == 1'b1 ? ONE  : IDLE);
        ONE     :   state <= (pi_one == 1'b1 ? TWO  : ONE );
        TWO     :   state <= (pi_one == 1'b1 ? IDLE : TWO );
        default :   state <= IDLE;
    endcase        
end
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(sys_rst_n == 1'b0)
        po_cola <= 1'b0;
    else if((state == TWO) && (pi_one == 1'b1))
        po_cola <= 1'b1;
    else
        po_cola <= 1'b0;
end
 
endmodule //simple_fsm
 
module tb_simple_fsm ();
reg     sys_clk;
reg     sys_rst_n;
reg     pi_one;
wire    po_cola;
 
wire [2:0] state = simple_fsm_inst.state;
 
initial begin
    sys_clk     =   1'b0;
    sys_rst_n   <=  1'b0;
    pi_one      <=  1'b0;
    #10
    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 == 0)
        pi_one <= 1'b0;
    else
        pi_one <= {$random} % 2;
initial begin
    $dumpfile("simple_fsm.vcd");
    $dumpvars;
    #2000    $finish;
end
simple_fsm simple_fsm_inst(
    .sys_clk     (sys_clk),
    .sys_rst_n   (sys_rst_n),
    .pi_one      (pi_one),
    .po_cola     (po_cola)
);
endmodule //tb_simple_fsm

波形图

一个稍复杂的例子:自助可乐贩卖机

一台贩卖售价为2.5元的可乐贩卖机,每次可投入1元硬币或5角硬币,投入超过2.5元时出一瓶可乐,多出部分找零。

首先分析它的输入输出和状态

输入:是否投入1元硬币(0表示没投,1表示投了)、是否投入5角硬币(0表示没投,1表示投了),注意由于投币口只有一个,无法同时投入1元与5角硬币。

输出:是否出可乐(0表示不出,1表示出)、是否找零(0表示不找,1表示找)

状态:初始状态、有0.5元、有1元、有1.5元、有2元

然后分析状态转换条件(画出状态转换图)

最后根据状态转换图编程、调试

程序及仿真代码

module complex_fsm (
    input   wire    sys_clk     ,
    input   wire    sys_rst_n   ,
    input   wire    pi_one      ,
    input   wire    pi_half     , 
 
    output  reg     po_cola     ,
    output  reg     po_money      
);
 
wire    [1:0]   pi_money;
 
assign  pi_money = {pi_half,pi_one};
 
parameter   IDLE    =   5'b00001,
            HALF    =   5'b00010,
            ONE     =   5'b00100,
            ONE_HALF=   5'b01000,
            TWO     =   5'b10000;
reg     [4:0]   state;
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(sys_rst_n == 1'b0)
        state <= IDLE;
    else    case (state)
        IDLE    :
            if(pi_money == 2'b10)
                state <= HALF;
            else if(pi_money == 2'b01)
                state <= ONE;
            else
                state <= IDLE;
        HALF    :
            if(pi_money == 2'b10)
                state <= ONE;
            else if(pi_money == 2'b01)
                state <= ONE_HALF;
            else
                state <= HALF;
        ONE     :
            if(pi_money == 2'b10)
                state <= ONE_HALF;
            else if(pi_money == 2'b01)
                state <= TWO;
            else
                state <= ONE;
        ONE_HALF:
            if(pi_money == 2'b10)
                state <= TWO;
            else if(pi_money == 2'b01)
                state <= IDLE;
            else
                state <= ONE_HALF;
        TWO     :
            if(pi_money == 2'b10)
                state <= IDLE;
            else if(pi_money == 2'b01)
                state <= IDLE;
            else
                state <= TWO;
            default :   state <= IDLE;
    endcase        
end
 
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(sys_rst_n == 1'b0)
        po_cola <= 1'b0;
    else if((state == TWO) && (^pi_money == 1'b1))
        po_cola <= 1'b1;
    else if((state == ONE_HALF) && (pi_one == 1'b1))
        po_cola <= 1'b1;
    else
        po_cola <= 1'b0;
end
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(sys_rst_n == 1'b0)
        po_money <= 1'b0;
    else if((state == TWO) && (pi_one == 1'b1))
        po_money <= 1'b1;
    else
        po_money <= 1'b0;
end
 
endmodule //complex_fsm
 
module tb_complex_fsm ();
 
reg     sys_clk;
reg     sys_rst_n;
reg     pi_one;
reg     pi_half;
 
wire    po_cola;
wire    po_money;
 
wire [4:0] state = complex_fsm_inst.state;
 
initial begin
    sys_clk     =   1'b0;
    sys_rst_n   <=  1'b0;
    pi_one      <=  1'b0;
    pi_half     <=  1'b0;
    #10
    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 == 0)
        {pi_half,pi_one} <= 2'b0;
    else
        {pi_half,pi_one} <= {$random} % 3;
 
initial begin
    $dumpfile("complex_fsm.vcd");
    $dumpvars;
    #2000    $finish;
end
 
complex_fsm complex_fsm_inst(
    .sys_clk     (sys_clk),
    .sys_rst_n   (sys_rst_n),
    .pi_one      (pi_one),
    .pi_half     (pi_half), 
 
    .po_cola     (po_cola),
    .po_money    (po_money)  
);
 
endmodule //tb_complex_fsm

波形图

写代码时需要注意的地方:

在描述状态时,有三种编码方式:独热码、二进制码、格雷码。

编码方式

定义

特点

独热码

有几个状态就用几个比特

每一个状态对应一个比特位与其他比特位不同

例如:

状态一:001

状态二:010

状态三:100

废空间,省时间

二进制码

用二进制数表示状态

例如:

状态一:00

状态二:01

状态三:10

省空间,费时间

格雷码

类似二进制码,但相邻状态只改变一个比特位

例如:

状态一:00

状态二:01

状态三:11

介于中间态

FPGA的特性更利于使用独热码。

FPGA编程下,建议在低速机中,状态数小于4时使用二进制码,4~24之间使用独热码,大于24时使用格雷码;高速机中一律使用独热码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值