2021年5月3日 星期一

Consider a finite state machine with inputs s and w. Assume that the FSM begins in a reset state called A, as depicted below. The FSM remains in state A as long as s = 0, and it moves to state B when s = 1. Once in state B the FSM examines the value of the input w in the next three clock cycles. If w = 1 in exactly two of these clock cycles, then the FSM has to set an output z to 1 in the following clock cycle. Otherwise z has to be 0. The FSM continues checking w for the next three clock cycles, and so on. The timing diagram below illustrates the required values of z for different values of w.

Use as few states as possible. Note that the s input is used only in state A, so you need to consider just the w input.



當s0時,進入B狀態,然後會檢查w的值,如果在接下來的三個週期中w值有兩個週期都為1,那麼z輸出1,否則z輸出0。注意,這裡隱含的條件是不重疊檢測,意味著每三個週期檢查一次,週期與週期之間不重疊。

首先,我按照題目中給出的狀態轉移圖寫了基礎的狀態機模組;接著,用一個計數器進行計數,在狀態B時,counter計數三次清零,然後迴圈;然後,我使用了類似邊沿檢測的方法,w打了兩拍,判定條件為三拍中兩拍為高,如果滿足條件,z輸出1,否則輸出0


初始狀態為A,當檢測到s=1時,則跳轉到B狀態。進入B狀態後,3個週期為一個迴圈,在3個週期中檢測到兩次w=1,則在第三個週期輸出z=1,其他時候輸出z=0

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
  parameter A = 1'b0, B = 1'b1;
    reg         current_state;
    reg         next_state;
    
    always@(posedge clk)begin
        if(reset)begin
            current_state <= A;
        end
        else begin
            current_state <= next_state;
        end
    end
    
always@(*)begin
        case(current_state)
            A:begin
                next_state = s ? B : A;
            end
            B:begin
                next_state = B;
            end
        endcase
    end
    reg w_reg1;
    reg w_reg2;
    always@(posedge clk)begin
        if(reset)begin
            w_reg1 <= 1'b0;
            w_reg2 <= 1'b0;
        end
        else if(next_state == B)begin
            w_reg1 <= w;
            w_reg2 <= w_reg1;
        end
        else begin
            w_reg1 <= 1'b0;
            w_reg2 <= 1'b0;
        end
    end  
    always@(posedge clk)begin
        if(reset)begin
            z <= 1'b0;
        end
        else if(current_state == B && counter == 2'd0)begin
            if(~w & w_reg1 & w_reg2 | w & ~w_reg1 & w_reg2 | w & w_reg1 & ~w_reg2)begin   //3個週期為一個迴圈,在3個週期中檢測到兩次w=1,則在第三個週期輸出z=1,其他時候輸出z=0
                z <= 1'b1;
            end
            else begin
                z <= 1'b0;
            end
        end
        else begin
            z <= 1'b0;
        end
    end
    
    reg [1:0] counter;
    always@(posedge clk)begin
        if(reset)begin
            counter <= 2'd0;
        end
        else if(counter == 2'd2)begin
            counter <= 2'd0;
        end
        else if(next_state == B)begin
            counter <= counter + 1'b1;
        end
    end
endmodule

//另一方法

module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);
parameter [1:0] A = 2'b01;
    parameter [1:0] B = 2'b10;
    reg [1:0] cs, ns;
    
    always @(posedge clk)begin
        if(reset)
            cs <= A;
        else
            cs <= ns;
    end
    
    always @(*)begin
       ns = A;
        case(cs)
            A: ns = s? B:A;
            B: ns = B;
            default: ns = A;
        endcase
    end
    
    reg [1:0] cnt,cnt_w;
    wire add_cnt,end_cnt;
    always @(posedge clk)begin
        if(reset)begin
            cnt <= 2;
            cnt_w <= 0; 
        end
        else if(add_cnt)begin
            if(end_cnt)begin
                cnt <= 0;
                cnt_w <= w;
            end
            else begin
                cnt <= cnt + 1;
                cnt_w <= cnt_w + w;
            end
        end
    end
    assign add_cnt = (cs==B);
    assign end_cnt = add_cnt && (cnt==2);

    assign z = end_cnt && (cnt_w==2);
endmodule

沒有留言:

張貼留言

Messaging API作為替代方案

  LINE超好用功能要沒了!LINE Notify明年3月底終止服務,有什麼替代方案? LINE Notify將於2025年3月31日結束服務,官方建議改用Messaging API作為替代方案。 //CHANNEL_ACCESS_TOKEN = 'Messaging ...