HDLBits-Circuits学习小结(十)有限状态机终章(Q8~Q2b)

1 设计一个Mealy型的有限状态机

实现一个 mealy 类型的有限状态机,它可以识别输入信号 x 上的序列“101”。当检测到“101”序列时,FSM 应该有一个输出信号 z,这个信号被断言为逻辑 -1。您的 FSM 还应该有一个活动-低异步复位。在状态机中可能只有3个状态。你的 FSM 应该识别重叠序列。

solution:

module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z );
    parameter s0=0,s1=1,s2=2;
    reg [1:0] state,next;
    always @(*) begin
        case(state)
            s0 : next = x ? s1 : s0;
            s1 : next = x ? s1 : s2;
            s2 : next = x ? s1 : s0;
        endcase
    end
    
    always @(posedge clk or negedge aresetn) begin
        if (~aresetn)
            state <= s0;
        else
            state <= next;
    end
    
    assign z = (state==s2 & x==1);

endmodule

2 Serial 2’s complementer

2.1 Serial 2’s complementer(Moore)

你将要设计一个单输入单输出串行的2进制补码器Moore型状态机。 输入(x)是一系列数字(每个时钟周期一个),从数字的最低有效位开始,而输出(Z)是输入的2进制补码。 状态机将接受任意长度的输入数字。该电路需要异步复位。 转换在reset低电平时开始,并在reset高电平时停止。

根据下一题的提示,可以知道本题输入是默认负数的,除了第一次的出现的1以外,其余每一位都相应取反,因为第一次出现的1是最高位,即符号位。

状态转换图来自这篇文章

2.1

三个状态分别表示的是:

  • A表示的是等待直到出现第一个1(未出现则一致在状态A),然后跳转至状态B;
  • B表示的是输出output是1的情况,由A跳转来之后,下一个输入是0则输出相应取反,output则为1;若下一个输入是1则跳转至状态C;
  • C表示的是输出output是0的情况,造成这一情况的原因有两种,一个是B跳转,一个是C状态时的输入是1。若C状态时的输入是0则输出取反,跳转至状态B。

solution;

module top_module (
    input clk,
    input areset,
    input x,
    output z
);
    parameter A=0,B=1,C=2;
    reg [1:0] state,next;
    always @(*) begin
        case(state)
            A: next = x ? B : A;
            B: next = x ? C : B;
            C: next = x ? C : B;
        endcase
    end
    
    always @(posedge clk or posedge areset) begin
        if(areset)
            state <= A;
        else
            state <= next;
    end
    
    assign z = (state==B);
                
endmodule

2.2 Serial two’s complementer(Mealy FSM)

下图是2进制补码器在Mealy型状态机上的实现。 使用独热码编码实现。
状态转换图:
2.2.1
波形图:
2.2.2

solution:

module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    parameter A=0,B=1;
    reg state,next;
    
    always @(*) begin
        case(state)
            A: next = x ? B : A;
            B: next = B;
        endcase
    end
    
    always @(posedge clk or posedge areset) begin
        if(areset)
            state <= A;
        else
            state <= next;
    end
    
    assign z = (state==A) ? x : ~x; 

endmodule

3 FSM(Q3)

3.1 FSM(Q3a)

考虑一个输入为s和w的有限状态机。 假定FSM以复位状态A开始,如下所示。
只要s = 0,FSM就会保持状态A,而当s = 1时,FSM会进入状态B。
一旦进入状态B,FSM就会在接下来的三个时钟周期中检查输入w的值。 如果恰好在这些时钟周期中的两个时钟周期中w = 1,则FSM必须在下一个时钟周期中将输出z设置为1。 否则z必须为0。FSM在接下来的三个时钟周期中继续检查w,依此类推。 下面的时序图说明了不同w值所需的z值。
使用尽可能少的状态。
请注意,s输入仅在状态A中使用,因此只需要考虑w输入。

Q3a

面对需要检测重复周期的脉冲信号时,不妨采用状态机+计数器的方法。这里还需要移位寄存器来存储待检测的信号,但是这里移位寄存器似乎只能这样写(即先描述两个寄存器变量w_reg1和w_reg2,用来存储之前状态的值,w_reg1存储前一状态的值,w_reg2存储w_reg2的值),否则出错。

solution:

