FPGA学习笔记

1. UART串口协议以及串口接收端设计

1 原理图
2 Verilog 代码
3 Modelsim仿真
4. FPGA板级验证

1.1 串口协议接收端设计

  • 目标:FPGA接收其他设备通过UART发送过来的数据。
  • 实验现象:在Quartusz II中调用in system sources and probes
    editor工具,查看UART接收模块接受到的数据,数据有pc机发出。
  • 知识点:
    1. uart的通信协议原理和工业环境下的数据接受实现
    2. in system sources and probes editor(ISSP)调试工具的使用

1. 原理图

  • 模块组成:

    1. 输入信号同步模块
    2. 起始数据检测模块
    3. 波特率产生模块
    4. 数据接受进程

(1). 发送端实验室数据采集时序图

  • 实验室环境:采样一个数据的中点

(2). 发送端工业数据采集时序图

  • 工业环境:工业环境的电磁干扰严重,噪音信号容易导致错误,只采样一次的数据不准确。
  • 方法:采每位数据采样的中间6次的结果,根据这6次结果的电平(0,1)出现的次数,判定最终结果。

2. Verilog 代码

//----top---------------------------------------
module uart_rx_r0
(input              clk,input               rst_n,input                 rs232_rx,input [2:0]            baud_set,output     reg     rx_done,
//  output          rx_state,output reg  [7:0]   data_byte
);reg rs232_rx_reg1;reg rs232_rx_reg2;reg rs232_rx_syn1;reg rs232_rx_syn2;reg uart_state;reg [8:0] div_cnt;reg [8:0] cnt_max;//div_cnt max valuereg baud_clk;reg [7:0] baud_cnt;reg [3:0] reg_data_byte [7:0];reg [2:0] START;reg [2:0] STOP;
//  wire pos_edge;wire neg_edge;//----asynch rs232_rx--> synch-----------always@(posedge clk or negedge rst_n)if(!rst_n)beginrs232_rx_syn1 <= 0;rs232_rx_syn2 <= 0;end else beginrs232_rx_syn1 <= rs232_rx;rs232_rx_syn2 <= rs232_rx_syn1;end
//----start bit detect------------------always@(posedge clk or negedge rst_n)if(!rst_n)beginrs232_rx_reg1 <= 0;rs232_rx_reg2 <= 0;end else beginrs232_rx_reg1 <= rs232_rx_syn2;rs232_rx_reg2 <= rs232_rx_reg1;end
//  assign pos_edge = (rs232_rx_reg1 & !rs232_rx_reg2);assign neg_edge = (!rs232_rx_reg1 & rs232_rx_reg2); //------baud_set------------------------always@(*)case(baud_set)3'd0: cnt_max <= 9'd325;3'd1: cnt_max <= 9'd163;3'd2: cnt_max <= 9'd81;3'd3: cnt_max <= 9'd54;3'd4: cnt_max <= 9'd27;default: cnt_max <= 9'd325;endcase
//----uart_state-------------------------always@(posedge clk or negedge rst_n)if(!rst_n)uart_state <= 0;else if(neg_edge)uart_state <= 1;else if(rx_done || (baud_cnt==12 && (START > 2))) uart_state <= 0;elseuart_state <= uart_state;
//----frequence div-->baud_clk-----------always@(posedge clk or negedge rst_n)if(!rst_n)div_cnt <= 0;else if(uart_state)beginif(div_cnt == cnt_max)div_cnt <= 0;elsediv_cnt <= div_cnt + 9'd1;end elsediv_cnt <= 0;always@(posedge clk or negedge rst_n)if(!rst_n)baud_clk <= 1'd0;else if(div_cnt == 9'd1)baud_clk <= 1'd1;elsebaud_clk <= 1'd0;
//----baud_cnt--------------------------always@(posedge clk or negedge rst_n)if(!rst_n)baud_cnt <= 0;else if(rx_done || (baud_cnt==12 && (START > 2)))baud_cnt <= 0;else if(baud_clk)baud_cnt <= baud_cnt + 8'd1;elsebaud_cnt <= baud_cnt;//----rx_done----------------------------always@(posedge clk or negedge rst_n)if(!rst_n)rx_done <= 1'b0;else if(baud_cnt == 8'd159)rx_done <= 1'b1;else rx_done <= 1'b0;//----data_byte--------------------------always@(posedge clk or negedge rst_n) // asynchronos transimiter, reg_data_byte is used to keep input data stable if(!rst_n)data_byte <= 8'd0;else if(baud_cnt == 8'd159)begindata_byte[0] <= reg_data_byte[0][2];data_byte[1] <= reg_data_byte[1][2];data_byte[2] <= reg_data_byte[2][2];data_byte[3] <= reg_data_byte[3][2];data_byte[4] <= reg_data_byte[4][2];data_byte[5] <= reg_data_byte[5][2];data_byte[6] <= reg_data_byte[6][2];data_byte[7] <= reg_data_byte[7][2];end//----reg_data_byte----------------------always@(posedge clk or negedge rst_n)beginif(!rst_n)beginSTART <= 3'd0;reg_data_byte[0] <= 3'd0; reg_data_byte[1] <= 3'd0;reg_data_byte[2] <= 3'd0;reg_data_byte[3] <= 3'd0;reg_data_byte[4] <= 3'd0;reg_data_byte[5] <= 3'd0;reg_data_byte[6] <= 3'd0;reg_data_byte[7] <= 3'd0;STOP <= 3'd0;end else if(baud_clk)begincase(baud_cnt) //0:initial baud_cnt=0 --> after sending data, rs232_tx always be 0; 0: beginSTART <= 3'd0;reg_data_byte[0] <= 3'd0; reg_data_byte[1] <= 3'd0;reg_data_byte[2] <= 3'd0;reg_data_byte[3] <= 3'd0;reg_data_byte[4] <= 3'd0;reg_data_byte[5] <= 3'd0;reg_data_byte[6] <= 3'd0;reg_data_byte[7] <= 3'd0;STOP <= 3'd0;end6,7,8,9,10,11: START <= START + rs232_rx_reg2;22,23,24,25,26,27:       reg_data_byte[0] <= reg_data_byte[0] + rs232_rx_reg2;38,39,40,41,42,43:       reg_data_byte[1] <= reg_data_byte[1] + rs232_rx_reg2;54,55,56,57,58,59:       reg_data_byte[2] <= reg_data_byte[2] + rs232_rx_reg2;70,71,72,73,74,75:       reg_data_byte[3] <= reg_data_byte[3] + rs232_rx_reg2;86,87,88,89,90,91:       reg_data_byte[4] <= reg_data_byte[4] + rs232_rx_reg2;102,103,104,105,106,107: reg_data_byte[5] <= reg_data_byte[5] + rs232_rx_reg2;118,119,120,121,122,123: reg_data_byte[6] <= reg_data_byte[6] + rs232_rx_reg2;130,131,132,133,134,135: reg_data_byte[7] <= reg_data_byte[7] + rs232_rx_reg2;148,149,150,151,152,153: STOP <= STOP + rs232_rx_reg2;default beginSTART <= START;reg_data_byte[0] <= reg_data_byte[0]; reg_data_byte[1] <= reg_data_byte[1];reg_data_byte[2] <= reg_data_byte[2];reg_data_byte[3] <= reg_data_byte[3];reg_data_byte[4] <= reg_data_byte[4];reg_data_byte[5] <= reg_data_byte[5];reg_data_byte[6] <= reg_data_byte[6];reg_data_byte[7] <= reg_data_byte[7];STOP <= STOP;             endendcaseendend    endmodule
//------------------------------------------------
//----testbench-----------------------------------
`timescale 1ns/1ns
`define clk_period 20module uart_rx_r0_tb;reg clk;reg rst_n;reg [7:0] data_byte_tx;wire rx_done;reg send_en;reg [2:0] baud_set;wire [7:0] data_byte_rx;wire    rs232_rx;wire   tx_done;//wire  uart_state; wire led;uart_rx_r0 uut_rx(.clk(clk),.rst_n(rst_n),.rs232_rx(rs232_rx),.baud_set(baud_set),.rx_done(rx_done),.data_byte(data_byte_rx));uart_tx_r0 uut_tx(.clk(clk),.rst_n(rst_n),.send_en(send_en),.baud_set(baud_set),.tx_done(tx_done),.data_byte(data_byte_tx),.uart_state(led),.rs232_tx(rs232_rx));initial beginclk = 1;rst_n = 0;send_en = 0;baud_set = 3'd4;#(`clk_period*20+1);rst_n = 1;#(`clk_period*50);data_byte_tx = 8'haa;//8'b1010_1010send_en = 1;#`clk_period;send_en = 0;@(posedge tx_done)#(`clk_period*5000);data_byte_tx = 8'h55;//0101_0101send_en = 1;#`clk_period;send_en = 0;@(posedge tx_done)#(`clk_period*5000);$stop;endalways begin #(`clk_period/2) clk = ~clk;endendmodule

