【基本知识】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 ...
随机推荐
- LINUX下的gdb调试方法
首先对目标文件进行编译 例如: gcc test.c -o test 这时会生成一个文件test,然后我们就可以对test进行调试了 示例: gdb test 好了以后是设定断点 示例: break ...
- uni-app 网络请求
uni.request发起网络请求 url 开发者服务器接口地址 data 请求的参数 header method dataType responseType 设置响应的数据类型 statusCode ...
- ES6 fetch方法封装
// 请求路径 let url = 'http://jsonplaceholder.typicode.com/users' // 传输数据参数 const dataName = { name: &qu ...
- Android Studio 之 Activity 的生命周期
翻转屏幕,会重新加载Activity package com.example.activitylivecycle; import android.os.Bundle; import android.u ...
- java 多页pdf转化为多张图片
相关jar包: <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian ...
- java8 instant localDateTime
- 使用Signature Tool自动生成P/Invoke调用Windows API的C#函数声明【转】
原文链接:https://blog.csdn.net/Donjuan/article/details/3865026在网上看到很多网友在.NET程序中调用Win32 API,或者调用自己的VC DLL ...
- MyBatis(九):Mybatis Java API批量操作(增、删、改、查)
最近工作中用到了mybatis的Java API方式进行开发,顺便也整理下该功能的用法,接下来会针对基本部分进行学习: 1)Java API处理一对多.多对一的用法: 2)增.删.改.查的用法: 3) ...
- grpc使用记录(三)简单异步服务实例
目录 grpc使用记录(三)简单异步服务实例 1.编写proto文件,定义服务 2.编译proto文件,生成代码 3.编写服务端代码 async_service.cpp async_service2. ...
- 使用SpringEL功能来动态化模板数据
在类似excel导出功能里,如果excel的格式很复杂,通过程序去动态生成格式显然是很吃力的,我们可以采用模板文件+动态表达式占位来生成目标文件. 如果只是纯粹生成纯文本,使用freemarker等模 ...