文章目录

  • 前言
  • 一、UART关键参数
  • 二、数据接收子功能介绍
    • 1.子功能函数
    • 2.仿真测试模块
  • 总结

前言

使用FPGA自带USB转串口实现指定波特率的单个数据的发送。


一、UART关键参数

1、波特率:每秒钟可以发送或接收的数据比特的个数,发送和接收的设备需要波特率一致才可,常见的波特率有9600、19200、38400、57600等。
2、一帧数据:包含一位起始位;1或1.5或2位停止位;5到8位数据位;1位或没有奇偶校验位。在RS232标准中,最常用的配置是使用8位数据位、1位停止位、1位起始位、无奇偶校验位进行,共十位数据。
3、UART发送一字节数据时序图:

串口接收和串口发送方式略有不同,工业情况下,常常有强电磁干扰,导致数据会被影响,因此只采样一次就作为该数据的电平状态时不可靠的,为消除干扰,采用多次采样求概率的方式进行状态判定:

对于Bit_x这一位数据,共分成16次采样,在发生变化后和即将发生变化时有可能不稳定,因此忽略掉深色部分,对中间六次采样数据进行概率比较,出现次数多的电平为有效电平。(通常不会出现低电平和高电平均为3个的时候,数据不可靠,不做处理)

二、数据接收子功能介绍

  1. 使用两个寄存器消除亚稳态
  2. 查找表查找bps

    记采样计数值最大值为bps_DR。
  3. 分频计数器:将系统50MHz的时钟进行分频,每记数到一个bps_DR即输出一个bps_clk。
  4. 波特率时钟:波特率时钟,每进行一次分频,bps_clk置1,时间为一个系统周期(20ns)。
  5. 波特率时钟计数器:
    计数满判定:rx_done
    rx_done判定:bps_cnt=16*10=160-1时,rx_done置1
    清零判定:起始错误
  6. 数据接收采样:bps_cnt=0时,寄存器r_data_byte置0
    当bps_cnt=6时开始采样,此后每加16即为每位数据起始采样点,采样到的数据进行累加并加上同步后的rs232_rx即s1_rs232_rx。
  7. 数据状态分析:
    采样6次,高电平大于三次即为1,反之为0,大于三的有100、101、110,因此只需最高位为1即为1,引入二重数组:[2:0]r_data_byte[7:0]进行判定,结果存在data_byte中。

1.子功能函数

  1. 定义:
module uart_byte_rx(clk,rst_n,baud_set,rs232_rx,data_byte,rx_done
);input clk;input rst_n;input [2:0]baud_set;input rs232_rx;output reg[7:0]data_byte;output reg rx_done;reg s0_rs232_rx,s1_rs232_rx;//同步寄存器,消除亚稳态reg tmp0_rs232_rx,tmp1_rs232_rx;//数据寄存器reg [15:0]bps_DR;//分频计数器计数最大值reg [15:0]div_cnt;//分频计数器计数最大值reg uart_state;reg [2:0] r_data_byte[7:0];  reg [2:0] START_BIT,STOP_BIT;reg bps_clk;//波特率时钟reg [7:0]bps_cnt;wire nedege;
  1. 消除亚稳态
//同步寄存器,消除亚稳态
always @(posedge clk or negedge rst_n)
if(!rst_n)begins0_rs232_rx<=1'b0;s1_rs232_rx<=1'b0;
end
else begins0_rs232_rx<=rs232_rx;s1_rs232_rx<=s0_rs232_rx;
end
  1. 数据寄存器
//数据寄存器
always @(posedge clk or negedge rst_n)
if(!rst_n)begintmp0_rs232_rx<=1'b0;tmp1_rs232_rx<=1'b0;
end
else begintmp0_rs232_rx<=s1_rs232_rx;tmp1_rs232_rx<=tmp0_rs232_rx;
endassign nedege=!tmp0_rs232_rx & tmp1_rs232_rx;
  1. 查找表查找bps
always @(posedge clk or negedge rst_n)
if(!rst_n)bps_DR<=16'd324;
else begincase(baud_set)0:bps_DR<=16'd324;1:bps_DR<=16'd162;2:bps_DR<=16'd80;3:bps_DR<=16'd53;4:bps_DR<=16'd26;default:bps_DR<=16'd324;endcase
end
  1. 分频计数器
always @(posedge clk or negedge rst_n)
if(!rst_n)div_cnt<=16'd0;
else if(uart_state)beginif(div_cnt==bps_DR)div_cnt<=16'd0;elsediv_cnt<=div_cnt+1'b1;
end
elsediv_cnt<=16'd0;
  1. 波特率时钟
