基于FPGA自适应串口通信(Auto Baud Rate)
做的课设,相当于复习了一遍verilog。
实现了
1.接收端固定模式:8N1 BAUD:921600。
2.发送端8N1,任意波特率(不取极端值)。
3.数码管显示波特率(16进制)。
用了
1.两天一夜。
2.ego1平台+usb2uart。
整体框图

输入tx信号经过频率捕获层获得100Mhz下的计数值,送给波特率产生层得到接收层波特率。
接收层接收数据送给串口FIFO层,串口FIFO层根据发送层的反馈将数据送出FIFO。
发送层将数据按固定921600波特率发给PC机。从而实现波特率交换。
频率捕获层算法
1.uart协议

这里只考虑最常用的8N1,即8位数据,无校验,1位停止位。
在时钟线上升沿,tx线下降沿并维持到下一个上升沿即为一个开始位。然后8位数据(低位在前)。然后到第10位停止位高电平。
值得一提的是,tx线不会在某个电平完后恢复初始电平,比如说上一个数据位是低,当前位还是低,这个数据位结束后不会变回高再变低。
有什么影响?倘若tx发送0xff,那么其实只有一个低电平脉宽!即起始位那个脉宽。
2.算法
先打两拍,同步时钟以及滤除尖峰脉冲。考虑到输入的数据信号大多为ascii码。

