Uart串口receive端实现
一、Uart串口:
串行通信:占用引脚少,但速度慢。
异步通信:不带有时钟同步信号,通过波特率限定通信。
全双工:可同时进行双向通信。
二、Uart通信数据格式(一般不使用停止位)
![](/assets/blank.gif)
三、时序图
![](/assets/blank.gif)
四、信号介绍
信号名称 |
介绍 |
操作 |
FREQ |
系统时钟频率(单位MHz) |
input |
BPS |
波特率 |
input |
clk |
系统时钟 |
input |
rst_n |
低电平复位 |
input |
rxd |
信号输入 |
input |
dat_vld |
输出数据有效使能(1个clock) |
output |
dat_o |
输出数据【7:0】 |
output |
dn_edge |
下降沿检测 |
对输入的rxd接收数据进行下降沿检测,获得开始接受数据的启动信号。 |
rx_flag |
发送使能状态 |
当检测到启动信号后拉高,直到rx_cnt=9的前一个时钟拉低 |
clk_cnt |
波特率计数,时钟信号匹配 |
在发送使能期间循环计数 |
rx_cnt |
对uart串口数据格式计数 |
发送使能时计数 |
五、代码展示
// data width = 8module uart_rx#(parameter FREQ = 50 ,//clock frequency MHzparameter BPS = 115200 //baud rate)(clk ,//input, clockrst_n ,//input, reset active in lowrxd ,//input, receive datadat_vld ,//output, data validdat_o //output, output data );input clk ;input rst_n ;input rxd ;output reg dat_vld ;output reg [7:0] dat_o ;localparam CLK_CNT_MAX = FREQ*1000000 / BPS - 1;localparam CCM_BIT = $clog2(CLK_CNT_MAX);reg [1:0] rxd_r ;reg [CCM_BIT-1:0] clk_cnt ;reg rx_flag ;reg [3:0] rx_cnt ;//0-9(data:1-8)//get the down edge of the input data(rxd) always@(posedge clk or negedge rst_n) beginif (!rst_n)rxd_r <= 2'b00;elserxd_r <= {rxd_r[0],rxd};endwire dn_edge = (!rxd_r[0]) & rxd_r[1];//down edge of the rxd//division of the clkalways@(posedge clk or negedge rst_n) beginif (!rst_n)clk_cnt <= 'b0;else if (rx_flag)clk_cnt <= (clk_cnt == CLK_CNT_MAX)? 'b0 : (clk_cnt + 1'b1);elseclk_cnt <= 'b0;end//rx_flagalways@(posedge clk or negedge rst_n) beginif (!rst_n)rx_flag <= 1'b0;else if (dn_edge)rx_flag <= 1'b1;else if ((rx_cnt == 4'd9) && (clk_cnt == CLK_CNT_MAX/2))rx_flag <= 1'b0;elserx_flag <= rx_flag;end//rx_cntalways@(posedge clk or negedge rst_n) beginif (!rst_n)rx_cnt <= 'b0;else if (rx_flag)rx_cnt <= (clk_cnt == CLK_CNT_MAX)? (rx_cnt + 1'b1) : rx_cnt;elserx_cnt <= 'b0;end//dat_vldalways@(posedge clk or negedge rst_n) beginif (!rst_n)dat_vld <= 1'b0;else if ((rx_cnt == 4'd8) && (clk_cnt == CLK_CNT_MAX))dat_vld <= 1'b1;elsedat_vld <= 1'b0;end//dat_oalways@(posedge clk or negedge rst_n) beginif (!rst_n)dat_o <= 'b0;else if(rx_flag) beginif (clk_cnt == CLK_CNT_MAX/2)case(rx_cnt)4'd1 : dat_o[0] <= rxd_r[1]; 4'd2 : dat_o[1] <= rxd_r[1];4'd3 : dat_o[2] <= rxd_r[1];4'd4 : dat_o[3] <= rxd_r[1];4'd5 : dat_o[4] <= rxd_r[1];4'd6 : dat_o[5] <= rxd_r[1];4'd7 : dat_o[6] <= rxd_r[1];4'd8 : dat_o[7] <= rxd_r[1];default: dat_o <= dat_o;endcaseelsedat_o <= dat_o;endelsedat_o <= dat_o;endendmodule
六、结果测试
使用上位机串口调试助手发送一个数据,将这个数据显示到FPGA开发板上面的led数码管显示。
需要添加两个代码:
1、8位的二进制数据转换为12位的BCD码。
2、BCD码显示在FPGA开发板上面的代码。
![](/assets/blank.gif)
module bin2BCD(bin , bcd);input [7:0] bin;output [11:0] bcd;reg [3:0] hundreds ;reg [3:0] tens ;reg [3:0] ones ; integer i;always@(*) beginhundreds = 4'b0000;tens = 4'b0000;ones = 4'b0000;for(i=7;i>=0;i=i-1) beginif(hundreds >= 5) hundreds = hundreds + 2'b11;if(tens >= 5) tens = tens + 2'b11;if(ones >= 5) ones = ones + 2'b11;hundreds = hundreds << 1;hundreds[0] = tens[3];tens = tens << 1;tens[0] = ones[3];ones = ones << 1;ones[0] = bin[i];endendassign bcd = {hundreds,tens,ones};endmodule
//FPGA board have the six display led: seg_scn
//default:not display the dot,just number: seg_led[7]=1module BCD_led_disp#(parameter CLK_FREQ = 50, // the frequency the clock MHzparameter DISP_INTV = 100,//the switch interval of the led, usparameter LED_NUM = 3 //the number of the LED used)(clk , rst_n ,bcd_vld ,bcd ,seg_scn ,seg_led );input clk ;input rst_n ;input bcd_vld ;//input, data_bcd enable 1 clockinput [4*LED_NUM-1:0] bcd ;output reg [5:0] seg_scn ;output [7:0] seg_led ;localparam CNTSCN_MAX = DISP_INTV * 100 / 20 - 1;reg [$clog2(CNTSCN_MAX)-1:0] cnt_scn;reg [4*LED_NUM-1:0] bcd_r;assign seg_led[7] = 1'b1; always@(posedge clk or negedge rst_n) beginif (!rst_n)cnt_scn <= 'b0;else if (bcd_vld || (cnt_scn == CNTSCN_MAX))cnt_scn <= 'b0;elsecnt_scn <= cnt_scn + 1'b1;endalways@(posedge clk or negedge rst_n) beginif (!rst_n)seg_scn <= 6'b111111;else if (bcd_vld)seg_scn <= 6'b111110;else if (cnt_scn == CNTSCN_MAX)seg_scn <= {seg_scn[5:(6-LED_NUM)],seg_scn[LED_NUM-2:0],seg_scn[LED_NUM-1]};endalways@(posedge clk or negedge rst_n) beginif (!rst_n)bcd_r <= 'b0;else if (bcd_vld)bcd_r <= bcd;else if (cnt_scn == CNTSCN_MAX)bcd_r <= {bcd_r[3:0],bcd_r[LED_NUM*4-1:4]};endwire [3:0] bcdnum_temp = bcd_r[3:0];led_disp u_led_disp(.num (bcdnum_temp),.led (seg_led[6:0]));endmodulemodule led_disp(num ,led );input [3:0] num ;output reg [6:0] led ;always@(*) begincase(num)4'b0000: led = 7'b1000000;4'b0001: led = 7'b1111001;4'b0010: led = 7'b0100100;4'b0011: led = 7'b0110000;4'b0100: led = 7'b0011001;4'b0101: led = 7'b0010010;4'b0110: led = 7'b0000010;4'b0111: led = 7'b1111000;4'b1000: led = 7'b0000000;4'b1001: led = 7'b0010000;4'b1010: led = 7'b0001000;4'b1011: led = 7'b0000011;4'b1100: led = 7'b1000110;4'b1101: led = 7'b0100001;4'b1110: led = 7'b0000110;4'b1111: led = 7'b0001110;default: led = 7'b1111111;endcaseend
endmodule
测试时需要将三个代码例化到一个top里面:
module top(clk , rst_n ,rxd ,seg_scn ,seg_led );input clk ;input rst_n ;input rxd ;output [5:0] seg_scn ;output [7:0] seg_led ;wire dat_vld ;wire [7:0] dat_o ;wire [11:0] bcd ;assign txd = 1;uart_rx#(.FREQ(50),.BPS(115200)//baud rate)u_uart_rx(.clk (clk ),.rst_n (rst_n ),.rxd (rxd ),//input, receive data.dat_vld (dat_vld),//output, data valid.dat_o (dat_o ) //output, output data );bin2BCD u_bin2BCD(.bin (dat_o), .bcd (bcd));BCD_led_disp#(.CLK_FREQ (50 ), // the frequency the clock MHz.DISP_INTV (100),//the switch interval of the led, us.LED_NUM (3 ) //the number of the LED used)(.clk (clk ), .rst_n (rst_n ),.bcd_vld (dat_vld),.bcd (bcd ),.seg_scn (seg_scn),.seg_led (seg_led));endmodule
七、测试结果展示
![](/assets/blank.gif)
![](/assets/blank.gif)
Uart串口receive端实现相关推荐
- ZYNQ进阶之路14--PS端uart串口接收不定长数据
ZYNQ进阶之路14--PS端uart串口接收不定长数据 导语 ZYNQ串口简介 实现步骤 导语 繁忙的博主又来了,本节我们实现一个比较简单的东西:串口.之前的章节中我们也有使用PS端的串口进行收发数 ...
- 串口的偶校验位设置_详解UART串口
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,通常称作UART) 是一种串行异步收发协议,应用十分广泛.UART工作原理是将数据的二进制位 ...
- SJXXX串口扩展芯片 4串口芯片 UART串口芯片
SJXX串口扩展芯片 1 概述 SJ000是一款具备I2C总线/SPI总线/UART接口的四通道异步收发器件,通过模式选择使得该器件工作于以上任何一种主接口模式下.器件的四个通道UART可提供高达2M ...
- 【FPGA】——UART串口通信
UART串口简介 串行通信分为两种方式:同步串行通信和异步串行通信.同步串行通信要求通信双方使用同一时钟,异步则没有这个要求.UART是一种采用异步串行通信方式的通用异步收发传输器(univers ...
- linux裸机串口,裸机系列-UART串口
下面我们就给出如何用s3c2440来实现非FIFO的UART通信.要实现某种通信,就必须遵循该通信协议.UART的协议包括传输数据的位数,停止位的位数,以及是否进行奇偶校验,这些设置是利用ULCONn ...
- MTK:UART串口收发数据
MTK之UART串口收发数据 转:https://blog.csdn.net/ivy_reny/article/details/51192110 寄存器 UARTn_RBR: Rx Buffer Re ...
- 基于FPGA实现uart串口模块(Verilog)--------接收模块及思路总结
基于FPGA实现uart串口模块(Verilog)--------接收模块及思路总结 uart通信协议简单理解为串转并和并转串的两个模块.同时必须保证数据的正确性.且输入输出端为串行. 此次实现uar ...
- 【正点原子MP157连载】 第十六章 UART串口通信实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- UART串口DB9的连接
在PC端,UART串口DB9的管脚2用来对PC机来说是接收 管脚3是PC机串口的发送
最新文章
- 物理化学 化学平衡
- 极速写作2017彻底卸载_如何将 Flash 从 Mac 和 Windows 系统中彻底卸载?
- Spring Data MongoDB级联保存在DBRef对象上
- AI算法连载15:统计之数据降维
- 字符串匹配(一)—— KMP / MP
- wps中,点空格或者enter之后首字母变大写问题
- U盘的用法用途与维护
- mysql高级用法(函数)
- 什么是php 的精华,在用PHP开发中的精华和技巧总结
- Excel VBA 循环读取一个目录下面多个文件的内容,放到另外一个文件中
- wxParse空格解析不生效的解决方案
- HTML5全套视频教程合集分享-2018年千锋最新录制
- 基于MT5的沪深股票回测一 创建自定义合约
- 云原生数据库-Amazon RDS
- 教你如何制作并压缩高质量视频
- 怎么把计算机里面的解压到桌面上,电脑桌面怎么加压文件
- 人工智能入门:基于Linux与Python的神经网络
- java:从左至右显示“12345678”,接着显示“23456781”,在接着显示“34567812”,一直到“81234567”, 然后返回“12345678”
- MCK主机加固数据安全解决方案
- 一文看懂:零代码、0代码、无代码平台是什么?怎么选?
热门文章
- java介于编译型和解释型
- 前端小项目-Thunder Raid(全民飞机大战)-html+css+js 含视频课程+全套代码
- Django_rest框架片段高亮显示实践项目(一)url和view里面的代码的书写
- 检測wifi是否须要portal验证 公共场所wifi验证
- opencvBGR转RGB,图片灰度、腐蚀、膨胀、降噪、模糊的代码例子
- 红芯电子对FPGA逻辑设计的解读
- Android ImageCropper 矩形 圆形 裁剪框
- 计算机网络 第三章 数据链路层总结
- 热电偶基础知识介绍-04
- 嵌入式音频架构 - AudioWeaver 整体概念