牛客刷题<21>三段式状态机

题目:根据状态转移表实现时序电路_牛客题霸_牛客网

FSM有限状态机序列检测,涉及到:;

(1)摩尔型与米利型状态机;

(2)一段式、两段式、三段式状态机;

(3)状态编码(二进制、格雷码、独热码);

摩尔型和米利型状态机

摩尔型:输出只与当前状态有关;

米利型:输出不仅与当前状态有关,还与当前输入有关

// one step                                              第一段
always@(posedge clk or negedge rst_n)begin
        if(!rst_n)                                       时序逻辑
            curr_state <=2'b00;
        else                                             次态赋给现态
            curr_state <= next_state;                    cs <= ns
    end
//two step
always@(*)begin                                             第二段
        case(curr_state)
            2'b00: next_state = A?2'b11:2'b01;              组合逻辑
            2'b01: next_state = A?2'b00:2'b10;
            2'b10: next_state = A?2'b01:2'b11;              现态和输入决定次态
            2'b11: next_state = A?2'b10:2'b00;
            default : next_state = 2'b00;
        endcase                                             case(cs)
    end                                                     ....
                                                            endcase

三段式寄存器输出,不产生毛刺,有利于时序约束

(1)一段式:一个always块,既描述状态转移,又描述状态的输入输出当前状态用寄存器输出

(2)二段式:两个always块,时序逻辑与组合逻辑分开,一个always块采用同步时序描述状态转移另一个always块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出,当前状态用组合逻辑输出,可能出现竞争冒险产生毛刺,而且不利于约束,不利于综合器和布局布线器实现高性能的设计;

(当然,第二个always里的状态跳转和输出可以拆分用组合逻辑描述,也可能有三个always块,但是这并不是三段式,和三段式的区别在于输出到底是组合逻辑还是时序逻辑)

(3)三段式:三个always块,一个always模块采用同步时序描述状态转移;一个always采用组合逻辑判断状态转移条件,描述状态转移规律;第三个always块使用同步时序描述状态输出,寄存器输出

三段式与二段式相比,关键在于根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。

二进制码Binary Code和格雷码Gray Code占用的位宽少,相应的使用的触发器资源少,但是状态对比时需要比较多个bit,消耗的组合逻辑比较多,适用于组合电路资源丰富的情况(CPLD);

独热码One-Hot Code的状态比较时只比较1 bit,节省逻辑资源,使用的触发器资源比较多,适用于触发器资源丰富的情况(FPGA);

总体来讲,状态较少时(4-24个状态)用独热码效果好,状态多时格雷码(状态数大于24)效果好。

对四个状态编码:

二进制码:

S0 = 2’b00;

S1 = 2’b01;

S2 = 2’b10;

S3 = 2’b11;

格雷码相邻码元之间有且只有一位不同:

S0 = 2’b00;

S1 = 2’b01;

S2 = 2’b11;

S3 = 2’b10;

独热码只有一位是“1”:

S0 = 4’b0001;

S1 = 4’b0010;

S2 = 4’b0100;

S3 = 4’b1000;

有时候也是用连续编码,状态值连续:

S0 = 2’d0;

S1 = 2’d1;

S2 = 2’d2;

S3 = 2’d3;

解法一

`timescale 1ns/1ns
module seq_circuit(
    input    A,
    input    clk,
    input    rst_n,
    
    output wire  Y
);
    reg [1:0] curr_state;
    reg [1:0] next_state;
    // one step
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            curr_state <=2'b00;
        else
            curr_state <= next_state;
    end

    //two step
    always@(*)begin
        case(curr_state)
            2'b00: next_state = A?2'b11:2'b01;
            2'b01: next_state = A?2'b00:2'b10;
            2'b10: next_state = A?2'b01:2'b11;
            2'b11: next_state = A?2'b10:2'b00;
        endcase
    end
    
    assign Y = (curr_state==2'b11)?1:0;
endmodule

解法二

基础的时序电路设计,可采用列激励方程、输出方程,进而用D触发器和组合逻辑电路实现的方案。

由状态表可得出,电路共4个状态,所以使用2个寄存器来实现状态的寄存。两个寄存器的输出为Q1和Q0。

由状态转换表可列出激励方程如下:

`timescale 1ns/1ns



module seq_circuit(
      input                A   ,
      input                clk ,
      input                rst_n,
 
      output   wire        Y   
);

reg Q1 ;
reg Q0 ;
      
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      Q1 <= 1'b0;
   else
      Q1 <= Q1 ^ Q0 ^A;
end 
always @(posedge clk or negedge rst_n)begin
   if(!rst_n)
      Q0 <= 1'b0;
   else
      Q0 <= ~Q0;
end 
    
assign Y = Q1 & Q0; 
   
endmodule

 解法三:三段式状态机

`timescale 1ns/1ns
module seq_circuit(
    input A,
    input clk,
    input rst_n,
    output wire Y
);
    localparam ZERO = 2'b00;
    localparam ONE = 2'b01;
    localparam TWO = 2'b10;
    localparam THREE = 2'b11;
    reg Y_temp;
    assign Y = Y_temp;
    reg [1:0] curr_state;
    reg [1:0] next_state;
    //状态转移
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            curr_state <= ZERO;
        else 
            curr_state <= next_state;
    end
    //状态判断逻辑
    always@(*)begin
        case(curr_state)
            ZERO : next_state = A ? THREE : ONE;
            ONE  : next_state = A ? ZERO  : TWO;
            TWO  : next_state = A ? ONE   : THREE;
            THREE : next_state = A ? TWO : ZERO;
            default: next_state = ONE;
        endcase
    end
    //输出
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            Y_temp <= 1'b0;
        else begin
            case(next_state)
                ZERO : Y_temp <= 1'b0;
                ONE  : Y_temp <= 1'b0;
                TWO  : Y_temp <= 1'b0;
                THREE : Y_temp <= 1'b1;
            endcase
        end
    end
endmodule

解法四:容易理解 都是curr_state 没有next_state

`timescale 1ns/1ns
module seq_circuit(
    input A,
    input clk,
    input rst_n,
    output wire Y
);
    reg [1:0] curr_state;
    parameter IDLE = 2'b00;
    parameter ONE = 2'b01;
    parameter TWO = 2'b10;
    parameter THREE = 2'b11;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
        curr_state <= IDLE;
        else
            case(curr_state)
                IDLE:
                if(A== 1'b0)
                    curr_state <= ONE;
                else if(A == 1'b1)
                    curr_state <= THREE;
                else
                    curr_state <= curr_state;
                ONE:
                if(A== 1'b0)
                    curr_state <= TWO;
                else if(A == 1'b1)
                    curr_state <= IDLE;
                else
                    curr_state <= curr_state;    
                TWO:
                if(A== 1'b0)
                    curr_state <= THREE;
                else if(A == 1'b1)
                    curr_state <= ONE;
                else
                    curr_state <= curr_state;   
                THREE:
                if(A== 1'b0)
                     curr_state <= IDLE;
                else if(A == 1'b1)
                    curr_state <= TWO;
                else
                    curr_state <= curr_state;    
            endcase
    end
    assign Y = (curr_state==THREE) ? 1 : 0;
endmodule 

解法五:不太容易想到

`timescale 1ns/1ns
module seq_circuit(
    input A,
    input clk,
    input rst_n,
    output wire Y
);
    reg [1:0] q = 2'b00;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            q <= 2'b00;
        end
        else begin
            q <= A ? (q-1'b1):(q+1'b1);
        end
    end
    assign Y = q[0] & q[1];
endmodule

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值