首页 > 其他分享 >FPGA串口发送模块

FPGA串口发送模块

时间:2022-12-10 21:55:30浏览次数:43  
标签:en FPGA Tx Send 模块 串口 byte tx reg

1、串口原理

通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART)
是一种异步收发传输器,其在数据发送时将并行数据转换成串行数据来传输,
在数据接收时将接收到的串行数据转换成并行数据,可以实现全双工传输和接收。
它包括了 RS232、RS449、RS423、RS422 和 RS485 等接口标准规范和总线标准规范。
换句话说,UART 是异步串行通信的总称。而 RS232、RS449、RS423、RS422 和 RS485 等,
是对应各种异步串行通信口的接口标准和总线标准,
它们规定了通信口的电气特性、传输速率、连接特性和接口的机械特性等内容。

image
串口的引脚很多,但是常用引脚为RXD、TXD、GND。

2、串口发送时序

串口默认数据位为8位;
常用的波特率为9600, 19200, 115200 等;
奇偶效验位跟在数据位后来判断数据是否出错,但是不常用;
数据位前面有一位低电平作为起始位;
数据位后面有一位高电平作为停止位;(没有奇偶效验位时)

image

3、串口发送模块

(1)模块代码

`timescale 1ns / 1ps

module uart_byte_tx(
    input       [7:0]   Data,
    input               Send_en,
    input               Clk,
    input               Rst_n,
    output  reg        Uart_Tx,
    output  reg        Tx_done
    );
    
    parameter   TX_BAUD  = 9600;
    parameter   CLK_FQC  = 50_000_000;
    parameter   BAUD_CNT = CLK_FQC/TX_BAUD;
    
    reg   [15:0]   baud_cnt;
    reg   [ 3:0]   bit_cnt;
    reg            Send_en_r;
    reg            Send_en_rr;
    reg            Tx_flag;
    
    always @(posedge Clk) begin
        Send_en_r <= Send_en;
        Send_en_rr <= Send_en_r;
    end
       
    always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            Tx_flag <= 0;
        else if(~Send_en_rr & Send_en_r)
            Tx_flag <= 1'b1;
        else if(bit_cnt == 10 - 1 & baud_cnt == BAUD_CNT - 1)
            Tx_flag <= 1'b0;
    end   
        
    always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            baud_cnt <= 0;
        else if(baud_cnt == BAUD_CNT - 1)
            baud_cnt <= 0;
        else if(Tx_flag)
            baud_cnt <= baud_cnt + 1'b1;
    end
    
    always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            bit_cnt <= 0;
        else if(bit_cnt == 10 - 1 & baud_cnt == BAUD_CNT - 1)
            bit_cnt <= 0;
        else if(baud_cnt == BAUD_CNT - 1)
            bit_cnt <= bit_cnt + 1'b1;
     end
    
    always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            Uart_Tx <= 1'b1;
        else if(Tx_flag == 0)
            Uart_Tx <= 1'b1;
        else case(bit_cnt)
            0: Uart_Tx <= 1'b0;
            1: Uart_Tx <= Data[0];
            2: Uart_Tx <= Data[1];
            3: Uart_Tx <= Data[2];
            4: Uart_Tx <= Data[3];
            5: Uart_Tx <= Data[4];
            6: Uart_Tx <= Data[5];
            7: Uart_Tx <= Data[6];
            8: Uart_Tx <= Data[7];
            9: Uart_Tx <= 1'b1;
            default: Uart_Tx <= 1'b1;
         endcase
     end
    
     always @(posedge Clk or negedge Rst_n) begin
        if(Rst_n == 0)
            Tx_done <= 1'b0;
        else if(bit_cnt == 9 & baud_cnt == BAUD_CNT - 1)
            Tx_done <= 1'b1;
        else
            Tx_done <= 1'b0;
     end
endmodule

(2)仿真文件

`timescale 1ns / 1ps