always @(posedge clk or negedge rst_n)
if(!rst_n)bps_clk<=1'b0;
else if(div_cnt==16'd1)bps_clk<=1'b1;
elsebps_clk<=1'b0;
  1. 波特率时钟计数器
//波特率时钟计数器   always @(posedge clk or negedge rst_n)if(!rst_n)bps_cnt<=8'b0;else if(rx_done | (bps_cnt==8'd12 && (START_BIT>2)))bps_cnt<=8'b0;else if(bps_clk)bps_cnt<=bps_cnt+1'b1;else bps_cnt<=bps_cnt;
  1. 接收完毕信号
always @(posedge clk or negedge rst_n)
if(!rst_n)rx_done<=1'b0;
else if(bps_cnt==8'd159)rx_done<=1'b1;
elserx_done<=1'b0;
  1. 数据接收采样
always @(posedge clk or negedge rst_n)
if(!rst_n)beginSTART_BIT=3'd0;r_data_byte[0]<=3'd0;r_data_byte[1]<=3'd0;r_data_byte[2]<=3'd0;r_data_byte[3]<=3'd0;r_data_byte[4]<=3'd0;r_data_byte[5]<=3'd0;r_data_byte[6]<=3'd0;r_data_byte[7]<=3'd0;STOP_BIT=3'd0;
end
else begincase(bps_cnt)0:beginSTART_BIT=3'd0;r_data_byte[0]<=3'd0;r_data_byte[1]<=3'd0;r_data_byte[2]<=3'd0;r_data_byte[3]<=3'd0;r_data_byte[4]<=3'd0;r_data_byte[5]<=3'd0;r_data_byte[6]<=3'd0;r_data_byte[7]<=3'd0;STOP_BIT=3'd0;end6,7,8,9,10,11:START_BIT<=START_BIT+s1_rs232_rx;22,23,24,25,26,27:r_data_byte[0]<=r_data_byte[0]+s1_rs232_rx;38,39,40,41,42,43:r_data_byte[1]<=r_data_byte[1]+s1_rs232_rx;54,55,56,57,58,59:r_data_byte[2]<=r_data_byte[2]+s1_rs232_rx;70,71,72,73,74,75:r_data_byte[3]<=r_data_byte[3]+s1_rs232_rx;86,87,88,89,90,91:r_data_byte[4]<=r_data_byte[4]+s1_rs232_rx;102,103,104,105,106,107:r_data_byte[5]<=r_data_byte[5]+s1_rs232_rx;118,119,120,121,122,123:r_data_byte[6]<=r_data_byte[6]+s1_rs232_rx;134,135,136,137,138,139:r_data_byte[7]<=r_data_byte[7]+s1_rs232_rx;150,151,152,153,154,155:STOP_BIT<=STOP_BIT+s1_rs232_rx;default;endcase
end
  1. 数据状态分析
always @(posedge clk or negedge rst_n)
if(!rst_n)data_byte<=8'd0;
else if(bps_cnt==8'd159) begindata_byte[0]=r_data_byte[0][2];data_byte[1]=r_data_byte[1][2];data_byte[2]=r_data_byte[2][2];data_byte[3]=r_data_byte[3][2];data_byte[4]=r_data_byte[4][2];data_byte[5]=r_data_byte[5][2];data_byte[6]=r_data_byte[6][2];data_byte[7]=r_data_byte[7][2];
end
  1. uart_state状态
always @(posedge clk or negedge rst_n)
if(!rst_n)uart_state<=1'b0;
else if(nedege)uart_state<=1'b1;
else if(rx_done || (bps_cnt==8'd12 && (START_BIT>2)))uart_state<=1'b0;
elseuart_state<=uart_state;

2.仿真测试模块

`timescale 1ns/1ns
`define clk_period 20module uart_byte_rx_tb;reg clk;reg rst_n;reg [2:0]baud_set;reg rs232_rx;wire [7:0]data_byte_r;wire rx_done;reg send_en;reg [7:0]data_byte_t;wire rs232_tx;wire tx_done;wire uart_state;uart_byte_rx uart_byte_rx(.clk(clk),.rst_n(rst_n),.baud_set(baud_set),.rs232_rx(rs232_rx),.data_byte(data_byte_r),.rx_done(rx_done));uart_byte_tx uart_byte_tx1(.clk(clk),.rst_n(rst_n),.send_en(send_en),.data_byte(data_byte_t),.baud_set(baud_set),.rs232_tx(rs232_tx),.tx_done(tx_done),.uart_state(uart_state));initial clk=1;always #(`clk_period/2) clk=~clk;initial beginrst_n=1'b0;send_en=1'b0;data_byte_t=8'd0;baud_set=3;#(`clk_period*20+1)rst_n=1'b1;send_en=1'b1;data_byte_t=8'haa;#`clk_period;send_en=1'b0;@(posedge tx_done)#(`clk_period*5000);data_byte_t=8'h55;send_en=1'b1;#`clk_period;send_en=1'b0;@(posedge tx_done)#(`clk_period*5000);$stop;end
endmodule

总结

以上便是UART串行异步通信实现单个数据的接收原理及代码。板级验证时使用FPGA自带的USB转串口实现数据接收。

FPGA之实现UART串行异步通信-一字节数据接收相关推荐

  1. 关于STM32的串行异步通信

    [串行异步通信] STM32F4 的串口资源相当丰富的,功能也相当强劲. STM32F407ZGT6 最多可提供 6 路串口,有分数波特率发生器.支持同步单线通信和 半双工单线通讯.支持 LIN.支持 ...

  2. 基于FPGA实现的高速串行交换模块实现方法研究

    基于FPGA实现的高速串行交换模块实现方法研究 https://wenku.baidu.com/view/9a3d501a227916888486d7ed.html 转载于:https://www.c ...

  3. 【微机接口】可编程串行异步通信芯片8250

    8250能实现数据串并变换,实现全双工异步通信. 支持异步通信协议,数据格式.通信速率由初始化编程设定. 内部有中断机制,CPU可用查询中断方式与之交换信息. 8250内部寄存器:  发送保持寄存器: ...

  4. 串行异步通信_单片机串行口介绍

    串行口是单片机与外界进行信息交换的工具,8051单片机的通信方式有两种: 并行通信:数据的各位同时发送或接收. 串行通信:数据一位一位次序发送或接收. 串行通信的方式 异步通信 用一个起始位0表示字符 ...

  5. 树莓派 SPI,I2C,UART串行总线介绍

    很多人对总线,串行等概念不熟悉特别是SPI,I2C,UART,GPIO等概念. 因此我收集了一些资料,用于总结.希望对大家有所帮助. 首先看一下树莓派上的接口: GPIO引脚 x 26 UART总线 ...

  6. uart串行口通信(一)

    前言 人类生存于世,少不了沟通.沟通使人类互相认知,传递信息,提升生活品质.但然单片机也需要,不然单单一个机器,无法构成一个系统,发挥更大的力量.只有单片机与外围设备传递信息,互相反馈才会有一个完美的 ...

  7. 串行异步通信_串行通信中 同步通信和异步通信的区别及使用情况(转)

    在计算机系统中,CPU和外部通信有两种通信方式:并行通信和串行通信.而按照串行数据的时钟控制方式,串行通信又可分为同步通信和异步通信两种方式. 1.异步串行方式的特点 所谓异步通信,是指数据传送以字符 ...

  8. 基于FPGA的通用8251串行异步收发器(6600+字)

    1.简介与仿真结论 随着集成电路技术的发展,电子设计自动化(EDA)逐渐成为重要的设计手段,已经广泛应用于模拟与数字电路系统等许多领域.电子设计自动化是一种实现电子系统或电子产品自动化设计的技术,它与 ...

  9. 串行异步通信_什么是并行传输、串行传输、异步传输?

    串行通讯 一条信息的各位数据被逐位按顺序传送的通讯方式称为串行通讯.串行通讯的特点是:数据位传送,传按位顺序进行,最少只需一根传输线即可完成,成本低但送速度慢.串行通讯的距离可以从几米到几千米. 根据 ...

最新文章

  1. (三)硕博生常用的英文文献下载的网站
  2. Android.mk 文件语法详解
  3. 【转】每天一个linux命令(39):grep 命令
  4. Python-day06-2018.7.9_编码以及小知识点补充
  5. 二维有限元方程matlab,有限元法求解二维Poisson方程的MATLAB实现
  6. 英寸和厘米的交互python_Python的新手-尝试将厘米编码为英寸,反之亦然
  7. 绝大部分博士目前都无法进入大学
  8. BOE(京东方)供货荣耀60 Pro流光四曲屏
  9. css3之背景属性之background-size
  10. 解决git push远程分支错误
  11. Bailian2756 二叉树(POJ NOI0306-1758)【二叉树】
  12. Java多线程系列---“基础篇”08之 join()
  13. adt matlab 加速退化,可靠性加速退化试验
  14. bugkuCTF之散乱的密文
  15. CSS中的行盒(line-boxes)和行内盒子(line-box)
  16. 贵州省 建筑标准规范 合集
  17. 2016,Java成神初年
  18. 这才是做生意的正确方法,360行,行行出状元,摆摊也能赚大钱
  19. java框架的利与弊_Java编程的利与弊
  20. java常见问题处理

热门文章

  1. 袁国宝:从内容营销到超级传播,数字时代如何快速引爆产品和品牌
  2. WebGL自学课程(6):WebGL加载跨域纹理出错Uncaught Error: SECURITY_ERR: DOM Exception 18
  3. iOS11 和 iPhone X 的适配
  4. python tempstr 转换面积 平方米_python中的TempStr应用和温度转换
  5. 如何接入一个全平台实时互动白板
  6. 论文笔记:CycleMorph: Cycle Consistent UnsupervisedDeformable Image Registration
  7. 游戏模型设计用什么软件
  8. python隔5秒后执行
  9. 怎样快速有效地学会蛙泳技术
  10. 发布WordPress支持列表显示的音乐播放器插件