UART+FIFO

发布时间 2023-08-12 16:17:51作者: ALright壹

UART+FIFO

目标:接收外部串口数据并通过fifo缓存,通过按钮发送缓存的数据

Source

top_module

  • uart模块
  • 按钮按下检测电路
    • 此处可以改进增加消抖电路
  • fifo读写数据控制
`timescale 1ns / 1ps
/**
    串口收发+fifo缓冲
*/
module top_module(
    clk,
    reset_in,
    rx,     
    tx,
    en,         // 使能信号 拨码开关
    mode_trans, // 模式切换 按钮
    rx_full,     // 接收满信号 LED1 
    rx_empty,   // 接收空信号 LED2
    tx_full,    // 发射满信号 LED3
    tx_empty,     // 发送空信号 LED4   
    tx_rx_mode      // 发送接收模式 LED8
    );
    input clk;
    input reset_in;
    input rx;
    output wire tx;
    input en;
    input mode_trans;

    output wire rx_full;
    output wire tx_empty;
    output wire rx_empty;
    output wire tx_full;

    wire reset;
    assign reset = ~reset_in;

    output reg tx_rx_mode=1;   // 默认为串口接收状态

    reg [7:0] data_tx_fifo = 0;
    wire [7:0] data_rx_fifo;

    reg fifo_tx_wr_en = 0;
    reg fifo_rx_rd_en = 0;

    wire fifo_tx_full;
    wire fifo_tx_empty;
    wire fifo_rx_empty;
    wire fifo_rx_full;

    wire fifo_tx_wr_rst_busy;
    wire fifo_tx_rd_rst_busy;
    wire fifo_rx_rd_rst_busy;
    wire fifo_rx_wr_rst_busy;

    wire fifo_rx_valid;

    assign rx_full = fifo_rx_full;
    assign tx_empty = fifo_tx_empty;
    assign rx_empty = fifo_rx_empty;
    assign tx_full = fifo_tx_full;

    uart
    #(
        .baud_rate(115200),
        .clk_freq(50000000)
    )uart_inst(
        .clk(clk),
        .reset(reset),
        .tx_rx_mode(tx_rx_mode),
        .en(en),
        .rx(rx),
        .tx(tx),

        .data_tx_fifo(data_tx_fifo),
        .fifo_tx_wr_en(fifo_tx_wr_en),
        .fifo_tx_full(fifo_tx_full),
        .fifo_tx_empty(fifo_tx_empty),
        .fifo_tx_wr_rst_busy(fifo_tx_wr_rst_busy), // 后期可以把rx_fifo的wr_busy引脚接到uart_rx中
        .fifo_tx_rd_rst_busy(fifo_tx_rd_rst_busy),

        .data_rx_fifo(data_rx_fifo),
        .fifo_rx_rd_en(fifo_rx_rd_en),
        .fifo_rx_full(fifo_rx_full),
        .fifo_rx_empty(fifo_rx_empty),
        .fifo_rx_valid(fifo_rx_valid),
        .fifo_rx_rd_rst_busy(fifo_rx_rd_rst_busy), // 后期可以把tx_fifo的rd_busy引脚接到uart_tx中
        .fifo_rx_wr_rst_busy(fifo_rx_wr_rst_busy)
    );

// detect the tx_rx_mode transition
    reg [1:0] mode_trans_cap = 1;   
    wire mode_trans_negedge ;
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            mode_trans_cap <= 2'b11;
        end
        else begin
            mode_trans_cap[1] <= mode_trans_cap[0];
            mode_trans_cap[0] <= mode_trans;
        end
    end
    assign mode_trans_negedge = mode_trans_cap[1]&~mode_trans_cap;
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            tx_rx_mode <= 1;    // 默认接收模式
        end
        else begin
            if(mode_trans_negedge) begin
                tx_rx_mode <= ~tx_rx_mode;        
            end
        end
    end

// write data to tx_fifo or read data from rx_fifo
    // read control
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            
        end
        else begin
            if(tx_rx_mode == 0) begin   // 发送模式下从rx_fifo读数据并写入到tx_fifo中
                if(~fifo_rx_empty) begin
                    fifo_rx_rd_en <= 1;
                end
                else begin
                    fifo_rx_rd_en <= 0;
                end
            end
        end
    end
    // read data from rx_fifo
    always @(posedge clk or posedge reset) begin
        if(reset) begin
            data_tx_fifo <= 0;
        end
        else begin
            if(tx_rx_mode == 0) begin
                if(fifo_rx_valid) begin
                    data_tx_fifo <= data_rx_fifo;
                end
            end
        end
    end

    // write control
    always @(posedge clk or posedge reset) begin
        if(reset) begin
            fifo_tx_wr_en <= 0;
        end
        else begin
            if(tx_rx_mode == 0) begin
                if(fifo_rx_valid & ~fifo_tx_full) begin //读出数据并且fifo_tx未满
                    fifo_tx_wr_en <= 1;
                end
                else begin
                    fifo_tx_wr_en <= 0;
                end
            end
        end
    end
    
endmodule

uart

内部例化uart_tx和uart_rx模块,以及对应的fifo模块

并实现uart_tx从fifo_uart_tx中读数据 及 uart_rx向fifo_uart_rx中写数据

uart_tx输出1字节开始发送信号tx_start,当串口处于tx_mode且tx_start有效且此时fifo_tx中的数据不为空时,向fifo_tx发送读请求

uart_rx输出1字节接收完成信号rx_done,当uart_rx接收到完整的一个字节数据并且fifo未满并且处于rx模式,向fifo_rx发送写请求

  • uart_tx

  • uart_rx

  • fifo_juart_tx 缓存串口发送数据

  • fifo_uart_rx 缓存串口接收数据

    其实实现需求用一块fifo即可,此处用两块fifo便于之后的拓展

`timescale 1ns / 1ps

