https://hdlbits.01xz.net/wiki/FSM答案

1.Simple FSM

module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output out);//  

    parameter A=1'b0, B=1'b1; 
    reg state, next_state;

    always @(state or in) begin    // This is a combinational always block
        // State transition logic
        case({{state},{in}})
            2'b00 : next_state = B;
            2'b01 : next_state = A;
            2'b10 : next_state = A;
            2'b11 : next_state = B;
            default:;
        endcase
    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 == A) ? 1'b0 : 1'b1;

endmodule

这类似一个T触发器。是摩尔型FSM。还有一点就是这是个两段式的FSM,时序部分和组合部分做了分离。
摩尔型:输出只与状态有关。
米莉型:输出与状态和输入有关。
2.FSM1s

// 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
    parameter A = 1'b0, B = 1'b1;

    reg present_state, next_state;

    always @(posedge clk) begin
        if (reset) begin  
            // Fill in reset logic
            present_state = B;
        end else begin
            case (present_state)
                // Fill in state transition logic
                A: begin if(in) next_state = A; else next_state = B;end
                B: begin if(in) next_state = B; else next_state = A;end 
				default:;                
            endcase
            // State flip-flops
            present_state = next_state;
        end
            case (present_state)
                // Fill in output logic
                A: out <= 1'b0;
                B: out <= 1'b1;
                default:;
            endcase
    end
endmodule

我这里把题目给的结构稍微改了一下,因为他的输出部分是包含在状态转换中的,所以reset就没有输出了。我就将他放在else的end后面去了。
在这里时序部分中使用了阻塞赋值,这是不推荐的,但是以及写的语句里用了所以也没办法了。
3.FSM2

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

    parameter OFF=1'b0, ON=1'b1; 
    reg state, next_state;

    always @(state or j or k) begin
        // State transition logic
        casex({{state},{j},{k}})
            3'b00x: next_state = OFF;
            3'b01x: next_state = ON;
            3'b1x0: next_state = ON;
            3'b1x1: next_state = OFF;
            default:;
        endcase
    end

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

    // Output logic
    // assign out = (state == ...);
    assign out = (state == ON) ? 1'b1 : 1'b0;
endmodule

4.FSM2s

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

    parameter OFF=1'b0, ON=1'b1; 
    reg state, next_state;

    always @(state or j or k) begin
        // State transition logic
        casex({{state},{j},{k}})
               3'b00x: next_state <= OFF;
               3'b01x: next_state <= ON;
               3'b1x0: next_state <= ON;
               3'b1x1: next_state <= OFF;
               default:;
        endcase
    end

    always @(posedge clk) begin
        // State flip-flops with synchronous reset
        if(reset)
            state <= OFF;
        else
            state <= next_state;
    end
    // Output logic
    // assign out = (state == ...);
    assign out = (state == OFF)? 1'b0 : 1'b1;
endmodule

5.Fsm3Combo

module top_module(
    input in,
    input [1:0] state,
    output [1:0] next_state,
    output out); //

    parameter A=2'b0, B=2'b1, C=2'b10, D=2'b11;

    // State transition logic: next_state = f(state, in)
    always@(state or in)
        begin
            case({{state},{in}})
                3'b000: next_state = A;
                3'b001: next_state = B;
                3'b010: next_state = C;
                3'b011: next_state = B;
                3'b100: next_state = A;
                3'b101: next_state = D;
                3'b110: next_state = C;
                3'b111: next_state = B;
                default:;
            endcase
        end
    // Output logic:  out = f(state) for a Moore state machine
    assign out = (state == D)? 1'b1: 1'b0;
endmodule

6.FSM3onehot

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] = (~in) & (state[A]|state[C]);
    assign next_state[B] = in & (state[A]|state[B]|state[D]);
    assign next_state[C] = (~in) & (state[B]|state[D]);
    assign next_state[D] = in & state[C];

    // Output logic: 
    assign out = (state[D])? 1'b1:1'b0;

endmodule

这是onehot的方法。各用一位表示状态使得读取状态更简单。
7.FSM3 ASY

