2021年4月29日 星期四

HBLbits_Verilog Basic_Finite State Machines

 HBLbits_Verilog Basic_Finite State Machines

3.2.5 Finite State Machines

3.2.5.1 Simple FSM 1 (asynchronous reset)

This is a Moore state machine with two states, one input, and one output. Implement this state machine. Notice that the reset state is B. This exercise is the same as fsm1s, but using asynchronous reset.
  • 两段式:状态调转(当前状态和下一个状态)用时序逻辑写,下一个状态的判断是组合逻辑写!(个人理解,记得不太清楚了)
//第一种写法,不写第二种了,后面状态机太多!
module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output out);//  

    parameter A=0, B=1; 
    reg state, next_state;

    always @(*) begin    // This is a combinational always block
        // State transition logic
        if(!in) next_state = ~state;
        else next_state = state;
    end

    always @(posedge clk, posedge areset) begin    // This is a sequential always block
        // State flip-flops with asynchronous reset
        if(areset) state <= B;
        else 
            state <= next_state;
    end

    // Output logic
    // assign out = (state == ...);
     assign out = state == B;
endmodule

3.2.5.2 Simple FSM 1 (synchronous reset)

  • 用的网站提供的格式,时序逻辑中不应该全部用<=吗?但是自己把后面加了<=,验证失败!
// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);
    input clk;
    input reset;    // Synchronous reset to state B
    input in;
    output out;//  
    reg out;

    // Fill in state name declarations
    localparam A =1'b0,B=1'b1;

    reg present_state, next_state;

    always @(posedge clk) begin
        if (reset) begin  
            // Fill in reset logic
            out <= B;
            present_state <= B;
        end else begin
            case (present_state)
                // Fill in state transition logic
                A:
                    if(in) next_state = present_state;
                    else next_state = ~present_state;
                B:
                    if(in) next_state = present_state;
                    else next_state = ~present_state;
                default:;
            endcase

            // State flip-flops
            present_state = next_state;   

            case (present_state)
                // Fill in output logic
                A:out = A;
                B:out = B;
                default:;
            endcase
        end
    end

endmodule

3.2.5.3 Simple FSM 2 (asynchronous reset)

module top_module(
    input clk,
    input areset,    // Asynchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF=0, ON=1; 
    reg state, next_state;

    always @(*) begin
        // State transition logic
        if(state == OFF)begin
            if(j) next_state = ON;
            else next_state = OFF;
        end
        else begin
            if(k) next_state = OFF;
            else next_state = ON;
        end
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset)begin
              state <= OFF; 
        end
        else 
             state <= next_state;
    end

    // Output logic
    // assign out = (state == ...);
    assign out = state == ON;
endmodule

3.2.5.4 Simple FSM 2 (synchronous reset)