module uart(
    // control signal
    clk,            
    reset,           // reset uart when in high level
    tx_rx_mode,         // 0--tx_mode   1--rx_mode
    en,              // enable the uart tx or rx mode
                     // for tx, en start the transmit of data in transmit fifo
                     // for rx, en enable uart_rx to write data received to fifo

    // data signal
    rx,                 // rx bus
    tx,                 // tx bus

    // control signal
    data_tx_fifo,      // write data to fifo_tx 
    fifo_tx_wr_en,		// fifo_tx_data 写使能
    fifo_tx_full,
    fifo_tx_empty,
    fifo_tx_wr_rst_busy,
    fifo_tx_rd_rst_busy,

    data_rx_fifo,		// read data from fifo_rx
    fifo_rx_rd_en,		// uart_
    fifo_rx_full,
    fifo_rx_empty,
    fifo_rx_valid,
    fifo_rx_rd_rst_busy,
    fifo_rx_wr_rst_busy
    );

    parameter baud_rate = 115200;       // default baudrate [Hz]
    parameter clk_freq = 50000000;      // default clock frequency [Hz]

    input clk;
    input reset;    
    input tx_rx_mode;
    input en; 
    
    input rx; 
    output tx; 
    input [7:0] data_tx_fifo;
    output wire [7:0] data_rx_fifo; 
               

// uart tx module
    wire [7:0] data_tx;
    wire tx_start;
    wire uart_inst_tx_en;
    
    input wire fifo_tx_wr_en;
    wire fifo_tx_rd_en;

    output wire fifo_tx_full;
    wire fifo_tx_al_full;
    // output wire fifo_tx_wr_ack;
    
    output wire fifo_tx_empty;
    wire fifo_tx_al_empty;
    wire fifo_tx_valid;

    output wire fifo_tx_wr_rst_busy;
    output wire fifo_tx_rd_rst_busy;
    // enable the uart_tx when in tx mode, en is valid and fifo_tx is not empty
    assign uart_tx_inst_en = en & ~tx_rx_mode & ~fifo_tx_empty;
    
    uart_tx 
    #(
        .baud_rate(baud_rate),
        .clk_freq(50000000)
    )
    uart_tx_inst(
        .clk(clk),
        .reset(reset),
        .tx(tx),
        .data(data_tx),
        .en(uart_tx_inst_en),
        .tx_start(tx_start)
    );

    // uart_tx 每次发送开始 & fifo非空 & tx mode
    assign fifo_tx_rd_en = tx_start & (~fifo_tx_empty) & (~tx_rx_mode);
