2021年5月2日 星期日

HBLbits_Verilog Basic_Fsm ps2

HBLbits_Verilog Basic_Fsm ps2 

The PS/2 mouse protocol sends messages that are three bytes long. However, within a continuous byte stream, it's not obvious where messages start and end. The only indication is that the first byte of each three byte message always has bit[3]=1 (but bit[3] of the other two bytes may be 1 or 0 depending on data).
We want a finite state machine that will search for message boundaries when given an input byte stream. The algorithm we'll use is to discard bytes until we see one with bit[3]=1. We then assume that this is byte 1 of a message, and signal the receipt of a message once all 3 bytes have been received (done).
The FSM should signal done in the cycle immediately after the third byte of each message was successfully received.
Some timing diagrams to explain the desired behaviour
Under error-free conditions, every three bytes form a message:


這是一個通信協議傳送的問題,將上面的英文翻譯下來如下:

 PS / 2滑鼠協定發送三位元組長的消息。 但是,在連續的位元組流中,消息的開始和結束位置並不明顯。 唯一的指示是,每個三位元組消息的第一個位元組始終具有bit [3] = 1(但其他兩個位元組的bit [3]取決於資料,可能是10)。

 我們想要一個有限狀態機,當給定輸入位元組流時,它將搜索消息邊界。 我們將使用的演算法是丟棄位元組,直到看到bit [3] = 1的位元組為止。 然後,我們假設這是消息的位元組1,並在接收到所有3個位元組(完成)後,發出接收消息的信號。

在成功接收到每個消息的第三個位元組之後,FSM應該立即在週期中發出完成信號。

根據時序圖以及題目描述,我們可以大概畫出狀態轉移圖:



當輸入資料的in[7:0]bit[3]=1時,開始接收資料;一次接收3位元組的資料,存入輸出out_bytes[23:0],並使能接收完成done=1

狀態轉換圖
說明:現態state_c=Done時,若接收資料的bit[3]=1,則接收下一次的3位元組數;若bit[3]=0則重新接收資料。

module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
    
parameter Byte1=0, Byte2=1, Byte3=2, Done=3;
    reg [2:0] state_c, state_n;
    wire Byte12Byte2, Byte22Byte3, Byte32Done, Done2Byte1, Done2Byte2;
    reg [7:0] data1, data2, data3;
    
    always@(posedge clk) begin
        if(reset)
            state_c <= Byte1;
        else begin
            state_c <= state_n;
        end
    end
    
    always@(*) begin
        case (state_c)
            Byte1:begin
                if(Byte12Byte2)
                    state_n = Byte2;
                else
                    state_n = state_c;
            end
            Byte2:begin
                if(Byte22Byte3)
                    state_n = Byte3;
            end
            Byte3:begin
                if(Byte32Done)
                    state_n = Done;
            end
            Done:begin
                if(Done2Byte1)
                    state_n = Byte1;
                else 
                    state_n = Byte2;
            end
        endcase 
    end
    assign Byte12Byte2 = in[3]==1;
    assign Byte22Byte3 = 1;
    assign Byte32Done = 1;
    assign Done2Byte1 = in[3]==0;
    
    always@(posedge clk) begin
        if(reset) begin
            data1<=0;
            data2<=0;
            data3<=0;
        end
        else begin
            if(state_c == Byte1)
                data1 <= in;
            else if(state_c == Byte2)
                data2 <= in;
            else if(state_c == Byte3)
                data3 <= in;
            else if(state_c == Done)
                data1 <= in;
            else begin
                data1<=0;
            data2<=0;
            data3<=0;
        end
        end
    end
   
    assign done = state_c == Done;
    //assign out_bytes = (state_c == Done)?{data1, data2, data3}:24'hZZZZZZ;
endmodule

實際上就是要求找出FRAME HEADER幀頭,在資料流程中找出三位元組中的第一個位元組,bit[3]=1為第一個位元組,與之後的兩個位元組組成一個資料幀,因此編寫狀態機時可以程式設計四個狀態:

IDLE BYTE1 BYTE2 BYTE3

但之前一直困惑我的是第一個位元組 bit[3]=1,但第二個與第三個位元組的bit[3]也能是1,那麼bit[3]=1是不是就不能作為第一個位元組的判斷依據呢?但後來聯繫實際的硬體電路想想,一個資料流程總有一個起始位元,即第一個位元組,不可能直接從第二個位元組開始,對應著軟體設計就是有一個reset的設計,因此在復位之後再對bit[3]進行檢測,若bit[3]=1則代表檢測到了第一個位元組,否則沒有檢測到第一個位元組



module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
    
 parameter IDLE  = 4'b0001;
    parameter BYTE1 = 4'b0010;
    parameter BYTE2 = 4'b0100;
    parameter BYTE3 = 4'b1000;
    reg [3:0] state, nstate;
    // State transition logic (combinational)
    always @(*)begin
        nstate = 4'd0;
        case(state)
            IDLE: nstate = in[3]? BYTE1:IDLE;
            BYTE1:nstate = BYTE2;
            BYTE2:nstate = BYTE3;
            BYTE3:nstate = in[3]? BYTE1:IDLE;
            default:nstate = IDLE;
        endcase
    end
    // State flip-flops (sequential)
    always @(posedge clk)begin
        if(reset)begin     //应加深对复位的理解
            state <= IDLE;
        end
        else begin
            state <= nstate;
        end
    end
    // Output logic
    assign done = (state == BYTE3);
endmodule



沒有留言:

張貼留言

2024_09 作業3 以Node-Red 為主

 2024_09 作業3  (以Node-Red 為主  Arduino 可能需要配合修改 ) Arduino 可能需要修改的部分 1)mqtt broker  2) 主題Topic (發行 接收) 3) WIFI ssid , password const char br...