module top_module(
    input clk,
    input reset,    // Synchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF=0, ON=1; 
    reg state, next_state;

    always @(*) begin
        // State transition logic
        if(state == OFF)begin
            if(j) next_state = ON;
            else next_state = OFF;
        end
        else begin
            if(k) next_state = OFF;
            else next_state = ON;
        end
    end

    always @(posedge clk) begin
        // State flip-flops with synchronous reset
        if(reset)begin
              state <= OFF; 
        end
        else 
             state <= next_state;
    end

    // Output logic
    // assign out = (state == ...);
    assign out = state == ON;
endmodule

  • 同步复位 sync:复位信号只有在时钟上升沿到来时才能有效。
  • 异步复位 async:无论时钟沿是否到来,只要复位信号有效,就进行复位。

3.2.5.5 Simple state transitions 3(Fsm3comb)

//第一种写法
module top_module(
    input in,
    input [1:0] state,
    output [1:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    // State transition logic: next_state = f(state, in)
    always@(*)begin
        case(state)
            A:
                if(in)
                    next_state = B;
                else
                    next_state = A;
            B:
                if(in)
                    next_state = B;
                else
                    next_state = C;
            C:
                if(in)
                    next_state = D;
                else
                    next_state = A;
            D:
                if(in)
                    next_state = B;
                else
                    next_state = C;
        endcase
    end

    // Output logic:  out = f(state) for a Moore state machine
    assign out = state == D;
endmodule


//第二种写法
module top_module(
    input in,
    input [1:0] state,
    output [1:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    // State transition logic: next_state = f(state, in)
    always@(*)begin
        case(state)
            A:
                next_state = in ? B : A;
            B:
                next_state = in ? B : C;
            C:
                next_state = in ? D : A;
            D:
                next_state = in ? B : C;
        endcase
    end

    // Output logic:  out = f(state) for a Moore state machine
    assign out = state == D;
endmodule

3.2.5.6 Simple one-hot state transitions 3(Fsm3onehot)

Use the following one-hot state encoding: A=4'b0001, B=4'b0010, C=4'b0100, D=4'b1000.
module top_module(
    input in,
    input [3:0] state,
    output [3:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    // State transition logic: Derive an equation for each state flip-flop.
    assign next_state[A] = state[A] & ~in | state[C] & ~in;
    assign next_state[B] = state[A] & in | state[B] & in | state[D] & in;
    assign next_state[C] = state[B] & ~in | state[D] & ~in;
    assign next_state[D] = state[C] & in;

    // Output logic: 
    assign out = state[D];

endmodule

参考的博文链接 这道题目作者是想让我们用one-hot(独热码)的编码逻辑完成。不过大家也注意到了,该题和我们平时使用的one-hot逻辑不同,我们平时使用的one-hot逻辑实在parameter中定义,比如定义四个状态,那么分别是4'b0001、4'b0010、4'b0100、4'b1000,,这道题目中的parameter还是定义为十进制的1、2、3、4,因为这里作者将输入状态和输出状态都定义为4bit,所以1、2、3、4位定义着state和next_state的4位。 大家要注意,一般我们的状态机编码为了方便都是设置为二进制码,但是如果是状态转移是按顺序转移的话,那么我们可以使用格雷码,因为格雷码每次只变化一个bit,这样可以节约功耗。如果要说速度快,那么可以使用one-hot编码,因为每次仅需判断一位就可以了,当然这种编码会消耗更多的寄存器资源,但是消耗更少的组合逻辑资源。关于这一点,不知道大家还记不记得3-8译码器,one-hot编码可以认为是已经进行过译码的编码单元,所以相比二进制编码和格雷码更节约组合逻辑资源。 如果状态较少,建议大家使用one-hot编码,如果状态较多,建议大家使用格雷码,如果功耗的影响不是那么大并且为了尽快完成设计,建议直接使用二进制编码就好了。

3.2.5.7 Simple FSM 3 (asynchronous reset)(Fsm3)

Include an asynchronous reset that resets the FSM to state A.
module top_module(
    input clk,
    input in,
    input areset,
    output out); //

    reg [1:0] state,next_state;
    localparam A=2'b00,B=2'b01,C=2'b10,D=2'b11;
    // State transition logic
    always@(*)begin
        case(state)
            A:
                next_state = in?B:A;
            B:
                next_state = in?B:C;
            C:
                next_state = in?D:A;
            D:
                next_state = in?B:C;
        endcase
    end

    // State flip-flops with asynchronous reset
    always@(posedge clk or posedge areset)begin
    if(areset) begin
        state <= A;
    end
    else
        state <= next_state;
    end

    // Output logic
    assign out = state==D;
endmodule

3.2.5.8 Simple FSM 3 (synchronous reset)(Fsm3s)

module top_module(
    input clk,
    input in,
    input reset,
    output out); //

    reg [1:0] state,next_state;
    localparam A=2'b00,B=2'b01,C=2'b10,D=2'b11;
    // State transition logic
    always@(*)begin
        case(state)
            A:
                next_state = in?B:A;
            B:
                next_state = in?B:C;
            C:
                next_state = in?D:A;
            D:
                next_state = in?B:C;
        endcase
    end

    // State flip-flops with synchronous reset
    always@(posedge clk)begin
    if(reset) begin
        state <= A;
    end
    else
        state <= next_state;
    end

    // Output logic
    assign out = state==D;
endmodule

3.2.5.9 Design a Moore FSM(Exams/ece241 2013 q4)

Also include an active-high synchronous reset that resets the state machine to a state equivalent to if the water level had been low for a long time (no sensors asserted, and all four outputs asserted).
module top_module (
    input clk,
    input reset,
    input [3:1] s,
    output reg fr3,
    output reg fr2,
    output reg fr1,
    output reg dfr
);


    // Give state names and assignments. I'm lazy, so I like to use decimal numbers.
    // It doesn't really matter what assignment is used, as long as they're unique.
    // We have 6 states here.
    parameter A2=0, B1=1, B2=2, C1=3, C2=4, D1=5;
    reg [2:0] state, next;      // Make sure these are big enough to hold the state encodings.



    // Edge-triggered always block (DFFs) for state flip-flops. Synchronous reset.    
    always @(posedge clk) begin
        if (reset) state <= A2;
        else state <= next;
    end



    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
    always@(*) begin
        case (state)
            A2: next = s[1] ? B1 : A2;
            B1: next = s[2] ? C1 : (s[1] ? B1 : A2);
            B2: next = s[2] ? C1 : (s[1] ? B2 : A2);
            C1: next = s[3] ? D1 : (s[2] ? C1 : B2);
            C2: next = s[3] ? D1 : (s[2] ? C2 : B2);
            D1: next = s[3] ? D1 : C2;
            default: next = 'x;
        endcase
    end



    // Combinational output logic. In this problem, a procedural block (combinational always block) 
    // is more convenient. Be careful not to create a latch.
    always@(*) begin
        case (state)
            A2: {fr3, fr2, fr1, dfr} = 4'b1111;
            B1: {fr3, fr2, fr1, dfr} = 4'b0110;
            B2: {fr3, fr2, fr1, dfr} = 4'b0111;
            C1: {fr3, fr2, fr1, dfr} = 4'b0010;
            C2: {fr3, fr2, fr1, dfr} = 4'b0011;
            D1: {fr3, fr2, fr1, dfr} = 4'b0000;
            default: {fr3, fr2, fr1, dfr} = 'x;
        endcase
    end

endmodule

3.2.5.10 Lemmings 1(Lemmings1)

  • 旅鼠游戏
In the Lemmings' 2D world, Lemmings can be in one of two states: walking left or walking right. It will switch directions if it hits an obstacle. In particular, if a Lemming is bumped on the left, it will walk right. If it's bumped on the right, it will walk left. If it's bumped on both sides at the same time, it will still switch directions.
module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    output walk_left,
    output walk_right); //  

    // parameter LEFT=0, RIGHT=1, ...
    parameter LEFT = 0, RIGHT = 1;
    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            LEFT:
                if(bump_left)
                    next_state = RIGHT;
                else
                    next_state = LEFT;
            RIGHT:
                if(bump_right)
                    next_state = LEFT;
                else
                    next_state = RIGHT;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset) state <= LEFT;
        else 
            state <= next_state;
    end

    // Output logic
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);

endmodule


//参考答案
module top_module (
    input clk,
    input areset,
    input bump_left,
    input bump_right,
    output walk_left,
    output walk_right
);

    // Give state names and assignments. I'm lazy, so I like to use decimal numbers.
    // It doesn't really matter what assignment is used, as long as they're unique.
    parameter WL=0, WR=1;
    reg state;
    reg next;


    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
    always@(*) begin
        case (state)
            WL: next = bump_left  ? WR : WL;
            WR: next = bump_right ? WL : WR;
        endcase
    end


    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
    always @(posedge clk, posedge areset) begin
        if (areset) state <= WL;
        else state <= next;
    end


    // Combinational output logic. In this problem, an assign statement are the simplest.
    // In more complex circuits, a combinational always block may be more suitable.     
    assign walk_left = (state==WL);
    assign walk_right = (state==WR);


endmodule

3.2.5.11 Lemmings 2(Lemmings2)

In addition to walking left and right, Lemmings will fall (and presumably go "aaah!") if the ground disappears underneath them. In addition to walking left and right and changing direction when bumped, when ground=0, the Lemming will fall and say "aaah!". When the ground reappears (ground=1), the Lemming will resume walking in the same direction as before the fall. Being bumped while falling does not affect the walking direction, and being bumped in the same cycle as ground disappears (but not yet falling), or when the ground reappears while still falling, also does not affect the walking direction.
module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    output walk_left,
    output walk_right,
    output aaah ); 

    localparam WL=0;//向左走
    localparam WR=1;//向右走
    localparam WL_D=2;//向左走下跌
    localparam WR_D=3;//向右走下跌

    reg [1:0] state,next_state;

    always@(*)begin
        case(state)
            WL:
                if(!ground )
                    next_state = WL_D;
                else if(bump_left)
                    next_state = WR;
                else
                    next_state = WL;
            WR:
                if(!ground)
                    next_state = WR_D;
                else if(bump_right)
                    next_state = WL;
                else
                    next_state = WR;
            WL_D:
                if(ground)
                    next_state = WL;                    
                else
                    next_state = WL_D;     
            WR_D:
                if(ground)
                    next_state = WR;                    
                else
                    next_state = WR_D;                     
       endcase
    end


    //时序电路,状态转移
    always@(posedge clk,posedge areset)begin
        if(areset) 
            state <= WL;
        else
            state <= next_state;   
    end

    //向下跌的状态图        
    always@(posedge clk)
        if(!ground)
            aaah <= 1'b1;
        else
            aaah<=1'b0;

    assign walk_left = (state==WL);
    assign walk_right = (state==WR);

endmodule

3.2.5.12 Lemmings 3(Lemmings3)

In addition to walking and falling, Lemmings can sometimes be told to do useful things, like dig (it starts digging when dig=1). A Lemming can dig if it is currently walking on ground (ground=1 and not falling), and will continue digging until it reaches the other side (ground=0). At that point, since there is no ground, it will fall (aaah!), then continue walking in its original direction once it hits ground again. As with falling, being bumped while digging has no effect, and being told to dig when falling or when there is no ground is ignored. (In other words, a walking Lemming can fall, dig, or switch directions. If more than one of these conditions are satisfied, fall has higher precedence than dig, which has higher precedence than switching directions.)


module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output walk_left,
    output walk_right,
    output aaah,
    output digging ); 

    parameter LEFT   = 0,  RIGHT  = 1;
    parameter DIG_L  = 2,  DIG_R  = 3;
    parameter FALL_L = 4,  FALL_R = 5;

    reg [2:0] state,next_state; 


    //状态时序图,第一段
    always@(posedge clk,posedge areset)begin
        if(areset)
            state <= LEFT;
        else
            state <= next_state;
    end

    //next_state变化,第二段
    always@(*)begin
        case(state)
            LEFT:
                if(!ground)
                    next_state = FALL_L;
                else if(dig)
                    next_state = DIG_L;
                else if(bump_left)
                    next_state = RIGHT;
                else 
                    next_state = LEFT;
            RIGHT:
                if(!ground)
                    next_state = FALL_R;
                else if(dig)
                    next_state = DIG_R;
            else if(bump_right)
                    next_state = LEFT;
                else 
                    next_state = RIGHT;
            DIG_L:
                if(!ground)
                    next_state = FALL_L;
                else
                    next_state = DIG_L;
            DIG_R:
                if(!ground)
                    next_state = FALL_R;
                else
                    next_state = DIG_R;    
            FALL_L:
                if(ground)
                    next_state = LEFT;
                else
                    next_state = FALL_L;
            FALL_R:
                if(ground)
                    next_state = RIGHT;
                else
                    next_state = FALL_R;
        endcase    
    end

    //shuchu
    assign walk_left = (state == LEFT);
    assign walk_right = (state == RIGHT);
    assign aaah = ( state == FALL_L || state == FALL_R);
    assign digging = ( state==DIG_L || state == DIG_R);
endmodule

3.2.5.13 Lemmings 4(Lemmings4)

Although Lemmings can walk, fall, and dig, Lemmings aren't invulnerable. If a Lemming falls for too long then hits the ground, it can splatter. In particular, if a Lemming falls for more than 20 clock cycles then hits the ground, it will splatter and cease walking, falling, or digging (all 4 outputs become 0), forever (Or until the FSM gets reset). There is no upper limit on how far a Lemming can fall before hitting the ground. Lemmings only splatter when hitting the ground; they do not splatter in mid-air.


module top_module(
    input clk,
    input areset,    // Freshly brainwashed Lemmings walk left.
    input bump_left,
    input bump_right,
    input ground,
    input dig,
    output walk_left,
    output walk_right,
    output aaah,
    output digging ); 

    parameter LEFT=0, RIGHT=1, FALL_L=2, FALL_R=3, DIG_L=4, DIG_R=5, SPLAT=6;
    reg [2:0] state, next_state;
    reg [7:0] cnt_20;
    //State Transition Logic
    always@(*) begin
        case (state)
            LEFT  : next_state = ground ? (dig ? DIG_L:(bump_left  ? RIGHT:LEFT)):FALL_L;
            RIGHT : next_state = ground ? (dig ? DIG_R:(bump_right ? LEFT:RIGHT)):FALL_R;
            FALL_L: next_state = ground ? (cnt_20 > 5'd20 ? SPLAT:LEFT) :FALL_L;
            FALL_R: next_state = ground ? (cnt_20 > 5'd20 ? SPLAT:RIGHT):FALL_R;
            DIG_L : next_state = ground ? DIG_L:FALL_L;
            DIG_R : next_state = ground ? DIG_R:FALL_R;
            SPLAT : next_state = SPLAT;
            default ;
        endcase
    end
    //State Flip-flops
    always@(posedge clk, posedge areset) begin
        if (areset) state <= LEFT; //The only way to jump out of SPLAT
        else state <= next_state;
    end

    //Counter for falling period
    always@(posedge clk, posedge areset) begin
        if (areset) begin
            cnt_20 <= 5'd0;
        end
        else begin
            if (~ground) cnt_20 <= cnt_20+1'b1;
            else cnt_20 <= 5'd0;
        end
    end

    //四个输出
    assign walk_left  = (state == LEFT);
    assign walk_right = (state == RIGHT);
    assign aaah       = (state == FALL_L || state == FALL_R);
    assign digging    = (state == DIG_L || state == DIG_R);

endmodule

3.2.5.14 One-hot FSM(Fsm onehot)

Suppose this state machine uses one-hot encoding, where state[0] through state[9] correspond to the states S0 though S9, respectively. The outputs are zero unless otherwise specified.
//这是自己写的答案,可是没有success!
module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);

    parameter s0=10'b00_0000_0001;
    parameter s1=10'b00_0000_0010;
    parameter s2=10'b00_0000_0100;
    parameter s3=10'b00_0000_1000;
    parameter s4=10'b00_0001_0000;
    parameter s5=10'b00_0010_0000;
    parameter s6=10'b00_0100_0000;
    parameter s7=10'b00_1000_0000;
    parameter s8=10'b01_0000_0000;
    parameter s9=10'b10_0000_0000;


    always@(*)begin
        case(state)
            s0:next_state = in ? s1:s0;
            s1:next_state = in ? s2:s0;
            s2:next_state = in ? s3:s0;
            s3:next_state = in ? s4:s0;
            s4:next_state = in ? s5:s0;
            s5:next_state = in ? s6:s8;
            s6:next_state = in ? s7:s9;
            s7:next_state = in ? s7:s0;
            s8:next_state = in ? s1:s0;
            s9:next_state = in ? s1:s0;
            default:
                next_state = s0;
        endcase 
    end

    //输出
    assign out1 = state==s8||state==s9;
    assign out2 = state==s7||state==s9;

endmodule

推荐其他博文:HDLBits 系列(27)孰对孰错 之 Fsm onehot?

module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);

    assign next_state[0] = ~in & (state[0] | state[1] | state[2] | state[3] | state[4] | state[7] | state[8] | state[9]);
    assign next_state[1] = in & (state[0] | state[8] | state[9]);
    assign next_state[2] = in & state[1];
    assign next_state[3] = in & state[2];
    assign next_state[4] = in & state[3];
    assign next_state[5] = in & state[4];
    assign next_state[6] = in & state[5];
    assign next_state[7] = in & (state[6] | state[7]);
    assign next_state[8] = ~in & state[5];
    assign next_state[9] = ~in & state[6];

    assign out1 = state[8] | state[9];
    assign out2 = state[7] | state[9];

endmodule

3.2.5.15 PS/2 packet parser(Fsm ps2)

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //

    parameter  s1=0,s2=1,s3=2,s4=3;
    reg [2:0] state,next_state;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            s1:next_state=in[3]?s2:s1;
            s2:next_state=s3;
            s3:next_state=s4;
            s4:next_state=in[3]?s2:s1;
            default:next_state=s1;
        endcase
    end

    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset)
           state <= s1;
        else
           state <= next_state;
    end

    // Output logic
    assign done = state == s4;

endmodule

3.2.5.16 PS/2 packet parser and datapath(Fsm ps2data)

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output [23:0] out_bytes,
    output done); //

    // FSM from fsm_ps2
    parameter  s1=0,s2=1,s3=2,s4=3;
    reg [2:0] state,next_state;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            s1:next_state=in[3]?s2:s1;
            s2:next_state=s3;
            s3:next_state=s4;
            s4:next_state=in[3]?s2:s1;
            default:next_state=s1;
        endcase
    end

    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset)
           state <= s1;
        else
           state <= next_state;
    end
    assign done = state == s4;

    // New: Datapath to store incoming bytes.
    always@(posedge clk)begin
        case(state)
            s1:out_bytes[23:16]=in;
            s2:out_bytes[15:8]=in;
            s3:out_bytes[7:0]=in;
            s4:out_bytes[23:16]=in;//个人觉得这样写不妥,但是这样有success了
        endcase 
    end