// transmit data fifo 
    fifo_uart fifo_uart_tx(
        .clk(clk),
        .rst(reset),
        .din(data_tx_fifo),
        .dout(data_tx),

        .wr_en(fifo_tx_wr_en),
        .full(fifo_tx_full),
        .almost_full(fifo_tx_al_full),
        // .wr_ack(fifo_tx_wr_ack),
        .wr_rst_busy(fifo_tx_wr_rst_busy),

        .rd_en(fifo_tx_rd_en),
        .empty(fifo_tx_empty),
        .almost_empty(fifo_tx_al_empty),
        .valid(fifo_tx_valid),
        .rd_rst_busy(fifo_tx_rd_rst_busy)
    );

// uart rx module
    wire [7:0] data_rx;
    wire rx_done;
    wire uart_rx_inst_en;
    assign uart_rx_inst_en = en & tx_rx_mode & ~fifo_rx_full;
    // wire rx_valid;
    uart_rx
    #(
        .baud_rate(baud_rate),
        .clk_freq(50000000)
    )
    uart_rx_inst(
        .clk(clk),
        .reset(reset),
        .rx(rx),
        .data(data_rx),
        .rx_done(rx_done),
        .en(uart_rx_inst_en)
    );


// receive data fifo
    wire fifo_rx_wr_en;
    input fifo_rx_rd_en;

    output wire fifo_rx_full;
    wire fifo_rx_al_full;
    wire fifo_rx_wr_ack;

    output wire fifo_rx_empty;
    wire fifo_rx_al_empty;
    output wire fifo_rx_valid;

    output wire fifo_rx_rd_rst_busy;
    output wire fifo_rx_wr_rst_busy;

    fifo_uart fifo_uart_rx(
        .clk(clk),
        .rst(reset),
        .din(data_rx),
        .dout(data_rx_fifo),

        .wr_en(fifo_rx_wr_en),
        .full(fifo_rx_full),
        .almost_full(fifo_rx_al_full),
        .wr_ack(fifo_rx_wr_ack),
        .overflow(fifo_rx_overflow),
        .wr_rst_busy(fifo_rx_wr_rst_busy),
        
        .rd_en(fifo_rx_rd_en),
        .empty(fifo_rx_empty),
        .almost_empty(fifo_rx_al_empty),
        .valid(fifo_rx_valid),
        .underflow(fifo_rx_underflow),
        .rd_rst_busy(fifo_rx_rd_rst_busy)
    );

// write data to fifo_uart_rx
    // uart_rx 接收到完整的一个字节数据 && fifo未满 && 处于rx模式
    assign fifo_rx_wr_en = rx_done & en & ~fifo_rx_full & tx_rx_mode;
    
    

endmodule

uart_tx

`timescale 1ns / 1ps

module uart_tx(
    clk,
    tx,
    reset,      // 高电平复位
    data,
    en,
    tx_start        // 开始进入发送状态
    );
    parameter clk_freq = 50000000;
    parameter baud_rate = 115200;   // 默认波特率为115200Hz
    parameter counter_max = clk_freq/baud_rate - 1;

    input clk;
    input [7:0] data;
    input reset;
    input en;
    output reg tx = 1;  


    // data transmitter
    /*
        state 0: idle
        state 1: start bit
        state 2~9: data bit
        state 10: stop bit
    */
    reg [3:0] state = 0;
    reg [3:0] next_state = 0;   
    // counter
    reg [15:0] counter = 0;

    always @(posedge clk or posedge reset) begin
        if (reset) begin // when reset is effective
            counter <= 0;
        end
        else if (state != 0) begin
            if (counter == counter_max) begin
                counter <= 0;
            end
            else begin
                counter <= counter + 1;
            end
        end
    end

    // next_state logic
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            next_state <= 0;
        end
        else begin
            if (en == 1 & state == 0)begin
                next_state <= 1;
            end
            else if(counter == counter_max) begin
                if (next_state == 10) begin
                    if(en == 1) begin
                        next_state <= 1;
                    end
                    else 
                        next_state <= 0;
                end
                else begin
                    next_state <= next_state + 1;
                end
            end
        end
    end

    // state change logic
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= 0;
        end
        else begin
            state <= next_state;
        end
    end

    //output logic
    always @(*) begin
        case (state)
            4'd0: begin
                tx = 1;
            end
            4'd1: begin 
                tx = 0;
            end
            4'd2: begin 
                tx = data[0];
            end
            4'd3: begin 
                tx = data[1];
            end
            4'd4: begin 
                tx = data[2];
            end
            4'd5: begin 
                tx = data[3];
            end
            4'd6: begin
                tx = data[4];
            end
            4'd7: begin 
                tx = data[5];
            end
            4'd8: begin 
                tx = data[6];
            end
            4'd9: begin
                tx = data[7];
            end
            4'd10: begin
                tx = 1;
            end
            default: begin 
                tx = 1;
            end
        endcase
    end


// 采用state切换检测一个字节发送完成
    reg[3:0] state_last_clk = 0;
    reg[3:0] state_now = 0;
    always @(posedge clk or posedge reset) begin
        if(reset) begin
            state_last_clk <= 0;
            state_now <= 0;
        end
        else begin
            state_last_clk <= state_now;
            state_now <= state;
        end
    end

    output wire tx_start;  // 1字节开始传输,长达一个时钟周期
    assign tx_start = (state_last_clk == 4'd0 | state_last_clk == 4'd10)&(state_now == 4'd1);

endmodule

uart_rx

`timescale 1ns / 1ps

