跳轉到

Finite State Machines

Simple FSM 1 (asynchronous reset)

原題:Simple FSM 1 (asynchronous reset)

先依狀態圖實作 FSM,再視需要化簡狀態。

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

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

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

    // Output logic
    assign out = state;
endmodule

Simple FSM 1 (synchronous reset)

原題:Simple FSM 1 (synchronous reset)

重點是同步 reset 版本的 FSM 寫法。

Verilog
// 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;

    // Fill in state name declarations

    reg present_state, next_state;

    always@(*)begin
        case(present_state)
            1'b0: next_state = in? 1'b0: 1'b1;
            1'b1: next_state = in? 1'b1: 1'b0;
        endcase
    end

    always @(posedge clk) begin
        if (reset)present_state <= 1'b1;
        else present_state <= next_state;
    end
    assign out = present_state;
endmodule

Simple FSM 2 (asynchronous reset)

原題:Simple FSM 2 (asynchronous reset)

依照新的 transition logic 調整 FSM。

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

    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            1'b1: next_state = k? 1'b0: 1'b1;
            1'b0: next_state = j? 1'b1: 1'b0;
        endcase
    end

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

    // Output logic
    assign out = state;
endmodule

Simple FSM 2 (synchronous reset)

原題:Simple FSM 2 (synchronous reset)

重點是同步 reset 版本的 FSM 寫法。

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

    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            1'b1: next_state = k? 1'b0: 1'b1;
            1'b0: next_state = j? 1'b1: 1'b0;
        endcase
    end

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

    // Output logic
    assign out = state;
endmodule

Simple state transitions 3

原題:Simple state transitions 3

只需實作 combinational transition logic,不需要處理 clock。

Verilog
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)
            2'b00: next_state = in? 2'b01: 2'b00;
            2'b01: next_state = in? 2'b01: 2'b10;
            2'b10: next_state = in? 2'b11: 2'b00;
            2'b11: next_state = in? 2'b01: 2'b10;
        endcase
    end

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

Simple one-hot state transitions 3

原題:Simple one-hot state transitions 3

此題的 state 是 one-hot vector,transition table 可直接用 assign 描述。

Verilog
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[0] | state[2]);
    assign next_state[B] = in & (state[0] | state[1] | state[3]);
    assign next_state[C] = ~in & (state[1] | state[3]);
    assign next_state[D] = in & (state[2]);

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

endmodule

Simple FSM 3 (asynchronous reset)

原題:Simple FSM 3 (asynchronous reset)

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

    // State transition logic
    reg [1:0] state, next_state;
    always@(*)begin
        case(state)
            2'b00: next_state = in? 2'b01: 2'b00;
            2'b01: next_state = in? 2'b01: 2'b10;
            2'b10: next_state = in? 2'b11: 2'b00;
            2'b11: next_state = in? 2'b01: 2'b10;
        endcase
    end
    // State flip-flops with asynchronous reset
    always@(posedge clk, posedge areset)begin
        if(areset) state <= 2'b00;
        else state <= next_state;
    end
    // Output logic
    assign out = &state;
endmodule

Simple FSM 3 (synchronous reset)

原題:Simple FSM 3 (synchronous reset)

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

    // State transition logic
    reg [1:0] state, next_state;
    always@(*)begin
        case(state)
            2'b00: next_state = in? 2'b01: 2'b00;
            2'b01: next_state = in? 2'b01: 2'b10;
            2'b10: next_state = in? 2'b11: 2'b00;
            2'b11: next_state = in? 2'b01: 2'b10;
        endcase
    end
    // State flip-flops with synchronous reset
    always@(posedge clk)begin
        if(reset) state <= 2'b00;
        else state <= next_state;
    end
    // Output logic
    assign out = &state;
endmodule

Design a Moore FSM

原題:Design a Moore FSM

考閱讀,依照題意接FSM。

Verilog
module top_module (
    input clk,
    input reset,
    input [3:1] s,
    output fr3,
    output fr2,
    output fr1,
    output dfr
); 
    reg [1:0]state, next_state;
    assign next_state = {s[2],~(s[3]^s[2])&s[1]};

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

    always@(*)begin
        case(state)
            2'b00: {fr3,fr2,fr1} = 3'b111;
            2'b01: {fr3,fr2,fr1} = 3'b011;
            2'b10: {fr3,fr2,fr1} = 3'b001;
            2'b11: {fr3,fr2,fr1} = 3'b000;
        endcase
    end

    always@(posedge clk)begin
        if(reset) dfr <= 1'b1;
        else begin
            if(state > next_state) dfr <= 1'b1;
            else if(state== next_state) dfr <= dfr;
            else dfr <= 1'b0;
        end
    end