endmodule

3.2.5.17 Serial receiver(Fsm serial)

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    parameter  idle=0,start=1,s1=2,s2=3,s3=4,s4=5,s5=6,s6=7,s7=8,s8=9,stop=10,pause=11;
    reg [3:0] state,next_state;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            idle:next_state=in?idle:start;
            start: next_state=s1;
            s1:next_state=s2;
            s2:next_state=s3;
            s3:next_state=s4;
            s4:next_state=s5;
            s5:next_state=s6;
            s6:next_state=s7;
            s7:next_state=s8;
            s8:next_state=in?stop:pause;
            stop:next_state=in?idle:start;
            pause:next_state=in?idle:pause;
            default:next_state=idle;
        endcase
    end

    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset)
           state <= idle;
        else
           state <= next_state;
    end
    assign done = state == stop;
endmodule

3.2.5.18 Serial receiver and datapath(Fsm serialdata)

  • 在上题的基础上加了数据输出!
module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //

    // Use FSM from Fsm_serial
    parameter  idle=0,start=1,s1=2,s2=3,s3=4,s4=5,s5=6,s6=7,s7=8,s8=9,stop=10,pause=11;
    reg [3:0] state,next_state;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            idle:next_state=in?idle:start;
            start: next_state=s1;
            s1:next_state=s2;
            s2:next_state=s3;
            s3:next_state=s4;
            s4:next_state=s5;
            s5:next_state=s6;
            s6:next_state=s7;
            s7:next_state=s8;
            s8:next_state=in?stop:pause;
            stop:next_state=in?idle:start;
            pause:next_state=in?idle:pause;
            default:next_state=idle;
        endcase
    end

    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset)
           state <= idle;
        else
           state <= next_state;
    end
    assign done = state == stop;
    // New: Datapath to latch input bits.
    always@(posedge clk)begin
        case(state)
            start:out_byte[0]<=in;
            s1:out_byte[1]<=in;
            s2:out_byte[2]<=in;
            s3:out_byte[3]<=in;
            s4:out_byte[4]<=in;
            s5:out_byte[5]<=in;
            s6:out_byte[6]<=in;
            s7:out_byte[7]<=in;
            default:;
        endcase   
    end