module uart_rx(
    clk,
    reset,      // 高电平复位
    rx,
    data,
    en,         // en使能后才会进入接收状态
    rx_done
    );
    parameter clk_freq = 50000000;
    parameter baud_rate = 115200;   // 默认波特率为115200Hz
    parameter counter_max = clk_freq/baud_rate - 1;

    input clk;
    output reg [7:0] data;
    input reset;
    input rx;
    input en;
    output wire rx_done;

    // rx negedge detect
    reg [1:0] rx_cap = 2'b11;
    wire rx_negedge;
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            rx_cap <= 2'b11;
        end
        else begin
            rx_cap[1] <= rx_cap[0];
            rx_cap[0] <= rx;
        end
    end
    assign rx_negedge = rx_cap[1]&&(~rx_cap[0]);

// data receiver
    /*
        state 0: idle
        state 1: start bit
        state 2~9: data bit
        state 10: stop bit
    */
    reg [3:0] state = 0;
    reg [3:0] next_state = 0;
// counter
    reg [15:0] counter = 0;
 
    always @(posedge clk or posedge reset) begin
        if(reset) begin
            counter <= 0;
        end
        else if (state != 0) begin
            if(counter == counter_max) begin
                counter <= 0;
            end
            else begin
                counter <= counter + 1;
            end
        end
    end
// next state logic
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            next_state <= 0;
        end
        else begin
            if (rx_negedge == 1 && en == 1 && (state == 0|| state == 10)) begin      // rx_negedge captured and is idle state
                next_state <= 1;
            end
            else if(counter == counter_max) begin
                if(next_state == 10) begin
                    next_state <= 0;
                end
                else begin
                    next_state <= next_state + 1;
                end
            end
        end
    end
// state change logic
    always @(posedge clk or posedge reset) begin
        if(reset) begin
            state <= 0;
        end
        else begin
            state <= next_state;
        end
    end

//output logic
    always @(posedge clk or posedge reset) begin
        if(reset) begin
            data <= 0;
        end
        else begin 
            if(counter == counter_max/2) begin
                case (state)
                    4'd2: begin
                        data[0] <= rx;
                    end
                    4'd3: begin
                        data[1] <= rx;
                    end
                    4'd4: begin
                        data[2] <= rx;
                    end
                    4'd5: begin
                        data[3] <= rx;
                    end
                    4'd6: begin
                        data[4] <= rx;
                    end
                    4'd7: begin
                        data[5] <= rx;
                    end
                    4'd8: begin
                        data[6] <= rx;
                    end
                    4'd9 : begin
                        data[7] <= rx;
                    end
                    default:;
                endcase
            end
        end
    end

// 采用state切换检测发送状态
    reg [3:0] state_last_clk = 0;
    reg [3:0] state_now = 0;
    always @(posedge clk or posedge reset) begin
        if(reset) begin
            state_last_clk <= 0;
            state_now <= 0;
        end
        else begin
            state_last_clk <= state_now;
            state_now <= state;
        end
    end
