赞
踩
UART(Universal Asynchronous Receiver/Transmitter)是一种通用的异步收发传输协议,用于在计算机系统和外部设备之间进行串行数据传输。UART 协议定义了数据的传输格式和通信规则,使得不同设备之间能够进行可靠的数据交换。
首先先把设计代码放到这里:UART_TX完整代码下载
以下是 UART 协议的几个关键要素:
1、异步传输:UART 使用异步传输方式,不需要共享时钟信号来进行数据同步。发送端和接收端通过起始位、数据位和停止位进行数据的有效传输。
2、起始位和停止位:在每个数据字节的开始之前,UART 使用一个起始位来标识传输的起始点。而在数据字节的末尾,UART 添加一个或多个停止位以标识传输的结束。起始位和停止位的数量可以根据协议和设置进行配置。
3、数据位:UART 协议规定了数据位的传输顺序和位数。数据位是实际传输的数据位数,典型的位数为 5、6、7 或 8 位,具体取决于协议和配置。重要的一点:UART的传输数据为:
4、波特率:UART 通信的波特率指的是每秒传输的位数。发送端和接收端必须以相同的波特率进行通信,以确保数据的正确传输。常见的波特率包括 9600、115200 等。
5、校验位(可选):为了增加数据传输的可靠性,UART 还可以使用校验位进行错误检测。校验位是在数据位之后添加的一个位,用于验证数据的准确性。常见的校验方式包括奇校验和偶校验。
UART 协议在许多应用中得到广泛应用,例如串口通信、嵌入式系统、传感器和外围设备等。它提供了一种简单而有效的数据传输方式,允许设备之间进行可靠的异步通信。
本章将介绍如何使用Verilog实现UART发送部分并进行下板验证:
根据概述可以简单的提取出来,如下图:UART接受传输的数据格式:
讲解几个关键点:
LSB → MSB,从最低位到最高位
例如:d=8'b1011_0011 :传输顺序:d[0],d[1] ....... d[6],d[7]
异步通信:“不需要额外的时钟线进行数据的同步传输”
全双工传输:UART 只需要两条信号线:RXD 和 TXD ,可以同时进行传输
采用波特率作为传输数据的速率(每秒传输二进制位数的多少),单位:BPS,常用波特率有9600、14400、38400、57600...115200。
例如波特率=115200,则它传输一位数据位(1bit)的时间为1/115200s
两个设备通过UART传输的时候,必须是相同波特率。
涉及到两个量:
1、FPGA时钟主频率:FPGA 主频指的是 FPGA 设备上时钟信号的频率,通常以赫兹(Hz)为单位。
2、波特率:波特率指的是数据传输的速率,以位每秒(bps)为单位。
根据这两个量,可以计算出数据传输的时间,所需要的时钟周期:、
例如:时钟频率100M,波特率115200bps
bps_cnt = 100_000_000 / 9600 = 868
可以得出:FPGA传输数据,需要翻转868个时钟周期,才可以传输一位数据。
简单一点就是时钟频率除以波特率就是需要的计数。
端口名称 | 端口属性 | 介绍 |
i_clk | 输入端口 | FPGA输入时钟 |
i_reset | 输入端口 | FPGA输入复位,高有效 |
i_data[7:0] | 输入端口 | UART发送数据 |
i_valid | 输入端口 | 输入数据有效 |
o_ready | 输出端口 | 数据传输完成 |
o_txd | 输出端口 | UART输出接口 |
部分代码:
- module uart_tx #(
- parameter CHECK_BIT = "None", //“None”无校验 “Odd”奇校验 “Even”偶校验
- parameter BPS = 115200, //系统波特率
- parameter CLK = 25_000_000, //系统时钟频率 hz
- parameter DATA_BIT = 8, //数据位(6、7、8)
- parameter STOP_BIT = 1 //停止位 (1、2、3... 整数)
- )(
- input i_reset,
- input i_clk,
- input [DATA_BIT-1:0] i_data,
- input i_valid,
- output reg o_ready,
- output reg o_txd
- );
-
- endmodule
代码中采用三段式状态机:
IDLE:空闲状态,无数据传输,输出高电平,当i_valid信号到来时跳转到START状态;
START:起始位,无数据传输,输出低电平为 ,无条件跳转至DATA状态;
DATA:数据位,进行数据传输,先发送低比特,根据数据输出高低电平,假如有校验位,跳到CHECK状态,假如数据传输不设校验位,跳转到STOP状态;
CHECK:奇偶校验位处理状态,根据CHECK_BIT参数进行添加校验位值。
STOP:停止位状态,输出STOP_BIT个高电平。
部分代码:
- reg [3:0] c_state, n_state;
- parameter IDLE = 0,
- STATE = 1,
- DATA = 2,
- CHECK = 3,
- STOP = 4;
-
- ///* FSM *3 *//
- always @(posedge i_clk, posedge i_reset) begin
- if (i_reset)
- c_state <= 0;
- else
- c_state <= n_state;
- end
-
- always @(*) begin
- case (c_state)
- IDLE : begin
- if (tx_en && i_valid)
- n_state = STATE;
- else
- n_state = IDLE;
- end
-
- STATE : begin
- if (tx_en)
- n_state = DATA;
- else
- n_state = STATE;
- end
-
- DATA : begin
- if (tx_en && tx_cnt >= DATA_BIT && CHECK_BIT == "None")
- n_state = STOP;
- else if (tx_en && tx_cnt >= DATA_BIT)
- n_state = CHECK;
- else
- n_state = DATA;
- end
-
- CHECK : begin
- if (tx_en)
- n_state = STOP;
- else
- n_state = CHECK;
- end
-
- STOP : begin
- if (tx_en && stop_cnt == 1)
- n_state = IDLE;
- else
- n_state = STOP;
- end
-
- default : n_state = 0;
-
- endcase
- end
此模块用于辅助大家更好的运用UART_TX模块,展示了握手信号的工作方式,以及串口发送模块的调用方法。
为了方便大家理解,给大家画了一个发送数据的时序图:
在数据发送过程中,握手信号的细致描述如下:(接收端即UART_TX模块)
初始状态:发送端准备好发送数据,并将VALID信号置高,表示数据有效。接收端处于等待状态,READY信号为低电平,表示接收端尚未准备好接收数据。
数据传输开始:发送端在VALID信号置高后,开始传输数据。发送端将要发送的数据值放置在DATA线上,并保持稳定。VALID信号保持高电平,表示数据一直有效。
握手信号等待:接收端检测到VALID信号置高后,开始等待READY信号的响应。接收端会持续监测READY信号状态,直到它被置高。
数据接收和响应:一旦接收端检测到READY信号置高,它表示接收端已经准备好接收数据。在READY信号置高后,发送端可以改变DATA的值,并且VALID信号也可以跟随着改变。这表示发送端可以发送下一个数据。
握手信号完成:发送端发送数据后,继续保持VALID信号的高电平,表示数据仍然有效。接收端在接收完数据后,如果准备好接收下一个数据,则保持READY信号的高电平。这样一个完整的握手信号周期就完成了。
通过这种握手信号的交互,发送端和接收端能够进行同步的数据传输。VALID信号的高电平表示数据有效,READY信号的高电平表示接收端准备好接收数据。只有在READY信号置高后,发送端才能改变数据并发送下一个数据。
这种握手机制确保了数据的可靠传输,发送端和接收端在数据传输过程中能够以协调的方式进行通信。
部分代码:
- module UART_tx_gen_data(
- input clk_a,
- input rst_n,
- output txd
- );
-
- reg [7:0] temp_data;
- reg [7:0] tx_data;
- reg tx_valid;
- wire ready;
-
-
- reg [3:0] c_state, n_state;
- parameter S0 = 0,
- S1 = 1;
-
- uart_tx #(
- .CHECK_BIT ("None" ) , //“None”无校验 “Odd”奇校验 “Even”偶校验
- .BPS (115200 ) , //系统波特率
- .CLK (25_000_000) , //系统时钟频率 hz
- .DATA_BIT (8 ) , //数据位(6、7、8)
- .STOP_BIT (1 ) //停止位
- ) TX (
- .i_reset(!rst_n),
- .i_clk(clk_a),
- .i_data(tx_data),
- .i_valid(tx_valid),
- .o_ready(ready),
- .o_txd(txd)
- );
-
- always @(posedge clk_a, negedge rst_n) begin
- if (!rst_n)
- c_state <= 0;
- else
- c_state <= n_state;
- end
通过上面两个模块,既可以对串口发送进行验证,把UART_tx_gen_data置为顶层,然后对端口进行引脚约束,生成下载文件,然后下载到板卡:
同时打开串口调试助手,选择波特率115200,数据位8,停止位1,校验位none,按16进制显示:
然后运行程序,即可在接收窗口收到连续变换的数据:
这样的话,此UART_TX设计已经完全完成了,下一期将更新UART_RX的设计和讲解。
如果感觉文章对您有用,麻烦三连支持一下,方便下次用到的时候,就可以快速找到我,非常感谢您的支持!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。