野火FPGA跟练(四)——串口RS232、亚稳态

目录

  • 简介
  • 接口与引脚
  • 通信协议
  • 亚稳态
  • RS232接收模块
    • 模块框图
    • 时序波形
    • RTL 代码
    • 易错点
    • Testbench 代码
    • 仿真
  • RS232发送模块
    • 模块框图
    • 时序波形
    • RTL 代码
    • Testbench 代码
    • 仿真


简介

  • UART:Universal Asynchronous Receiver/Transmitter,异步串行通信接口。发送数据时并行转串行,接收数据时串行转并行。
  • RS232:UART包括多种接口标准规范和总线标准规范,RS232为其一,还有RS499、RS423、RS422、RS485等。

接口与引脚

在这里插入图片描述在这里插入图片描述
重点关注RXD、TXD即可。

通信协议

  • 帧结构:包含8bit有效数据和起始位、停止位。空闲状态是高电平,起始位低电平,停止位高电平。低位数据先发,后发高位。
    在这里插入图片描述
    假设我要传输字符“1”,对应的ASCII码值是0x31,即“0011 0001” ,低位先发,那么我的这帧数据波形为 0 1000 1100 1

  • 波特率:假设波特率为9600Bps,传输一个码元(一个码元在这里代表一个二进制数,就是1bit数据)需要1/9600秒。假设系统时钟50MHz(周期为20ns),那么传输1bit数据所需的时间为 (1/9600)/(20*e-9) = 5208.33 ≈ 5208 个时钟周期。

亚稳态

  • 产生原因:
    触发器采集输入信号时需要一定的建立时间和保持时间,如果在这一期间输入信号发生变化,那么触发器将无法稳定输出,导致输出信号在高低电平间快速振荡,即进入亚稳态。

  • 不良影响:
    如果处于亚稳态的信号直接接入组合逻辑电路,会导致亚稳态在整个系统中传递,从而影响整个电路的运行,导致不稳定。

  • 解决方案:
    单比特信号可以采用“打两拍”,多比特信号可以采用异步FIFO、格雷码、握手。

RS232接收模块

模块框图

在这里插入图片描述
输入输出描述:

  1. 时钟:50MHz,每10ns翻转一次
  2. 复位:高电平异步复位
  3. RX:接收的串口数据
  4. DATA:处理后的数据,并行输出
  5. FLAG:置高时代表已处理好一帧数据,只维持一个时钟周期

时序波形

示意时序图,以9600波特率为例。

在这里插入图片描述

时序图分析:

  • RX_REG
    • RX_REG1:是将 RX 同步到时钟信号上。
    • RX_REG2、3:打两拍,避免亚稳态。
  • START_FLAG 标志数据接收的开始、WORK_EN 标志数据接收的状态
    • START_FLAG:这里使用的是组合方式赋值,通过 RX_REG2、3 检测 RX_REG 的下降沿。由于 RX_REG 的数据位中也有可能存在下降沿,所以 START_FLAG 置高的前提条件还应有 WORK_EN 为 0 。
    • WORK_EN:WORK_EN 通过判断 START_FLAG 的状态而置高,通过判断 BIT_CNT、BIT_FLAG 的状态而置低,其余时刻保持不变。
  • BAUD_CNT、BIT_FLAG
    • BAUD_CNT:BAUD_CNT 只在 WORK_EN 为高时计数
    • BIT_FLAG:在每比特数据传输时的中间时刻拉高
  • RX_DATA
    由于是低位数据先发,所以 RX_REG 的数据存在 RX_DATA 的高位,每次更新时 RX_DATA 右移,实现数据的串行转并行。RX_DATA 的值在 BAUD_CNT 为 1-8 并且 BIT_FLAG 为高时采集 RX_REG。

RTL 代码

