题解 | 基础版21#根据状态转移表实现时序电路#

根据状态转移表实现时序电路

http://www.nowcoder.com/practice/455c911bee0741bf8544a75d958425f7

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

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

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

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

1. 题目

某同步时序电路转换表如下,请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。 

2. 解析

2.1 题目本身解析

有状态转移表,最好也要画出来状态转移图,状态跳转如下图所示:

问题:本题为了使输出恰好符合给定答案的时序,所以在用摩尔型状态机判断的时候,要用两段式状态机,或者考虑米利型状态机。

 

本题为了简便起见,使用二进制编码。

 

2.2 摩尔型和米利型状态机

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

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

 

摩尔型输出比米利型晚一个时钟周期。

 

2.3 一段式、两段式、三段式状态机

 

 

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

 

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

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

 

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

————————————————

版权声明:本文为CSDN博主「DengFengLai123」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/DengFengLai123/article/details/114557016

 

2.4 状态编码

 

二进制码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;

 

3. 代码

`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&nbs***bsp;negedge rst_n)
        begin
            if( ~rst_n ) begin
                curr_state <= 2'b00;
                next_state <= 2'b00;
            end 
            else begin
                curr_state <= next_state;
            end 
        end 
    
    // two step
    always @ (*)
        begin
            case(curr_state)
                2'b00 : next_state = (A == 1'b1) ? 2'b11 : 2'b01;
                2'b01 : next_state = (A == 1'b1) ? 2'b00 : 2'b10;
                2'b10 : next_state = (A == 1'b1) ? 2'b01 : 2'b11;
                2'b11 : next_state = (A == 1'b1) ? 2'b10 : 2'b00;
                default : next_state = 2'b00;
            endcase
        end
    
    assign Y = (curr_state == 2'b11) ? 1 : 0;
    
endmodule

全部评论
next_state在两个always块中被赋值会报错 if( ~rst_n ) begin curr_state <= 2'b00; next_state <= 2'b00; end case(curr_state) 2'b00 : next_state = (A == 1'b1) ? 2'b11 : 2'b01; 2'b01 : next_state = (A == 1'b1) ? 2'b00 : 2'b10; 2'b10 : next_state = (A == 1'b1) ? 2'b01 : 2'b11; 2'b11 : next_state = (A == 1'b1) ? 2'b10 : 2'b00; default : next_state = 2'b00; endcase
1 回复 分享
发布于 2022-06-18 10:20
如何选择一份实习?——聊聊实习和对秋招的影响https://www.nowcoder.com/discuss/953291
点赞 回复 分享
发布于 2022-05-20 20:59

相关推荐

微风不断:兄弟,你把四旋翼都做出来了那个挺难的吧
点赞 评论 收藏
分享
35 12 评论
分享
牛客网
牛客企业服务