天天看點

HDLBits 系列(31)Serial Receiver and Datapath

目錄

序言

原題複現

我的設計

上篇博文:

HDLBits 系列(30)Serial Receiver

寫了串行接收器如何接收8位串行資料,正确接收8位串行資料後給一個接收完畢标志信号,這篇博文來繼續進一步輸出正确接收的串行資料,在done有效時刻輸出并行的8bit資料。

特别容易實作,對上篇部落格的代碼進行略微添加即可。需要注意的是這種uart協定先發送的bit位為低bit位。

先給出原題,在給出設計:

Now that you have a finite state machine that can identify when bytes are correctly received in a serial bitstream, add a datapath that will output the correctly-received data byte. out_byte needs to be valid when done is 1, and is don't-care otherwise.

Note that the serial protocol sends the least significant bit first.

HDLBits 系列(31)Serial Receiver and Datapath

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

    // Use FSM from Fsm_serial
    localparam START = 0, B1 = 1, B2 = 2, B3 = 3, B4 = 4, B5 = 5, B6 = 6, B7 = 7, B8 = 8, STOP = 9, DONE0 = 10, DONE1 = 11;
    reg [3:0] state, next_state;
    always@(*) begin
        case(state)
            START: begin
                if(in == 0) next_state = B1;
                else next_state = START;
            end
            B1: begin
                next_state = B2;
            end
            B2: begin
                next_state = B3;
            end
            B3: begin
                next_state = B4;
            end
            B4: begin
                next_state = B5;
            end
            B5: begin
                next_state = B6;
            end
            B6: begin
                next_state = B7;
            end
            B7: begin
                next_state = B8;
            end
            B8: begin
                next_state = STOP;
            end
            STOP: begin
                if(in == 0) next_state = DONE1;
                else next_state = DONE0;
            end
            DONE0: begin
                if(in == 1) next_state = START;
                else next_state = B1;
            end
            DONE1: begin
                if(in == 0) next_state = DONE1;
                else next_state = START;
            end
            default: begin
                next_state = START;
            end
            
        endcase
    end
    
    always@(posedge clk) begin
        if(reset) state <= START;
        else state <= next_state;
    end
    
    assign done = (state == DONE0) ? 1 : 0;


    // New: Datapath to latch input bits.
    reg [7:0] out_byte_mid;
    always@(*) begin
        case(state)
            START: begin
                ;
            end
            B1: begin
                out_byte_mid[0] = in;
            end
            B2: begin
                out_byte_mid[1] = in;
            end
            B3: begin
                out_byte_mid[2] = in;
            end
            B4: begin
                out_byte_mid[3] = in;
            end
            B5: begin
                out_byte_mid[4] = in;
            end
            B6: begin
                out_byte_mid[5] = in;
            end
            B7: begin
                out_byte_mid[6] = in;
            end
            B8: begin
                out_byte_mid[7] = in;
            end
            STOP: begin
                ;
            end
            DONE0: begin
                ;
            end
            DONE1: begin
                ;
            end
            default: begin
                ;
            end
            
        endcase
    end
    assign out_byte = (done == 1)? out_byte_mid:'bz;

endmodule