一、什么是串口
UART的全称是通用异步收发器;
UART 只需要两条信号线:RXD 和 TXD,其中 RXD 是 UART 的接收端,TXD 是 UART 的发送端,接收与发送是全双工形式。对于FPGA来说,RXD 是input,TXD 是output 。
数据帧格式
波特率
在信息传输通道中,携带数据信息的信号单元叫码元(因为串口是1bit进行传输的,所以其码元就是代表一个二进制数),每秒钟通过信号传输的码元数称为码元的传输速率,简称波特率,常用符号“Baud”表示,其单位为“波特每秒(Bps)”。串口常见的波特率有4800、9600、115200等。
比特率
每秒钟通信信道传输的信息量称为位传输速率,简称比特率,其单位为“每秒比特数(bps)”。比特率可由波特率计算得出,公式为:比特率=波特率 * 单个调制状态对应的二进制位数。如果使用的是115200的波特率,其串口的比特率为:115200Bps * 1bit= 115200bps。
由计算得串口发送或者接收1bit数据的时间为一个波特,即1/115200秒,如果用10MHz(周期为20ns)的系统时钟来计数,需要计数的个数为cnt = (1s * 10^9)ns / 115200bit)ns / 100ns ≈ 87个系统时钟周期,即每个bit数据之间的间隔要在10MHz的时钟频率下计数87次。
二、设计思路
UART模块分为两个模块:接收模块和发送模块;
2.1 uart_rx 模块
系统时钟:10Mhz;
系统复位:低有效同步复位;
波特率:115200;无校验;8位数据;1位起始位,1位停止位;
状态机采用三段式状态机;
第一步:异步信号同步处理,使用两级缓存器将RXD信号延两拍。
第二步:IDLE状态判断低电平,开始接收数据;
第三步:RX_START状态判断起始位是否满足1bit所持续的时间,满足跳到RX_DATA状态;
第四步:开始接收数据,定义一个8bit位宽的寄存器,当周期计数器到达 1bit所持续的时间时,缓存当前的信号状态。累计接收8个bit。
第五步:接收完8bit数据之后,到达RX_STOP状态,在该状态下,计数器累加到 1bit所持续的时间时,跳到RX_DONE状态,接收数据完成。
第五步:在RX_DONE状态输出数据和valid信号。
2.2 uart_tx 模块
系统时钟:10Mhz;
系统复位:低有效同步复位;
波特率:115200;无校验;8位数据;1位起始位,1位停止位;
状态机采用三段式状态机;
第一步:IDLE状态下,判断写使能;
第二步:TX_START状态:发送起始位,计数器累加,跳到TX_DATA状态。
第三步:TX_DATA状态:发送数据,先发低bit,再发高bit,发完之后跳到TX_STOP状态;
第四步:TX_STOP状态:发送停止位,发送 完之后跳到TX_DONE状态。
第五步:TX_DONE状态:输出发送完成标志。
2.3 UART_TOP模块
为满足调试要求:采用了一个 PLL和FIFO ip核,PLL用来输出10MHz的时钟,FIFO用来缓存uart_rx模块接收到的数据。再通过uart_tx发送模块将数据发送出来。
三、代码仿真
3.1 UART_TOP
`timescale 1ns / 1ps
module uart_top(
input i_sys_clk_50m ,
output logic o_uart_tx ,
input i_uart_rx
);
logic i_sys_clk_10m;
logic i_sys_rst_n;
logic [7:0] data;
logic tx_wr;
logic o_tx_done;
logic wr_en;
logic rd_en;
logic empty;
logic o_tx_active;
logic [7:0] dout;
logic valid;
assign rd_en= ~empty & ~o_tx_active;
clk_wiz_0 clk_wiz_0
(
// Clock out ports
.clk_out1(i_sys_clk_10m), // output clk_out1
// Status and control signals
.locked(i_sys_rst_n), // output locked
// Clock in ports
.clk_in1(i_sys_clk_50m)); // input clk_in1
uart_rx uart_rx
(
.i_sys_clk_10m (i_sys_clk_10m ),
.i_sys_rst_n (i_sys_rst_n ),
.i_uart_rx (i_uart_rx ),
//.i_uart_rx (o_uart_tx ),
.o_rx_done (wr_en ),
.o_rx_data (data )
);
uart_tx uart_tx (
.i_sys_clk_