【FPGA】UART串口通信

2023-05-16

文章目录

  • 一、通信方式
      • 1.串行通信
      • 2.并行通信
  • 二、UART串口通信
      • 1.模块设计与时序图
      • 2.代码实现
  • 三、测试结果
      • 1.仿真结果
      • 2.上板验证

一、通信方式

1.串行通信

串行通信是指利用一条传输线将数据一位位地顺序传送。(也就是说串行通信传输的数据是1比特1比特的传送的)
在这里插入图片描述常见串行通信接口
在这里插入图片描述
串行通信优点是传输距离远、占用资源少。
串行通信缺点是发送速度慢。

2.并行通信

并行是指多比特数据同时通过并行线进行传送,这样数据传送速度大大提高。

但并行传送的线路长度受到限制,因为长度增加,干扰就会增加,数据也就容易出错。
在这里插入图片描述
并行通信优点是发送速度快。
并行通信缺点是传输距离短、资源占用多。

二、UART串口通信

UART是一种异步全双工通信方式
在这里插入图片描述

1.模块设计与时序图

在这里插入图片描述

uart_tx模块时序图
在这里插入图片描述

uart_rx模块时序图
在这里插入图片描述

2.代码实现

uart.v(顶层模块)

module  uart
(
    input   clk     ,
    input   rst_n   ,

    input   u_rx    ,
    output  u_tx       
);

wire    [7:0]   data    ;
wire            start   ;

uart_rx uart_rx(
    .clk        (clk)   ,
    .rst_n      (rst_n) ,

    .data       (data)  ,
    .start      (start) ,
    .u_rx       (u_rx)
);

uart_tx uart_tx(
    .clk        (clk)   ,
    .rst_n      (rst_n) ,
    
    .data       (data)  ,
    .start      (start) ,
    .u_tx       (u_tx)  
);

endmodule

uart_tx

module uart_tx
#(
    parameter BAUD_MAX  = 5208,
    parameter BAUD_FLAG = 1
)
(
    input           clk         ,
    input           rst_n       ,

    input   [7:0]   data        ,
    input           start       ,

    output  reg     u_tx             
);

reg     [14:0]      baud_cnt    ;
reg     [4:0]       bit_cnt     ;

reg                 data_state  ;
reg                 bit_flag    ;
reg                 done        ;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        data_state <= 1'b0 ;
    else if(start)
        data_state <= 1'b1 ;
    else if(done)
        data_state <= 1'b0 ;
    else
        data_state <= data_state ; 
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        baud_cnt <= 1'b0 ;
    else if(data_state)begin
        if(baud_cnt == BAUD_MAX - 1)
            baud_cnt <= 1'b0 ;
        else
            baud_cnt <= baud_cnt + 1'b1 ;
    end
    else
        baud_cnt <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        bit_flag <= 1'b0 ;
    else if(baud_cnt == BAUD_FLAG)
        bit_flag <= 1'b1 ;
    else
        bit_flag <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        bit_cnt <= 1'b0 ;
    else if(bit_flag)begin
        if(bit_cnt == 9)
            bit_cnt <= 1'b0 ;
        else
            bit_cnt <= bit_cnt + 1'b1 ;
    end
    else
        bit_cnt <= bit_cnt ;
end

always @(posedge clk or negedge rst_n) begin  
    if(!rst_n)
        u_tx <= 1'b1 ;  
    else if(bit_flag)begin
        case(bit_cnt)
            0 : u_tx <= 1'b0    ;
            1 : u_tx <= data[0] ;
            2 : u_tx <= data[1] ;
            3 : u_tx <= data[2] ;
            4 : u_tx <= data[3] ;
            5 : u_tx <= data[4] ;
            6 : u_tx <= data[5] ;
            7 : u_tx <= data[6] ;
            8 : u_tx <= data[7] ;
            9 : u_tx <= 1'b1    ;
            default : u_tx <= 1'b1 ;
        endcase
    end
    else
        u_tx <= u_tx ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        done <= 1'b0 ;
    else if(bit_cnt == 9 && bit_flag)
        done <= 1'b1 ;
    else
        done <= 1'b0 ;