我们从里面找一个最特殊的,U,这个字符二进制为10101010,再加上开始结束位的tx线电平变化为:
0101010101,这里有4个或者说5个低电平脉宽,这是最理想的情况。这样测出来的脉宽都是波特率。
但是如果是一般的字符,发送一个字节可能获得多个低电平脉宽,从里面找最小的有极大可能就是波特率(极小可能最小的低电平脉宽是波特率的倍数)。
所以我们的算法就是多次测频率,从里面找一个最小的,即认为是波特率。注意这里的频率,波特率都是相对于ego1的100Mhz时钟,并不需要化为实际波特率。
程序
`timescale 1ns / 1ps module cap_freqence(
input clk,
input rst_n,
input freq_in,
input cap_en,
output freq_cap//27bit 0-134,217,727 对输入信号波特率测得的频率
);
reg[:] freq_cap = 'd10416; //rst ??????
reg[:] tmp_cap,sequence_cap[:]; //cap 5 times and Use the smallest one as baud
reg [:] cap_cnt;
// reg cap_finish;
reg s0_RS_232_RX,s1_RS_232_RX; //同步寄存器,消除亚稳态
reg tmp0_RS_232_RX,tmp1_RS_232_RX; //数据寄存器,移位寄存器
reg cap_state; //0:idle 1:work
wire neg_RX;//下降沿
always@(posedge clk or negedge rst_n)//同步寄存器,消除亚稳态
if(!rst_n)
begin
s0_RS_232_RX <= 'b0;
s1_RS_232_RX <= 'b0;
end
else
begin
s0_RS_232_RX <= freq_in; //次态
s1_RS_232_RX <= s0_RS_232_RX;//现态
end
always@(posedge clk or negedge rst_n)//数据寄存器
if(!rst_n)
begin
tmp0_RS_232_RX <= 'b0;
tmp1_RS_232_RX <= 'b0;
end
else
begin
tmp0_RS_232_RX <= s1_RS_232_RX;
tmp1_RS_232_RX <= tmp0_RS_232_RX;
end
//共打两拍再检测输入脚
assign neg_RX = (!tmp0_RS_232_RX) & tmp1_RS_232_RX;//下降沿检测 always@(posedge clk or negedge rst_n)//cap工作状态
if(!rst_n)begin
cap_state <= ;
end
else if(neg_RX) //下降沿开始测频
cap_state <= ;
else if (tmp0_RS_232_RX) //高电平退出测频
cap_state <= ; always@(posedge clk or negedge rst_n)//以100Mhz时钟测输入引脚低电平脉宽
if(!rst_n)
begin
tmp_cap <= 'd0; end
else if(cap_state) //串口工作状态(接受)时计数
begin
if(tmp0_RS_232_RX) //计完一次频率
begin
sequence_cap[cap_cnt] <= tmp_cap;
tmp_cap <= 'd0;
cap_cnt <= cap_cnt + ;//0 1 2 3,4测完4次后为4
end
else
tmp_cap <= tmp_cap + 'b1;
end integer i;
reg[:] min_cap; always@(cap_cnt) //测完一个序列便从测频序列里找出最小脉宽即为bps
begin
if (cap_cnt == 'd5)
begin
min_cap=sequence_cap[];//1st one as minimal cap
for (i=;i<;i=i+)
if (sequence_cap[i] < min_cap)
if (sequence_cap[i] > )
min_cap = sequence_cap[i];
if (cap_en) //手动控制更新baud
freq_cap = min_cap;
end
end endmodule
这个程序有瑕疵,用了初始化。不懂
freq_cap
这个变量放在rst里面复位后,之后都不能被下面
freq_cap = min_cap;
这句更新,暂时这么写吧!
效果


基于FPGA自适应串口通信(Auto Baud Rate)的更多相关文章
- 012 基于FPGA的网口通信实例设计【转载】
一.网口通信设计分类 通过上面其他章节的介绍,网口千兆通信,可以使用TCP或者UDP协议,可以外挂PHY片或者不挂PHY片,总结下来就有下面几种方式完成通信: 图8‑17基于FPGA的网口通信实例设计 ...
- 【Delphi】基于状态机的串口通信
通信协议 串行通信接口(如RS232.RS485等)作为计算机与单片机交互数据的主要接口,广泛用于各类仪器仪表.工业监测及自动控制领域中. 通信协议是需要通信的双方所达成的一种约定,它对包括数据格式. ...
- 基于FPGA的光口通信开发案例|基于Kintex-7 FPGA SFP+光口的10G UDP网络通信开发案例
前言 自著名华人物理学家高锟先生提出"光传输理论",实用化的光纤传输产品始于1976年,经历了PDH→SDH→DWDM→ASON→MSTP的发展历程.本世纪初期,ASON/OADM ...
- 纠错:基于FPGA串口发送彩色图片数据至VGA显示
今天这篇文章是要修改之前的一个错误,前面我写过一篇基于FPGA的串口发送图片数据至VGA显示的文章,最后是显示成功了,但是显示的效果图,看起来确实灰度图,当时我默认我使用的MATLAB代码将图片数据转 ...
- QT5 TK1 串口通信
对TK1中基于QT5的串口通信过程进行总结.按照软件安装及通信实现的顺序. 1.QT5安装 较简洁方式:打开软件中心(类似A形),搜索qtcreator,点击安装即可. 2.串口通信库安装 采用上述方 ...
- 基于FPGA的红外遥控解码与PC串口通信
基于FPGA的红外遥控解码与PC串口通信 zouxy09@qq.com http://blog.csdn.net/zouxy09 这是我的<电子设计EDA>的课程设计作业(呵呵,这个月都拿 ...
- [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)
星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...
- PC和FPGA间的串口通信实现
应用笔记 V1.0 2015/03/26 PC和FPGA间的串口通信实现 概述 本文将介绍PC和FPGA间的串口通信实现的基本思路和Verilog代码,对于通信而言,收发双方都要有相应的控制. ...
- VS2008基于对话框的MFC上位机串口通信(C++实现)简单例程
首先,在 vs2008 环境下创建 MFC 运用程序 设置项目名称为 ComTest(这个地方随意命名,根据个人习惯),点击确定后,点击下一步 出现如下界面 选择"基于对话框"模式 ...
随机推荐
- go零碎总结
1.go里通过首字母大小写来区分它是私有的还是公有的,比如对于一个结构体属性一般就以大写开头(和Java不一样,不需要什么getter,setter方法):而对于方法而言,它是隶属于包(包名一定是小写 ...
- [转帖]时间序列数据库 (TSDB)
时间序列数据库 (TSDB) https://www.jianshu.com/p/31afb8492eff 0.3392019.01.28 10:51:33字数 5598阅读 4030 背景 2017 ...
- Redis持久化RDB、AOF
持久化的意思就是保存,保存到硬盘.第一次接触这个词是在几年前学习EF. 为什么要持久化 redis定义:Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代 ...
- JDK1.8 的 HashMap 源码之文件注释
文章目录 null 插入,key的位置变化 迭代操作时间 性能因素 负载因子 Comparable 加锁 迭代器修改 null 插入,key的位置变化,迭代操作时间,性能因素,负载因子,Compara ...
- STM32之SPI时钟相位选择
SPI的时钟模式分为四种,由SPI_CR1寄存器的两位CPOL,CPHA组合选择. CPOL 如果为1,则时钟的空闲电平为高电平:CPOL 如果为0,则时钟的空闲电平为低电平.空闲电平影响不大. CP ...
- Scrapy框架1——简单使用
一.设置与编写 打开cmd,选择好路径 1.创建项目scrapy startproject projectname d:\爬虫\11.scrapy>scrapy startproject tes ...
- Python-19-元类
一.定义 元类就是类的类 type是python的一个内建元类 类的两种定义方式 # 定义类的两种方式 class Foo(object): def __init__(self, name, age) ...
- C++11<functional>深度剖析:背景、原理、接口与实现
自C++11以来,C++标准每3年修订一次.C++14/17都可以说是更完整的C++11:即将到来的C++20也已经特性完整了. C++11已经有好几年了,它的年龄比我接触C++的时间要长10倍不止吧 ...
- 如何在mongoengine中使用referencefield引用本类
引用:原文 from mongoengine import * class Employee(Document): name = StringField() boss = ReferenceField ...
- Python内存加载shellcode
生成 首先生成一个测试的msf shellcode msfvenom -p windows/x64/exec CMD=calc.exe -f python 把其中的shellcode复制出来留待待会使 ...