endmodule

3.2.5.19 Serial receiver with parity checking(Fsm serialdp)

You are provided with the following module that can be used to calculate the parity of the input stream (It's a TFF with reset). The intended use is that it should be given the input bit stream, and reset at appropriate times so it counts the number of 1 bits in each byte.
module parity (
    input clk,
    input reset,
    input in,
    output reg odd);

    always @(posedge clk)
        if (reset) odd <= 0;
        else if (in) odd <= ~odd;

endmodule

  • 好好品尝,这三个题是层层递进的,只需要在前一个的基础上稍加修改!
module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //

    // Modify FSM and datapath from Fsm_serialdata
     // Use FSM from Fsm_serial
    parameter  idle=0,start=1,s1=2,s2=3,s3=4,s4=5,s5=6,s6=7,s7=8,s8=9,stop=10,pause=11,parity=12;
    reg [3:0] state,next_state;
    reg [7:0] out_byte_reg;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            idle:next_state=in?idle:start;
            start: next_state=s1;
            s1:next_state=s2;
            s2:next_state=s3;
            s3:next_state=s4;
            s4:next_state=s5;
            s5:next_state=s6;
            s6:next_state=s7;
            s7:next_state=s8;
            s8:next_state=parity;
            parity:next_state=in?stop:pause;
            stop:next_state=in?idle:start;
            pause:next_state=in?idle:pause;
            default:next_state=idle;
        endcase
    end

    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset)
           state <= idle;
        else
           state <= next_state;
    end
    // New: Datapath to latch input bits.
    always@(posedge clk)begin
        case(state)
            start:out_byte_reg[0]<=in;
            s1:out_byte_reg[1]<=in;
            s2:out_byte_reg[2]<=in;
            s3:out_byte_reg[3]<=in;
            s4:out_byte_reg[4]<=in;
            s5:out_byte_reg[5]<=in;
            s6:out_byte_reg[6]<=in;
            s7:out_byte_reg[7]<=in;
            default:;
        endcase   
    end

    always@(posedge clk)begin
        if(reset) done <= 1'b0;
        else if(next_state == stop && odd)
            done <= 'b1;
        else  done <= 'b0;
    end   


    wire odd;
    always@(posedge clk)begin
        if(reset)
            out_byte<='d0;
        else if(next_state == stop && odd)
            out_byte <=out_byte_reg;
        else out_byte <= 'd0;
    end
    wire en;
    assign en = (reset || next_state == idle || next_state == start);
    // New: Add parity checking.
    parity u_parity(
        .clk        (clk        ),
        .reset      (en        ),
        .in         (in            ),
        .odd        (odd        )
    );
