【基本知识】UART接口
1.简介
(1)UART一种通用异步串口数据总线,最低采用两路信号(TX/RX)即可实现全双工通信,十分简单;
(2)UART采用LSB模式传输,串口数据传输格式如下图所示:

起始位:长度为1位的时间,用于表示发送字符的开始;
数据位:长度长度不固定,一般是8位;
校验位:可以加也可以不加。
停止位:一般是1位、1.5位、2位长度,用于告知接收端字符传输结束;
(3)每个字符的发送都需要有起始位和停止位,对于连续数据也是如此;
2.内部结构

3.实现
发送模块代码如下:
module uart_tx_path #
(
parameter BAUD_DIV = 'd9, //baud
parameter BAUD_DIV_CAP = 'd4 //baud capture point
)
(
input clk, //main clk
input rst_n, //reset
input uart_tx_en, //send one byte data enable
input[:] uart_tx_byte, //one byte data
output uart_txd, //the txd pin
output uart_tx_done //send one byte data done
); //------------------------- Baud rate generator -------------------------
reg[:] cnt_baud_div;
reg baud_cap;
reg baud_start; always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_baud_div <= 'd0;
end
else begin
if(baud_start) begin
if(cnt_baud_div >= BAUD_DIV) begin
cnt_baud_div <= 'd0;
end
else begin
cnt_baud_div <= cnt_baud_div + 'b1;
end
end
else begin
cnt_baud_div <= 'd0;
end
end
end always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
baud_cap <= 'b0;
end
else begin
if(cnt_baud_div==BAUD_DIV_CAP) begin
baud_cap <= 'b1;
end
else begin
baud_cap <= 'b0;
end
end
end //-------------------------capture the uart_tx_en posedge-------------------------
reg uart_tx_en_r0,uart_tx_en_r1;
wire uart_tx_en_p; always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
uart_tx_en_r0 <= 'b0; //uart_tx_en of the idle state is low
uart_tx_en_r1 <= 'b0;
end
else begin
uart_tx_en_r0 <= uart_tx_en;
uart_tx_en_r1 <= uart_tx_en_r0;
end
end assign uart_tx_en_p = (~uart_tx_en_r1 & uart_tx_en_r0)? 'b1:1'b0; //capture the uart_tx_en posedge //------------------------- capture the txd data -------------------------
localparam TX_IDLE = 'b0;
localparam TX_WORK = 'b1; reg state_tx;
reg uart_tx_done_r;
reg[:] send_data;
reg[:] tx_bit; always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
state_tx <= TX_IDLE;
send_data <= 'b1111_1111_11;
uart_tx_done_r <= 'b0;
end
else begin
case(state_tx)
TX_IDLE: if(uart_tx_en_p) begin
baud_start <= 'b1;
send_data <= {'b1,uart_tx_byte,1'b0};
state_tx <= TX_WORK;
uart_tx_done_r <= 'b0;
end
else begin
baud_start <= 'b0;
send_data <= 'b1111_1111_11;
state_tx <= TX_IDLE;
uart_tx_done_r <= 'b0;
end
TX_WORK: if(tx_bit == 'd10) begin
baud_start <= 'b1;
send_data <= 'b1111_1111_11;
state_tx <= TX_WORK;
uart_tx_done_r <= 'b0;
end
else if(tx_bit>='d11) begin
baud_start <= 'b0;
send_data <= 'b1111_1111_11;
state_tx <= TX_IDLE;
uart_tx_done_r <= 'b1;
end
else begin
baud_start <= 'b1;
send_data <= send_data;
state_tx <= TX_WORK;
uart_tx_done_r <= 'b0;
end
default: ;
endcase
end
end
//------------------------- the uart txd work -------------------------
reg uart_txd_r; always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
uart_txd_r <= 'b1; //uart_txd of the idle state is high
tx_bit <= 'd0;
end
else begin
if(state_tx == TX_WORK) begin
if(baud_cap) begin
if (tx_bit <= 'd9)
uart_txd_r <= send_data[tx_bit];
else
uart_txd_r <= 'b1;
tx_bit <= tx_bit + 'b1;
end
else begin
uart_txd_r <= uart_txd_r;
tx_bit <= tx_bit;
end
end
else begin
uart_txd_r <= 'b1;
tx_bit <= 'd0;
end
end
end assign uart_tx_done = uart_tx_done_r;
assign uart_txd = uart_txd_r; endmodule
UART_TX_PATH
接收模块代码如下:
module uart_rx_path #
(
parameter BAUD_DIV = 'd9, //baud
parameter BAUD_DIV_CAP = 'd4 //baud capture point
)
(
input clk, //main clk
input rst_n, //reset
input uart_rxd, //the rxd pin
output uart_rx_done, //receive one byte data done
output[:] uart_rx_byte //one byte data
); //------------------------- Baud rate generator -------------------------
reg[:] cnt_baud_div;
reg baud_cap;
reg baud_start; always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
cnt_baud_div <= 'd0;
end
else begin
if(baud_start) begin
if(cnt_baud_div >= BAUD_DIV) begin
cnt_baud_div <= 'd0;
end
else begin
cnt_baud_div <= cnt_baud_div + 'b1;
end
end
else begin
cnt_baud_div <= 'd0;
end
end
end always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
baud_cap <= 'b0;
end
else begin
if(cnt_baud_div==BAUD_DIV_CAP) begin
baud_cap <= 'b1;
end
else begin
baud_cap <= 'b0;
end
end
end //------------------------- capture the uart start bit -------------------------
reg uart_rxd_r0,uart_rxd_r1,uart_rxd_r2,uart_rxd_r3;
wire uart_rxd_n; always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
uart_rxd_r0 <= 'b1; //uart_rxd of the idle state is high
uart_rxd_r1 <= 'b1;
uart_rxd_r2 <= 'b1;
uart_rxd_r3 <= 'b1;
end
else begin
uart_rxd_r0 <= uart_rxd;
uart_rxd_r1 <= uart_rxd_r0;
uart_rxd_r2 <= uart_rxd_r1;
uart_rxd_r3 <= uart_rxd_r2;
end
end assign uart_rxd_n = (uart_rxd_r3 & uart_rxd_r2 & ~uart_rxd_r1 & ~uart_rxd_r0)? 'b1 : 1'b0; //capture the uart_rxd negedge //------------------------- the uart rxd work -------------------------
localparam[:] UART_IDLE = 'd0; //IDLE
localparam[:] UART_START= 'd1; //START BIT
localparam[:] UART_BIT0 = 'd2; //BIT0
localparam[:] UART_BIT1 = 'd3; //BIT1
localparam[:] UART_BIT2 = 'd4; //BIT2
localparam[:] UART_BIT3 = 'd5; //BIT3
localparam[:] UART_BIT4 = 'd6; //BIT4
localparam[:] UART_BIT5 = 'd7; //BIT5
localparam[:] UART_BIT6 = 'd8; //BIT6
localparam[:] UART_BIT7 = 'd9; //BIT7
localparam[:] UART_STOP = 'd10; //STOP BIT reg[:] state_rx;
reg uart_rx_done_r;
reg[:] uart_rx_byte_r0;
reg[:] uart_rx_byte_r1; always@(posedge clk or negedge rst_n)
begin
if(!rst_n) begin
state_rx <= UART_IDLE;
uart_rx_done_r <= 'b0;
uart_rx_byte_r0 <= 'd0;
uart_rx_byte_r1 <= 'd0;
baud_start <= 'b0;
end
else begin
case(state_rx)
UART_IDLE: if(uart_rxd_n) begin
uart_rx_done_r <= 'b0;
baud_start <= 'b1;
state_rx <= UART_START;
end
else begin
uart_rx_done_r <= 'b0;
baud_start <= 'b0;
state_rx <= UART_IDLE;
end
UART_START: if(baud_cap) begin
state_rx <= UART_BIT0;
end
else begin
state_rx <= UART_START;
end
UART_BIT0: if(baud_cap) begin
uart_rx_byte_r0[] <= uart_rxd;
state_rx <= UART_BIT1;
end
else begin
uart_rx_byte_r0 <= uart_rx_byte_r0;
state_rx <= UART_BIT0;
end
UART_BIT1: if(baud_cap) begin
uart_rx_byte_r0[] <= uart_rxd;
state_rx <= UART_BIT2;
end
else begin
uart_rx_byte_r0 <= uart_rx_byte_r0;
state_rx <= UART_BIT1;
end
UART_BIT2: if(baud_cap) begin
uart_rx_byte_r0[] <= uart_rxd;
state_rx <= UART_BIT3;
end
else begin
uart_rx_byte_r0 <= uart_rx_byte_r0;
state_rx <= UART_BIT2;
end
UART_BIT3: if(baud_cap) begin
uart_rx_byte_r0[] <= uart_rxd;
state_rx <= UART_BIT4;
end
else begin
uart_rx_byte_r0 <= uart_rx_byte_r0;
state_rx <= UART_BIT3;
end
UART_BIT4: if(baud_cap) begin
uart_rx_byte_r0[] <= uart_rxd;
state_rx <= UART_BIT5;
end
else begin
uart_rx_byte_r0 <= uart_rx_byte_r0;
state_rx <= UART_BIT4;
end
UART_BIT5: if(baud_cap) begin
uart_rx_byte_r0[] <= uart_rxd;
state_rx <= UART_BIT6;
end
else begin
uart_rx_byte_r0 <= uart_rx_byte_r0;
state_rx <= UART_BIT5;
end
UART_BIT6: if(baud_cap) begin
uart_rx_byte_r0[] <= uart_rxd;
state_rx <= UART_BIT7;
end
else begin
uart_rx_byte_r0 <= uart_rx_byte_r0;
state_rx <= UART_BIT6;
end
UART_BIT7: if(baud_cap) begin
uart_rx_byte_r0[] <= uart_rxd;
state_rx <= UART_STOP;
end
else begin
uart_rx_byte_r0 <= uart_rx_byte_r0;
state_rx <= UART_BIT7;
end
UART_STOP: if(baud_cap) begin
uart_rx_done_r <= 'b1;
uart_rx_byte_r1 <= uart_rx_byte_r0;
baud_start <= 'b0;
state_rx <= UART_IDLE;
end
else begin
uart_rx_done_r <= 'b0;
uart_rx_byte_r1 <= uart_rx_byte_r1;
baud_start <= 'b1;
state_rx <= UART_STOP;
end
default: state_rx <= UART_IDLE;
endcase
end
end assign uart_rx_done = uart_rx_done_r;
assign uart_rx_byte = uart_rx_byte_r1;
endmodule
UART_RX_PATH
4.参考资料
《通信IC设计》 李庆华著
【基本知识】UART接口的更多相关文章
- UART接口基本知识
Universal asynchronous transciever即同一异步收发器,也就是我们平时所说的串口,是一种最简单,最基本的通信接口. 通信接口按照不同的标准有不同的分类,常见的有同步或异步 ...
- 【原创】FPGA开发手记(一) UART接口
以下内容均以Xilinx的Nexys3作为开发板 1. UART简介 UART(即Universal Asynchronous Receiver Transmitter 通用异步收发器)是广泛使用的串 ...
- UART接口
1.UART UART(Universal Asynchronous Receiver and Transmitter)通用异步收发器(异步串行通信口),是一种通用的数据通信协议,它包括了RS232. ...
- UART接口与COM口的区别
原文地址:https://blog.csdn.net/wordwarwordwar/article/details/78883732 简单的讲:(UART与COM) 嵌入式里面说的串口,一般是指UAR ...
- UART接口介绍
1. 简介 UART, Universal Asynchronous Receiver-Transmitter, 通用异步收发传输器 UART协议规定了通信双方所遵守的规定,属于数据链路层RS232接 ...
- uart接口介绍和认识
接口/总线/驱动 UART (Universal Asynchronous Receiver/Transmitter) 通用异步收发器. UART是用于控制计算机与串行设备的芯片.有一点要注意的是,它 ...
- Cypress的开发板的UART接口打印调试信息
说实话,在官方论坛现在还没有找到相关有用的消息,因为我们这个开发板的UART没引出来. http://www.cypress.com/?app=forum&id=167&rID=527 ...
- MVVM设计模式基础知识--ICommand接口
命令是 Windows Presentation Foundation (WPF) 中的输入机制,它提供的输入处理比设备输入具有更高的语义级别. 命令有若干用途: 第一个用途是将语义以及调用命令的对象 ...
- UART Explained(转载)
做嵌入式开发,UART几乎是必不可少的,调试串口.GPS.GPRS.Bluetooth等模块很多都是用的UART接口.时下火热的IoT也不乏UART的身影,串口的BLE.WIFI.Zigbee.Lor ...
随机推荐
- RookeyFrame 一些心得 或者 调试技巧等
因为没有依赖具体的实现层,类库的输出路径又没有设置在web层的bin目录,所以每次都要拷贝实现层的DLL过去,有时候拷贝过去了还是没有反应,估计是缓存什么的吧, 解决:先那几个web层bin目录的 D ...
- Impala 架构探索-Impala 系统组成与使用调优
要好好使用 Impala 就得好好梳理一下他得结构以及他存在得一些问题或者需要注意得地方.本系列博客主要想记录一下对 Impala 架构梳理以及使用上的 workaround. Impala 简介 首 ...
- pytesseract.pytesseract.TesseractError: (1, 'Error opening data file /usr/local/share/tessdata/chi_sim.traineddata Please make sure the TESSDATA_PREFIX environment variable is set to your "tessdata"
pytesseract.pytesseract.TesseractError: (1, 'Error opening data file /usr/local/share/tessdata/chi_s ...
- 【CSP膜你赛】大逃亡
题目描述 魔王撒旦为了建立魔物的乐土,率领亚多拉玛雷克.艾谢尔.路西菲尔.以 及马纳果达这四位恶魔大元帅进攻人类世界.然而此时手持圣剑的勇者艾米莉亚出现了. 战败的魔王逃跑时穿越到了地球,以真奥贞夫 ...
- 责任链模式(chainOfResponsibility)
参考文章:http://wiki.jikexueyuan.com/project/design-pattern-behavior/chain-four.html 定义: 使多个对象都有机会处理请求,从 ...
- count(*) count(1) count(字段) 区别
count(*) count(1) count(字段) 区别 count(*)和count(字段) count(*)和count(字段)使用的目的是不一样的,在必须要使用count(字段)的时候还是要 ...
- linux中SIGHUP与nohup的关系
SIGHUP信号与控制终端 UNIX中进程组织结构为 session (会话)包含一个前台进程组及一个或多个后台进程组,一个进程组包含多个进程.一个session可能会有一个session首进程, ...
- File checksum
File checksum https://golang.org/pkg/io/#Copy https://blog.iphpo.com/blog/2017/03/golang-產生檔案的md5-ha ...
- ES6----拓展运算符 三个点【...】
[...]拓展运算符是什么? es6中引入扩展运算符(...),它用于把一个数组转化为用逗号分隔的参数序列,它常用在不定参数个数时的函数调用,数组合并等情形.因为typeScript是es6的超集,所 ...
- Nodejs 包与 npm第三方模块安装和 package.json 以及 cnpm
包与 NPM 1. 包 Nodejs 中除了它自己提供的核心模块外,可以自定义模块,也可以使用第三方的模块.Nodejs 中第三方模块由包组成,可以通过包来对一组具有相互依 赖关系的模块进行统一管理. ...