module top_module(
    input clk,
    input in,
    input areset,
    output out); //
    parameter A=2'b00, B=2'b01, C=2'b10, D=2'b11;
    
    reg[1:0] state;
    reg[1:0] next_state;
    // State transition logic
    always@(in or state)
        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;
                default:;
            endcase
        end
    // State flip-flops with asynchronous reset
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                state <= A;
            else
                state <= next_state;
        end
    // Output logic
    assign out = (state==D)? 1'b1:1'b0;
endmodule

8.FSM SYN

module top_module(
    input clk,
    input in,
    input reset,
    output out); //
	parameter A=2'b00, B=2'b01, C=2'b10, D=2'b11;
    reg[1:0] state;
    reg[1:0] next_state;
    // State transition logic
    always@(state or in)
        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;
                default:;
            endcase
        end
    // State flip-flops with synchronous reset
    always@(posedge clk)
        begin
            if(reset)
                state <= A;
            else
                state <= next_state;
        end
    // Output logic
    assign out = (state==D)? 1'b1:1'b0;
endmodule

9.Design a MOORE FSM

module top_module (
    input clk,
    input reset,
    input [3:1] s,
    output fr3,
    output fr2,
    output fr1,
    output dfr
); 
    parameter A=2'b00, B=2'b01, C=2'b10, D=2'b11;
    reg[1:0] state;
    reg[1:0] next_state;
    reg L;
    
    always@(s or state)
        begin
            case(state)
                A: next_state = (s[1])? B: A;
                B: next_state = (s[2])? C: ((s[1])? B: A);
                C: next_state = (s[3])? D: ((s[2])? C: B);
                D: next_state = (s[3])? D: C;
                default:;
            endcase
        end
    always@(posedge clk)
        begin
            if(reset)
                begin
                    state <= A;
                    L <= 1'b1;
                end
            else
                begin
                    if(next_state < state)
                        L <= 1'b1;
                    else if(L && (next_state == state))//我漏了这一句因而debug了很长时间,这里类似jk等于则保持原有的零或一
                        L <= 1'b1;
                    else 
                        L <= 1'b0;
                    state <= next_state;                    
                end
        end
    
    always@(state or L)
        begin
            case(state)
                A: {{fr1},{fr2},{fr3}} = 3'b111; 
                B: {{fr1},{fr2},{fr3}} = 3'b110;
                C: {{fr1},{fr2},{fr3}} = 3'b100;
                D: {{fr1},{fr2},{fr3}} = 3'b000;
                default:;
            endcase
            
            if(L)
                dfr = 1'b1;
            else
                dfr = 1'b0;
        end
endmodule

这一题完全是自己设计状态机,非常有难度。
标准解将我这里的L也设计入状态里了,这要科学多了,我单独设置了L因而在时序上一度出现很大的问题。漏了注释中那一句。这样设置写case看起来简单点,但是时序分析的难度极大地提升了。
建议大家还是按照标准解的方法做一遍。
10.Lemming1

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 = 1'b0, RIGHT = 1'b1;
    // parameter LEFT=0, RIGHT=1, ...
    reg state, next_state;
    always @(bump_left or bump_right or state) begin
        // State transition logic
        case(state)
            LEFT:  next_state = (bump_left)? RIGHT: LEFT;
            RIGHT: next_state = (bump_right)?LEFT: RIGHT; 
            default:;
        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 == ...);
    // assign walk_right = (state == ...);
    assign walk_left =  (state==LEFT)? 1'b1: 1'b0;
    assign walk_right = (state==RIGHT)? 1'b1:1'b0;

endmodule