module RS232_RX
#(parameter UART_BPS = 'd9600,parameter CLK_FREQ = 'd50_000_000
)
(input   wire         clk,input   wire         rst,input   wire         rx,output  reg   [7:0]  data,output  reg          flag);parameter BAUD_CNT_MAX = CLK_FREQ / UART_BPS;reg rx_reg1;reg rx_reg2;reg rx_reg3;wire start_flag;reg work_en;reg [16:0] baud_cnt;reg bit_flag;reg [3:0] bit_cnt;reg [7:0] rx_data;reg data_flag;// 赋值rx_reg1always@(posedge clk or posedge rst) beginif(rst == 1'b1)rx_reg1 <= 1'b1;elserx_reg1 <= rx;end// 赋值rx_reg2always@(posedge clk or posedge rst) beginif(rst == 1'b1)rx_reg2 <= 1'b1;elserx_reg2 <= rx_reg1;end// 赋值rx_reg3always@(posedge clk or posedge rst) beginif(rst == 1'b1)rx_reg3 <= 1'b1;elserx_reg3 <= rx_reg2;end// 赋值start_flagassign start_flag = ((rx_reg2 == 1'b0) && (rx_reg3 == 1'b1));// 赋值work_enalways@(posedge clk or posedge rst) beginif(rst == 1'b1)work_en <= 1'b0;else if(start_flag == 1'b1)work_en <= 1'b1;else if((bit_flag == 1'b1) && (bit_cnt == 4'd8))work_en <= 1'b0;elsework_en <= work_en;end// 赋值baud_cntalways@(posedge clk or posedge rst) beginif(rst == 1'b1)baud_cnt <= 17'b0;else if((baud_cnt == BAUD_CNT_MAX - 1) || (work_en == 1'b0))baud_cnt <= 17'b0;elsebaud_cnt <= baud_cnt + 1'b1;end // 赋值bit_flagalways@(posedge clk or posedge rst) beginif(rst == 1'b1)bit_flag <= 1'b0;else if(baud_cnt == BAUD_CNT_MAX / 2 - 1)bit_flag <= 1'b1;elsebit_flag <= 1'b0;end  // 赋值bit_cntalways@(posedge clk or posedge rst) beginif(rst == 1'b1)bit_cnt <= 4'b0;else if((bit_flag == 1'b1) && (bit_cnt == 4'd8))bit_cnt <= 4'b0;else if(bit_flag == 1'b1)bit_cnt <= bit_cnt + 1'b1;elsebit_cnt <= bit_cnt;end// 赋值rx_dataalways@(posedge clk or posedge rst) beginif(rst == 1'b1)rx_data <= 8'b0;else if((bit_cnt >= 4'd1) && (bit_cnt <= 4'd8) && (bit_flag == 1'b1))rx_data <= {rx_reg3,rx_data[7:1]};elserx_data <= rx_data;end// 赋值data_flagalways@(posedge clk or posedge rst) beginif(rst == 1'b1)data_flag <= 1'b0;else if((bit_flag == 1'b1) && (bit_cnt == 4'd8))data_flag <= 1'b1;elsedata_flag <= 1'b0;end// 赋值dataalways@(posedge clk or posedge rst) beginif(rst == 1'b1)data <= 8'd0;else if(data_flag == 1'b1)data <= rx_data;elsedata <= data;end// 赋值flagalways@(posedge clk or posedge rst) beginif(rst == 1'b1)flag <= 1'b0;elseflag <= data_flag;end
endmodule

易错点

如果数据是多位的,赋值时需要注意其位宽大小。如果一个多位宽的数据赋值为“1’b0”,这将只赋值给这个数据的最低位,其他位将保留原值,与本意相悖。

Testbench 代码