endmodule

Lemmings 1

原題:Lemmings 1

透過FSM實作遊戲的原理。

Verilog
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, RIGHT=0, ...
    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            1'b0: next_state = bump_right? 1'b1: 1'b0;
            1'b1: next_state = bump_left?  1'b0: 1'b1;
        endcase
    end

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

    // Output logic
    assign walk_left = state;
    assign walk_right = ~state;
endmodule

Lemmings 2

原題:Lemmings 2

上題的延伸,主要是bump的條件要多寫。

Verilog
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 ); 
    //0 right_fall, 1 left_fall, 2 right, 3 left
    reg [1:0]state,next_state;

    always@(*)begin
        if(~ground) next_state = {1'b0,state[0]};
        else begin
            case(state)
                2'b00: next_state = 2'b10;
                2'b01: next_state = 2'b11;
                2'b10: next_state = bump_right? 2'b11: 2'b10;
                2'b11: next_state = bump_left ? 2'b10: 2'b11;
            endcase
        end
    end

    always@(posedge clk,posedge areset)begin
        if(areset) state <= 2'b11;
        else state <= next_state;
    end

    assign walk_left = &state;
    assign walk_right = state[1] & ~state[0];
    assign aaah = ~state[1];
endmodule

Lemmings 3

原題:Lemmings 3

上題的延伸,主要是dig的條件要多寫,然後如果依照fsm格式寫應該會快樂不少。

Verilog
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 ); 
    //right 3'b000, left 3'b001, bump right 3'b010, bump left 3'b011, dig right 3'b100, dig left 3'b101
    reg [2:0] state,next_state;

    always@(*)begin
        case(state)
            3'b000: next_state= ground? (dig? 3'b100: (bump_right? 3'b001:3'b000)): 3'b010;
            3'b001: next_state= ground? (dig? 3'b101: (bump_left ? 3'b000:3'b001)): 3'b011;
            3'b010: next_state= ground? 3'b000: 3'b010;
            3'b011: next_state= ground? 3'b001: 3'b011;
            3'b100: next_state= ground? 3'b100: 3'b010;
            3'b101: next_state= ground? 3'b101: 3'b011;
            default: next_state= 3'bxxx;
        endcase
    end

    always@(posedge clk,posedge areset)begin
        if(areset) state <= 3'b001;
        else state <= next_state;
    end

    assign walk_left = ~state[2] & ~state[1] & state[0];
    assign walk_right = &(~state);
    assign aaah = ~state[2] & state[1];
    assign digging = state[2];
endmodule

Lemmings 4

原題:Lemmings 4

上題的延伸,也是FSM 和 counter的結合,這裡只需要注意counter 在 sequential logic不要寫錯了,我當時把if(~next_state[2] & next_state[1])寫成if(~state[2] & state[1]),一直少算一回合。

Verilog
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 ); 
    //right 3'b000, left 3'b001, bump right 3'b010, bump left 3'b011, dig right 3'b100, dig left 3'b101,splatter 3'b110
    reg [2:0] state,next_state;
    reg [7:0] count;

    always@(*)begin
        case(state)
            3'b000: next_state= ground? (dig? 3'b100: (bump_right? 3'b001:3'b000)): 3'b010;
            3'b001: next_state= ground? (dig? 3'b101: (bump_left ? 3'b000:3'b001)): 3'b011;
            3'b010: next_state= ground? ((count>8'd20)? 3'b110: 3'b000): 3'b010;
            3'b011: next_state= ground? ((count>8'd20)? 3'b110: 3'b001): 3'b011;
            3'b100: next_state= ground? 3'b100: 3'b010;
            3'b101: next_state= ground? 3'b101: 3'b011;
            3'b110: next_state = 3'b110;
            default: next_state= 3'bxxx;
        endcase
    end

    always@(posedge clk,posedge areset)begin
        if(areset)begin
            state <= 3'b001;
            count <= 8'd0;
        end
        else begin
            state <= next_state;
            if(~next_state[2] & next_state[1])
                count <= count + 8'd1;
            else
                count <= 8'd0;
        end
    end

    assign walk_left = ~state[2] & ~state[1] & state[0];
    assign walk_right = &(~state);
    assign aaah = ~state[2] & state[1];
    assign digging = state[2] & ~state[1];