endmodule

3.2.5.20 Sequence recognition(Fsm hdlc)

module top_module(
    input clk,
    input reset,    // Synchronous reset
    input in,
    output disc,
    output flag,
    output err);

    parameter S1 = 4'd1, S2 = 4'd2, S3 = 4'd3, S4 = 4'd4, S5 = 4'd5;
    parameter S6 = 4'd6, S7 = 4'd7, DISC = 4'd8, ERR = 4'd9, FLAG = 4'd10;

    reg    [3:0]   state;
    reg [3:0]    next_state;

    always@(posedge clk)begin
        if(reset)begin
            state <= S1;
        end
        else begin
            state <= next_state;
        end
    end

    always@(*)begin
        case(state)
            S1:next_state = in ? S2 : S1;
            S2:next_state = in ? S3 : S1;
            S3:next_state = in ? S4 : S1;
            S4:next_state = in ? S5 : S1;
            S5:next_state = in ? S6 : S1;
            S6:next_state = in ? S7 : DISC;
            S7:next_state = in ? ERR : FLAG;
            DISC:next_state = in ? S2 : S1;
            FLAG:next_state = in ? S2 : S1;
            ERR:next_state = in ? ERR : S1;
            default:begin
                next_state = S1;
            end
        endcase
    end

    assign disc = (state == DISC);
    assign err = (state == ERR);
    assign flag = (state == FLAG);