`timescale 1ns / 1ps
module tb_RS232_RX();reg     clk;reg     rst;reg     rx;wire [7:0]  data;wire    flag;// 初始化clk和rstinitial beginclk <= 1'b0;rst <= 1'b1;#60;rst <= 1'b0;end always #10 clk = ~clk;// 初始化rxinitial beginrx <= 1'b1;#100;rx_bit(8'b1001_0001);rx_bit(8'b0101_0010);rx_bit(8'b1110_0101);rx_bit(8'b0110_1000);rx_bit(8'b0110_1011);rx_bit(8'b0011_0110);rx_bit(8'b0001_1110);end// rx_bit函数,生成串行数据task rx_bit(input [7:0] rx_data);integer i;for(i = 0; i < 10; i = i + 1) begincase(i)0: rx <= 1'b0;1: rx <= rx_data[0];2: rx <= rx_data[1];3: rx <= rx_data[2];4: rx <= rx_data[3];5: rx <= rx_data[4];6: rx <= rx_data[5];7: rx <= rx_data[6];8: rx <= rx_data[7];9: rx <= 1'b1;endcase#(5208*20);   end         endtask// 实例化模块RS232_RX #(.UART_BPS(9600),.CLK_FREQ(50_000_000))tb_RS232_RX(.clk      (clk  ),.rst      (rst  ),.rx       (rx   ),.data     (data ),.flag     (flag ));
endmodule

仿真

在这里插入图片描述

RS232发送模块

模块框图

在这里插入图片描述
输入输出描述:

  1. 时钟:50MHz,每10ns翻转一次
  2. 复位:高电平异步复位
  3. DATA:待发送的并行数据
  4. FLAG:数据标志位
  5. TX:输出处理后的串行数据

时序波形

示意时序图,以9600波特率为例。

在这里插入图片描述

时序图分析:

  • WORK_EN:WORK_EN 通过判断 START_FLAG 的状态而置高,通过判断 BIT_CNT、BIT_FLAG 的状态而置低,其余时刻保持不变。
  • BAUD_CNT、BIT_FLAG
    • BAUD_CNT:BAUD_CNT 只在 WORK_EN 为高时计数
    • BIT_FLAG:在 BAUD_CNT 计数为1时刻拉高

RTL 代码

module RS232_TX
#(parameter UART_BPS = 'd9600,parameter CLK_FREQ = 'd50_000_000
)
(input wire clk,input wire rst,input wire [7:0] data,input wire flag,output reg tx);parameter BAUD_CNT_MAX = CLK_FREQ / UART_BPS;reg work_en;reg [16:0] baud_cnt;reg bit_flag;reg [3:0] bit_cnt;// 赋值work_enalways@(posedge clk or posedge rst) beginif(rst == 1'b1)work_en <= 1'b0;else if(flag == 1'b1)work_en <= 1'b1;else if((bit_flag == 1'b1) && (bit_cnt == 4'd10))work_en <= 1'b0;elsework_en <= work_en;end// 赋值baud_cntalways@(posedge clk or posedge rst) beginif(rst == 1'b1)baud_cnt <= 17'b0;else if((baud_cnt == BAUD_CNT_MAX - 1'b1) || (work_en == 1'b0))baud_cnt <= 17'b0;elsebaud_cnt <= baud_cnt + 1'b1;end// 赋值bit_flagalways@(posedge clk or posedge rst) beginif(rst == 1'b1)bit_flag <= 1'b0;else if(baud_cnt == 17'b1)bit_flag <= 1'b1;elsebit_flag <= 1'b0;end// 赋值bit_cntalways@(posedge clk or posedge rst) beginif(rst == 1'b1)bit_cnt <= 4'b0;else if((bit_flag == 1'b1) && (bit_cnt == 4'd10))bit_cnt <= 4'b0;else if(bit_flag == 1'b1)bit_cnt <= bit_cnt + 1'b1;elsebit_cnt <= bit_cnt;end// 赋值txalways@(posedge clk or posedge rst) beginif(rst == 1'b1)tx <= 1'b1;else begincase(bit_cnt)4'd1: tx <= 1'b0;4'd2: tx <= data[0];4'd3: tx <= data[1];4'd4: tx <= data[2];4'd5: tx <= data[3];4'd6: tx <= data[4];4'd7: tx <= data[5];4'd8: tx <= data[6];4'd9: tx <= data[7];4'd10: tx <= 1'b1;default: tx <= 1'b1;endcaseendend
endmodule

Testbench 代码

`timescale 1ns / 1ps
module tb_RS232_TX();reg clk;     reg rst;    reg [7:0] data;reg flag;wire tx;       // 初始化clk和rstinitial beginclk <= 1'b0;rst <= 1'b1;#60;rst <= 1'b0;end always #10 clk = ~clk;// 初始化data和flaginitial begindata <= 8'd0;flag <= 1'd0;#200;// 数据1data <= 8'b0010_1011;flag <= 1'd1;#20;flag <= 1'd0;#(5208*12*20);// 数据2data <= 8'b0111_0101;flag <= 1'd1;#20;flag <= 1'd0;#(5208*12*20);// 数据3data <= 8'b1010_0001;flag <= 1'd1;#20;flag <= 1'd0;#(5208*12*20);end// 实例化模块RS232_TX #(.UART_BPS(9600),.CLK_FREQ(50_000_000))tb_RS232_TX(.clk    (clk),       .rst    (rst),       .data   (data),.flag   (flag),      .tx     (tx)      );
endmodule