11.Lemming2

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 ); 
    parameter LEFT = 2'b00, LEFT_FALL = 2'b01, RIGHT = 2'b10, RIGHT_FALL = 2'b11;
    reg[1:0] state;
    reg[1:0] next_state;
    always@(state or bump_left or bump_right or ground)
        begin
            case(state)
                LEFT:	   next_state = (ground)? ((bump_left)? RIGHT: LEFT): LEFT_FALL;
                LEFT_FALL: next_state = (ground)? LEFT : LEFT_FALL;
                RIGHT:     next_state = (ground)? ((bump_right)? LEFT: RIGHT): RIGHT_FALL;
                RIGHT_FALL:next_state = (ground)? RIGHT: RIGHT_FALL;
                default:;
            endcase
        end
    always@(posedge clk or posedge areset)
        begin
        if(areset)
            state <= LEFT;
    	else
            state <= next_state;
        end
    assign walk_left = (state==LEFT)? 1'b1: 1'b0;
    assign walk_right = (state==RIGHT)? 1'b1: 1'b0;
    assign aaah = ((state==LEFT_FALL) || (state==RIGHT_FALL))? 1'b1:1'b0;
endmodule

12.lemming3

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_WALK = 3'd0, LEFT_FALL = 3'd1, LEFT_DIG = 3'd2, 
    		  RIGHT_WALK = 3'd3, RIGHT_FALL = 3'd4, RIGHT_DIG = 3'd5;
    reg[2:0] state;
    reg[2:0] next_state;
    
    always@(state or bump_left or bump_right or ground or dig)
        begin
            case(state)
                LEFT_WALK : next_state = (ground)? ((dig)? LEFT_DIG : (bump_left)? RIGHT_WALK: LEFT_WALK): LEFT_FALL;
                LEFT_FALL : next_state = (ground)? LEFT_WALK : LEFT_FALL;
                LEFT_DIG  : next_state = (ground)? LEFT_DIG : LEFT_FALL;
                RIGHT_WALK: next_state = (ground)? ((dig)? RIGHT_DIG: (bump_right)? LEFT_WALK: RIGHT_WALK): RIGHT_FALL;
                RIGHT_FALL: next_state = (ground)? RIGHT_WALK : RIGHT_FALL;
                RIGHT_DIG : next_state = (ground)? RIGHT_DIG : RIGHT_FALL;
                default:;
            endcase
        end
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                state <= LEFT_WALK;
            else
                state <= next_state;
        end
    assign walk_left  = (state==LEFT_WALK)? 1'b1: 1'b0;
    assign walk_right = (state==RIGHT_WALK)? 1'b1: 1'b0;
    assign aaah       = ((state==LEFT_FALL)||(state==RIGHT_FALL))? 1'b1: 1'b0;
    assign digging    = ((state==LEFT_DIG)||(state==RIGHT_DIG))? 1'b1: 1'b0;
endmodule

要注意的是这里dig一旦开始就不会停止。
13.lemming4

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_WALK = 3'd0, LEFT_FALL = 3'd1, LEFT_DIG = 3'd2,
    	  	  RIGHT_WALK= 3'd3, RIGHT_FALL = 3'd4, RIGHT_DIG = 3'd5, SPLATTER = 3'd6;
    reg[2:0] state;
    reg[2:0] next_state;
    integer fall_time;
    always@(state or bump_left or bump_right or ground or dig)
        begin
            case(state)
                LEFT_WALK : next_state = (ground)? ((dig)? LEFT_DIG : ((bump_left)? RIGHT_WALK : LEFT_WALK)): LEFT_FALL;
                LEFT_DIG  : next_state = (ground)? LEFT_DIG : LEFT_FALL;
                LEFT_FALL : next_state = (ground)? (LEFT_WALK): LEFT_FALL;
                RIGHT_WALK: next_state = (ground)? ((dig)? RIGHT_DIG : ((bump_right)? LEFT_WALK : RIGHT_WALK)): RIGHT_FALL;
                RIGHT_DIG : next_state = (ground)? RIGHT_DIG : RIGHT_FALL;
                RIGHT_FALL: next_state = (ground)? (RIGHT_WALK): RIGHT_FALL;
                SPLATTER:   next_state = SPLATTER;
                //死亡是不宜用状态转移去写,会多出很多不必要的信号。
                default:;
            endcase
        end
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                begin
                    state <= LEFT_WALK;
                    fall_time <= 0;
                end
            else
                begin
                    if((state==LEFT_FALL)||(state==RIGHT_FALL))
                        //这里的判断则必须根据当前状况。如果用下一状况,死亡必然是落地时发生,这里就永远不会死了因为time被清零
                        fall_time <= fall_time + 1;
                    else
                        fall_time <= 0;
                    if(fall_time >= 20 && ((next_state==LEFT_WALK)||(next_state==RIGHT_WALK)))
                        //等于二十是因为,当state变为fall的时候这个时候实际上已经过了一个周期了。这一点波形图可以很好反映出来
                        state <= SPLATTER;
                    else
                        state <= next_state;
                end
        end
    assign walk_left  = (state==LEFT_WALK)? 1'b1: 1'b0;
    assign walk_right = (state==RIGHT_WALK)? 1'b1:1'b0;
    assign aaah       = ((state==LEFT_FALL)||(state==RIGHT_FALL))? 1'b1: 1'b0;
    assign digging    = ((state==LEFT_DIG)||(state==RIGHT_DIG))? 1'b1: 1'b0;
