FPGA self study notes -- Serial Communication sending multi byte data (verilog version)

1. Demand analysis

About the implementation of uart protocol, you can refer to my last blog. FPGA self study notes -- implementation of serial communication (vivado Verilog version) . In the last blog, we mainly realized the sending of single byte data. In fact, we used the module of the last blog to send multi byte data.

In the process of real data transmission, we can not only send 678 bit data, but also send 121620 bit data, so we need to call the serial port sending module many times to send multi byte data. Through the implementation of state machine, suppose we send a 40 bit, 5-byte data this time, so in a simple way, we can have 6 states, 0 state is the waiting state of the whole module, and 1,2,3,4,5 states are the sending state of 5-byte data respectively.

2. Overall module and state transition diagram.

In the previous blog, the single byte serial port sending module was uart_tx. The specific functions are as follows: when send_go is the high level. Send the parallel data in data as serial data. When the transmission is completed, tx_done generates a single pulse. We need to call this module in the upper module. The block diagram of the upper module is shown in the figure above. UART to be called_ TX module is shown on the right.

        

Therefore, trans is required_ Go starts the state machine, and the state machine produces send_go signal, transmitting one byte of data. After sending, uart_tx module will generate tx_done signal, TX_ The done signal is used to activate the next state of the state machine, start sending the next data, and generate a send again_ Go pulse, send data data and send 5 bytes of data successively. When the last byte is sent, the last state 5 is in TX_ Return to the first state under done and generate a five byte transmission completion signal, trans_down. After returning to the first state, wait for the trans of the next forty bit, five byte data to be sent_ go.

The state transition diagram is as follows.

Of course, this state transition diagram can also be simplified. Because I am also in Xiaobai state at present, I can only write this easy to understand and simple writing method. You can also try a more advanced writing method in the future. That is, only two state machines are used to implement it, or the latter five states are summarized into one large state,

3. Design documents and testbench documents

Instantiate UART in top file_ byte_ TX module, please refer to the previous blog for the specific code of this part. The code refers to the video of xiaomeige in station B. Novice strongly recommended.

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/04/30 20:20:59
// Design Name: 
// Module Name: uart_tx_5byte
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
// Use the serial port to send 5 bytes (40 bit) of data to the computer

module uart_tx_5byte(
    clk,
    reset,
    data40,
    trans_go,
    uart_tx,
    trans_done
    );
    
    input clk;
    input reset;
    input trans_go;
    input [39:0]data40;
    output uart_tx;
    output reg trans_done;
    reg [7:0]data;
    reg send_go;
    //reg tx_done;
    
uart_byte_tx uart_byte_tx(
        .clk(clk),
        .reset(reset),
        .send_go(send_go),
        .data(data),
        .baud_set(4),
        .uart_tx(uart_tx),
        .tx_done(tx_done)
    );

    reg [2:0]state;
   
    always@(posedge clk or negedge reset)
        if(!reset)begin
            state <= 0;
            send_go <= 0;
            data <= 0;
            trans_done <= 0;
        end
        else if(state == 0)begin
            trans_done <= 0;
            //if(tx_done)begin / / send a new message when it is finished
            if(trans_go)begin             //  By trans_go ignites the first state with tx_done is a TX that cannot start the state machine_ Done is the 0 status end flag
                data <= data40[7:0];
                send_go <= 1;
                state <= 1;
            end
            else begin
                data <= data;
                send_go <= 0;
                state   <= 0;
            end        
        end
        else if(state == 1)begin
            if(tx_done)begin
                data <= data40[15:8];
                send_go <= 1;
                state <= 2;
            end
            else begin
                data <= data;
                send_go <= 0;
                state   <= 1;
            end        
        end
        else if(state == 2)begin
            if(tx_done)begin
                data <= data40[23:16];
                send_go <= 1;
                state <= 3;
            end
            else begin
                data <= data;
                send_go <= 0;
                state   <= 2;
            end        
        end
        else if(state == 3)begin
            if(tx_done)begin
                data <= data40[31:24];
                send_go <= 1;
                state <= 4;
            end
            else begin
                data <= data;
                send_go <= 0;
                state   <= 3;
            end        
        end
        else if(state == 4)begin
            if(tx_done)begin
                data <= data40[39:32];
                send_go <= 1;
                state <= 5;
            end
            else begin
                data <= data;
                send_go <= 0;
                state   <= 4;
            end        
        end
        else if(state == 5)begin
            if(tx_done)begin               // Return to the initial state when the hair is finished
                send_go <= 0;
                state <= 0;
                trans_done <= 1;
            end
            else begin                    // When it's not finished, wait for him to finish it
                data <= data;
                send_go <= 0;
                state   <= 5;
            end        
        end
endmodule

Corresponding testbench file

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2022/04/30 21:51:02
// Design Name: 
// Module Name: uart_tx_5byte_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_tx_5byte_tb(
    );
    reg clk;
    reg reset;
    reg [39:0]data40;
    reg trans_go;
    wire trans_done;
    wire uart_tx;
   
    
uart_tx_5byte uart_tx_5byte(
    .clk(clk),
    .reset(reset),
    .data40(data40),
    .trans_go(trans_go),
    .uart_tx(uart_tx),
    .trans_done(trans_done)
    );
    
    initial clk = 1;
    always #10 clk = ~clk;
    
    initial begin
    reset = 0;
    data40 = 0;
    trans_go = 0;
    # 201;
    # 200;
    reset = 1;
    data40 = 40'h123456789a;
    trans_go = 1;
    # 20
    trans_go = 0;
    
    @(posedge trans_done);
    # 200000;
    data40 = 40'habc1234655;
    trans_go = 1;
    # 20
    trans_go = 0;
    @(posedge trans_done);
    # 200000;
    $stop;
    end 
endmodule

 4. Analysis of simulation results

 

Obviously, as shown in the figure, it must be noted that for multi byte transmission, there are still start bits and end bits in each byte, so it should still be 10 bits and 10 bits. When looking at the sequence diagram, don't be wrong. After removing the flag bits shown by the arrow, compare the data, parallel 40 bit input and serial output, and the results are consistent, from low to high, which is completely correct. Interested students can download my vivado project directly.

 

Tags: vivado

Posted by albatros21 on Sun, 01 May 2022 18:12:52 +0300