// 1字节数据接收完成信号
    assign rx_done = (state_last_clk == 9)&(state_now == 10);

endmodule

Testbench

top_module_tb

`timescale 1ns / 1ps
module top_module_tb(

    );

    reg clk = 0;
    always #10 clk <= ~clk;
    
    reg reset = 0;  
    wire pc_tx,pc_rx;

    reg en = 0;
    reg mode_button = 1;    // 按钮未按下为高电平

    wire rx_full,tx_empty;

    top_module inst(
        .clk(clk),
        .reset(reset),
        .rx(pc_tx),
        .tx(pc_rx),
        .en(en),
        .mode_trans(mode_button),
        .rx_full(rx_full),
        .tx_empty(tx_empty)
    );

    reg[11:0] counter = 1000;   // 循环1000次

    initial begin
        reset <= 0;
        #500;
        reset <= 1;
        #1000;
        reset <= 0;
        #100;
        en <= 1;
        while (counter >=1) begin
            counter <= counter - 1;
            wait(rx_full == 1) begin    // 等待rx_fifo接受满时按下mode button,切换成发送状态
                mode_button <= 0;
                #100;
                mode_button <= 1;
            end
            #100;
            wait(tx_empty == 1) begin   // 等待tx_fifo发送空时按下mode button,切换成接收状态
                mode_button <= 0;
                #100;
                mode_button <= 1;
            end
        end
    end

    
// pc发送数据
    reg [7:0] pc_data = 8'b00000001;
    wire tx_start;

    uart_tx uart_tx_inst(
        .clk(clk),
        .reset(reset),
        .tx(pc_tx),
        .data(pc_data),
        .tx_start(tx_start),
        .en(en)
    );

    always @(posedge clk or posedge reset) begin
        if (reset == 1) begin
            pc_data <= 8'b00000001;
        end
        else begin
            if (tx_start == 1) begin
               pc_data <= {pc_data[6:0],pc_data[7]}; 
            end
        end
    end    


endmodule

uart_tb

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/08/09 21:45:40
// Design Name: 
// Module Name: uart_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_tb(

    );
    // 50MHz时钟信号-20ns
    reg clk = 0;
    always #10 clk = ~clk;

    reg reset = 1;
    reg tx_rx_mode = 1;
    reg en = 0;

    wire rx;
    wire tx;

    // ports for fifo_uart_tx
    reg [7:0] data_tx_fifo = 8'b01001001;
    reg fifo_tx_wr_en = 0;
    wire fifo_tx_full;
    wire fifo_tx_empty;
    wire fifo_tx_wr_rst_busy;
    wire fifo_tx_rd_rst_busy;
    
    // ports for fifo_uart_rx
    wire [7:0] data_rx_fifo;
    reg fifo_rx_rd_en = 0;
    wire fifo_rx_full;
    wire fifo_rx_empty;
    wire fifo_rx_rd_rst_busy;
    wire fifo_rx_wr_rst_busy;

    // 测试往fifo_uart_tx写入数据并通过串口发送
    uart 
    #(
        .baud_rate(115200),
        .clk_freq(50000000)
    )uart_inst(
        .clk(clk),
        .reset(reset),
        .tx_rx_mode(tx_rx_mode),
        .en(en),

        .rx(rx),
        .tx(tx),

        .data_tx_fifo(data_tx_fifo),
        .fifo_tx_wr_en(fifo_tx_wr_en),
        .fifo_tx_full(fifo_tx_full),
        .fifo_tx_empty(fifo_tx_empty),
        .fifo_tx_rd_rst_busy(fifo_tx_rd_rst_busy),
        .fifo_tx_wr_rst_busy(fifo_tx_wr_rst_busy),

        .data_rx_fifo(data_rx_fifo),
        .fifo_rx_rd_en(fifo_rx_rd_en),
        .fifo_rx_full(fifo_rx_full),
        .fifo_rx_empty(fifo_rx_empty),
        .fifo_rx_rd_rst_busy(fifo_rx_rd_rst_busy),
        .fifo_rx_wr_rst_busy(fifo_rx_wr_rst_busy)
    );

// verify the uart_rx and fifo_uart_rx module
    reg [7:0] data_tx_test = 8'b01001010;
    wire tx_start;
    reg uart_tx_inst_en = 1;
    uart_tx
    #(
        .clk_freq(50000000),
        .baud_rate(115200)
    )uart_tx_inst(
        .clk(clk),
        .tx(rx),
        .reset(reset),
        .data(data_tx_test),
        .en(uart_tx_inst_en),
        .tx_start(tx_start)
    );
    // change the tx port data by byte
    always @(posedge tx_start) begin
        if (tx_start) begin
            data_tx_test <= {data_tx_test[6:0],data_tx_test[7]};
        end
    end
    // read data from rx_fifo
    always @(posedge clk) begin //  只要非空就从fifo里面读数据
        if(~fifo_rx_empty) begin
            fifo_rx_rd_en <= 1;
        end
        else if(fifo_rx_empty) begin
            fifo_rx_rd_en <= 0;
        end
    end

    initial begin
        reset <= 1;
        tx_rx_mode <= 1;
        #500;
        reset = 0;
        en = 1;
        uart_tx_inst_en <= 1;
        #1000000000;
    end

// verify the uart_tx and fifo_uart_tx_module
    // write data to the tx_fifo
    // reg [11:0] counter = 1000;
    // always @(posedge clk) begin
    //     if (~fifo_tx_full && fifo_tx_wr_en) begin
    //         data_tx_fifo <= {data_tx_fifo[6:0],data_tx_fifo[7]};
    //     end
    // end
    // initial begin
    //     reset = 1;
    //     #200;
    //     reset = 0;
    //     wait(~fifo_tx_wr_rst_busy) begin
    //         #1000;
    //         fifo_tx_wr_en = 1;
    //         en = 1;
    //     end
    //     #1000000000;
    // end
endmodule

uart_tx_tb

`timescale 1ns / 1ps