endmodule

这一题较为综合,需要仔细琢磨。
14.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]) ? 1'b1: 1'b0;
    assign out2 = (state[7]|state[9]) ? 1'b1: 1'b0;
endmodule

这个题目我试图用case或者干脆if去写都不成功。
15.PS/2 packet parser

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
    parameter BYTE1 = 2'b01, BYTE2 = 2'b10, BYTE3 = 2'b11, IDLE = 2'b00;
    reg[1:0] state;
    reg[1:0] next_state;
    // State transition logic (combinational)
    always@(state or in)
        begin
            case(state)
                BYTE1: next_state = BYTE2;
                BYTE2: next_state = BYTE3;
                BYTE3: next_state = (in[3])? BYTE1: IDLE;
                IDLE:  next_state = (in[3])? BYTE1: IDLE;
                default:;
            endcase
        end
    // State flip-flops (sequential)
    always@(posedge clk)
        begin
            if(reset)
               state <= IDLE;
            else
               state <= next_state;
        end
    // Output logic
    assign done = (state==BYTE3)? 1'b1:1'b0;
endmodule

16.serial reciever

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output [23:0] out_bytes,
    output done); 
    parameter BYTE1 = 2'b01, BYTE2 = 2'b10, BYTE3 = 2'b11, IDLE = 2'b00;
    reg[1:0] state;
    reg[1:0] next_state;
    reg[7:0] storage[3:1];
    // State transition logic (combinational)
    always@(state or in)
        begin
            case(state)
                BYTE1: next_state = BYTE2;
                BYTE2: next_state = BYTE3;
                BYTE3: next_state = (in[3])? BYTE1: IDLE;
                IDLE:  next_state = (in[3])? BYTE1: IDLE;
                default:;
            endcase
        end
    // State flip-flops (sequential)
    always@(posedge clk)
        begin
            if(reset)
               state <= IDLE;
            else
               state <= next_state;
        end
    always@(posedge clk)
        begin    
            storage[next_state] <= in;
        end
    // Output logic
    assign done = (state==BYTE3)? 1'b1:1'b0;
    assign out_bytes = (done)? ({{storage[1]},{storage[2]},{storage[3]}}): 24'b0;
endmodule

注意这里的存储必然是同步的,而且必须通过ns来判断。
16.

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    parameter IDLE = 2'b00, START = 2'b01, TRANS = 2'b10,STOP = 2'b11;
    integer count;
    reg[1:0] state;
    reg[1:0] next_state;
    
    always@(state or in or count)
        begin
            case(state)
                IDLE:  next_state = (~in)? START: IDLE;
                START: next_state = TRANS;
                TRANS: next_state = (in && count>7)? ((count==8)? STOP : IDLE): TRANS;
                STOP : next_state = (in)? IDLE : START;
                default:;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state <= IDLE;
            else
                begin 
                    if(next_state == TRANS)
                        count <= count + 1;
                    else if(next_state == START)
                        count <= 0;
                    else
                        count <= count;
                    state <= next_state;
                end
        end
    assign done = (state==STOP)? 1'b1 : 1'b0;