endmodule

3.2.5.21 Q8: Design a Mealy FSM(Exams/ece241 2013 q8)

  • 检测101序列或者10101序列!
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_state;

    always@(posedge clk or negedge aresetn)begin
        if(!aresetn) state <= S0;
        else state <= next_state;
    end
    always@(*)begin
        case(state)
            S0:
                next_state=x?S1:S0;
            S1:
                next_state=x?S1:S2;
            S2:
                next_state=x?S1:S0;
        endcase
    end
    assign z=(state==S2)&&(x=='b1);

endmodule

//参考答案
module top_module (
    input clk,
    input aresetn,
    input x,
    output reg z
);

    // Give state names and assignments. I'm lazy, so I like to use decimal numbers.
    // It doesn't really matter what assignment is used, as long as they're unique.
    parameter S=0, S1=1, S10=2;
    reg[1:0] state, next;       // Make sure state and next are big enough to hold the state encodings.

    // Edge-triggered always block (DFFs) for state flip-flops. Asynchronous reset.         
    always@(posedge clk, negedge aresetn)
        if (!aresetn)
            state <= S;
        else
            state <= next;



    // Combinational always block for state transition logic. Given the current state and inputs,
    // what should be next state be?
    // Combinational always block: Use blocking assignments.    
    always@(*) begin
        case (state)
            S: next = x ? S1 : S;
            S1: next = x ? S1 : S10;
            S10: next = x ? S1 : S;
            default: next = 'x;
        endcase
    end

    // Combinational output logic. I used a combinational always block.
    // In a Mealy state machine, the output depends on the current state *and*
    // the inputs.
    always@(*) begin
        case (state)
            S: z = 0;
            S1: z = 0;
            S10: z = x;     // This is a Mealy state machine: The output can depend (combinational) on the input.
            default: z = 1'bx;
        endcase
    end

endmodule

3.2.5.22 Q5a: Serial two's complementer (Moore FSM)(Exams/ece241 2014 q5a)

//模仿上一篇作者答案的命名风格
module top_module (
    input clk,
    input areset,
    input x,
    output z
); 

    parameter S=0, S1=1, S10=2;
    reg    [1:0]   state;
    reg    [1:0]   next;

    always@(posedge clk or posedge areset)begin
        if(areset)
            state <= S;
        else 
            state <= next;
    end

    always@(*)begin
        case(state)
            S:
                next = x ? S1 : S;
            S1:
                next = x ? S10 : S1;
            S10:
                next = x ? S10 : S1;
            default:
                next = S;
        endcase
    end

    assign z = state == S1;

endmodule

3.2.5.23 Q5b: Serial two's complementer (Mealy FSM)(Exams/ece241 2014 q5b)

//在上一题的基础上进行了修改
module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    parameter S=0, S1=1;// S10=2;
    reg    [1:0]   state;
    reg    [1:0]   next;

    always@(posedge clk or posedge areset)begin
        if(areset)
            state <= S;
        else 
            state <= next;
    end

    always@(*)begin
        case(state)
            S:
                next = x ? S1 : S;
            S1:
                next = S1 ;
            default:
                next = S;
        endcase
    end

    assign z = (state == S && x==1)||(state == S1 && x==0);
endmodule

3.2.5.24 Q3a: FSM(Exams/2014 q3fsm)

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
    parameter A=1'b0,B=1'b1;
    reg state,next;

    always@(posedge clk)begin
        if(reset)
            state <= A;
        else
            state <= next;
    end

    always@(*)begin
        case(state)
            A:
                next=s?B:A;
            B:
                next=B;
            default:;
        endcase 
    end

    //采集数据连续的3bit数据,如果加起来=2,则在下一拍将z置位1  
    reg [1:0] cnt_3;
    always@(posedge clk)begin
        if(state == B)begin
            if(cnt_3 == 'd2)begin
                cnt_3 <= 2'd0;
            end
            else begin
               cnt_3 <= cnt_3 + 2'b1;
            end
        end 
        else 
            cnt_3 <= 2'd0;
    end

    reg [1:0] reg_W=2'b00;
    always@(*)begin
        if(cnt_3 == 0)begin
           reg_W =  w;
        end 
        else reg_W = reg_W + w;
   end 
    //输出z
    assign z = reg_W == 2'b10;
endmodule


推荐参考代码


module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
parameter a = 1'b0, b = 1'b1;
    reg state , next_state;

    always @(posedge clk)
        if(reset)
            state <= a;
        else
            state <= next_state;

    always @(*)
        case(state)
            a: next_state = s ? b : a;
            b: next_state = b;
            default : next_state = a;
        endcase

    reg [1:0] counter;
    always @(posedge clk)
        if(reset)
            counter <= 0;
    else if(counter == 2'd2)
        counter <= 0;
    else if(state == b)
        counter <= counter + 1;

    reg [1:0] exact2;
    always @(posedge clk)
        if(reset)
            exact2 <= 0;
    else if(counter == 2'd0 && w == 0)
        exact2 <= 0;
    else if(counter == 2'd0 && w==1)
        exact2 <= 1;
    else if(w == 1 && state == b)
        exact2 <= exact2 + 1;

    assign z = (state == b && exact2 == 2 && counter == 0);
endmodule

3.2.5.25 Q3b: FSMExams/2014 q3bfsm)

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] state,next;

    always@(posedge clk)begin
        if(reset)state <= S0;
        else state <=next;
    end

    always@(*)begin
        case(state)
            S0:next=x?S1:S0;
            S1:next=x?S4:S1;
            S2:next=x?S1:S2;
            S3:next=x?S2:S1;
            S4:next=x?S4:S3;
            default:next=S0;            
        endcase
    end

    assign z=state==S3||state==S4;
endmodule

3.2.5.26 Q3c: FSM logic(Exams/2014 q3c)

module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    parameter S0=3'b000,S1=3'b001,S2=3'b010,S3=3'b011,S4=3'b100;
    reg [2:0] state,next;


    always@(negedge clk)begin//在上题的基础上修改的,这部分没什么用!
         state <=next;
    end

    always@(*)begin
        case(y)
            S0:next=x?S1:S0;
            S1:next=x?S4:S1;
            S2:next=x?S1:S2;
            S3:next=x?S2:S1;
            S4:next=x?S4:S3;
            default:next=S0;            
        endcase
    end

    assign z=y==S3||y==S4;
    assign Y0=next[0];
endmodule

3.2.5.27 Q6b: FSM next-state logic(Exams/m2014 q6b)

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

    parameter A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100,F=3'b101;
    reg [2:0] next;

    always@(*)begin
        case(y[3:1]) 
            A:next=w?A:B;
            B:next=w?D:C;
            C:next=w?D:E;
            D:next=w?A:F;
            E:next=w?D:E;
            F:next=w?D:C;
            default:;
        endcase
    end
    assign Y2= next[1];//和上一题类似
    //assign Y2= next==C||next==D;   
endmodule

3.2.5.28 Q6c: FSM one-hot next-state logic(Exams/m2014 q6c)

For this part, assume that a one-hot code is used with the state assignment 'y[6:1] = 000001, 000010, 000100, 001000, 010000, 100000 for states A, B,…, F, respectively. Write a logic expression for the next-state signals Y2 and Y4. (Derive the logic equations by inspection assuming a one-hot encoding. The testbench will test with non-one hot inputs to make sure you're not trying to do something more complicated).
//我的答案,是错的!
module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);
    //parameter A=3'b000,B=3'b001,C=3'b010,D=3'b011,E=3'b100,F=3'b101;
    parameter A=6'b000001;
    parameter B=6'b000010;
    parameter C=6'b000100;
    parameter D=6'b001000;
    parameter E=6'b010000;
    parameter F=6'b100000;

    reg [5:0] next;

    always@(*)begin
        case(y[6:1]) 
            A:next=w?A:B;
            B:next=w?D:C;
            C:next=w?D:E;
            D:next=w?A:F;
            E:next=w?D:E;
            F:next=w?D:C;
            default:;
        endcase
    end
    assign Y2 = next[1]&&(~w),Y4 = next[3] &&  w;//和上一题类似
    //assign Y2 = next==B,Y4=next==D;

endmodule


//别人的答案,是对的
module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);

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

