2021年7月19日 星期一

HDLBits/Sequential Logic/Finite State Machines/Fsm serialdp

HDLBits/Sequential Logic/Finite State Machines/Fsm serialdp

Serial Receiver with Parity Checking

See also: Serial receiver and datapath

We want to add parity checking to the serial receiver. Parity checking adds one extra bit after each data byte. We will use odd parity, where the number of 1s in the 9 bits received must be odd. For example, 101001011 satisfies odd parity (there are 5 1s), but 001001011 does not.

Change your FSM and datapath to perform odd parity checking. Assert the done signal only if a byte is correctly received and its parity check passes. Like the serial receiver FSM, this FSM needs to identify the start bit, wait for all 9 (data and parity) bits, then verify that the stop bit was correct. If the stop bit does not appear when expected, the FSM must wait until it finds a stop bit before attempting to receive the next byte.

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

Note that the serial protocol sends the least significant bit first, and the parity bit after the 8 data bits.

上題的基礎上多了一個輸出,要求是當正確接收數據時做出輸出,即在 done 信號為高電平時做出輸出。所以該題代碼與上題基本一致,只需要多一個8 bit 寄存器來寄存得到的數據並在 done 信號為高電平時候輸出即可。

這需要使用移位寄存器來實現移位寄存,可以從波形圖看出這是右移寄存器,因為不確定接收到的數據是否正確,所以只需不斷移位寄存即可,當 done 信號為正時進行輸出即為正確接收到的數據。狀態機與上題一致,波形圖如下。

基礎上進行進化,增添了奇偶校驗位。奇偶校驗(Parity Check)是一種校驗代碼傳輸正確性的方法。根據被傳輸的一組二進制代碼的數位中“1”的個數是奇數或偶數來進行校驗。采用奇數的稱為奇校驗,反之,稱為偶校驗。奇偶校驗是在傳輸中保障數據接收正確的常用方法,也是最初級的校驗方式。

采用的是奇校驗(odd parity)的方式,並且提供了奇偶校驗模塊。原本 start 和 stop 位之間的8 bit 變為了9 bit,新增的1 bit 為奇校驗位,從而使得這9 bit 中“1”的數量為奇數個,即題目中提供的奇偶校驗模塊輸出為1時表面數據正確,否則數據錯誤不予接收。波形圖如下所示。



碼中多了 odd 和 start 變量,odd 是出題人提供的奇偶校驗模塊的輸出,由 odd 是否為1判斷校驗是否正確。這里需要注意的是 start,該變量用於控制奇偶校驗模塊的開啟。需要注意,奇偶校驗模塊不能一直開啟,只有當開始接收數據,即出現起始標記後才開啟,並且每次開啟時需要覆位從頭進行,否則前面計算得到的 odd 輸出會對下一次判斷產生影響造成錯誤。簡單來說就是每次接收新一字節數據時要重啟奇偶校驗模塊。正是因為這個原因,所以在邏輯 always 塊中,針對當前狀態為 IDLE 或 STOP 時,需要將 start 置1,因為只有這兩個狀態的後一個狀態可能是 DATA 狀態。

module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //
  parameter IDLE = 0, DATA = 1, CHECK = 2, STOP = 3, ERROR = 4;
   
    reg[2:0] state, next_state;
    reg[3:0] cnt;
    reg[7:0] out;
    reg check;
    wire odd, start;
    
    parity parity_inst(
        .clk(clk),
        .reset(reset | start),
        .in(in),
        .odd(odd));    
    
    //transition
    always@(*)begin
        start = 0;
        case(state)
            IDLE:begin next_state=in?IDLE:DATA; start=1; end
            DATA:next_state=(cnt==8)?CHECK:DATA;
            CHECK:next_state=in?STOP:ERROR;
            STOP:begin next_state=in?IDLE:DATA; start=1; end
            ERROR:next_state=in?IDLE:ERROR;
        endcase
    end
    
    //state
    always@(posedge clk)begin
        if(reset)
            state<=IDLE;
        else
            state<=next_state;
    end
    
    //cnt
    always@(posedge clk)begin
        if(reset)
            cnt<=0;
        else
            case(state)
                DATA:cnt<=cnt+1;
                default:cnt<=0;
            endcase
    end
    
    //out
    always@(posedge clk)begin
        if(reset)
            out<=0;
        else
            case(next_state)
                DATA:out<={in,out[7:1]};
            endcase
    end
    
    //check
    always@(posedge clk)begin
        if(reset)
            check<=0;
        else
            check<=odd;
    end
    
    assign out_byte=out;
    assign done=check&(state==STOP);
                
endmodule

沒有留言:

張貼留言

Messaging API作為替代方案

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