endmodule

注意分析时序。
17.Serial reciever

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //
    parameter IDLE = 2'b00, START = 2'b01, TRANS = 2'b10, STOP = 2'b11;
    reg[1:0] state;
    reg[1:0] next_state;
    reg[7:0] mem;
    integer count;
    // Use FSM from Fsm_serial
    always@(state or in or count)
        begin
            case(state)
                IDLE:  next_state = (~in)? START: IDLE;
                START: next_state = TRANS;
                TRANS: next_state = (in && count>7)? ((count==8)? STOP : IDLE): TRANS;
                STOP : next_state = (in)? IDLE : START;
                default:;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state <= IDLE;
            else
                begin 
                    if(next_state == TRANS)
                        	count <= count + 1;
                    else if(next_state == START)
                        	count <= 0;
                    else
                        count <= count;
                    state <= next_state;
                end
        end
    // New: Datapath to latch input bits.
    always@(posedge clk)
        begin
            if(reset)
                mem <= 8'b0;
            else
                begin
                    if(next_state==TRANS)//因为实际上数据是需要时间建立的,所以时序上对应的实际上是下一个周期的上升沿
                        mem[count] <= in; 
                end
        end
    assign done = (state==STOP)? 1'b1:1'b0;
    assign out_byte = (done)? mem: 8'b0;
endmodule