end

endmodule

uart_rx

module uart_rx
#(
    parameter BAUD_MAX  = 5208,
    parameter BAUD_FLAG = 2604 
)
(
    input   clk     ,
    input   rst_n   ,

    input   u_rx    ,

    output reg        start ,
    output reg  [7:0] data
);

reg                 u_rx0       ;
reg                 u_rx1       ;
reg                 u_rx2       ;

reg     [14:0]      baud_cnt    ;
reg     [4:0]       bit_cnt     ;

reg                 data_state  ;
reg                 bit_flag    ;
reg                 done        ;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        u_rx0 <= 1'b1 ;
        u_rx1 <= 1'b1 ;
        u_rx2 <= 1'b1 ;
    end
    else begin
        u_rx0 <= u_rx  ;
        u_rx1 <= u_rx0 ;
        u_rx2 <= u_rx1 ;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        data_state <= 1'b0 ;
    else if((!u_rx1) && (u_rx2))
        data_state <= 1'b1 ;
    else if(done)
        data_state <= 1'b0 ;
    else
        data_state <= data_state ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        baud_cnt <= 1'b0 ;
    else if(data_state)begin
        if(baud_cnt == BAUD_MAX - 1)
            baud_cnt <= 1'b0 ;
        else
            baud_cnt <= baud_cnt + 1'b1 ;
    end
    else
        baud_cnt <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        bit_flag <= 1'b0 ;
    else if(baud_cnt == BAUD_FLAG)
        bit_flag <= 1'b1 ;
    else
        bit_flag <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        bit_cnt <= 1'b0 ;
    else if(bit_flag)begin
        if(bit_cnt == 9)
            bit_cnt <= 1'b0 ;
        else
            bit_cnt <= bit_cnt + 1'b1 ;
    end
    else
        bit_cnt <= bit_cnt ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        data <= 8'b00000000 ;
    else if(bit_flag)begin     
        case(bit_cnt)
            0 : data    <= data  ;
            1 : data[0] <= u_rx2 ;
            2 : data[1] <= u_rx2 ;
            3 : data[2] <= u_rx2 ;
            4 : data[3] <= u_rx2 ;
            5 : data[4] <= u_rx2 ;
            6 : data[5] <= u_rx2 ;
            7 : data[6] <= u_rx2 ;
            8 : data[7] <= u_rx2 ;
            9 : data    <= data  ;
            default : data <= data ;
        endcase
    end
    else
        data <= data ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        done <= 1'b0 ;
    else if(bit_cnt == 9 && bit_flag)
        done <= 1'b1 ;
    else
        done <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        start <= 1'b0 ;
    else
        start <= done ;
end

endmodule

uart_tb