module uart_tx_tb(

    );
    reg clk = 0;
    always #10 clk = ~clk;

    wire tx;
    reg reset = 1;
    reg [7:0] data = 8'b00001111;
    reg en = 0;
    wire tx_done;

    uart_tx 
    #(
        .baud_rate(115200)
    )uart_tx_inst
    (
        .clk(clk),
        .tx(tx),
        .reset(reset),
        .data(data),
        .en(en),
        .tx_done(tx_done)
    );

    event tx_finish,tx_start;
    always @(posedge tx_done) begin
        ->tx_finish;
    end
    always @(negedge tx_done) begin
        ->tx_start;
    end
    always @(tx_finish) begin
        data = {data[6:0],data[7]};
        en <= 1;
    end
    always @(tx_start) begin
        en <= 0;
    end

    initial begin
        reset = 1;
        #1000;
        reset = 0;
        en = 1; 
        #100000000;
    end

endmodule

uart_rx_tb

`timescale 1ns / 1ps

module uart_rx_tb(
    
    );
    
    reg clk = 0;
    always #10 clk = ~clk;

    reg reset = 1;
    wire rx;
    wire[7:0] data_rx;
    wire rx_done;
    wire rx_valid;

    uart_rx 
    #(
        .clk_freq(50000000),
        .baud_rate(115200)
    ) uart_rx_inst(
        .clk(clk),
        .reset(reset),
        .rx(rx),
        .data(data_rx),
        .rx_done(rx_done),
        .rx_valid(rx_valid)
    );

    reg [7:0] data_tx = 8'b10100011;
    reg tx_en = 0;
    wire tx_done;

    uart_tx 
    #(
        .baud_rate(115200)
    )uart_tx_inst
    (
        .clk(clk),
        .tx(rx),
        .reset(reset),
        .data(data_tx),
        .en(tx_en),
        .tx_done(tx_done)
    );



    event tx_start;
    event tx_finish;

    always @(posedge tx_done) begin
        -> tx_finish;
    end
    always @(negedge tx_done) begin
        -> tx_start;
    end
    always @(tx_finish) begin
        data_tx <= {data_tx[6:0],data_tx[7]};
        tx_en <= 1;
    end
    always @(tx_start) begin
        tx_en <= 0;
    end


    initial begin
        reset <= 1;
        #1000;
        reset <= 0;
        tx_en <= 0;
        #1000000000;
    end

endmodule

板上验证

reset后

发送512字节数据直至rx_fifo满

按下mode_trans进入tx状态,同时rx_fifo被读出并写入tx_fifo