module top_module(
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
    parameter s0=0,s1=1;
    reg state,next;
    reg [2:0] data;
    always @(*) begin
        case (state)
            s0: next <= s ? s1 : s0;
            s1: next <= s1;
        endcase
    end
    
    reg	w_reg1;
    reg w_reg2;
    always@(posedge clk)begin
        if(reset)begin
            w_reg1 <= 1'b0;
            w_reg2 <= 1'b0;
            state <= s0;
        end
        else if(next == s1)begin
            w_reg1 <= w;
            w_reg2 <= w_reg1;
            state <= next;
        end
        else begin
            w_reg1 <= 1'b0;
            w_reg2 <= 1'b0;
        	state <= next;
        end
    end  

    
    reg [1:0] cnt;
    always @(posedge clk) begin
        if(reset) begin
        	cnt <= 0;
        end
        else if(state==s1) begin
            if (cnt == 2'd2)
            	cnt <= 0;
            else
                cnt <= cnt + 2'b1;
        end
    end
    
    always @(posedge clk) begin
        if(reset) begin
            z <= 0;
        end
        else if(state==s1 & cnt == 2'd2) begin
            if(~w & w_reg1 & w_reg2 | w & ~w_reg1 & w_reg2 | w & w_reg1 & ~w_reg2)
                z <= 1;
            else
                z <= 0;
        end
        else
            z <= 0; //这里不能漏掉
    end
    
endmodule

3.2 FSM(Q3b)

给定如下所示的状态分配表,实现该有限状态机。 重置应将FSM重置为000状态。

3.2

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input x,
    output z
);
    parameter s0=0,s1=1,s2=2,s3=3,s4=4;
    reg [2:0] state,next;
    
    always @(*) begin
        case (state)
            s0 : next = x==0 ? s0 : s1;
            s1 : next = x==0 ? s1 : s4;
            s2 : next = x==0 ? s2 : s1;
            s3 : next = x==0 ? s1 : s2;
            s4 : next = x==0 ? s3 : s4;
        endcase
    end
    
    always @(posedge clk) begin
        if(reset)
            state <= s0;
        else
            state <= next;
    end
    
    assign z = (state==s3)|(state==s4);   

endmodule

3.3 FSM(Q3c)

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

module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    parameter s0=3'd0,s1=3'd1,s2=3'd2,s3=3'd3,s4=3'd4;
    
    always @(*) begin
        case ({x,y})
            {1'b0,s0} : Y0 = s0[0];
            {1'b1,s0} : Y0 = s1[0];
            {1'b0,s1} : Y0 = s1[0];
            {1'b1,s1} : Y0 = s4[0];
            {1'b0,s2} : Y0 = s2[0];
            {1'b1,s2} : Y0 = s1[0];
            {1'b0,s3} : Y0 = s1[0];
            {1'b1,s3} : Y0 = s2[0];
            {1'b0,s4} : Y0 = s3[0];
            {1'b1,s4} : Y0 = s4[0];
        endcase
    end
    
    assign z = (y==s3)|(y==s4);
    
endmodule

4 FSM(Q6)

4.1 FSM next-state logic(Q6b)

考虑下面显示的状态机,它有一个输入w和一个输出z。
Q6B
假设你希望使用三个触发器和状态码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);
    
    parameter s0=3'd0,s1=3'd1,s2=3'd2,s3=3'd3,
    s4=3'd4,s5=3'd5;
    
    always@(*) begin
        case ({y,w})
            {s0,1'b0}: Y2 = s1[1];
            {s0,1'b1}: Y2 = s0[1];
            {s1,1'b0}: Y2 = s2[1];
            {s1,1'b1}: Y2 = s3[1];
            {s2,1'b0}: Y2 = s4[1];
            {s2,1'b1}: Y2 = s3[1];
            {s3,1'b0}: Y2 = s5[1];
            {s3,1'b1}: Y2 = s0[1];
            {s4,1'b0}: Y2 = s4[1];
            {s4,1'b1}: Y2 = s3[1];
            {s5,1'b0}: Y2 = s2[1];
            {s5,1'b1}: Y2 = s3[1];
        endcase
    end

endmodule

4.2 FSM one-hot next-state logic(Q6c)

考虑下面显示的状态机,它有一个输入w和一个输出z。
对于此部分,假设使用独热码分别为状态A,B,…,F编码,状态分配为y [6:1] = 000001、000010、000100、001000、010000、100000。
编写次态信号y2和y4的逻辑表达式。

独热码的问题思路就是看输出信号可能来自于什么情况,然后列出这些情况。

Q6c

module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);
    
    parameter s1=6'b000001,s2=6'b000010,s3=6'b000100,s4=6'b001000,s5=6'b010000,s6=6'b100000;
    reg [5:0] next;
        
    always@(*) begin
        case ({y,w})
            {s1,1'b0}: begin next = s2; end
            {s1,1'b1}: begin next = s1; end
            {s2,1'b0}: begin next = s3; end
            {s2,1'b1}: begin next = s4; end //
            {s3,1'b0}: begin next = s5; end
            {s3,1'b1}: begin next = s4; end //
            {s4,1'b0}: begin next = s6; end
            {s4,1'b1}: begin next = s1; end
            {s5,1'b0}: begin next = s5; end
            {s5,1'b1}: begin next = s4; end //
            {s6,1'b0}: begin next = s3; end 
            {s6,1'b1}: begin next = s4; end //
        endcase
    end
    
    assign Y2 = y[1] & ~w; //Y2是1的情况只有s2,即状态B
    assign Y4 = (y[2]&w) | (y[3]&w) | (y[5]&w) | (y[6]&w);//Y4是1的情况只有s4,即状态D
    
endmodule

4.3 FSM(Q6)

考虑下面显示的状态机,它有一个输入w和一个输出z。
Q6

module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);
    
    parameter s1=6'b000001,s2=6'b000010,s3=6'b000100,s4=6'b001000,s5=6'b010000,s6=6'b100000;
    reg [5:0] state,next;
    
    always@(*) begin
        case ({state,w})
            {s1,1'b0}: begin next = s2; end
            {s1,1'b1}: begin next = s1; end
            {s2,1'b0}: begin next = s3; end
            {s2,1'b1}: begin next = s4; end //
            {s3,1'b0}: begin next = s5; end
            {s3,1'b1}: begin next = s4; end //
            {s4,1'b0}: begin next = s6; end
            {s4,1'b1}: begin next = s1; end
            {s5,1'b0}: begin next = s5; end
            {s5,1'b1}: begin next = s4; end //
            {s6,1'b0}: begin next = s3; end 
            {s6,1'b1}: begin next = s4; end //
        endcase
    end
    
    always @(posedge clk) begin
        if(reset)
            state <= s1;
        else
            state <= next;
    end
    
    assign z = (state==s5)|(state==s6);

endmodule

5 FSM(Q2)

5.1 FSM(Q2a)

考虑下面显示的状态机。
在这里插入图片描述
编写代表此FSM的完整Verilog代码。 对状态表和状态触发器使用单独的Always块。 使用连续赋值语句或Always块描述FSM的输出z。 状态编码随你心意。

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    input w,
    output z
);
    
    parameter s1=6'b000001,s2=6'b000010,s3=6'b000100,s4=6'b001000,s5=6'b010000,s6=6'b100000;
    reg [5:0] state,next;
    
    always@(*) begin
        case ({state,w})
            {s1,1'b0}: begin next = s1; end
            {s1,1'b1}: begin next = s2; end
            {s2,1'b0}: begin next = s4; end
            {s2,1'b1}: begin next = s3; end //
            {s3,1'b0}: begin next = s4; end
            {s3,1'b1}: begin next = s5; end //
            {s4,1'b0}: begin next = s1; end
            {s4,1'b1}: begin next = s6; end
            {s5,1'b0}: begin next = s4; end
            {s5,1'b1}: begin next = s5; end //
            {s6,1'b0}: begin next = s4; end 
            {s6,1'b1}: begin next = s3; end //
        endcase
    end
    
    always @(posedge clk) begin
        if(reset)
            state <= s1;
        else
            state <= next;
    end
    
    assign z = (state==s5)|(state==s6);

endmodule

5.2 One-hot FSM equations(Q2b)

考虑下面显示的状态机。
在这里插入图片描述
假设使用独热码进行状态分配,y [5:0] = 000001(A),000010(B),000100(C),001000(D),010000(E),100000(F)
写出状态触发器y [1]输入Y1的逻辑表达式。
写出状态触发器y [3]输入Y3的逻辑表达式。

module top_module (
    input [5:0] y,
    input w,
    output Y1,
    output Y3
); 
    //Y1为1的情况只有状态B,y3为1的情况只有状态D
    assign Y1 = y[0] & w;
    assign Y3 = y[1]&~w | y[2]&~w | y[4]&~w | y[5]&~w;
    
endmodule

5.3 an arbiter circuit(Q2a)

该FSM充当仲裁器电路,该电路控制三个请求设备对某种类型资源的访问。每个设备通过设置信号r [i] = 1来请求资源,其中r [i]为r [1],r [2]或r [3]。

在这里插入图片描述

每个r [i]是FSM的输入信号,代表三个设备之一。只要没有请求,FSM就会保持状态A。当发生一个或多个请求时,FSM决定哪个设备接收到使用该资源的授权,并更改为将该设备的g [i]信号设置为1的状态。

每个g [i]是FSM的输出。有一个优先级系统,即设备1的优先级高于设备2的优先级,而设备3的优先级最低。因此,例如,当FSM处于状态A时,如果设备3是唯一发出请求的设备,则设备3将仅接收授权。一旦设备(即,FSM给了设备i)授权,该设备将继续接收授权,只要它的请求r [i] = 1。

编写代表此FSM的完整Verilog代码,对状态表和状态触发器使用单独的Always块。使用连续赋值语句或Always块(自行决定)描述FSM输出g [i]。状态分配随你所意。

module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input [3:1] r,   // request
    output [3:1] g   // grant
); 
    parameter s0=0,s1=1,s2=2,s3=3;
    reg [1:0] state,next;
    always @(*) begin
        case (state)
            s0 : begin
                if(r[1])
                    next = s1;
                else if(r[2])
                    next = s2;
                else if(r[3])
                    next = s3;
                else
                    next = s0;
            end
            s1 : begin
                if(r[1])
                    next = s1;
                else
                    next = s0;
            end
            s2 : begin
                if(r[2])
                    next = s2;
                else
                    next = s0;
            end
            s3 : begin
                if(r[3])
                    next = s3;
                else
                    next = s0;
            end
        endcase
    end
    
    always @(posedge clk) begin
        if(~resetn)
            state <= s0;
        else
            state <= next;
    end
    
    assign g = {state==s3,state==s2,state==s1};
    
endmodule

5.4 an arbiter circuit(Q2b)

考虑用于控制某种类型电动机的有限状态机。FSM具有来自电动机的输入x和y,并产生控制电动机的输出f和g。还有一个时钟输入叫clk和一个复位输入叫resetn。
FSM必须按以下方式工作:
只要复位输入有效,FSM保持初始状态,即状态A。
复位信号无效后,在下一个时钟沿之后,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(直到复位)。
(最初的考试问题仅要求提供状态图。但是,在这里实施FSM。)

这道题其实有很多条件没有讲清楚:

  • FSM在输出f设置为1后,是否应该保持为1,如果不是那么应该保持多少个周期?根据多次试错,可以知道f在设置为1后维持一个周期即变为了0;
  • “然后,FSM必须监视x输入,当x在三个连续的时钟周期中产生值1,0,1时”,这里监视x输入是在f设置为1这一时刻开始,还是f设置为1这一时刻后的一个时钟周期开始。根据多次试错,可以知道应该是后者。
  • 监视y输出同上,是在g=1这一时刻的后一个时钟周期开始。

于是这里代码中判断状态变换的情况就都是state,而不是next。

module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input x,
    input y,
    output f,
    output g
); 
    parameter s0=0,s1=1,s2=2,s3=3,s4=4,s5=5;
    reg [2:0] state,next;
    
    reg [2:0] data_x;
    always @(posedge clk) begin
        if (~resetn) begin
            data_x <= 3'b0;
        end
        else if(state==s2) begin
            data_x <= {data_x[1:0],x};
        end
        else begin
            data_x <= 3'b0;
        end
    end
    
    reg cnt;
    reg y_reg;
    always @(posedge clk) begin
        if (~resetn) begin
            y_reg <= 1'b0;
            cnt <= 1'b0;
        end
        else if(cnt==1'b1)
            cnt = 0;
        else if(state==s3) begin
            cnt <= cnt + 1'b1;
            y_reg <= y;
        end
    end
            
        
    always @(*) begin
        case (state)
            s0: next = s1;
            s1: next = s2;
            s2: next = ({data_x[1:0],x}==3'b101) ? s3 : s2;
            s3: next = (cnt==1'b1) ? (({y_reg,y}==2'b00) ? s4 : s5) : s3;
            s4: next = s4;
            s5: next = s5;
        endcase
    end
    
    reg k;
    always @(posedge clk) begin
        if (~resetn)
            state <= s0;
        else begin
            state <= next;
        end
    end
    
    assign f = (state==s1);
    assign g = (state==s5)|(state==s3);

endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值