Verlog-串口发送-FPGA

Verlog-串口发送-FPGA

引言:

​ 随着电子技术的不断进步,串口通信已成为嵌入式系统和计算机外设中一种广泛使用的异步通信方式。串口通信因其简单性、可靠性以及对硬件资源的低要求,在数据传输领域扮演着重要角色。在FPGA(现场可编程门阵列)设计中,实现串口通信功能是连接外部处理器和FPGA、实现数据交换的关键技术之一。 本实验旨在通过Verilog语言,设计并实现一个能够在FPGA上运行的串口发送模块。通过本实验,将有机会深入了解FPGA的通信接口设计,掌握Verilog语言在串口通信应用中的编程技巧,以及如何将理论知识应用到实际的硬件设计中。

希望你在本次学习过后,能够有一定的收获!!!

​ 冲啊!!!! ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶

文章目录

  • Verlog-串口发送-FPGA
    • 一、任务介绍
    • 二、知识基础
      • 1、字符编码(GBK)
      • 2、串口通信
    • 三、实验内容
      • 1、实验代码
        • ctrl.v
        • uart_tx.v
      • 2、实验原理
      • 3、实验器材
      • 4、引脚配置图
    • 四、实验效果
    • 五、总结

一、任务介绍

  1. 熟悉FPGA的开发流程
  2. 练习并且巩固有关于verilog代码的相关内容
  3. 使用Verilog语言编写程序实现FPGA的串口输出
  4. 了解熟悉GBK编码

二、知识基础

1、字符编码(GBK)

GBK编码概述: GBK是一种用于简体中文字符的编码方式,它是对GB2312编码的扩展,支持更多的汉字和符号。GBK编码可以表示21003个汉字和图形符号,包括6763个汉字,并且兼容ASCII编码中的所有字符。

GBK编码特点:

  1. 双字节表示: 每个GBK字符由两个字节组成,最高位为1,这样可以与ASCII编码区分开来。
  2. 兼容GB2312: GBK继承了GB2312的编码规则,同时增加了对更多汉字的支持。
  3. 广泛的应用: 在中文操作系统、数据库和网页中,GBK被广泛用于表示中文字符。

GBK编码在串口通信中的应用: 在FPGA的串口通信中,经常需要发送或接收文本信息。由于ASCII编码只能表示128个字符,不足以涵盖所有的中文字符,因此,使用GBK编码可以传输完整的中文文本。在设计串口发送模块时,需要将待发送的字符串转换为GBK编码的字节序列,然后通过串口发送出去。

GBK编码转换:

  1. 编码转换: 将需要发送的字符串转换为GBK编码的字节序列。这可以通过编程实现,也可以使用专门的工具完成。
  2. 串口发送: 将转换后的GBK字节序列通过FPGA的串口发送出去。在Verilog代码中,需要设计一个发送状态机来控制数据的发送过程。

实验中的GBK应用: 在本实验中,将学习如何将字符串转换为GBK编码,并在FPGA上实现串口发送模块,将GBK编码的数据通过串口发送出去。这不仅涉及到GBK编码的知识,还需要掌握Verilog语言的编程技巧和FPGA的串口通信机制。

编码转换网站:查看字符编码(简体中文) (mytju.com)

在这里插入图片描述

2、串口通信

串口通信概述: 串口通信是一种计算机硬件设备之间常用的串行通信方式,它允许数据以串行的方式在设备之间传输。串口通信广泛应用于嵌入式系统、计算机外设、工业控制系统等领域。

串口通信特点:

  1. 串行传输: 数据一位接一位地在发送设备和接收设备之间传输。
  2. 异步通信: 发送和接收设备使用各自的时钟信号,不需要同步时钟。
  3. 简单易用: 只需要少数几根线(如TX、RX、GND),易于实现和扩展。
  4. 波特率: 串口通信的数据传输速率,以比特每秒(bps)计量。

串口通信的关键参数:

  • 数据位: 每个字符的数据宽度,常见的有7位、8位等。
  • 停止位: 数据传输结束后的一位或两位空闲状态,用于标识数据结束。
  • 奇偶校验位: 用于检测数据传输中的错误,可以是奇校验、偶校验或无校验。

串口通信在FPGA设计中的应用: 在FPGA设计中,实现串口通信功能可以用于:

  1. 与外部设备通信: 如与PC机、微控制器或其他FPGA芯片交换数据。
  2. 调试和监控: 通过串口输出FPGA内部的状态信息,便于调试和监控。
  3. 数据传输: 实现与其他系统的串行数据传输。