3.2.5.29 Q6: FSM(Exams/m2014 q6)

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

    parameter A=6'b000001;
    parameter B=6'b000010;
    parameter C=6'b000100;
    parameter D=6'b001000;
    parameter E=6'b010000;
    parameter F=6'b100000;

    reg [5:0] state,next;

      always@(posedge clk)begin
        if(reset)state <= A;
        else state <=next;
    end

    always@(*)begin
        case(state) 
            A:next=w?A:B;
            B:next=w?D:C;
            C:next=w?D:E;
            D:next=w?A:F;
            E:next=w?D:E;
            F:next=w?D:C;
            default:next=A;
        endcase
    end
    assign z = state==E|state==F;//在上题的基础上

endmodule

3.2.5.30 Q2a: FSM(Exams/2012 q2fsm)

Write complete Verilog code that represents this FSM. Use separate always blocks for the state table and the state flip-flops, as done in lectures. Describe the FSM output, which is called z, using either continuous assignment statement(s) or an always block (at your discretion). Assign any state codes that you wish to use.
  • 在上一题的基础上,将w改为~w即可!(自己改完才发现)
module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    input w,
    output z
);
    parameter A=6'b000001;
    parameter B=6'b000010;
    parameter C=6'b000100;
    parameter D=6'b001000;
    parameter E=6'b010000;
    parameter F=6'b100000;

    reg [5:0] state,next;

      always@(posedge clk)begin
        if(reset)state <= A;
        else state <=next;
    end

    always@(*)begin//在上一题的基础上,将w改为~w即可!
        case(state) 
            A:next=w?B:A;
            B:next=w?C:D;
            C:next=w?E:D;
            D:next=w?F:A;
            E:next=w?E:D;
            F:next=w?C:D;
            default:next=A;
        endcase
    end
    assign z = state==E|state==F;//在上题的基础上