还是时序很容易出问题,然后是关于存储实际上早来的再低位,晚来的在高位。
这个FSM的时序设计不是很好,接下来的题目再做进一步改进。
18.Serial Reciever with Parity Checking

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output reg [7:0] out_byte,
    output reg done
); //
    parameter IDLE = 3'd0, START = 3'd1, TRANS = 3'd2, STOP = 3'd3, JUDGE = 3'd4, WAIT = 3'd5;
    reg[2:0] state;
    reg[2:0] next_state;
    reg odd;
    reg[3:0] count;
    reg[7:0] mem;
    wire reset1;

    always@(state or in or count)
        begin
            case(state)
                IDLE :   next_state = (~in)? START: IDLE;
                START:   next_state = TRANS;
                TRANS:   next_state = (count==4'd8)? JUDGE : TRANS;
                WAIT:    next_state = (in)? IDLE: WAIT;
                JUDGE:   next_state = (in)? STOP: WAIT; 
                STOP :   next_state = (~in)? START: IDLE;
                default: next_state = IDLE;
            endcase
        end

    always@(posedge clk)
        begin
            if(reset)
                state <= IDLE;
            else
                state <= next_state;
        end
    
    // Modify FSM and datapath from Fsm_serialdata    
    always@(posedge clk)
        begin
            if(reset)
                begin
                    out_byte <= 8'b0;
                    done <= 1'b0;
                end
            else
            begin
            case(next_state)
                TRANS:
                    begin
                        mem[count] <= in;                        
                        count <= count + 4'd1;
                        done  <= 1'b0;
                        out_byte <= 8'b0;
                    end
                STOP:
                    begin
                        count <= 4'd0;
                        done <= odd;
                        out_byte <= (odd)? mem: 8'b0; 
                    end
                default:
                    begin
                        count <= 4'd0;
                        done <= 1'b0;
                        out_byte <= 8'b0;
                    end
            endcase
            end
        end
    // New: Add parity checking.    
    assign reset1 = (next_state==START||reset==1'b1)? 1'b1:1'b0;
    parity P1(clk, reset1, in, odd);
endmodule

这一题我debug了十几个小时,开始感觉是时序上有点问题,然后直接画了个波形图对着分析,没想到居然是前面的状态转移出了bug,后面的输出反而一直是对的。
总之看到SUCCESS时实在是禁不住流下了感动的泪水。如果再耗下去真是人要没了,饭也不香,觉也难眠。
19.Sequence Recognition

    always@(posedge clk)
        begin
            if(reset)
                state <= START;
            else
                state <= next_state;
        end
    
    always@(posedge clk)
        begin
            if(reset)
                begin
                    flag <= 1'b0;
                    disc <= 1'b0;
                    err  <= 1'b0;
                    count<= 3'b0;
                end
            else
                begin
                    case(next_state)
                        ERROR: begin
                            count<= 3'b0;
                            flag <= 1'b0;
                            disc <= 1'b0;
                            err  <= 1'b1;
                        end
                        START: begin
                            count <= 3'b0;
                            if(count==6)
                                begin
                                	flag <= 1'b1;
                                    disc <= 1'b0;
                                    err  <= 1'b0;
                                end
                            else if(count==5)
                                begin
                                	flag <= 1'b0;
                                    disc <= 1'b1;
                                    err  <= 1'b0;                                    
                                end
                            else
                                begin
                                	flag <= 1'b0;
                                    disc <= 1'b0;
                                    err  <= 1'b0;                                     
                                end
                        end
                        JUDGE: begin
                            count <= count + 3'b1;
                            flag  <= 1'b0;
                            disc  <= 1'b0;
                            err   <= 1'b0;
                        end
                        default: begin
                            count<= 3'b0;
                            flag <= 1'b0;
                            disc <= 1'b0;
                            err  <= 1'b0;
                        end                            
                    endcase
                end
        end
endmodule

20.Design a merely FSM

module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z ); 
	parameter CHECK1 = 2'b00, CHECK0 = 2'b01, CHECK2 = 2'b11;
    reg[1:0] state;
    reg[1:0] next_state;
    reg[2:0] mem;
    
    always@(state or x)
        begin
            case(state)
                CHECK1: next_state = (x)? CHECK0 : CHECK1;
                CHECK0: next_state = (x)? CHECK0 : CHECK2;
                CHECK2: next_state = (x)? CHECK0 : CHECK1;
                default: next_state = CHECK1;
            endcase
        end
    
    always@(posedge clk or negedge aresetn)
        begin
            if(~aresetn)
                state <= CHECK1;
            else
                state <= next_state;
        end
    
    always@(*)
        begin
            if(~aresetn)
                z <= 1'b0;
            else
                begin
                    if(state == CHECK2)
                        z <= x;
                    else
                        z <= 1'b0;
                end
        end
endmodule

这里要注意输出只能是异步的,准确的说是MEALY型实际上我觉得波形图有点问题,怎么样说信号也应该稍微滞后于最后一个1到达的地方。
状态并不复杂,注意设置合理的状态也很重要。
21.Serial 2's complement MOORE

module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
	parameter IDLE = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
    reg[1:0] state;
    reg[1:0] next_state;
    
    always@(state or x)
        begin
            case(state)
            	IDLE: next_state = (x)? S2 : S1;
            	S1:   next_state = (x)? S2 : S1;
            	S2:   next_state = (x)? S3 : S2;
            	S3:   next_state = (x)? S3 : S2;
            	default: next_state = IDLE;
            endcase
        end
    
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                state <= IDLE;
            else
                state <= next_state;
        end
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                z <= 1'b0;
            else
                begin
                    case(next_state)
                        S1: z <= 1'b0;
                        S2: z <= 1'b1;
                        S3: z <= 1'b0;
                        default: z <= 1'bz;
                    endcase
                end
        end
endmodule

这个的输出是同步的(摩尔型)。
19.Serial 2's complement MEALY

module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
	parameter A = 1'b0, B = 1'b1;
    reg state;
    reg next_state;
    
    always@(state or x)
        begin
            case(state)
                A: next_state = (x)? B:A;
                B: next_state = B;
                default: next_state = A;
            endcase
        end
    
    always@(posedge clk or posedge areset)
        begin
            if(areset)
                state <= A;
            else
                state <= next_state;
        end
    
    always@(*)
        begin
            case(state)
                A: z = x;
                B: z = ~x;
                default z = 1'b0;
            endcase                
        end
endmodule

在输出上不能加areset信号,因为此时还有最后一位要输出。reset后自然之后的输出都会变化的。因为reset是异步置位的。
22.Q3a

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
	parameter A = 1'b0, B = 1'b1;
    reg state;
    reg next_state;
    reg[1:0] count;
    reg[1:0] count_w;
    always@(*)
        begin
            case(state)
                A: next_state = (s)? B: A;
                B: next_state = B;
                default: next_state = A;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state <= A;
            else
                state <= next_state;
        end
    
    always@(posedge clk)
        begin
            if(reset)
                begin
                	z <= 1'b0;
                    count <= 2'b1;
                    count_w <= 2'b0;
                end
            else
                begin                    
                    if(state == B)
                        begin
                            if(count==3)
                                begin 
                                    if(w)
                                        count_w = count_w + 1'b;
                                    z <= (count_w==2)? 1'b1 : 1'b0;
                                    count   <= 2'b1;
                                    count_w <= 2'b0;
                                end
                            else
                                begin
                                    if(w)
                                        count_w = count_w + 1'b;
                                    z <= 1'b0;
                                    count <= count + 2'b1;
                                end
                        end
                end
        end
endmodule

从时序上分析这里的count_w必须使用阻塞,在边沿触发中使用阻塞,是不推荐的。
23.Q3b FSM

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;
    reg[2:0] next_state;
    always@(*)
        begin
            case(state)
                S0: next_state = (~x)? S0 : S1;
                S1: next_state = (~x)? S1 : S4;
                S2: next_state = (~x)? S2 : S1;
                S3: next_state = (~x)? S1 : S2;
                S4: next_state = (~x)? S3 : S4;
                default: next_state = S0;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state <= S0;
            else
                state <= next_state;
        end
    
    always@(posedge clk)
        begin
            if(reset)
                z = 1'b0;
            else
                z = (next_state==S3 || next_state==S4)? 1'b1: 1'b0;
        end
endmodule

24.FSM logic

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] next_state;
    always@(*)
        begin
            case(y)
                S0: next_state = (~x)? S0 : S1;
                S1: next_state = (~x)? S1 : S4;
                S2: next_state = (~x)? S2 : S1;
                S3: next_state = (~x)? S1 : S2;
                S4: next_state = (~x)? S3 : S4;
                default: next_state = S0;
            endcase
        end
    always@(*)
        begin
            z = (y==3'b011 || y==3'b100)? 1'b1 : 1'b0;
            Y0 = (next_state==3'b000 || next_state==3'b010 || next_state==3'b100)? 1'b0: 1'b1;
        end        
endmodule

25.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_state;
    always@(*)
        begin
            case(y)
                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;
                default: next_state = A;                
            endcase
        end
    assign Y2 = next_state[1];
endmodule

26.q6c

module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);
	parameter A = 6'd1, B = 6'd2, C = 6'd4, D = 6'd8, E = 6'd16, F = 6'd32;
    reg[6:1] next_state;
    
    assign next_state[1] = (y[1] && w) || (y[4] && w);
    assign next_state[2] = y[1] && (~w);
    assign next_state[3] = (y[2] && (~w)) || (y[6] && w);
    assign next_state[4] = (y[2] && w) || (y[3] && w) || (y[5] && w) || (y[6] && w);
    assign next_state[5] = (y[3] && (~w)) || (y[5] && (~w));
    assign next_state[6] = y[4] && (~w);
    
    assign Y2 = next_state[2];
    assign Y4 = next_state[4];
