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接口的更多相关文章

  1. UART接口基本知识

    Universal asynchronous transciever即同一异步收发器,也就是我们平时所说的串口,是一种最简单,最基本的通信接口. 通信接口按照不同的标准有不同的分类,常见的有同步或异步 ...

  2. 【原创】FPGA开发手记(一) UART接口

    以下内容均以Xilinx的Nexys3作为开发板 1. UART简介 UART(即Universal Asynchronous Receiver Transmitter 通用异步收发器)是广泛使用的串 ...

  3. UART接口

    1.UART UART(Universal Asynchronous Receiver and Transmitter)通用异步收发器(异步串行通信口),是一种通用的数据通信协议,它包括了RS232. ...

  4. UART接口与COM口的区别

    原文地址:https://blog.csdn.net/wordwarwordwar/article/details/78883732 简单的讲:(UART与COM) 嵌入式里面说的串口,一般是指UAR ...

  5. UART接口介绍

    1. 简介 UART, Universal Asynchronous Receiver-Transmitter, 通用异步收发传输器 UART协议规定了通信双方所遵守的规定,属于数据链路层RS232接 ...

  6. uart接口介绍和认识

    接口/总线/驱动 UART (Universal Asynchronous Receiver/Transmitter) 通用异步收发器. UART是用于控制计算机与串行设备的芯片.有一点要注意的是,它 ...

  7. Cypress的开发板的UART接口打印调试信息

    说实话,在官方论坛现在还没有找到相关有用的消息,因为我们这个开发板的UART没引出来. http://www.cypress.com/?app=forum&id=167&rID=527 ...

  8. MVVM设计模式基础知识--ICommand接口

    命令是 Windows Presentation Foundation (WPF) 中的输入机制,它提供的输入处理比设备输入具有更高的语义级别. 命令有若干用途: 第一个用途是将语义以及调用命令的对象 ...

  9. UART Explained(转载)

    做嵌入式开发,UART几乎是必不可少的,调试串口.GPS.GPRS.Bluetooth等模块很多都是用的UART接口.时下火热的IoT也不乏UART的身影,串口的BLE.WIFI.Zigbee.Lor ...

随机推荐

  1. Android编程权威指南笔记3:Android Fragment讲解与Android Studio中的依赖关系,如何添加依赖关系

    Android Fragment 当我在学习时,了解了Fragment词汇 Fragment是一种控制器对象,我就把所了解的简单说一下.activity可以派fragment完成一些任务,就是管理用户 ...

  2. 04-树5 Root of AVL Tree (25 分)

    An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...

  3. java8 instant localDateTime

  4. 让ie10/11支持非单页面的vue/es6

    为了满足某些客户的要求,最近让前端同学实现了ie 10(windows 7)/11(windows 10)支持多页面的vue/es6,基本参考如下: https://www.cnblogs.com/n ...

  5. vs2015 项目调试出现未能加载文件或程序集“Antlr3.Runtime”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

    今天在调试项目不知道怎么了,突然就报未能加载文件或程序集“Antlr3.Runtime”或它的某一个依赖项.找到的程序集清单定义与程序集引用不匹配. (异常来自 HRESULT:0x80131040) ...

  6. 【4opencv】为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍

            基于OpenCV编写图像处理项目,除了算法以外,比较重要一个问题就是界面设计问题.对于c++语系的程序员来说,一般来说有QT/MFC两种考虑.QT的确功能强大,特别是QML编写andr ...

  7. node.js GET与POST请求

    node.js GET与POST请求 转 http://www.voidcn.com/article/p-ncglaiqx-bdx.html 标签 get post node.js 栏目 Node.j ...

  8. tensorflow 13:多gpu 并行训练

    多卡训练模式: 进行深度学习模型训练的时候,一般使用GPU来进行加速,当训练样本只有百万级别的时候,单卡GPU通常就能满足我们的需求,但是当训练样本量达到上千万,上亿级别之后,单卡训练耗时很长,这个时 ...

  9. fiddler抓包详解

    image.png 前言 fiddler是一个很好的抓包工具,默认是抓http请求的,对于pc上的https请求,会提示网页不安全,这时候需要在浏览器上安装证书. 一.网页不安全 1.用fiddler ...

  10. java中map和对象互转工具类的实现示例

    在项目开发中,经常碰到map转实体对象或者对象转map的场景,工作中,很多时候我们可能比较喜欢使用第三方jar包的API对他们进行转化,而且用起来也还算方便,比如像fastJson就可以轻松实现map ...