FPGA串口通信设计要点:

  1. 波特率发生器: 根据所需的波特率生成时钟信号,控制数据的发送和接收速率。
  2. 发送器(TX): 负责将并行数据转换为串行数据,并控制数据的发送。
  3. 接收器(RX): 负责将串行数据转换为并行数据,并处理接收到的数据。
  4. 状态机: 通常使用有限状态机(FSM)来控制数据的发送和接收过程。

实验中的串口通信实现: 在本实验中,将学习如何使用Verilog语言在FPGA上实现串口发送模块。这包括:

  • 设计波特率发生器,生成合适的时钟信号。
  • 实现发送器,将待发送的数据转换为串行格式,并控制数据的发送。
  • 通过FPGA的串口接口(如UART)与外部设备进行通信。

通过本实验,将深入理解串口通信的原理和实现方法,为未来在更复杂的通信协议和系统设计中打下坚实的基础。

三、实验内容

1、实验代码

ctrl.v
module ctrl (input clk,input rst_n,output tx
);wire    [7:0] send_data[31:0] ; // 发送的数据数组 -- Hello World !!! 你干嘛,哎哟~~~assign send_data[00] = {8'h48};assign send_data[01] = {8'h65};assign send_data[02] = {8'h6C};assign send_data[03] = {8'h6C};assign send_data[04] = {8'h6F};assign send_data[05] = {8'h20};assign send_data[06] = {8'h57};assign send_data[07] = {8'h6F};assign send_data[08] = {8'h72};assign send_data[09] = {8'h6C};assign send_data[10] = {8'h64};assign send_data[11] = {8'h20};assign send_data[12] = {8'h21};assign send_data[13] = {8'h21};assign send_data[14] = {8'h21};assign send_data[15] = {8'h20};assign send_data[16] = {8'hC4};assign send_data[17] = {8'hE3};assign send_data[18] = {8'hB8};assign send_data[19] = {8'hC9};assign send_data[20] = {8'hC2};assign send_data[21] = {8'hEF};assign send_data[22] = {8'hA3};assign send_data[23] = {8'hAC};assign send_data[24] = {8'hB0};assign send_data[25] = {8'hA5};assign send_data[26] = {8'hD3};assign send_data[27] = {8'hB4};assign send_data[28] = {8'h7E};assign send_data[29] = {8'h7E};assign send_data[30] = {8'h7E};assign send_data[31] = {8'h0A}; // 换行parameter TIME_pause   = 28'd 50_000_000;// 每次完整的发送时间 1sreg    [40-1:0]    cnt_pause     ; wire   add_cnt_pause ,  end_cnt_pause ; always @(posedge clk or negedge rst_n) if (!rst_n)cnt_pause  <= 40'b0;else if (add_cnt_pause )if (end_cnt_pause )cnt_pause <=40'b0;else cnt_pause  <= cnt_pause  +1'd1;else cnt_pause  <= cnt_pause ;assign add_cnt_pause  = 1'b1;assign end_cnt_pause  = add_cnt_pause  && (TIME_pause -1 == cnt_pause );// 每次完整的发送时间 1s// 每个1s 切换一次发送状态reg flag_sent;always @(posedge clk or negedge rst_n) beginif(!rst_n)flag_sent <= 1'b0;else if (end_cnt_pause)flag_sent <= ~flag_sent;else flag_sent <= flag_sent;end// 每个1s 切换一次发送状态// 每一个字符之间的间隔发送时间reg    [40-1:0]    cnt_bit_pause     ; wire   add_cnt_bit_pause ,  end_cnt_bit_pause ; always @(posedge clk or negedge rst_n) if (!rst_n)cnt_bit_pause  <= 40'b0;else if (add_cnt_bit_pause )if (end_cnt_bit_pause )cnt_bit_pause <=40'b0;else cnt_bit_pause  <= cnt_bit_pause  +1'd1;else cnt_bit_pause  <= cnt_bit_pause ;assign add_cnt_bit_pause  = flag_sent;assign end_cnt_bit_pause  = add_cnt_bit_pause  && (cnt_bit_pause == (300_00 -1));// 每一个字符之间的间隔发送时间// 一个句是否发送完成标志reg one_epoch;// 单个字符数据reg     [7:0]   tx_data         ;reg    [6-1:0]    cnt_bit     ; wire   add_cnt_bit ,  end_cnt_bit ; always @(posedge clk or negedge rst_n) if (!rst_n)cnt_bit  <= 6'b0;else if (add_cnt_bit)if (end_cnt_bit )cnt_bit <=6'b0;else cnt_bit  <= cnt_bit  +1'd1;else cnt_bit  <= cnt_bit ;assign add_cnt_bit  = flag_sent && end_cnt_bit_pause && !one_epoch;assign end_cnt_bit  = add_cnt_bit  && (6'd32-1 == cnt_bit );always @(posedge clk or negedge rst_n) beginif(!rst_n)one_epoch <= 1'b0;else if (end_cnt_bit)one_epoch <= 1'b1;else if(!flag_sent)one_epoch <= 1'b0;else one_epoch <= one_epoch;endalways @(*) begintx_data <= send_data[cnt_bit];enduart_tx inst_tx_uart (.clk                (clk),.rst_n              (rst_n),.din                (tx_data),.din_vld            (end_cnt_bit_pause && !one_epoch),.dout               (tx));endmodule
uart_tx.v
module uart_tx (input clk,input rst_n,input [7:0] din,input din_vld,output reg dout
);parameter BAUD = 434;reg [8:0] cnt_bsp;wire add_cnt_bsp;wire end_cnt_bsp;reg [3:0] cnt_bit;wire add_cnt_bit;wire end_cnt_bit;reg flag;reg [8:0] data;always @(posedge clk or negedge rst_n) beginif(!rst_n) cnt_bsp <= 0;else if(add_cnt_bsp)if(end_cnt_bsp) cnt_bsp <= 0;else cnt_bsp <= cnt_bsp + 1;else cnt_bsp <= cnt_bsp;endassign add_cnt_bsp = flag;assign end_cnt_bsp = add_cnt_bsp && (cnt_bsp == BAUD - 1);always @(posedge clk or negedge rst_n) beginif(!rst_n) cnt_bit <= 0;else if(add_cnt_bit)if(end_cnt_bit) cnt_bit <= 0;else cnt_bit <= cnt_bit + 1;else cnt_bit <= cnt_bit;endassign add_cnt_bit = end_cnt_bsp;assign end_cnt_bit = add_cnt_bit && (cnt_bit == 8);always @(posedge clk or negedge rst_n)beginif(!rst_n) flag = 0;else if (din_vld) flag <=1;else if (end_cnt_bit) flag <=0;else flag <= flag;endalways @(posedge clk or negedge rst_n)beginif(!rst_n) data <= !0;else if (din_vld)  data <= {din,1'b0} ; // 数据加上起始位else data <= data;endalways @(posedge clk or negedge rst_n)beginif(!rst_n) dout <=1;else if (cnt_bsp == 1) dout <= data[cnt_bit]; // 串行输出 LSBelse if (end_cnt_bit) dout <= 1'b1;else dout <= dout;  endendmodule

2、实验原理

模块功能概述: 本实验的目的是设计一个能够在FPGA上运行的串口发送模块,该模块能够通过串口发送预定义的字符串数据。代码中定义了一个发送数据数组send_data,包含了要发送的每个字符的ASCII码或GBK码。

串口发送原理:

  1. 数据数组定义: 使用一个寄存器数组send_data来存储要发送的字符数据,每个字符占用8位,数组长度可以根据需要发送的字符数量来定义。
  2. 发送数据加载: 通过assign语句将特定的ASCII码或GBK码赋给send_data数组的每个元素,形成要发送的数据序列。
  3. 波特率控制: 通过一个计数器生成与设定波特率相匹配的时钟信号,控制数据发送的速率。
  4. 发送状态机: 利用有限状态机(FSM)管理数据的发送过程,包括起始位的发送、数据位的逐位发送、以及停止位的添加。

代码实现细节:

  1. 数据发送控制: 使用标志位flag_sent来控制数据的发送,该标志位每秒切换一次,以实现每秒发送一次数据数组。
  2. 发送暂停计数: 使用cnt_pause计数器和相关逻辑来实现发送之间的暂停,以便在发送每个字符后提供适当的延迟。
  3. 位发送控制: 使用cnt_bit计数器来控制单个字符的位发送过程,确保每个字符的8位数据按顺序发送。
  4. 串口发送模块: 实例化uart_tx模块,它负责根据波特率控制信号逐位发送数据,并在每发送完一个字节后添加停止位。

波特率发生器:

  • uart_tx模块内部实现了一个波特率发生器,通过计数器cnt_bsp来控制发送速率,以匹配预设的波特率BAUD

数据发送:

  • 数据通过data寄存器存储,并在每个时钟周期发送最低位(LSB),直到8位数据全部发送完毕。

串口信号输出:

  • 串口的dout信号负责输出当前正在发送的位,起始位为0,停止位为1。

实验关键点:

  • 数据编码: 理解如何将字符转换为对应的ASCII或GBK编码。
  • 时序控制: 掌握如何使用计数器和状态机来控制数据的发送时序。
  • 串口通信规范: 了解串口通信的标准,包括起始位、数据位、停止位和波特率。

通过本实验,将能够理解并实践FPGA上串口发送模块的设计,为进一步学习更复杂的串口通信应用打下基础。

3、实验器材

在这里插入图片描述

在这里插入图片描述

4、引脚配置图

在这里插入图片描述

四、实验效果

v-串口

五、总结

经过本次实验,我成功设计并实现了一个FPGA上的串口发送模块,该模块能够按照预定的波特率发送存储在数据数组send_data中的字符串。通过这个过程,我深入理解了串口通信的工作原理和在FPGA上实现它所需的关键技术。 实验过程回顾:

  1. 我首先定义了一个包含所有要发送字符的数组send_data,并为每个字符分配了相应的ASCII或GBK编码。
  2. 我实现了一个发送控制逻辑,使用一个标志位flag_sent来控制每秒发送一次数据数组中的字符。
  3. 我设计了一个波特率发生器,通过计数器cnt_bsp来控制数据的发送速率,以匹配预设的波特率。
  4. 我利用了一个状态机来管理数据的发送过程,包括起始位的生成、数据位的逐位发送和停止位的添加。
  5. 我实例化了一个uart_tx模块,它负责实际的串口信号输出,包括数据位的串行化和波特率控制。

实验成果: 通过本次实验,我不仅掌握了Verilog语言在串口通信应用中的编程技巧,还学会了如何将理论知识应用到实际的硬件设计中。我能够独立完成从设计、仿真到硬件测试的整个FPGA设计流程,并且能够通过外部串口工具接收发送的数据。

实验反思: 在实验过程中,我遇到了一些挑战,比如确保数据在发送过程中的时序准确性,以及调试串口通信中的常见问题。通过不断测试和调整,我学会了如何对FPGA设计进行调试,解决可能出现的问题。

未来展望: 虽然本次实验已经完成,但我认识到在FPGA设计和串口通信方面还有许多可以学习和探索的地方。未来,我计划探索更复杂的通信协议,如SPI、I2C等,并尝试将这些技术应用到更大型的FPGA项目中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/325265.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AcwingWeb应用课学习笔记

y总Web课链接&#xff1a; VSCode自动格式化 选中Format On Save不起作用 在设置中搜索default formatter&#xff0c;修改成Prettier-Code formatter 标签 文本标签虽然很多&#xff0c;但大部分可看成是预定好样式的<div>和<span>。&#xff08;div也是由sp…

关于一致性,你该知道的事儿(下)

关于一致性&#xff0c;你该知道的事儿&#xff08;下&#xff09; 前言一、并发修改单个对象1.1 原子写操作1.2 显示加锁1.3 原子的TestAndSet1.4 版本号机制 二、 多个相关对象的一致性2.1 最大努力实现2.2 2PC && TCCC2.3.基于可靠消息的一致性方案2.4.Saga事务 三、…

ntfs文件系统的优势 NTFS文件系统的特性有哪些 ntfs和fat32有什么区别 苹果电脑怎么管理硬盘

对于数码科技宅在新购得磁盘之后&#xff0c;出于某种原因会在新的磁盘安装操作系统。在安装操作系统时&#xff0c;首先要对磁盘进行分区和格式化&#xff0c;而在此过程中&#xff0c;操作者们需要选择文件系统。文件系统也决定了之后操作的流程程度&#xff0c;一般文件系统…

基于opencv的车辆统计

车辆统计&#xff09; 一、项目背景二、整体流程三、常用滤波器的特点四、背景减除五、形态学开运算闭运算 六、项目完整代码七、参考资料 一、项目背景 检测并识别视频中来往车辆的数量 最终效果图&#xff1a; 二、整体流程 加载视频图像预处理&#xff08;去噪、背景减除…

picoCTF-Web Exploitation-Most Cookies

Description Alright, enough of using my own encryption. Flask session cookies should be plenty secure! server.py http://mercury.picoctf.net:53700/ Hints How secure is a flask cookie? 我们先下载server.py&#xff0c;分析逻辑 from flask import Flask, render…

【智能算法】鹭鹰优化算法(SBOA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;Y Fu受到自然界中鹭鹰生存行为启发&#xff0c;提出了鹭鹰优化算法&#xff08;Secretary Bird Optimization Algorithm, SBOA&#xff09;。 2.算法原理 2.1算法思想…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.5讲 GPIO中断实验-通用中断驱动编写

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

C++:友元

友元&#xff08;friend&#xff09;是 C 中的一个关键字&#xff0c;用于建立类之间的友好关系&#xff1b;通过友元关系&#xff0c;一个类可以授权其他类或函数访问其私有成员或受保护成员&#xff0c;从而突破了 C 中的封装性&#xff1b;友元可以是类或函数&#xff0c;可…

css案例 tab上下滚动,左右滚动

效果图&#xff1a; 完整代码&#xff1a; <template><view class"content"><view class"content-item"><view class"content-title"><h4>美食热搜</h4><ul><li>火鸡面</li><li>糖…

Java---类和对象第一节

目录 1.面向对象初步认识 1.1什么是面向对象 1.2面向对象和面向过程的区别 2.类的定义和使用 2.1简单认识类 2.2类的定义格式 2.3类的实例化 2.4类和对象的说明 3.this关键字 3.1访问本类成员变量 3.2调用构造方法初始化成员变量 3.3this引用的特性 4.对象的构造以…

MES系统与WMS集成方法(满分100学习资料)

导语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。专注分享智能仓储物流技术、智能制造等内容。 新书《智能物流系统构成与技术实践》 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载 这份文件是关于MES系…

运用分支结构与循环结构写一个猜拳小游戏

下面我们运用平常所学的知识来写一个小游戏&#xff0c;这样能够加强我们学习的趣味性&#xff0c;并且能够更加的巩固我们所学的知识。 游戏代码&#xff1a; 直接放代码&#xff1a;&#xff08;手势可以使用数字来代替&#xff0c;比如0对应石头&#xff0c;1对应剪刀&…

Sass深度解析:性能优化的秘密

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

Linux的基础IO:软硬连接 动态库 静态库

目录 软硬连接 硬链接的作用 静态库 制作静态库 安装自定义静态库 动态库 制作动态库 协助OS查找动态库的五种方法 总结 动态库加载 软硬连接 创建硬链接指令&#xff1a;ln 目标文件 链接者 创建软链接指令&#xff1a;ln -s 目标文件 链接者 删除链接指令&…

【管理咨询宝藏96】企业数字化转型的中台战略培训方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏96】企业数字化转型的中台战略培训方案 【格式】PDF版本 【关键词】SRM采购、制造型企业转型、数字化转型 【核心观点】 - 数字化转型是指&…

苹果电脑MAC清理系统空间工具CleanMyMacX4.15.3中文版下载

苹果电脑以其出色的性能、优雅的设计和高效的操作系统而受到许多用户的喜爱。然而&#xff0c;随着时间的推移和使用量的增加&#xff0c;你可能会发现你的Mac开始变得缓慢和响应迟缓。这通常是因为硬盘空间被大量占用&#xff0c;影响了系统的整体性能。幸运的是&#xff0c;有…

03.Linux文件操作

1.操作系统与Linux io框架 1.1 io与操作系统 1.1.1 io概念 io 描述的是硬件设备之间的数据交互&#xff0c;分为输⼊ (input) 与输出 (output)。 输⼊&#xff1a;应⽤程序从其他设备获取数据 (read) 暂存到内存设备中&#xff1b;输出&#xff1a;应⽤程序将内存暂存的数据…

蛋糕店做配送小程序的作用是什么

蛋糕烘焙除了生日需要&#xff0c;对喜吃之人来说往往复购率较高&#xff0c;除线下实体店经营外&#xff0c;更多的商家选择线上多种方式获客转化、持续提高生意营收&#xff0c;而除了进驻第三方平台外&#xff0c;构建品牌私域自营店铺也同样重要。 运用【雨科】平台搭建蛋…

zookeeper安装集群模式

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 ZooKeeper是一个分…

【大数据】分布式数据库HBase下载安装教程

目录 1.下载安装 2.配置 2.1.启动hadoop 2.2.单机模式 2.3.伪分布式集群 1.下载安装 HBase和Hadoop之间有版本对应关系&#xff0c;之前用的hadoop是3.1.3&#xff0c;选择的HBase的版本是2.2.X。 下载地址&#xff1a; Index of /dist/hbase 配置环境变量&#xff1a…