endmodule

3.2.5.31 Q2b: One-hot FSM equations(Exams/2012 q2b)

  • 借用前面的思维,这里一次做对了!
module top_module (
    input [5:0] y,
    input w,
    output Y1,
    output Y3
);
    assign Y1 = y[0] && w;//表示状态B
    assign Y3 = ~w && (y[1] | y[2]| y[4] | y[5] );//表示状态D

endmodule

3.2.5.32 Q2a: FSM(Exams/2013 q2afsm)

module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input [3:1] r,   // request
    output [3:1] g   // grant
); 
    parameter A=2'b00,B=2'b01,C=2'b10,D=2'b11;
    reg [1:0] state,next;

    always@(posedge clk)begin
        if(!resetn) state <= A;
        else state <= next;
    end

    always@(*)begin
        case(state)
            A:
                if(r==3'b000)     
                    next =A;
                else if(r[1]==1)    
                    next=B;
                else if(r[1]==0 && r[2]==1)
                    next=C;
                else if (r[1]==0 && r[2]==0 && r[3]==1)
                    next=D;
                else
                    next = A;
            B:
                if(r[1]==0)
                    next=A;
                else  
                    next = B;
            C:
                if(r[2]==0)
                    next=A;
                else 
                    next=C;
            D:
                if(r[3]==0)
                    next=A;
                else 
                    next=D;

            default:;
        endcase
    end
    always@(*)begin
        g[1]=state==B;
        g[2]=state==C;
        g[3]=state==D;
    end
endmodule

3.2.5.33 Q2b: Another FSM(Exams/2013 q2bfsm)

The FSM has to work as follows. As long as the reset input is asserted, the FSM stays in a beginning state, called state A. When the reset signal is de-asserted, then after the next clock edge the FSM has to set the output f to 1 for one clock cycle. Then, the FSM has to monitor the x input. When x has produced the values 1, 0, 1 in three successive clock cycles, then g should be set to 1 on the following clock cycle. While maintaining g = 1 the FSM has to monitor the y input. If y has the value 1 within at most two clock cycles, then the FSM should maintain g = 1 permanently (that is, until reset). But if y does not become 1 within two clock cycles, then the FSM should set g = 0 permanently (until reset).
module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input x,
    input y,
    output f,
    output g
); 
    parameter A = 4'd0, S1 = 4'd1, S2 = 4'd2, S3 = 4'd3, S4 = 4'd4;
    parameter S5 = 4'd5, FOREVER_ONE = 4'd6, FOREVER_ZERO = 4'd7;
    parameter F_OUT = 4'd8;

    reg    [3:0]   state;
    reg    [3:0]   next;

    always@(posedge clk)begin
        if(resetn == 1'b0)begin
            state <= A;
        end
        else begin
            state <= next;
        end
    end

    always@(*)begin
        case(state)
            A:begin
                next = F_OUT;
            end
            F_OUT:begin
                next = S1;
            end
            S1:begin
                next = x ? S2 : S1;
            end
            S2:begin
                next = x ? S2 : S3;
            end
            S3:begin
                next = x ? S4 : S1;
            end  
            S4:begin
                next = y ? FOREVER_ONE : S5;
            end
            S5:begin
                next = y ? FOREVER_ONE : FOREVER_ZERO;
            end
            FOREVER_ONE:begin
                next = FOREVER_ONE;
            end
            FOREVER_ZERO:begin
                next = FOREVER_ZERO;
            end
            default:begin
                next = A;
            end
        endcase
    end

    assign f = (state == F_OUT);
    assign g = (state == S4 || state == S5 || state == FOREVER_ONE);
endmodule

沒有留言:

張貼留言

WOKWI DHT22 & LED , Node-Red + SQLite database

 WOKWI DHT22 & LED , Node-Red + SQLite database Node-Red程式 [{"id":"6f0240353e534bbd","type":"comment&...