基于verilog实现uart串口协议发射端

设计要求:

可配置波特率、时钟频率。

进阶要求:

设计不同数据位宽的uart发送端口协议。比如说数据发送位宽需要为12bit,受限于上位机数据传输位的限制(一般最高到8bit)。则需要将12bit拆分为2个8bit进行传输,需要注意每8bit需要停止位后再继续传输到下一个8bit,传输完成后通过电脑解析出原数据。

设计时序:

参考uart接收端代码

module uart_tx
    #(
    parameter FREQ = 50,
    parameter BPS  = 115200
    )
    (
    clk     ,
    rst_n   ,
    dat_vld ,
    data    ,
    txd     
    );

    input           clk     ;
    input           rst_n   ;
    input           dat_vld ;
    input   [7:0]   data    ;
    output  reg     txd     ;

    parameter   CLK_CNT_MAX = FREQ * 1000000 / BPS - 1;

    reg [7:0]                       data_r ;
    reg [$clog2(CLK_CNT_MAX)-1:0]   clk_cnt;
    reg                             tx_flag;
    reg [3:0]                       tx_cnt ;

    always@(posedge clk or negedge rst_n) begin
        if (!rst_n)
            data_r <= 'b0;
        else if (!tx_flag && dat_vld)
            data_r <= data;
    end

    always@(posedge clk or negedge rst_n) begin
        if (!rst_n)
            clk_cnt <= 'b0;
        else if (tx_flag)
            clk_cnt <= (clk_cnt == CLK_CNT_MAX)? 'b0 : (clk_cnt + 1'b1);
        else
            clk_cnt <= 'b0;
    end

    always@(posedge clk or negedge rst_n) begin
        if (!rst_n)
            tx_flag <= 1'b0;
        else if (dat_vld)
            tx_flag <= 1'b1;
        else if ((tx_cnt == 9) && (clk_cnt == (CLK_CNT_MAX-CLK_CNT_MAX/20)))
            tx_flag <= 1'b0;
    end

    always@(posedge clk or negedge rst_n) begin
        if (!rst_n)
            tx_cnt <= 'b0;
        else if (tx_flag)
            tx_cnt <= (clk_cnt == CLK_CNT_MAX)? (tx_cnt + 1'b1) : tx_cnt;
        else
            tx_cnt <= 'b0;
    end

    always@(posedge clk or negedge rst_n) begin
        if (!rst_n)
            txd <= 1'b1;
        else if (tx_flag)
            case(tx_cnt)
                4'd0 : txd <= 1'b0;
                4'd1 : txd <= data_r[0];       
                4'd2 : txd <= data_r[1];
                4'd3 : txd <= data_r[2];
                4'd4 : txd <= data_r[3];
                4'd5 : txd <= data_r[4];
                4'd6 : txd <= data_r[5];
                4'd7 : txd <= data_r[6];
                4'd8 : txd <= data_r[7];
                4'd9 : txd <= 1'b1;
               default: txd <= txd;
            endcase
        else
            txd <= 1'b1;
    end

endmodule

测试结果:

通过结合上一篇uart接收端实现数据环回成功。

top层代码:

module top
    (
    clk     ,     
    rst_n   , 
    rxd     ,
    txd      
    );

    input   clk     ;
    input   rst_n   ;
    input   rxd     ;
    output  txd     ;

    wire dat_vld;
    wire [7:0] dat_o;
    
    uart_rx
        #(
        .FREQ(50),
        .BPS(115200)//baud rate
        )
        u_uart_rx
        (
        .clk     (clk    ),
        .rst_n   (rst_n  ),
        .rxd     (rxd    ),//input, receive data
        .dat_vld (dat_vld),//output, data valid
        .dat_o   (dat_o  ) //output, output data 
        );

    uart_tx         
        #(
        .FREQ (50),
        .BPS  (115200)
        )
        u_uart_tx
        (
        .clk     (clk    ),
        .rst_n   (rst_n  ),
        .dat_vld (dat_vld),
        .data    (dat_o ),
        .txd     (txd    )
        );


endmodule

你可能感兴趣的:(FPGA_PRJ,fpga开发)