HDLBits第十四章练习及答案4

21、Q8:设计一个Mealy FSM

米利型状态机

检测输入的X中”101“是否出现,出现的话输出Z为1,否则为0。复位为异步低电平复位;只允许出现3种状态;允许交叠检测:即输入若为10101时,Z应该在时刻3和时刻5各输出一次1。

代码中主要妙在两处:一是如何用3种状态表示,需在第三种状态中将输出与输入关联起来;二是如何进行交叠检测,状态的转移有妙处。

代码实现:

module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z ); 

    parameter S0 = 2'd0,S1 = 2'd1,S2 = 2'd2;
    reg [1:0] current_state,next_state;

    always @(*) begin
        case(current_state)
            S0: next_state = x ? S1 : S0;
            S1: next_state = x ? S1 : S2;
            S2: next_state = x ? S1 : S0;
        endcase
    end

    always @(posedge clk or negedge aresetn) begin
        if(~aresetn)
            current_state <= S0;
        else 
            current_state <= next_state;
    end

    always @(*) begin
        z = (current_state == S2) ? x : 1'b0;
    end

endmodule

验证结果:
在这里插入图片描述

22、Q5a:串行二进制补码器(Moor FSM)

您将设计一个单输入单输出串行 2 的补码摩尔状态机。输入 (x) 是从数字的最低有效位开始的一系列位(每个时钟周期一个),输出 (Z) 是输入的 2 的补码。机器将接受任意长度的输入数字。该电路需要异步复位。当转换开始复位释放后,停止复位有效。
在这里插入图片描述
注意:假设我们这边输入的都是负数,不用管符号位的问题;即补码全部都是取反加1求得。

以上图为例,输入的左边为低位数据,右边为高位数据;即输入为00110100,则取反加1后得输出为11001100;

取反操作好进行,主要麻烦在加一的操作上,不知道进位到哪一位为止,此时我们用状态机来解决;若最前面的输入都是0的话,取反均为1,低位加1的时候一直进位,则输出都是0,直到输入有个1为止(取反加1不进位),这一阶段我们用一个状态S0来表示;后面阶段就将输入取反进行输出即可,因为进位在S0状态已结束;

代码实现:

module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    parameter S0=2'd0,S1=2'd1,S2=2'd2;
    reg [1:0] current_state,next_state;
    
    always @(*) begin
        case(current_state)
            S0: next_state = x ? S1 : S0;
            S1: next_state = x ? S2 : S1;
            S2: next_state = x ? S2 : S1;
        endcase
    end
    
    always@(posedge clk or posedge areset) begin
        if(areset)
            current_state <= S0;
        else
            current_state <= next_state;
    end
    
    assign z = (current_state == S1);
    
endmodule

验证结果:
在这里插入图片描述

23、Q5b:串行二进制补码器(Mealy FSM)

下图是2 的补码器的Mealy机实现。使用 one-hot 编码实现。
在这里插入图片描述
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
	parameter S0=1'b0,S1=1'b1;
    reg current_state,next_state;
    
    always@(*)begin
        case(current_state)
            S0: begin
                if(x == 1)
                   next_state = S1;
                else
                   next_state = S0; 
                end
            S1: next_state = S1; 
        endcase
    end
    
    always@(posedge clk or posedge areset) begin
        if(areset)
            current_state <= S0;
        else
            current_state <= next_state;
    end
    
    assign z = ((current_state == S0) && x) | ((current_state == S1) && ~x);
    
endmodule

验证结果:
在这里插入图片描述

24、Q3a:FSM

考虑一个有输入s和w的有限状态机。假设FSM从一个名为a的重置状态开始,如下所示。当s = 0时,状态为A,当s = 1时,状态为B。一旦进入状态B, FSM就会检查接下来三个时钟周期中输入w的值。如果w在这两个时钟周期中恰好为1,则FSM必须在下一个时钟周期中将输出z设置为1。否则z等于0。FSM继续检查w是否有接下来的三个时钟周期,以此类推。下面的时序图说明了不同的w值所需的z值。

使用尽可能少的状态。注意,s输入只在状态A中使用,所以您需要只考虑w输入。
在这里插入图片描述在这里插入图片描述
提示:

当s为0时,进入B状态,然后会检查w的值,如果在接下来的三个周期中w值恰好有两个周期都为1,那么z输出1,否则z输出0。注意,由示例的波形图看应该是不重叠检测。