endmodule

One-hot FSM

原題:One-hot FSM

不用實作 DFF,且 state 為 one-hot vector,適合直接用 assign 寫 transition logic。

Verilog
module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);
    //next state
    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];
    //out
    assign out1 = state[8]| state[9];
    assign out2 = state[7]| state[9];
endmodule

PS/2 packet parser

原題:PS/2 packet parser

接近 edge detection;用 FSM 記錄序列通常比直接存多個歷史輸入更省空間。

Verilog
module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
    //2'b00 -> reset
    //2'b01 -> get the 1xx
    //2'b11 -> output done = 1
    reg [1:0]state, next_state;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            2'b00: next_state = in[3]? 2'b01: 2'b00;
            2'b01: next_state = 2'b10;
            2'b10: next_state = 2'b11;
            2'b11: next_state = in[3]? 2'b01: 2'b00;
        endcase
    end
    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset) state <= 2'b00;//reset
        else state <= next_state;
    end
    // Output logic
    assign done = state[1] & state [0];//done when state== 2'b11
endmodule

PS/2 packet parser and datapath

原題:PS/2 packet parser and datapath

延續前一題,另外加入 datapath 儲存收到的資料。

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

    // FSM from fsm_ps2
    //2'b00 -> reset
    //2'b01 -> get the 1xx
    //2'b11 -> output done = 1
    reg [1:0]state, next_state;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            2'b00: next_state = in[3]? 2'b01: 2'b00;
            2'b01: next_state = 2'b10;
            2'b10: next_state = 2'b11;
            2'b11: next_state = in[3]? 2'b01: 2'b00;
        endcase
    end
    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset) state <= 2'b00;//reset
        else state <= next_state;
    end
    // Output logic
    assign done = state[1] & state [0];//done when state== 2'b11

    // New: Datapath to store incoming bytes.
    reg [7:0] in1, in2, in3;
    always@(posedge clk)begin
        in1 <= in;
        in2 <= in1;
        in3 <= in2;
    end

    assign out_bytes = done? {in3, in2, in1}: {24{1'b0}};

endmodule

Serial receiver

原題:Serial receiver

重點是把題目敘述轉成 FSM 狀態與轉移條件。

Verilog
module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    //data*8 + start + stop + idle + ??? = 12state
    reg[3:0] state, next_state;
    always@(*)begin
        case(state)
            4'd0: next_state = in? 4'd0: 4'd1;//idle
            4'd1: next_state = 4'd2;//start
            4'd2: next_state = 4'd3;//data1
            4'd3: next_state = 4'd4;//data2
            4'd4: next_state = 4'd5;//data3
            4'd5: next_state = 4'd6;//data4
            4'd6: next_state = 4'd7;//data5
            4'd7: next_state = 4'd8;//data6
            4'd8: next_state = 4'd9;//data7
            4'd9: next_state = in? 4'd10: 4'd11;//data8
            4'd10: next_state = in? 4'd0: 4'd1;//stop
            4'd11: next_state = in? 4'd0: 4'd11;//???
            default: next_state = 4'bxxxx;
        endcase
    end

    assign done = (state == 4'd10);

    always@(posedge clk)begin
        if(reset) state <= 4'b0000;
        else state <= next_state;
    end
endmodule

Serial receiver and datapath

原題:Serial receiver and datapath

延續前一題,額外加入 datapath 儲存資料。

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

    // Use FSM from Fsm_serial
    //data*8 + start + stop + idle + ??? = 12state
    reg[3:0] state, next_state;
    always@(*)begin
        case(state)
            4'd0: next_state = in? 4'd0: 4'd1;//idle
            4'd1: next_state = 4'd2;//start
            4'd2: next_state = 4'd3;//data1
            4'd3: next_state = 4'd4;//data2
            4'd4: next_state = 4'd5;//data3
            4'd5: next_state = 4'd6;//data4
            4'd6: next_state = 4'd7;//data5
            4'd7: next_state = 4'd8;//data6
            4'd8: next_state = 4'd9;//data7
            4'd9: next_state = in? 4'd10: 4'd11;//data8
            4'd10: next_state = in? 4'd0: 4'd1;//stop
            4'd11: next_state = in? 4'd0: 4'd11;//???
            default: next_state = 4'bxxxx;
        endcase
    end

    assign done = (state == 4'd10);

    always@(posedge clk)begin
        if(reset) state <= 4'b0000;
        else state <= next_state;
    end
    // New: Datapath to latch input bits.
    reg [8:0] data;
    always@(posedge clk)begin
        data <= {in,data[8:1]};
    end
    assign out_byte = data[7:0];
endmodule

Serial receiver with parity checking

原題:Serial receiver with parity checking

接續上題,data input從8 bit變9 bit,所以FSM要改。然後有個細節要注意,就是parity的reset等到start階段時也要reset。至於說如何判別is_start,這裡得用assign is_start = (next_state == 4'd1);,不能用assign is_start = (state == 4'd1);的原因在於,會晚一個cycle。所以把握一個原則,sequential logic中若用到狀態,記得要寫next_state。

Verilog
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
    //data*8 + start + stop + idle + ??? = 12state
    reg[3:0] state, next_state;
    always@(*)begin
        case(state)
            4'd0: next_state = in? 4'd0: 4'd1;//idle
            4'd1: next_state = 4'd2;//start
            4'd2: next_state = 4'd3;//data1
            4'd3: next_state = 4'd4;//data2
            4'd4: next_state = 4'd5;//data3
            4'd5: next_state = 4'd6;//data4
            4'd6: next_state = 4'd7;//data5
            4'd7: next_state = 4'd8;//data6
            4'd8: next_state = 4'd9;//data7
            4'd9: next_state = 4'd10;//data8
            4'd10: next_state = in? 4'd11: 4'd12;//data9
            4'd11: next_state = in? 4'd0: 4'd1;//stop
            4'd12: next_state = in? 4'd0: 4'd12;//???
            default: next_state = 4'bxxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= 4'b0000;
        else begin
        state <= next_state;
        valid <= odd;
        end
    end
    // New: Datapath to latch input bits.
    reg [9:0] data;
    always@(posedge clk)begin
        data <= {in,data[9:1]};
    end

    // New: Add parity checking.
    wire odd,is_start;
    assign is_start = (next_state == 4'd1);
    parity pr(.clk(clk),.reset(reset|is_start),.in(in),.odd(odd));
    reg valid;

    assign out_byte = valid? data[7:0]: 8'd0;
    assign done = (state == 4'd11) & valid;
endmodule

Sequence recognition

原題:Sequence recognition

分別對連續5,6,7以上個1做判斷,並做相對應的輸出,其實很像進階版的edge detection,不過可以用FSM實現,可以少幾個register。

Verilog
module top_module(
    input clk,
    input reset,    // Synchronous reset
    input in,
    output disc,
    output flag,
    output err);
    reg [3:0] state, next_state;
    parameter none = 4'd0;
    parameter one = 4'd1;
    parameter two = 4'd2;
    parameter three = 4'd3;
    parameter four = 4'd4;
    parameter five = 4'd5;
    parameter six = 4'd6;
    parameter seven = 4'd7;
    parameter discard = 4'd8;
    parameter fg = 4'd9;

    always@(*)begin
        case(state)
            none: next_state = in? one: none;
            one: next_state = in? two: none;
            two: next_state = in? three: none;
            three: next_state = in? four: none;
            four: next_state = in? five: none;
            five: next_state = in? six: discard;
            six: next_state = in? seven: fg;
            seven: next_state = in? seven: none;
            discard: next_state = in? one: none;
            fg: next_state = in? one: none;
            default: next_state = 4'bxxxx;
        endcase
    end

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

    assign disc = (state == discard);
    assign flag = (state == fg);
    assign err = (state == seven);
endmodule

Q8: Design a Mealy FSM

原題:Q8: Design a Mealy FSM

明確要求 Mealy machine,因此輸出可直接依目前 state 與 input 決定。

Verilog
module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z ); 
    reg [1:0] state, next_state;
    parameter zero_bit = 2'b00;
    parameter one_bit = 2'b01;
    parameter two_bit = 2'b10;

    always@(*)begin
        case(state)
            zero_bit: next_state = x? one_bit: zero_bit;
            one_bit: next_state = x? one_bit: two_bit;
            two_bit: next_state = x? one_bit: zero_bit;
            default: next_state = 4'bxxxx;
        endcase
    end

    always@(posedge clk, negedge aresetn)begin
        if(~aresetn) state <= zero_bit;
        else state <= next_state;
    end

    assign z = (state == two_bit) && x;
endmodule

Q5a: Serial two's complementer (Moore FSM)

原題:Q5a: Serial two's complementer (Moore FSM)

用 Moore machine 實作二補數轉換;遇到第一個 1 後,後續 bit 取反。

Verilog
module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    reg [1:0] state, next_state;
    parameter idle = 2'b00;
    parameter zero = 2'b01;
    parameter one = 2'b10;

    always@(*)begin
        case(state)
            idle: next_state = x? zero: idle;
            zero: next_state = x? one: zero;
            one: next_state = x? one: zero;
            default: next_state = 2'bxx;
        endcase
    end

    always@(posedge clk, posedge areset)begin
        if(areset) state <= 2'b00;
        else state <= next_state;
    end

    assign z = (state == zero);
endmodule

Q5b: Serial two's complementer (Mealy FSM)

原題:Q5b: Serial two's complementer (Mealy FSM)

使用 Mealy machine 可減少狀態數,輸出也會比 Moore machine 早一個週期反應。

Verilog
module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    reg state, next_state;
    parameter idle = 1'b0;
    parameter comp = 1'b1;

    assign next_state = state | x;

    always@(posedge clk,posedge areset)begin
        if(areset) state = idle;
        else state = next_state;
    end

    assign z = (state & ~x) | (~state & x);
endmodule

Q3a: FSM

原題:Q3a: FSM

考怎麼算三個cycle內有兩個1,其實可以開個datapath,然後取xnor和or。然後有個細節要注意,就是當reset和A轉換為B時要將datapath更新成3'b000,這裡得寫else if(state == A) temp <= 3'b000;而不是寫else if(next_state == B) temp <= 3'b000;的原因在於,next_state == B也可能代表next_state == D

Verilog
module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);  
    reg [1:0] state, next_state;
    parameter A = 2'b00;
    parameter B = 2'b01;
    parameter C = 2'b10;
    parameter D = 2'b11;

    always@(*)begin
        case(state)
            A: next_state = s? B: A;
            B: next_state = C;
            C: next_state = D;
            D: next_state = B;
        endcase
    end

    reg [2:0]temp;
    always@(posedge clk)begin 
        if(reset) state <= A;
        else state <= next_state;
    end

    always@(posedge clk)begin 
        if(reset) temp <= 3'b000;
        else if(state == A) temp <= 3'b000;
        else temp <= {temp[1:0],w};
    end

    assign z = (state == B) && ~(^temp) && (|temp);
endmodule

Q3b: FSM

原題:Q3b: FSM

Verilog
module top_module (
    input clk,
    input reset,   // Synchronous reset
    input x,
    output z
);
    reg [2:0] state, next_state;

    always@(*)begin
        case(state)
            3'b000: next_state = x? 3'b001: 3'b000;
            3'b001: next_state = x? 3'b100: 3'b001;
            3'b010: next_state = x? 3'b001: 3'b010;
            3'b011: next_state = x? 3'b010: 3'b001;
            3'b100: next_state = x? 3'b100: 3'b011;
            default: next_state = 3'bxxx;
        endcase
    end

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

    assign z = (~state[2]& state[1] & state[0]) | (state[2]& ~state[1] & ~state[0]);
endmodule

Q3c: FSM logic

原題:Q3c: FSM logic

雖然題目提供 clk,但 y 是 input,因此不需要 sequential block,也不需要使用 clk

Verilog
module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    reg [2:0] next_state;

    always@(*)begin
        case(y)
            3'b000: next_state = x? 3'b001: 3'b000;
            3'b001: next_state = x? 3'b100: 3'b001;
            3'b010: next_state = x? 3'b001: 3'b010;
            3'b011: next_state = x? 3'b010: 3'b001;
            3'b100: next_state = x? 3'b100: 3'b011;
            default: next_state = 3'bxxx;
        endcase
    end

    assign Y0 = next_state[0];
    assign z = (~y[2]& y[1] & y[0]) | (y[2]& ~y[1] & ~y[0]);
endmodule

Q6b: FSM next-state logic

原題:Q6b: FSM next-state logic

Verilog
module top_module (
    input [3:1] y,
    input w,
    output Y2);
    parameter A = 3'd0;
    parameter B = 3'd1;
    parameter C = 3'd2;
    parameter D = 3'd3;
    parameter E = 3'd4;
    parameter F = 3'd5;

    reg [3:1]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 = 3'bxxx;
        endcase
    end
    assign Y2 = next_state[2];
endmodule

Q6c: FSM one-hot next-state logic

原題:Q6c: FSM one-hot next-state logic

和前一題類似,但改用 assign 完成;one-hot vector 的 transition logic 通常很適合這種寫法。

Verilog
module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);   
    assign Y2 = ~w & y[1];
    assign Y4 = w & (y[2] | y[3] | y[5] | y[6]);
endmodule

Q6: FSM

原題:Q6: FSM

這是前面題目的完整版本,補上 sequential logic 即可。

Verilog
module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);
    parameter A = 3'd0;
    parameter B = 3'd1;
    parameter C = 3'd2;
    parameter D = 3'd3;
    parameter E = 3'd4;
    parameter F = 3'd5;

    reg [2:0] state,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 = 3'bxxx;
        endcase
    end

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

    assign z = state[2] & ~state[1];
endmodule

Q2a: FSM

原題:Q2a: FSM

Verilog
module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    input w,
    output z
);
    parameter A = 3'd0;
    parameter B = 3'd1;
    parameter C = 3'd2;
    parameter D = 3'd3;
    parameter E = 3'd4;
    parameter F = 3'd5;

    reg [2:0] state,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 = 3'bxxx;
        endcase
    end

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

    assign z = state[2] & ~state[1];
endmodule

Q2b: One-hot FSM equations

原題:Q2b: One-hot FSM equations

Verilog
module top_module (
    input [5:0] y,
    input w,
    output Y1,
    output Y3
);
    assign Y1 = w & y[0];
    assign Y3 = ~w & (y[1] | y[2] | y[4] | y[5]);
endmodule

Q2a: FSM

原題:Q2a: FSM

依照狀態圖實作 FSM。

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

    reg [1:0] state, next_state;
    parameter A = 2'b00;
    parameter B = 2'b01;
    parameter C = 2'b10;
    parameter D = 2'b11;

    always@(*)begin
        case(state)
            A:begin
                if(~|r) next_state = A;
                else if(r[3:1] == 3'b100) next_state = D;
                else if(r[2:1] == 2'b10) next_state = C;
                else if(r[1]) next_state = B;
                else next_state = 2'bxx;
            end
            B: next_state = r[1]? B: A;
            C: next_state = r[2]? C: A;
            D: next_state = r[3]? D: A;
        endcase
    end

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

    assign g = {(state == D), (state == C), (state == B)};
endmodule

Q2b: Another FSM

原題:Q2b: Another FSM

依照題目敘述拆出狀態與轉移條件;建議先畫狀態圖再寫 Verilog。

Verilog
module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input x,
    input y,
    output f,
    output g
); 
    reg [3:0]state, next_state;
    parameter A = 4'd0;
    parameter f_1 = 4'd1;
    parameter zero_bit = 4'd2;
    parameter one_bit = 4'd3;
    parameter two_bit = 4'd4;
    parameter three_bit = 4'd5;
    parameter g_0 = 4'd6;
    parameter g_1 = 4'd7;
    parameter temp = 4'd8;

    always@(*)begin
        case(state)
            A: next_state = f_1;
            f_1: next_state = zero_bit;
            zero_bit: next_state = x? one_bit: zero_bit;
            one_bit: next_state = x?  one_bit: two_bit;
            two_bit: next_state = x? three_bit: zero_bit;
            three_bit: next_state = y? g_1: temp;
            g_0: next_state = g_0;
            temp: next_state = y? g_1: g_0;
            g_1: next_state = g_1;
            default: next_state = 4'bxxxx;
        endcase
    end

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

    assign f = (state == f_1);
    assign g = (state == three_bit) | (state == temp) | (state == g_1);
endmodule