3. Modelsim仿真

4. FPGA板级验证

  • 串口助手发送数据,ISSP软件实时接收数据。

[参考资料] FPGA系统设计与验证实战指南

【注】:个人学习笔记,如有错误,望不吝赐教,这厢有礼了~~~


FPGA学习笔记_UART串口协议_串口接收端设计相关推荐

  1. (实验50)单片机,STM32F4学习笔记,代码讲解【串口IAP实验】【正点原子】【原创】

    文章目录 ❤2023重新理解记录 其它文章链接,独家吐血整理 实验现象 主程序 IAP初始化程序 代码讲解 文章目录 ❤2023重新理解记录 其它文章链接,独家吐血整理 实验现象 主程序 IAP初始化 ...

  2. (实验4)单片机,STM32F4学习笔记,代码讲解【串口实验】【正点原子】【原创】

    文章目录 其它文章链接,独家吐血整理 实验现象 主程序 串口中断程序 代码讲解 其它文章链接,独家吐血整理 (实验3)单片机,STM32F4学习笔记,代码讲解[按键输入实验][正点原子][原创] (实 ...

  3. 小梅哥FPGA学习笔记

    小梅哥FPGA学习笔记 一.38译码器 功能: 译码器其任一时刻的稳态输出,仅仅与该时刻的输入变量的取值有关,它是一种多输入多输出的组合逻辑电路,负责将二进制代码翻译为特定的对象(如逻辑电平等).38 ...

  4. FPGA学习笔记(八)同步/异步信号的打拍分析处理及亚稳态分析

    系列文章目录 一.FPGA学习笔记(一)入门背景.软件及时钟约束 二.FPGA学习笔记(二)Verilog语法初步学习(语法篇1) 三.FPGA学习笔记(三) 流水灯入门FPGA设计流程 四.FPGA ...

  5. FPGA 学习笔记:Vivado 2020.2 MicroBlaze MIG 测试 DDR3 篇尾

    FPGA 学习笔记:Vivado 2020.2 MicroBlaze MIG 测试 DDR3 篇一 FPGA 学习笔记:Vivado 2020.2 MicroBlaze MIG 测试 DDR3 篇二 ...

  6. FPGA 学习笔记:Vivado 2018.2 MicroBlaze Uartlite 配置

    前言 Vivado 版本: Vivado 2018.2 + Vivado HLS 2018.2, Vivado HLS 2018.2 用于 SDK 开发,C语言开发 创建基于MicroBlaze的 [ ...

  7. FPGA学习笔记(八):ASK调制解调的仿真

    笔记八是ASK调制解调的仿真实现. ASK调制解调的实现原理:首先使用MATLAB产生存储基带波形的coe文件,再让ROM读取coe文件输出基带波形,然后DDS产生正弦波信号作为载波信号,接下来使用乘 ...

  8. FPGA学习笔记之Altera FPGA使用JIC文件配置固化教程

    FPGA学习笔记之Altera FPGA使用JIC文件配置固化教程 很多做过单片机的朋友都知 道,我们在对MCU烧写完程序固件后,那么该程序固件就存储在了该MCU内部.即使MCU断电了再重新上电,程序 ...

  9. IOS之学习笔记十五(协议和委托的使用)

    1.协议和委托的使用 1).协议可以看下我的这篇博客 IOS之学习笔记十四(协议的定义和实现) https://blog.csdn.net/u011068702/article/details/809 ...

最新文章

  1. Android studio 代码字体模糊的处理方法
  2. 一个button导致的慘案
  3. java聊天室 博客_java网络聊天室
  4. IOS 总结:NSArray,NSSet,NSDictionary
  5. python plot方法的使用_【python】matplotlib.pyplot入门
  6. 关于完美拖拽的问题三
  7. OpenStack精华问答 | OpenStack的网络类型有哪些?
  8. linux5 yum安装,(5)Linux_软件管理_yum安装本地软件
  9. 脚本中调用别的脚本,如何得到执行结果?
  10. Navicat for mysql破解版安装步骤
  11. NOI / 1.3编程基础之算术表达式与顺序执行——12:计算球的体积
  12. 2.12美团点评技术
  13. UC伯克利教授Stuart Russell人工智能基础概念与34个误区 (公号回复“AI基础概念”可下载PDF资料)
  14. 洛谷千题详解 | P1010 [NOIP1998 普及组] 幂次方【C++、Java、Python、Pascal语言】
  15. 黄健翔:观看欧冠决赛的建议!
  16. Linux FTP用户设置与宽带限制
  17. vue 高德地图 不同区域显示不同颜色_高德地图车机版4.0解析:看不见的升级才是重点...
  18. 牛逼,Python3竟然内置找茬神器!一起来找茬吧!
  19. cnpm : 无法加载文件 C:\Users\***\AppData\Roaming\npm\cnpm.ps1,因为在此系统上禁止运行脚本
  20. 华为mate10用的android版本,硬件有区别!华为Mate10哪个版本性价比更高

热门文章

  1. ios开发聊天气泡实现
  2. 解决Solaris应用程序开发内存泄漏问题
  3. 说说tushare pro积分规则或积分获取的那些坑!
  4. 收音机设计与制作漫谈(转)
  5. linux qt地图开发教程,基于QT的电子地图的设计与实现
  6. 输出任意边长的菱形————C语言实践应用(1)(完整源码)
  7. RealFlow在线教程翻译(2)——Foam with SPH Fluids(基于平滑粒子流体动力学算法(SPH)的流体泡沫)
  8. python每个数都可由集合中的某两个数相加而得
  9. Minecraft 1.18.1、1.18.2模组开发 05.发射器+投掷物
  10. 【51单片机】计时器/计数器中断