endmodule

27.q6

module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);
	parameter A = 3'b000, B = 3'b001, C = 3'b010, D = 3'b011, E = 3'b100, F = 3'b101;
    reg[2:0] state;
    reg[2:0] next_state;
    
    always@(*)
        begin
            case(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;
                default: next_state = A;                
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state <= A;
            else
                state <= next_state;
        end
    
    always@(posedge clk)
        begin
            if(reset)
                z <= 1'b0;
            else
                begin
        	        if(next_state==E || next_state==F)
        	            z <= 1'b1;
        	    	else
            	        z <= 1'b0;
                end
        end
endmodule

28.q2FSM

module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);
	parameter A = 3'b000, B = 3'b001, C = 3'b010, D = 3'b011, E = 3'b100, F = 3'b101;
    reg[2:0] state;
    reg[2:0] next_state;
    
    always@(*)
        begin
            case(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;
                default: next_state = A;                
            endcase
        end
    
    always@(posedge clk)
        begin
            if(reset)
                state <= A;
            else
                state <= next_state;
        end
    assign z = (state==F || state==E)? 1'b1 : 1'b0;
endmodule

29.q2b

module top_module (
    input [5:0] y,
    input w,
    output Y1,
    output Y3
);
    parameter A = 6'd1, B = 6'd2, C = 6'd4, D = 6'd8, E=6'd16, F=6'd32;
    reg[5:0] next_state;
    
    assign next_state[0] = (y[0] && (~w)) || (y[3] && (~w));
    assign next_state[1] = y[0] && w;
    assign next_state[2] = (y[1] && (w)) || (y[5] && (~w));
    assign next_state[3] = (y[1] && (~w)) || (y[2] && (~w)) || (y[4] && (~w)) || (y[5] && (~w));
    assign next_state[4] = (y[2] && (w)) || (y[4] && (w));
    assign next_state[5] = y[3] && (w);
    
    assign Y1 = next_state[1];
    assign Y3 = next_state[3];
endmodule

30.q2a

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;
    reg[1:0] next_state;
    
    always@(*)
        begin
            case(state)
                A: next_state = (r[1])? B : ((r[2])? C : ((r[3])? D : A));
                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)
                state <= A;
            else
                state <= next_state;
        end
    
    always@(posedge clk)
        begin
            if(~resetn)
                g <= 3'b0;
            else
                begin
                    case(next_state)
                        B: g <= 3'b001;
                        C: g <= 3'b010;
                        D: g <= 3'b100;
                        default: g <= 3'b0;
                    endcase
                end
        end