module uart_byte_tx_tb();
    
    reg        CLK_50M;
    reg        RST_N;
    reg [7:0]  Data;
    reg        Send_en;
        
    uart_byte_tx uart_byte_tx_inst(
    .Data          (Data),
    .Send_en       (Send_en),
    .Clk           (CLK_50M),
    .Rst_n         (RST_N),
    .Uart_Tx       (),
    .Tx_done       ()
    );
    
    defparam uart_byte_tx_inst.BAUD_CNT = 10;
    
    always #10 CLK_50M  <= ~CLK_50M;
    
    initial begin
    CLK_50M <= 1'b0;
    RST_N   <= 1'b0;
    Data    <= 8'b0;
    Send_en <= 1'b0;
    #100
    RST_N   <= 1'b1;
    Send_en <= 1'b1;
    Data    <= 8'b10111001;
    #20
    Send_en <= 1'b0;
    #2500
    Send_en <= 1'b1;
    #20
    Send_en <= 1'b0;
    #5000
    $stop;
    end
    
endmodule

image

4、应用示例

这里将发送模块应用为一个每隔10ms发送一个数据,每次发送的数据比前一个大1的例子.

(1)应用示例代码

`timescale 1ns / 1ps

module Tx_test(
    input               Clk,
    input               Rst_n,
    output              Uart_Tx
    );
    reg [18:0]  cnt_10ms;
    reg [ 7:0]  Data;
    reg         Send_en;
    wire        Tx_done;
    reg         Tx_done_r;
    reg         Tx_done_rr;
    reg         wait_10ms;
    
    parameter CNT_10MS = 500_000;
    
    uart_byte_tx    uart_byte_tx_inst(
    .Data       (Data),
    .Send_en    (Send_en),
    .Clk        (Clk),
    .Rst_n      (Rst_n),
    .Uart_Tx    (Uart_Tx),
    .Tx_done    (Tx_done)
    );
    defparam    uart_byte_tx_inst.TX_BAUD = 115200;
    
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            cnt_10ms <= 0;
        else if(cnt_10ms == CNT_10MS - 1)
            cnt_10ms <= 0;
        else if(wait_10ms == 1)
            cnt_10ms <= cnt_10ms + 1'b1;
    end
    
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            Send_en <= 0;
        else if(cnt_10ms == CNT_10MS - 1)
            Send_en <= 1'b1;
        else 
            Send_en <= 0;
    end
    
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            Data <= 8'b0;
        else if(Send_en == 1)
            Data <= Data + 1'b1;
        else 
            Data <= Data;
    end
    
    always @(posedge Clk ) begin
        Tx_done_r  <= Tx_done;
        Tx_done_rr <= Tx_done_r;
    end
    
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            wait_10ms <= 1'b1;
        else if(Tx_done_rr & ~Tx_done_r)
            wait_10ms <= 1'b1;
        else if(cnt_10ms == CNT_10MS - 1)
            wait_10ms <= 0;
    end
    
endmodule

(2)应用示例仿真

`timescale 1ns / 1ps

module Tx_test_tb();

    reg        CLK_50M;
    reg        RST_N;

    Tx_test     Tx_test_inst(
        .Clk            (CLK_50M),
        .Rst_n          (RST_N  ),
        .Uart_Tx        ()
        );
    
    defparam Tx_test_inst.uart_byte_tx_inst.BAUD_CNT = 10;
    defparam Tx_test_inst.CNT_10MS                   = 50;
    
   always #10 CLK_50M  <= ~CLK_50M;
    
    initial begin
    CLK_50M <= 1'b0;
    RST_N   <= 1'b0;
    #20
    RST_N   <= 1'b1;
    end    

endmodule

参考的内容

【【零基础轻松学习FPGA】小梅哥Xilinx FPGA基础入门到项目应用培训教程】 https://www.bilibili.com/video/BV1va411c7Dz/?share_source=copy_web&vd_source=c6135c3b3a9878c08e2ddc91acdf6853

标签:en,FPGA,Tx,Send,模块,串口,byte,tx,reg
From: https://www.cnblogs.com/Lclone/p/16972380.html

相关文章