FPGA串口接收学习
1.接收原理和思路
初步思路:除发送位和停止位外,在数据位的每一位数据的中间时刻进行采样,读取到高电平或者低电平,如图所示:图中读取到的数据位为0110(左至右)
但是,倘若有外界干扰,忽然将某数据位的电平拉低了一瞬间,如图:此时再在各个数据位的中间时刻检测会检测到:0010(从左至右)很显然是错误的。
解决办法:在每一位的数据位上进行多次采样,然后比较0和1的概率。1的概率大就为高电平,0的概率大就为低电平。
然后还需要检测起始位,怎么检测起始位呢?边缘检测电路!边缘检测电路原理如下:
当波形2的第一个上升沿检测到波形 1的的值为1,第二个上升沿检测到波形1的值为0时,就说明其产生了下降沿。边缘检测电路由两个触发器构成,如图所示:
接下来就可以开始代码编写啦!
源文件代码:
module uart_tx(input clk,input uart_rx, //从外部接收到的数据input rst,//复位input [2:0] Baud_set,//选择接收数据的波特率,要和发送数据的波特率一致output reg [7:0] Rx_Data, //最后我们看到的数据output reg Rx_Done);reg Rx_En;//开始接收数据 //设置波特率
reg [17:0] Baud;
always@(Baud_set)
case(Baud_set)3'd0:Baud=18'd166666;//波特率为3003'd1:Baud=18'd41666;//波特率为12003'd2:Baud=18'd20833;//波特率为24003'd3:Baud=18'd5208;//波特率为96003'd4:Baud=18'd2604;//波特率为192003'd5:Baud=18'd1302;//波特率为384003'd6:Baud=18'd868;//波特率为576003'd7:Baud=18'd434;//波特率为115200
endcase //波特率分频
reg [17:0] counter_Baud;
always@(posedge clk or negedge rst)if(!rst) counter_Baud<=0;else if(Rx_En)beginif(counter_Baud==Baud-1) counter_Baud<=0;else counter_Baud<=counter_Baud+1;endelse counter_Baud<=0;//检测起始位
reg [1:0] Detect;
always@(posedge clk or negedge rst)if(!rst) Detect<=2'b00;else if(!Rx_En)beginDetect[0] <= uart_rx;Detect[1] <= Detect[0];endelse Detect<=2'b00;//控制En
always@(posedge clk or negedge rst) if(!rst) Rx_En<=0;else if(Detect==2'b10) Rx_En<=1;else if(Rx_Done) Rx_En<=0;else Rx_En<=Rx_En; //设置采样时钟
//每位数据为分成16段,舍弃前5段后4段,取中间7段进行采样
reg [7:0] counter_1; //对采样次数进行计数
reg [4:0] counter_time; //counter_time计时到24时(1s/115200/16/20=24),为一个时间间隔
wire [14:0] caiyang; // 每位数据为分成16段,每一小段的时间为1s/115200/16,故每一小段的计数值为1s/115200/20/16=Baud/16;
assign caiyang = Baud/16;
always@(posedge clk or negedge rst) if(!rst) counter_time<=0;else if(Rx_En==1 )beginif(counter_time==caiyang-1) counter_time<=0;else counter_time<=counter_time+1;endelse if(Rx_Done) counter_time<=0;else counter_time<=0;
always@(posedge clk or negedge rst) if(!rst) counter_1<=0;else if(Rx_En==1)beginif(counter_1==160 && counter_time==18) counter_1<=0;else if(counter_time==caiyang-1) counter_1<=counter_1+1;else counter_1<=counter_1;endelse if(Rx_Done) counter_1<=0; else counter_1<=0; wire clk_16_caiyang;assign clk_16_caiyang = (counter_time==caiyang/2);//开始采样reg [3:0] x_bit [7:0]; //定义一个二维数组,该二维数组里面有7个元素,分别表示8个数据位,每个元素位宽三位 reg [3:0] start;//起始位reg [3:0] stop;//停止位always@(posedge clk or negedge rst)if(!rst) beginstart<=0;stop<=0;x_bit[0]<=0;x_bit[1]<=0;x_bit[2]<=0;x_bit[3]<=0;x_bit[4]<=0;x_bit[5]<=0;x_bit[6]<=0;x_bit[7]<=0;endelse if(clk_16_caiyang)begincase(counter_1)0: beginstart<=0;stop<=0;x_bit[0]<=0;x_bit[1]<=0;x_bit[2]<=0;x_bit[3]<=0;x_bit[4]<=0;x_bit[5]<=0;x_bit[6]<=0;x_bit[7]<=0;end5,6,7,8,9,10,11:start<=start+uart_rx;21,22,23,24,25,26,27:x_bit[0]<=x_bit[0]+uart_rx;37,38,39,40,41,42,43:x_bit[1]<=x_bit[1]+uart_rx;53,54,55,56,57,58,59:x_bit[2]<=x_bit[2]+uart_rx;69,70,71,72,73,74,75:x_bit[3]<=x_bit[3]+uart_rx;85,86,87,88,89,90,91:x_bit[4]<=x_bit[4]+uart_rx;101,102,103,104,105,106,107:x_bit[5]<=x_bit[5]+uart_rx;117,118,119,120,121,122,123:x_bit[6]<=x_bit[6]+uart_rx;133,134,135,136,137,138,139:x_bit[7]<=x_bit[7]+uart_rx;149,150,151,152,153,154,155:stop<=stop+uart_rx;default: beginstart<=start;x_bit[0]<=x_bit[0];x_bit[1]<=x_bit[1];x_bit[2]<=x_bit[2];x_bit[3]<=x_bit[3];x_bit[4]<=x_bit[4];x_bit[5]<=x_bit[5];x_bit[6]<=x_bit[6];x_bit[7]<=x_bit[7]; stop<=stop;endendcaseendelse beginstart<=start;x_bit[0]<=x_bit[0];x_bit[1]<=x_bit[1];x_bit[2]<=x_bit[2];x_bit[3]<=x_bit[3];x_bit[4]<=x_bit[4];x_bit[5]<=x_bit[5];x_bit[6]<=x_bit[6];x_bit[7]<=x_bit[7]; stop<=stop;end//控制Rx_Donealways@(posedge clk or negedge rst) if(!rst) Rx_Done<=0;else if(counter_1==160&&counter_time==18) Rx_Done<=1;else Rx_Done<=0; //判断采样得到的数据并且进行赋值reg Data_start;reg Data_stop;always@(posedge clk or negedge rst)if(!rst) Rx_Data<=0;else if(counter_1==159)beginData_start<=(start>=3'd4)?1'b1:1'd0;Data_stop<=(stop>=3'd4)?1'b1:1'd0;Rx_Data[0]<=(x_bit[0]>=3'd4)?1'b1:1'd0;Rx_Data[1]<=(x_bit[1]>=3'd4)?1'b1:1'd0;Rx_Data[2]<=(x_bit[2]>=3'd4)?1'b1:1'd0;Rx_Data[3]<=(x_bit[3]>=3'd4)?1'b1:1'd0;Rx_Data[4]<=(x_bit[4]>=3'd4)?1'b1:1'd0;Rx_Data[5]<=(x_bit[5]>=3'd4)?1'b1:1'd0;Rx_Data[6]<=(x_bit[6]>=3'd4)?1'b1:1'd0; Rx_Data[7]<=(x_bit[7]>=3'd4)?1'b1:1'd0; endelse Rx_Data<=Rx_Data;
endmodule
激励文件代码:
module uart_rx_tb();reg clk;reg uart_rx; //从外部接收到的数据reg rst;//复位reg [2:0] Baud_set;//选择接收数据的波特率,要和发送数据的波特率一致wire [7:0] Rx_Data; //最后我们看到的数据wire Rx_Done;uart_tx uart_tx_Inst(.clk(clk),.uart_rx(uart_rx),.rst(rst),.Baud_set(Baud_set),.Rx_Data(Rx_Data),.Rx_Done(Rx_Done)
);
initial clk=1;
initial Baud_set=3'd7;
always #10 clk=~clk;
initialbeginrst=0;uart_rx=1;#200;rst=1;uart_tx_byte(8'b11011011);@(posedge Rx_Done) #5000;uart_tx_byte(8'b10011010);@(posedge Rx_Done) #6000;uart_tx_byte(8'b10011110); endtask uart_tx_byte; //发送一个字节input [7:0] tx_data;beginuart_rx=1;#200;uart_rx=0;#8680;uart_rx=tx_data[0];#8680;uart_rx=tx_data[1];#8680;uart_rx=tx_data[2];#8680;uart_rx=tx_data[3];#8680;uart_rx=tx_data[4];#8680;uart_rx=tx_data[5];#8680;uart_rx=tx_data[6];#8680;uart_rx=tx_data[7];#8680;uart_rx=1;#8680;end
endtask
endmodule
代码已测试可以使用!
FPGA串口接收学习相关推荐
- FPGA 串口接收不准确,有误码
FPGA 串口接收不准确,有误码 FPGA 的Uart接收时,出现接收不正确的分析 波特率计数值= 时钟频率/波特率 FPGA 的Uart接收时,出现接收不正确的分析 波特率计数值= 时钟频率/波特率 ...
- FPGA串口接收与发送详解( part 3 )
之前的part1~2已经详解完了单个数据的串口接收与发送,链接如下: FPGA串口接收与发送 详解 (part 1 )_居安士的博客-CSDN博客 FPGA串口接收与发送详解( part 2 )_居安 ...
- HAL库的串口基础学习(包含串口接收不定长数据的实现)
HAL库的串口基础学习(1) HAL库有一个特点就是对于许多外设的初始化以及功能操作,都提供有一个weak版本的函数,这是充分的展现出库名字的含义(Hardware Abstraction Layer ...
- FPGA串口收发(四):接收数据并转发,间隔时间发送
FPGA串口收发(四):接收数据并转发,间隔时间发送 // Description: 串口收发:串口接收数据,内部生成数据,串口间隔特定时间发送数据 // 串口接收数据:串行信号线 1101_1000 ...
- FPGA串口多字节接收、解码和仿真
序 本项目采用Altera的FPGA,串口多字节接收,并解码以及采用ModelSim进行仿真.串口接收程序源自正点原子的例程. 程序基本框架 程序分为两个部分,单字节接收部分和多字节接收及解码部分,其 ...
- FPGA 串口中断_一个严谨的STM32串口DMA发送amp;接收(1.5Mbps波特率)机制
昨天分享的<嵌入式大杂烩读者福利:第一期>大家有去抽奖吗,没抽的可参与抽奖,碰碰运气.我最喜欢抽奖了,还记得前几个月疫情严重时期连抽中了3包口罩,真刺激,哈哈.之后多多安排抽奖,敬请期待. ...
- 【STM32入门100步--学习笔记】USART串口接收程序(含教学视频)
STM32串口接收的程序和8051单片机一样,有2种接收方式:中断处理和查询方式. 试过两种方式之后发现,中断处理方式更方便,可以扩展多个数据的接收.推荐中断方式. 我已经将本资料内容整理后录制了视频 ...
- C#串口通信学习笔记
因为参加一个小项目,需要对继电器进行串口控制,所以这两天学习了基本的串口编程.同事那边有JAVA的串口通信包,不过是从网上下载的,比较零乱,难以准确掌握串口通信的流程和内含.因此,个人通过学习网上大牛 ...
- FPGA串口(UART)通信协议制定与设计思路详解示例
串口(UART)通信协议制定与设计思路详解 1 概述 本文用于描述规定的串口通信协议,以及传输内容. 2 项目关于串口的要求 a) 支持BIT自检,1路UART上报BIT信息: b) 1路UART接口 ...
最新文章
- 电商系统如何做搜索引擎?
- Web 前端,易学难精,没有拿手的实战项目,怎么办?
- java数组编译后_Java中数组和集合的foreach操作编译后究竟是啥
- Linux 内核的文件 Cache 管理机制介绍
- 大量多风格多功能后台管理模板
- Azure SQL 数据库:服务级别与性能问答
- ubuntu19 安装git_在Ubuntu 18.04上安装Git
- Asp.Net回车键触发Button的OnClick事件解决方案
- Java中的自增操作符与中间缓存变量机制
- android webview 3d,Unity3d Android的web视图没有显示_webview_开发99编程知识库
- c# 操作redisclient 设置过期时间_C# Redis分布式锁 单节点
- 2.3 Hadoop安装与体验
- 项目中的设计模式【适配器模式】
- Linux系统中安装Nginx
- font-family 各字体一览表
- 金蝶标准版7.0计算机快捷,掌握金蝶KIS基本的技巧,快速操作金蝶软件!
- 看看十二星座哪个更适合当程序员
- ubuntu18.04 使用scp命令
- eclipse中的图片路径 image
- matlab坐标轴加粗
热门文章
- 解决谷歌的but your computer or network may be sending automated queries
- 一堂难忘的计算机课作文,一节电脑课作文600字
- No current assignment for partition 解决
- 查询分析器默认代码颜色
- 转图精灵算法分析!!
- 微信小程序招聘管理系统+后台管理系统
- 同元软控助力复杂系统数字孪生落地应用
- 【网络】计算机网络-数据链路层 Data Link Layer
- 是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
- 简单的快递管理系统(c语言版)--大一下的总结