`timescale 1ps/1ps

module uart_tb();

reg             clk     ;
reg             rst_n   ;

reg             u_rx    ;
wire            u_tx    ;

uart    u_uart
(
    .clk        (clk)   ,
    .rst_n      (rst_n) ,

    .u_rx       (u_rx)  ,
    .u_tx       (u_tx)  
);

initial begin
    clk = 1;
    forever
    #10
    clk=~clk;
end

initial begin
    rst_n = 1;
    #10;
    rst_n = 0;
    #20;
    rst_n = 1;
end

parameter TIMEPERIOD = 20;

initial begin
		u_rx = 1'b1;
		#200
		//发送起始位
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据0
		u_rx = 1'd1;
        #(5027*TIMEPERIOD);
		//发送数据1
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据2
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据3
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据4
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据5
		u_rx = 1'd1;
        #(5027*TIMEPERIOD);
		//发送数据6
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据7
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送结束位
		u_rx = 1'd1;
		#(100000*TIMEPERIOD);
		$stop ;
end

endmodule

三、测试结果

1.仿真结果

在这里插入图片描述

2.上板验证

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【FPGA】UART串口通信 的相关文章

  • 用Vscode编辑verilog代码配置

    这篇教程感觉很详细了 我这里分享一下vscode和插件的安装包链接 都是官网下载的 放心食用 用VSCode编辑verilog代码 iverilog编译 自动例化 自动补全 自动格式化等常用插件 链接 https pan baidu com
  • 【Xilinx】SynchronousInterruptHandler错误排查笔记

    SynchronousInterruptHandler错误排查笔记 一 ArmV8的异常处理 二 64位lscript ld的修改 三 asm vectors S的修改 四 SynchronousInterruptHandler函数解析 五
  • verilog 基本语法 {}大括号的使用

    的基本使用是两个 一个是拼接 一个是复制 下面列举了几种常见用法 基本用法 表示拼接 第一位 第二位 表示复制 4 a 等同于 a a a a 所以 13 1 b1 就表示将13个1拼接起来 即13 b1111111111111 拼接语法详
  • FPGA学习笔记(一)__电平知识

    常见电平标准 文章目录 1 TTL电平标准 2 LVTTL电平标准 1 LVTTL3V3 2 LVTTL2V5 3 CMOS电平标准 4 LVCOMS电平标准 1 LVCOMS3V3 2 LVCOMS2V5 3 LVCOMS1V8 4 LV
  • FPGA Lattice Diamond 开发环境搭建

    FPGA Lattice Diamond 开发环境搭建 Lattice Diamond 软件下载 在浏览器中输入 Lattice 的官网地址 http www latticesemi com 进入官网首页在上方选择产品系列选项 出现如下图所
  • [从零开始学习FPGA编程-38]:进阶篇 -语法-函数与任务

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 目录 前言 第1章 什么是函数Function 1 1 什么是函数 1 2 函
  • 64 位 ALU 输出在 TestBench 波上显示高阻抗

    我必须制作一个 64 位 ALU 它接受 A 和 B 64 位输入 进位输入输入并输出 64 位结果以及 1 位进位输出 还有一个 5 位功能选择 FS 其中 FS 0 控制 B 是否反转 使用 2to1 多路复用器 F 1 对 A 执行相
  • 启用并测试 UART 的本地环回

    我正在尝试进行 UART 内部环回测试并提出以下更改 include
  • IOError:[Errno 2]没有这样的文件或目录(当它确实存在时)Python [重复]

    这个问题在这里已经有答案了 我正在通过 python 中的 uart 传输文件文件夹 下面您可以看到简单的功能 但有一个问题 因为我收到如标题所示的错误 IOError Errno 2 No such file or directory 1
  • 在 C 中操作 80 位数据类型

    我正在用 C 实现一些加密算法 其中涉及 80 位密钥 特定操作涉及将密钥旋转移位 x 个位数 我已经尝试过 long double 类型 如果我没记错的话 它是 80 位 但这不适用于位移运算符 我能想到的唯一替代方案是使用 10 个元素
  • 如何生成异步复位verilog总是阻塞凿子

    Chisel 始终生成敏感度列表中仅包含时钟的块 always posedge clk begin end 是否可以将模块配置为使用异步重置并生成这样的始终块 always posedge clk or posedge reset begi
  • VHDL门控时钟如何避免

    我收到了避免使用门控时钟的建议 因为它可能会导致松弛和时序限制问题 但我想问一下我可以认为什么是门控时钟 例如 此代码对时钟进行门控 因为 StopCount 对它进行门控 process ModuleCLK begin if rising
  • Linux驱动程序DMA传输到PC作为主机的PCIe卡

    我正在开发一个 DMA 例程 将数据从 PC 传输到 PCIe 卡上的 FPGA 我阅读了 DMA API txt 和 LDD3 ch 15 详细信息 但是 我不知道如何从 PC 到 PCIe 卡上的一致 iomem 块进行 DMA 传输
  • 启用 DMA 的 UART Tx 模式

    我已经为 UART 在传输模式下编写了一个简单的设备驱动程序 并启用了 DMA 和中断 我使用的硬件是 omap 4460 pandaboard 其中加载了 Linux 3 4 下面我分享一下相关部分的代码 在开放阶段 dma map io
  • 模拟器和合成器之间初始化状态机的差异

    我的问题是关于合成状态机中使用的第一个状态 我正在使用莱迪思 iCE40 FPGA 用于仿真的 EDA Playground 和用于综合的莱迪思 Diamond Programmer 在下面的示例中 我生成一系列信号 该示例仅显示引用状态机
  • GATT 配置文件和 UART 服务

    我是开发通过蓝牙连接到外围设备的移动应用程序的新手 我搜索到 GATT 是用于蓝牙LE 通信的相关配置文件 但我们的客户建议我们使用 UART 服务 现在我很困惑 1 这两件事是如何关联的 2 我们是否必须选择其中之一 如果是的话 每一个的
  • 如何在Altera Quartus中生成.rbf文件?

    什么是 rbf 文件以及如何在 Windows 上从 Quartus 输出文件 sof 生成它们 An RBF is a 原始二进制文件例如 它代表原始数据 这些数据将被加载到闪存中 以便在上电时初始化 FPGA A SOF is an S
  • 从 OpenCV 代码到 FPGA 代码的转换是否比 Matlab 代码更容易? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想做一个关于图像处理的项目 我想知道如果我想在FPGA上实现这个项目 我应该在第一阶段选择Matla
  • 如何从 Spartan 6 写入 Nexys 3 FPGA 板上的 Micron 外部蜂窝 RAM?

    我到处都查过了 数据表 Xilinx 网站 digilent 等等 但什么也没找到 我能够使用 Adept 工具来验证我的蜂窝 RAM 是否正常运行 但我找不到任何库存 VHDL 代码作为控制器来写入数据和从中读取数据 帮助 找到了此链接
  • 在 Verilog 程序中使用连续分配?

    在 Verilog 程序中使用连续赋值是否可能和 或有用 例如 是否有任何理由将assign里面一个always堵塞 例如这段代码 always begin assign data in Data end 此外 是否可以用这种方法生成顺序逻

随机推荐

  • 通过路由器连接JetsonNano与地面站

    通过路由器连接JetsonNano与地面站 一 前期准备注意事项连接局域网虚拟机网络设置 二 获取IP地址和设备名称IP地址设备名称 三 配置Nano修改bashrc文件修改hosts文件 四 配置地面站修改bashrc文件修改hosts文
  • jvm 堆 栈中存什么?

    数据类型 Java虚拟机中 xff0c 数据类型可以分为两类 xff1a 基本类型和引用类型 基本类型的变量保存原始值 xff0c 即 xff1a 他代表的 值就是数值本身 xff1b 而引用类型的变量保存引用值 引用值 代表了某个对象的引
  • YOLOv5 数据集划分及生成labels

    0 本人文件夹存放格式 xff08 因为要测试多个数据集和不同的yolov5版本和其他算法 xff0c 所以数据集整体放到外面 xff09 1 划分数据集 验证集 测试集 coding utf 8 import os import rand
  • mission planner发送数据之mavlink

    前段时间研究mp的地面站 xff0c 看了几天有点体会 xff0c 看网上的解析比较少 xff0c 写上来和大家分享下 xff0c 全是自己的理解 xff0c 东西比较少 xff0c 硬货不多 xff0c 还请见谅 最开始是想做个无人机超声
  • 实验三、嵌入式Linux网络通信实验

    实验三 嵌入式Linux网络通信实验 一 实验目的 1 掌握TCP与UDP协议原理 2 掌握套接字通信原理 2 掌握TCP套接字服务器端与客户端通信方法 二 实验基本要求 1 学习TCP与UDP协议原理 2 掌握TCP套接字服务器端与客户端
  • QT重载keyPress焦点问题

    最近项目上需要用到键盘上的快捷键 xff0c 就重载了键盘的按下事件 xff0c 以为万事大吉 实际界面上有很多控件 xff0c 导致如果鼠标点击了其中一个不能接收焦点的控件 xff0c 就不知道焦点传到了什么地方 上网查大致两种思路 xf
  • QT实现地图或图片的细节图(抓取图片的细节,放大图片)

    最近由于项目上的要求 xff0c 需要实现一个细节图 xff0c 就是一个矩形框中加载一个大图 xff0c 右下或者左下方有一个小矩形框 xff0c 可以加载全图 xff0c 并显示大矩形框中图片在全图的位置 xff0c 有点拗口 xff0
  • centos7 搭建vtk7.1.1+Qt开发环境+运行编译工程

    一 CMAKE安装 vtk必须用cmake编译 xff0c 但是 xff0c 由于高版本的cmake没有支持qt5的gui xff0c 所以选择低版本的 xff0c 但是低版本的必须得依赖于qt4 xff0c 而qt4相较于qt5 xff0
  • centos搭建vtk开发环境

    一 OpenGL3 0 vtk有个硬性要求就是OpenGL3 0及以上版本 xff0c 由于笔者此前使用的是centos7 xff0c 照着网上的教程配置OpenGL xff0c 但是之后glxinfo grep OpenGL发现openg
  • 读取ugrid格式文件

    include lt iostream gt include lt vector gt include lt string gt include lt fstream gt using namespace std int main int
  • C语言:#define详解

    define定义标识符 语法 xff1a define name stuff tips xff1a 我们在define定义标识符的时候 xff0c 不建议在后面加上 xff1b xff0c 这样很容易出问题 比如说在以下的情况中 xff1a
  • FPGA学习-UART串口发送单字节(UART时序分析+真正的FPGA设计看图写代码)

    首先看UART发送时序图 xff1a 要发送一个完整字节 xff0c 需要 1位起始位 43 8位数据位 43 1位停止位 xff0c 图上的第11位 xff0c 是确认一个字节发送完的一位 重点是每一位之间的发送时间需要保持一致 xff0
  • STM32串口2初始化

    在STM32提供的官方库里只有串口一的初始化代码 xff0c 但当你需要用到两个以上的串口 xff0c 就得自己写相应的代码 xff0c 下面是串口2的 xff0c 其他的串口也差不多 usart2 c include 34 sys h 3
  • VINS-Fusion跑kitti stereo及stereo+GPS数据

    Stereo source vfusion devel setup bash roslaunch vins vins rviz launch source vfusion devel setup bash rosrun loop fusio
  • vue 配置代理,简单解决跨域问题

    开发环境下 xff0c 借助vue cli简单解决跨域问题 配置方式一 xff1a 在vue config js文件中添加以下代码 xff1a devServer proxy 39 被代理的基础路径 39 这种方式只能配置一个代理 xff0
  • Wireshark网络抓包疯狂聊天程序

    文章目录 一 疯狂聊天环境配置二 使用wireshark进行抓包三 分析抓包四 参考文献 一 疯狂聊天环境配置 下载好疯狂聊天软件后 xff0c 打开计算机管理 xff0c 设备管理器 网络适配器中需要禁用这几项 xff0c 否则无法双向通
  • 游戏客户端编程

    文章目录 一 代码框架二 新建项目三 演示效果 一 代码框架 本次实验使用的网游客户端框架来自课堂老师的资料 链接 xff1a https pan baidu com s 1WSkrRTFPuN1N34BsySkeaQ 提取码 xff1a
  • 数学图形与机器视觉基础(1)

    文章目录 一 图片处理及分析1 修改图片位数和颜色并进行分析2 修改图片格式并进行分析 二 用奇异值分解 xff08 SVD xff09 对一张图片进行特征值提取 xff08 降维 xff09 处理三 采用图像的开闭运算 腐蚀 膨胀 xff
  • STM32之串口通信

    文章目录 一 串口通信与USART二 程序编写输出Hello Windows三 GPIO波形参考链接 一 串口通信与USART 二 程序编写输出Hello Windows 串口通信 串口通信是一种设备间非常常用的串行通行方式 xff0c 其
  • 【FPGA】UART串口通信

    文章目录 一 通信方式1 串行通信2 并行通信 二 UART串口通信1 模块设计与时序图2 代码实现 三 测试结果1 仿真结果2 上板验证 一 通信方式 1 串行通信 串行通信是指利用一条传输线将数据一位位地顺序传送 xff08 也就是说串