UART协议及其verilog实现(1)

#学习记录#

1 UART协议介绍

UART全称是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),它是一种异步收发传输器,是设备之间进行异步通信的关键模块。UART负责处理数据总线和串行口之间的串/并、并/串转换,并规定了帧格式,通信双方只要采用相同的帧格式和波特率,就能在未共享时钟信号的情况下,仅用两根信号线(rx和tx)就可以完成通信过程,因此也称作异步串行通信。

1.1 UART数据传输的格式

UART数据传输帧格式如图1所示。

图1 UART传输帧格式

其中各位的含义如下:

  • 起始位:发送1位逻辑0(低电平)开始传输数据。
  • 数据位:可以是5~8位的数据,先发低位,再发高位。
  • 校验位:奇偶校验,1的位数为偶数(偶校验),1的位数为奇数(奇校验)。
  • 停止位:停止位是数据传输结束的标志,1位逻辑1(高电平)。
  • 空闲位:空闲时数据线为高电平。

UART通信包括数据位、起始位和停止位。波特率是UART通信中数据传输速率的度量,通常以比特每秒(bps)表示。波特率可以通过设置分频器的值来调整,分频器的值等于系统时钟频率除以期望的波特率。例如,如果系统的时钟是50MHZ,要设置波特率为9600bps,分频器的值应设置为50MHZ/9600bps=5208.333,实际应用中取接近的整数,即5209。

2 UART发送端的verilog描述

2.1 代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer:mr-pn-junction 
// 
// Create Date: 2024/04/21 20:52:15
// Design Name: 
// Module Name: uart_tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module uart_tx(
    input clk,
    input rst_n,
    input start,
    input [7:0] data,
    output reg rs232_tx,
    output reg done
    );
    reg [7:0] r_data;
    reg state;
    reg [12:0] baud_cnt;
    reg bit_flag;
    reg [3:0] bit_cnt;
//=======================r_data=================//
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        r_data<=8'b0;
    else if(start)
        r_data<=data;
    else
        r_data<=r_data;
end
//=====================state==================//
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        state<=1'b0;
    else if(start)
        state<=1'b1;
    else if(done)
        state<=1'b0;
    else
        state<=state;
end
//======================baud_cnt===================//
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        baud_cnt<=13'd0;
    else if(state)begin
        if(baud_cnt==13'd28)
            baud_cnt<=13'd0;
        else
            baud_cnt<=baud_cnt+13'd1;
    end
    else
        baud_cnt<=13'd0;
    
end
//================bit_flag===========================//
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        bit_flag<=1'b0;
    else if(baud_cnt == 'd1)
        bit_flag<=1'b1;
    else
        bit_flag<=1'b0;
end
//======================bit_cnt===================//
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        bit_cnt<=4'b0;
    else if(bit_flag)
        bit_cnt<=bit_cnt+4'd1;
    else if(bit_cnt ==4'd10)
        bit_cnt<= 4'b0;
    else
        bit_cnt<=bit_cnt;
        
    
end
//============================rs232_tx========================//
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        rs232_tx<=1'b1;
    else if(state)begin
        if(bit_flag)begin
            case(bit_cnt)
                4'd0: rs232_tx<=1'b0;
                4'd1: rs232_tx<=r_data[0];
                4'd2: rs232_tx<=r_data[1];
                4'd3: rs232_tx<=r_data[2];
                4'd4: rs232_tx<=r_data[3];
                4'd5: rs232_tx<=r_data[4];
                4'd6: rs232_tx<=r_data[5];
                4'd7: rs232_tx<=r_data[6];
                4'd8: rs232_tx<=r_data[7];
                4'd9: rs232_tx<=1'b1;
                default rs232_tx<=1'b1;
                endcase
        end
        else
            rs232_tx<=rs232_tx;
       end
    else
        rs232_tx<=1'b1;
    
end
//================================done================//
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        done<=1'b0;
    else if(bit_flag &&(bit_cnt == 4'd9))
        done<=1'b1;
    else
        done<=1'b0;
     
end
    
endmodule

2.2 testbench

`timescale 1ns / 1ps
//
// Company: 
// Engineer:mr-pn-junction 
// 
// Create Date: 2024/04/26 10:45:26
// Design Name: 
// Module Name: tb_uart_tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_uart_tx( );
    reg clk;
    reg rst_n;
    reg start;
    reg [7:0] data;
    wire rs232_tx;
    wire done;
initial clk=1'b0;
always #10 clk=~clk;
initial begin
    rst_n=1'b0;
    start=1'b0;
    data='d0;
    #100
    rst_n=1'b1;
    #200
    data='h55;
    start=1'b1;
    #20
    start=1'b0;
    #20000
    data='h58;
    start=1'b1;
    #20
    start=1'b0;
    #20000
    $stop;
    
end

uart_tx u_uart(
    .clk(clk),
    .rst_n(rst_n),
    .start(start),
    .data(data),
    .rs232_tx(rs232_tx),
    .done(done)

);
endmodule

3 仿真结果

图2 仿真结果

参考文献

[1] UART协议讲解-CSDN博客

[2] FPGA(UART通信协议,手把手学会分析时序并写出UART协议)_哔哩哔哩_bilibili

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值