endmodule

31.Another FSM

module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input x,
    input y,
    output f,
    output g
); 
    parameter A = 3'b000, B = 3'b001, C = 3'b010, D = 3'b011, 
    		  E = 3'b100, F = 3'b101, G = 3'b110, H = 3'b111;
    reg[2:0] state;
    reg[2:0] next_state;
    reg[1:0] count;
    
    always@(*)
        begin
            case(state)
                A: next_state = B;
                B: next_state = D;
                C: next_state = (x)? C : E;
                D: next_state = (x)? C : D;
                E: next_state = (x)? F : D;
                F: next_state = (y)? G : ((count==2'b10)?H : F);
                G: next_state = G;
                H: next_state = H;
                default: next_state = A;
            endcase
        end
    
    always@(posedge clk)
        begin
            if(~resetn)
                state <= A;
            else
                state <= next_state;
        end
    
    always@(posedge clk)
        begin
            if(~resetn)begin
                count <= 2'b00;
                f     <= 1'b0;
                g     <= 1'b0;
            end
            else begin
                case(next_state)
                    B: begin f <= 1'b1; g = 1'b0; count <= 2'b00;end
                    C: begin f <= 1'b0; g = 1'b0; count <= 2'b00;end
                    D: begin f <= 1'b0; g = 1'b0; count <= 2'b00;end
                    E: begin f <= 1'b0; g = 1'b0; count <= 2'b00;end
                    F: begin f <= 1'b0; g = 1'b1; count++ ;end
                    G: begin f <= 1'b0; g = 1'b1; count <= 2'b00;end
                    H: begin f <= 1'b0; g = 1'b0; count <= 2'b00;end
                    default: begin
                        count <= 2'b00;
                		f     <= 1'b0;
                		g     <= 1'b0;
                    end
                endcase
            end
        end
endmodule

以上就是状态机部分的全部习题答案了,前前后后我也做了四天。期间经常被卡住各种debug非常痛苦,但这都是学习的必经之路。希望继续努力能把Verilog学的好一点。
欢迎各位讨论批评。
习题链接

posted @ 2021-03-30 23:37  黑衣の甘铃儿  阅读(572)  评论(1)    收藏  举报