仿真

在这里插入图片描述

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

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

相关文章

网络流媒体协议——RTMP

流媒体协议常用实时信息传输协议(Real-Time Messaging Protocol,RTMP)和 HLS 协议。RTMP 为应用层协议,由 TCP 提供传输层的连接和传输服务,默认端口为1935。 RTMP URL rtmp://host:port/app/steamrtmp∶ 表示该URL必须以RTMP进行解析。host, port 分别表示主机地址和端口…

微服务开发与实战Day04

一、网关路由 网关&#xff1a;就是网络的关口&#xff0c;负责请求的路由、转发、身份校验。 在SpringCloud中网关的实现包括两种&#xff1a; 1. 快速入门 Spring Cloud Gateway 步骤&#xff1a; ①新建hm-gateway模块 ②引入依赖pom.xml(hm-gateway) <?xml version…

解锁俄罗斯市场:如何选择优质的俄罗斯云服务器

在当前云计算市场上&#xff0c;很多大型的云厂商并没有俄罗斯服务器的云节点&#xff0c;这给许多企业在拓展海外业务时带来了一定的困扰。然而&#xff0c;俄罗斯作为一个经济发展迅速的国家&#xff0c;其市场潜力不可忽视。因此&#xff0c;选择一台优质的俄罗斯云服务器成…

【MySQL】(基础篇三) —— 创建数据库和表

管理数据库和表 管理数据库 创建数据库 在MySQL中&#xff0c;创建数据库的SQL命令相对简单&#xff0c;基本语法如下&#xff1a; CREATE DATABASE 数据库名;如果你想避免在尝试创建已经存在的数据库时出现错误&#xff0c;可以添加 IF NOT EXISTS 子句&#xff0c;这样如…

04-4.1.2 串的存储结构

&#x1f44b; Hi, I’m Beast Cheng&#x1f440; I’m interested in photography, hiking, landscape…&#x1f331; I’m currently learning python, javascript, kotlin…&#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以订…

数据结构(C):二叉树前中后序和层序详解及代码实现及深度刨析

目录 &#x1f31e;0.前言 &#x1f688;1.二叉树链式结构的代码是实现 &#x1f688;2.二叉树的遍历及代码实现和深度刨析代码 &#x1f69d;2.1前序遍历 ✈️2.1.1前序遍历的理解 ✈️2.1.2前序代码的实现 ✈️2.1.3前序代码的深度解剖 &#x1f69d;2.2中序遍历 ✈…

Spring boot SSL证书路径配置

SSL证书路径配置: 1、打包到resouce下&#xff1a; server:port: 443ssl:enabled: truekey-store: classpath:XX.XX.com.p12key-store-password: your-passwordkeyStoreType: PKCS12keyAlias: your-alias 2、放到windows类型服务器硬盘上 Windows系统中&#xff0c;由于路径…

一些常用的frida脚本

这里整理一些常用的frida脚本&#xff0c;和ghidra 一起食用风味更佳&#xff5e; Trace RegisterNatives 注意到从java到c的绑定中&#xff0c;可能会在JNI_OnLoad动态的执行RegisterNatives方法来绑定java层的函数到c行数&#xff0c;可以通过这个方法&#xff0c;来吧运行…

VSCode 1.90版本 升级需谨慎~(Python)

由于再次出现justMyCode的问题&#xff0c;请使用Python的小伙伴要谨慎将Visual Studio Code升级到1.90版本&#xff08;两天前官方刚发布的&#xff09; 若已经升级到1.90的小伙伴&#xff0c;可以从这里下载1.89版本进行“补救“&#xff1a; 1.89.1版本下载链接&#xff1a;…

Android 14.0 修改wifi信号强度和信号等级

1.前言 在14.0的系统rom产品定制化开发中,在进行产品开发中,对应系统定制会有各种各样的需求,对纯wifi产品而言,对于wifi要求也是越来越高,因此有客户要求对wifi信号强度做定制,修改信号强度来增强显示wifi信号,所以要对wifi显示信号强度的相关代码做修改 2.修改wifi信…