代码实现:

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);

    parameter S0=1'b0,S1=1'b1;
    reg current_state,next_state;
    reg [1:0] cnt,num;
    
    always@(*)begin
        case(current_state)
            S0: begin
                if(s == 1)
                   next_state = S1;
                else
                   next_state = S0; 
                end
            S1: next_state = S1; 
            default: next_state = S0; 
        endcase
    end
    
    always@(posedge clk) begin
        if(reset)
            current_state <= S0;
        else
            current_state <= next_state;
    end
    
    always@(posedge clk) begin
        if(reset)
            cnt <= 2'd0;
        else if(cnt == 2'd2)
            cnt <= 2'd0;
        else if(current_state == S1)
            cnt <= cnt + 1'b1;
        else
            cnt <= cnt;
    end
    
    always@(posedge clk) begin
        if(reset)
            num <= 2'd0;
        else if(cnt == 2'd0)
            num <= w ? 1'b1 : 1'b0;
        else if(current_state == S1)
            num <= w ? (num+1'b1) : num;
        else
            num <= num;
    end
    
    assign z = (current_state == S1 && cnt == 2'd0 && num == 2'd2);
    
endmodule

验证结果:
在这里插入图片描述

25、Q3b:FSM

给定下面显示的状态分配表,实现有限状态机。重置应将 FSM 重置为状态 000。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input x,
    output z
);

    parameter S0=3'b000,S1=3'b001,S2=3'b010,S3=3'b011,S4=3'b100;
    reg [2:0] current_state,next_state;
    
    always@(*)begin
        case(current_state)
            S0: next_state = x ? S1 : S0;
            S1: next_state = x ? S4 : S1;
            S2: next_state = x ? S1 : S2;
            S3: next_state = x ? S2 : S1;
            S4: next_state = x ? S4 : S3;
        endcase
    end
    
    always@(posedge clk) begin
        if(reset)
            current_state <= S0;
        else
            current_state <= next_state;
    end
    
    assign z = (current_state == S3 || current_state == S4);
    
endmodule

验证结果:
在这里插入图片描述

26、Q3c:FSM 逻辑

给定如下所示的状态分配表,实现逻辑函数 Y[0] 和 z。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    
    assign z = (y == 3'b011 || y == 3'b100);
    assign Y0 = ((~y[2]&y[0])|(y==3'b100))&~x | (~y[2]&~y[0])&x;
        
endmodule

验证结果:
在这里插入图片描述

27、Q6b:FSM 下一状态逻辑

考虑下面显示的状态机,它有一个输入w和一个输出z。
在这里插入图片描述
假设您希望使用三个触发器和状态代码y[3:1] = 000, 001, … , 101 分别为状态 A、B、…、F实现 FSM 。显示此 FSM 的状态分配表。导出触发器y[2]的下一个状态表达式。

仅实现y[2]的下一个状态逻辑。

提示:
在这里插入图片描述
代码实现:

module top_module (
    input [3:1] y,
    input w,
    output Y2);
    
    assign Y2 = (y==3'b001)|(y==3'b101)|(((y==3'b010)|(y==3'b100))& w);

endmodule

验证结果:
在这里插入图片描述

28、Q6c:FSM one-hot 下一状态逻辑

考虑下面显示的状态机,它有一个输入w和一个输出z。
在这里插入图片描述
对于这一部分,假设状态分配 'y[6:1] = 000001, 000010, 000100, 001000, 010000, 100000 分别用于状态 A、B、…、F的独热码。

为下一状态信号 Y2 和 Y4 写一个逻辑表达式。

提示:

y[6:1]statew=0w=1
000001A000010000001
000010B000100001000
000100C010000001000
001000D100000000001
010000E010000001000
100000F000100001000

代码实现:

module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);

    assign Y2 = ~w & y[1];
    assign Y4 = (w & y[2])|(w & y[3])|(w & y[5])|(w & y[6]);
    
endmodule

验证结果:
在这里插入图片描述

29、Q6:FSM

实现下图显示的状态机,它有一个输入w和一个输出z。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);

    parameter A=3'd1,B=3'd2,C=3'd3,D=3'd4,E=3'd5,F=3'd6;
    reg [2:0] current_state,next_state;
    
    always@(*)begin
        case(current_state)
            A: next_state = w ? A : B;
            B: next_state = w ? D : C;
            C: next_state = w ? D : E;
            D: next_state = w ? A : F;
            E: next_state = w ? D : E;
            F: next_state = w ? D : C;
        endcase
    end
    
    always@(posedge clk) begin
        if(reset)
            current_state <= A;
        else
            current_state <= next_state;
    end
    
    assign z = (current_state == E || current_state == F);
    
endmodule

验证结果:
在这里插入图片描述

30、Q2a:FSM

实现下面显示的状态图。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    input w,
    output z
);

    parameter A=3'd1,B=3'd2,C=3'd3,D=3'd4,E=3'd5,F=3'd6;
    reg [2:0] current_state,next_state;
    
    always@(*)begin
        case(current_state)
            A: next_state = w ? B : A;
            B: next_state = w ? C : D;
            C: next_state = w ? E : D;
            D: next_state = w ? F : A;
            E: next_state = w ? E : D;
            F: next_state = w ? C : D;
        endcase
    end
    
    always@(posedge clk) begin
        if(reset)
            current_state <= A;
        else
            current_state <= next_state;
    end
    
    assign z = (current_state == E || current_state == F);
        
endmodule

验证结果:
在这里插入图片描述

31、Q2b:One hot FSM方程

状态使用独热编码,将状态中的y[1]和y[3]表示出来。

假设状态分配 y[5:0] = 000001(A), 000010(B), 000100©, 001000(D), 010000(E), 100000(F)

写出信号Y1的逻辑表达式,它是状态触发器y[1] 的输入。
写出信号Y3的逻辑表达式,它是状态触发器y[3] 的输入。
在这里插入图片描述
代码实现:

module top_module (
    input [5:0] y,
    input w,
    output Y1,
    output Y3
);

    assign Y1 = w & y[0];
    assign Y3 = (~w & y[1])|(~w & y[2])|(~w & y[4])|(~w & y[5]);
    
endmodule

验证结果:
在这里插入图片描述

32、Q2a:FSM

用状态机实现一个判优器。其中r1、r2、r3分别表示三种设备的request,g1、g2、g3表示资源的分配情况。由下面的状态图可见,设备1,2,3的优先级依次递减。当设备请求到资源时,需等其完成任务才能释放资源。
在这里插入图片描述
代码实现:

  module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input [3:1] r,   // request
    output [3:1] g   // grant
); 

    parameter A=2'd1,B=2'd2,C=2'd3,D=2'd4;
    reg [1:0] current_state,next_state;
    
    always@(*)begin
        case(current_state)
            A: begin
                if(r[1]==1'b1) 
                    next_state = B;
                else if(r[2]==1'b1)
                    next_state = C;
                else if(r[3]==1'b1)
                    next_state = D;
                else 
                    next_state = A;
            end
            B: next_state = r[1] ? B : A;
            C: next_state = r[2] ? C : A;
            D: next_state = r[3] ? D : A;
            default:next_state = A;
        endcase
    end
    
    always@(posedge clk) begin
        if(~resetn)
            current_state <= A;
        else
            current_state <= next_state;
    end
    
    assign g = {current_state == D,current_state == C,current_state == B};
    
endmodule

验证结果:
在这里插入图片描述

33、Q2b:另一个FSM

考虑一个用于控制某种类型电机的有限状态机。FSM有来自电机的输入x和y,并产生控制电机的输出f和g。还有一个时钟输入称为clk和一个复位输入称为resetn。

FSM 必须按如下方式工作。只要复位输入有效时,FSM停留在一开始的状态,所谓的国家一个。当复位信号无效时,在下一个时钟沿之后,FSM 必须将输出f设置为 1,持续一个时钟周期。然后,FSM 必须监视 x输入。当x在三个连续的时钟周期中产生了值 1、0、1 时,g应在下一个时钟周期设置为 1。在保持g = 1 的同时,FSM 必须监控y 输入。如果y在最多两个时钟周期内为 1,则 FSM 应保持g= 1 永久(即,直到重置)。但是如果y在两个时钟周期内没有变成 1,那么 FSM 应该永久设置g = 0(直到复位)。

提示:

该题的状态机共2输入2输出;当复位信号撤销时,在下一个周期内将f输出为1,需留意f为1持续一个周期;然后状态机取决于x的值,当x在连续的三个周期中产生值为1、0、1时,下一周期将g输出为1,在保持g为1时判断y的输入,如果y在两个周期中有任意一个周期为1了,那么g永久保持1;如果两个周期都没有1,那么g将永久保持0。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input x,
    input y,
    output f,
    output g
); 

    parameter IDLE=4'd0,FOUT=4'd1,S1=4'd2,S2=4'd3,S3=4'd4,S4=4'd5,S5=4'd6;
    parameter ALL_ZERO=4'd7,ALL_ONE=4'd8;
    reg [3:0] current_state,next_state;
    
    always@(*)begin
        case(current_state)
            IDLE: next_state = FOUT;
            FOUT: next_state = S1;
            S1: next_state = x ? S2 : S1;
            S2: next_state = x ? S2 : S3;
            S3: next_state = x ? S4 : S1;
            S4: next_state = y ? ALL_ONE : S5;
            S5: next_state = y ? ALL_ONE : ALL_ZERO;
            ALL_ONE: next_state = ALL_ONE;
            ALL_ZERO: next_state = ALL_ZERO;
            default:next_state = IDLE;
        endcase
    end
    
    always@(posedge clk) begin
        if(~resetn)
            current_state <= IDLE;
        else
            current_state <= next_state;
    end
    
    assign f = (current_state == FOUT);
    assign g = (current_state == S4) | (current_state == S5) | (current_state == ALL_ONE);
    
endmodule

验证结果:
在这里插入图片描述

参考资料: Verilog有限状态机.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值