计算机网络:数据链路层 - 扩展的以太网

计算机网络&#xff1a;数据链路层 - 扩展的以太网 集线器交换机自学习算法单点故障 集线器 这是以前常见的总线型以太网&#xff0c;他最初使用粗铜轴电缆作为传输媒体&#xff0c;后来演进到使用价格相对便宜的细铜轴电缆。 后来&#xff0c;以太网发展出来了一种使用大规模…

AI菜鸟向前飞 — LangChain系列之十七 - 剖析AgentExecutor

AgentExecutor 顾名思义&#xff0c;Agent执行器&#xff0c;本篇先简单看看LangChain是如何实现的。 先回顾 AI菜鸟向前飞 — LangChain系列之十四 - Agent系列&#xff1a;从现象看机制&#xff08;上篇&#xff09; AI菜鸟向前飞 — LangChain系列之十五 - Agent系列&#…

Springboot使用webupload大文件分片上传(包含前后端源码)

Springboot使用webupload大文件分片上传&#xff08;包含源码&#xff09; 1. 实现效果1.1 分片上传效果图1.2 分片上传技术介绍 2. 分片上传前端实现2.1 什么是WebUploader&#xff1f;功能特点接口说明事件APIHook 机制 2.2 前端代码实现2.2.1&#xff08;不推荐&#xff09;…

词向量对模型performance的影响

因为自己搭建了一个4层的transformer网络&#xff0c;然后词向量的维度是96(attention is all you need里面transformer block的dim512)&#xff0c;这里设置96是为了后续我需要做一些attack的任务。 然后使用transformer4对YELP(5分类)分类的时候&#xff0c;performance一直…

【深度学习基础】池化层

池化层&#xff08;Pooling Layer&#xff09;在卷积神经网络&#xff08;CNN&#xff09;中常用于计算机视觉任务&#xff0c;但在自然语言处理&#xff08;NLP&#xff09;任务中也有广泛的应用。池化层在NLP任务中可以帮助提取重要特征&#xff0c;降低数据维度&#xff0c;…

计算机组成原理之计算机系统层次结构

目录 计算机系统层次结构 复习提示 1.计算机系统的组成 2.计算机硬件 2.1冯诺依曼机基本思想 2.1.1冯诺依曼计算机的特点 2.2计算机的功能部件 2.2.1MAR 和 MDR 位数的概念和计算 3.计算机软件 3.1系统软件和应用软件 3.2三个级别的语言 3.2.1三种机器语言的特点 3…

★pwn 24.04环境搭建保姆级教程★

★pwn 24.04环境搭建保姆级教程★ &#x1f338;前言&#x1f33a;Ubuntu 24.04虚拟机&#x1f337;VM&#x1f337;Ubuntu 24.04镜像 &#x1f33a;工具&#x1f337;可能出现的git clone错误&#x1f337;复制粘贴问题&#x1f337;攻击&#x1f337;编题 &#x1f33a;美化&…

【AI大模型】Transformers大模型库(五):AutoModel、Model Head及查看模型结构

目录​​​​​​​ 一、引言 二、自动模型类&#xff08;AutoModel&#xff09; 2.1 概述 2.2 Model Head&#xff08;模型头&#xff09; 2.3 代码示例 三、总结 一、引言 这里的Transformers指的是huggingface开发的大模型库&#xff0c;为huggingface上数以万计的预…

使用 Keras 的 Stable Diffusion 实现高性能文生图

前言 在本文中&#xff0c;我们将使用基于 KerasCV 实现的 [Stable Diffusion] 模型进行图像生成&#xff0c;这是由 stable.ai 开发的文本生成图像的多模态模型。 Stable Diffusion 是一种功能强大的开源的文本到图像生成模型。虽然市场上存在多种开源实现可以让用户根据文本…

【会议征稿,IEEE出版】第三届能源与电力系统国际学术会议 (ICEEPS 2024,7月14-16)

如今&#xff0c;全球能源行业正面临着前所未有的挑战。一方面&#xff0c;加快向清洁、可再生能源转型是遏制能源环境污染问题的最佳途径之一&#xff1b;另一方面&#xff0c;电力系统中新能源发电、人工智能技术、电力电子装备等被广泛应用和期待&#xff0c;以提高能源可持…