FPGA(Verilog)实现uart传输协议传输数据(含仿真)

news2024/11/25 20:45:57

目录

实现功能:

1.接收uart串行数据,输出并行数据(1byte)。

2.输入并行数据(1byte),输出uart串行数据。

3.完成uart传输的1次环回。

uart协议的1帧数据传输

模块封装-port设置

Verilog代码实现

1.uart接收模块:接收串行数据,输出并行数据和其有效标志。

仿真结果:

2.uart发送模块:接收并行数据,发送串行数据。

仿真结果:

3.uart环回测试。

仿真验证:

仿真结果:

FPGA系统集成-RTL框图


实现功能:

1.接收uart串行数据,输出并行数据(1byte)。

2.输入并行数据(1byte),输出uart串行数据。

3.完成uart传输的1次环回。

uart协议的1帧数据传输

模块封装-port设置

Verilog代码实现
1.uart接收模块:接收串行数据,输出并行数据和其有效标志。
module uart_rx#(
	parameter	UART_BPS='d9600			,	//波特率:1s传输9600个bit
	parameter	CLK_FREQ='d50_000_000		//时钟频率:50MHz
)(
	input 	wire			clk			,
	input 	wire			rst_n		,
	input 	wire			rx			,	//接收的串行数据

	output 	reg		[7:0]	po_data		,	//输出并行数据
	output 	reg				po_flag			//输出有效并行数据的标志信号
);

首先对rx进行时钟同步,消除亚稳态,以及打拍处理提取下降沿;

always@(posedge clk or negedge rst_n)
	if(!rst_n) begin
		rx_d1<=1'b1;
		rx_d2<=1'b1;
		rx_d3<=1'b1;
	end
	else begin
		rx_d1<=rx;		//时钟同步,消除亚稳态
		rx_d2<=rx_d1;	//时钟同步,消除亚稳态
		rx_d3<=rx_d2;	//打拍处理
	end

assign rx_fall = ~rx_d2 & rx_d3 ;	//提取rx下降沿

然后需要数据帧的有效信号,以便知道什么时候计数;

always@(posedge clk or negedge rst_n)
	if(!rst_n) frame_val<=1'b0;
	else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag)	//接收完1帧数据
		frame_val<=1'b0;
	else if(rx_fall)
		frame_val<=1'b1;
	else
		frame_val<=frame_val;

1码元符号(1bit)所需的计数器;

always@(posedge clk or negedge rst_n)
	if(!rst_n) baud_cnt<=16'd0;
	else if(frame_val==1'b0)	//数据帧无效
		baud_cnt<=16'd0;
	else if(baud_cnt==BAUD_CNT_MAX-1'b1)
		baud_cnt<=16'd0;
	else
		baud_cnt<=baud_cnt+1'b1;

1bit稳定数据的采样标志信号;

always@(posedge clk or negedge rst_n)
	if(!rst_n) bit_flag<=1'b0;
	else if(baud_cnt==BAUD_CNT_MAX_HALF-1'b1)	//采样需要在中间数据才稳定
		bit_flag<=1'b1;
	else
		bit_flag<=1'b0;

对采样到的bit数据进行计数;

always@(posedge clk or negedge rst_n)
	if(!rst_n) bit_cnt<=4'd0;
	else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag)	//10bit数据采样完毕
		bit_cnt<=4'd0;
	else if(bit_flag)	//采样到1bit数据
		bit_cnt<=bit_cnt+1'b1;
	else
		bit_cnt<=bit_cnt;

将接收到的串行数据rx转化为并行数据po_data_t;

always@(posedge clk or negedge rst_n)
	if(!rst_n) po_data_t<=8'b0;
	else if((bit_cnt>=4'd1) && (bit_cnt<BIT_CNT_MAX-1'b1) && bit_flag)	//8bit数据
		po_data_t<={rx_d3,po_data_t[7:1]};	//起始位后接的是低位
	else
		po_data_t<=po_data_t;

并行数据全部拼接完成的标志信号;

always@(posedge clk or negedge rst_n)
	if(!rst_n) po_flag_t<=1'b0;
	else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag)
		po_flag_t<=1'b1;
	else
		po_flag_t<=1'b0;

输出并行数据和输出有效并行数据的标志信号。

always@(posedge clk or negedge rst_n)
	if(!rst_n) po_data<=8'b0;
	else if(po_flag_t)
		po_data<=po_data_t;
	else
		po_data<=po_data;

//po_flag_t延迟1拍与po_data同步
always@(posedge clk or negedge rst_n)
	if(!rst_n) po_flag<=1'b0;
	else
		po_flag<=po_flag_t;
仿真结果:

2.uart发送模块:接收并行数据,发送串行数据。
module uart_tx#(
	parameter	UART_BPS='d9600			,	//波特率:1s传输9600个bit
	parameter	CLK_FREQ='d50_000_000		//时钟频率:50MHz
)(
	input 	wire			clk			,
	input 	wire			rst_n		,
	input	wire			pi_flag		,	//输入并行数据
	input	wire	[7:0]	pi_data		,	//输入有效并行数据的标志信号

	output 	reg 			tx				//输出串行数据
);

首先同样是uart 1帧数据的有效信号;

always@(posedge clk or negedge rst_n)
	if(!rst_n) frame_val<=1'b0;
	else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag)	//发送完1帧数据
		frame_val<=1'b0;
	else if(pi_flag)	//接收到有效的并行数据
		frame_val<=1'b1;
	else
		frame_val<=frame_val;

1码元符号(1bit)所需的计数器;

always@(posedge clk or negedge rst_n)
	if(!rst_n) baud_cnt<=16'd0;
	else if(frame_val==1'b0)	//数据帧无效
		baud_cnt<=16'd0;
	else if(baud_cnt==BAUD_CNT_MAX-1'b1)
		baud_cnt<=16'd0;
	else
		baud_cnt<=baud_cnt+1'b1;

1bit数据的发送标志信号;

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

对bit数据的发送进行计数;

always@(posedge clk or negedge rst_n)
	if(!rst_n) bit_cnt<=4'd0;
	else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag)	//10bit数据计数完毕
		bit_cnt<=4'd0;
	else if(bit_flag)	//发送完1bit数据
		bit_cnt<=bit_cnt+1'b1;
	else
		bit_cnt<=bit_cnt;

输出串行数据。

always@(posedge clk or negedge rst_n)
	if(rst_n==1'b0) tx<=1'b1;	//空闲
	else if(bit_flag)
		case(bit_cnt)
			4'd0:	tx<=1'b0;		//起始位
			4'd1:	tx<=pi_data[0];	//最低位数据
			4'd2:	tx<=pi_data[1];
			4'd3:	tx<=pi_data[2];
			4'd4:	tx<=pi_data[3];
			4'd5:	tx<=pi_data[4];
			4'd6:	tx<=pi_data[5];
			4'd7:	tx<=pi_data[6];
			4'd8:	tx<=pi_data[7];	//最高位数据
			4'd9:	tx<=1'b1;		//结束位
			default:tx<=1'b1;
		endcase
仿真结果:

3.uart环回测试。
module uart_test#(
	parameter	UART_BPS='d9600			,	//波特率:1s传输9600个bit
	parameter	CLK_FREQ='d50_000_000		//时钟频率:50MHz
)(
	input 	wire clk	,
	input 	wire rst_n	,
	input 	wire rx		,	//接收的串行数据

	output 	wire tx			//发送的串行数据
);

wire [7:0] 	data		;
wire 		data_flag	;

uart_rx#(
	.UART_BPS(UART_BPS),
	.CLK_FREQ(CLK_FREQ)
)u_uart_rx(
	.clk	(clk	),
	.rst_n	(rst_n	),
	.rx		(rx		),

	.po_data(data),
	.po_flag(data_flag)
);

uart_tx#(
	.UART_BPS(UART_BPS),
	.CLK_FREQ(CLK_FREQ)
)u_uart_tx(
	.clk	(clk	),
	.rst_n	(rst_n	),
	.pi_data(data),
	.pi_flag(data_flag),

	.tx(tx)
);

endmodule
仿真验证:
`timescale 1ns/1ns
module tb_uart_test();

parameter	UART_BPS='d9600			;	//波特率:1s传输9600个bit
parameter	CLK_FREQ='d50_000_000	;	//时钟频率:50MHz

reg clk;
reg rst_n;
reg rx;

wire tx;

initial
begin
	clk=1'b0;
	rst_n<=1'b0;
	rx<=1'b1;
	#20
	rst_n<=1'b1;
end

always #10 clk=~clk;

initial
begin
	#200	//空闲状态
	rx_test();

	#(5208*10*20*3)
	#200
	$stop;
end

//输出uart数据帧(10-13)
task rx_test();	//任务函数,类似C语言
	integer j;
	for(j=10;j<13;j=j+1)
		rx_8bit(j);
endtask

//输入8bit并行数据,输出uart数据帧
task rx_8bit(
	input [7:0] data
);
integer i;

for(i=0;i<10;i=i+1)
begin
	case(i)
		0:rx<=1'b0;		//1帧数据
		1:rx<=data[0];
		2:rx<=data[1];
		3:rx<=data[2];
		4:rx<=data[3];
		5:rx<=data[4];
		6:rx<=data[5];
		7:rx<=data[6];
		8:rx<=data[7];
		9:rx<=1'b1;
	endcase
	#(5208*20);		//9600波特率
end
endtask

uart_test#(
	.UART_BPS(UART_BPS),
	.CLK_FREQ(CLK_FREQ)
)u_uart_test(
	.clk	(clk	),
	.rst_n	(rst_n	),
	.rx		(rx		),

	.tx(tx)
);

endmodule
仿真结果:

FPGA系统集成-RTL框图

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

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

相关文章

基于Java+SpringBoot+Vue企业员工管理系统(源码+文档+部署+讲解)

一.系统概述 随着社会的发展&#xff0c;系统的管理形势越来越严峻。越来越多的用户利用互联网获得信息&#xff0c;但各种信息鱼龙混杂&#xff0c;信息真假难以辨别。为了方便用户更好的获得信息&#xff0c;因此&#xff0c;设计一种安全高效的员工管理系统极为重要。 为设计…

swiftui macOS实现加载本地html文件

import SwiftUI import WebKitstruct ContentView: View {var body: some View {VStack {Text("测试")HTMLView(htmlFileName: "localfile") // 假设你的本地 HTML 文件名为 index.html.frame(minWidth: 100, minHeight: 100) // 设置 HTMLView 的最小尺寸…

【攻防世界】php_rce (ThinkPHP5)

进入题目环境&#xff0c;查看页面信息&#xff1a; 页面提示 ThinkPHP V5&#xff0c;猜测存在ThinkPHP5 版本框架的漏洞&#xff0c;于是查找 ThinkPHP5 的攻击POC。 构造 payload: http://61.147.171.105:50126/?sindex/think\app/invokefunction&functioncall_user_f…

续写Groq

这章写点Groq干货,理性的分析。 首先是Articical Analysis的关于Mixtral8*7B的吞吐比较 上图是有Mixtral 8*7BPaaS服务的AI服务商,Mistral自己居然排倒数第三 ,Groq是真的遥遥领先啊。 另外这个图是比较每100万tokens的cost,无论是推理速度还是cost,Groq都是遥遥领先…

如何把1G多的视频压缩到500兆以内?3个方法轻松减小文件内存~

微信已经成为了我们上班交流沟通时必不可少的通讯工具之一&#xff0c;在使用微信时&#xff0c;常常会遇到系统提示发送的word、ppt、pdf文件、视频、压缩包等文件超过1G&#xff0c;无法发送。有没有什么办法可以缩小文件的体积呢&#xff1f;今天给大家介绍几款可以用于视频…

Python中Python-docx 包的run介绍

先对run做一个简单地介绍。每个paragraph对象都包含一个run对象的列表。举例&#xff1a; 这是一个简短的段落。 from docx import Document doc Document("1.docx") #上面这段话保存在1.docx中 print("这一段的run个数是&#xff1a;",len(doc.paragr…

leetcode热题100.划分字母区间

Problem: 763. 划分字母区间 文章目录 题目思路复杂度Code 题目 给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段&#xff0c;同一字母最多出现在一个片段中。 注意&#xff0c;划分结果需要满足&#xff1a;将所有划分结果按顺序连接&#xff0c;得到的字符串仍…

基于Leaflet.js和Turf.js的等值线区间自定义及颜色自适应实践

目录 前言 一、Turf.js等值线相关制作 1、生成方法 2、主要参数 二、实际案例开发 1、新建展示页面 2、等值线生成 3、基于Leaflet的再优化 总结 前言 在气象方面的GIS应用当中&#xff0c;会根据实际的工作需要建立不同的监测站点。气象监测站的主要功能包括&#xff1…

如何快速识别陶瓷件的外观缺陷吗?

陶瓷件由陶瓷材料制成的物品或零部件&#xff0c;通常用于装饰、日常生活用品、工艺品或工业应用。陶瓷是一种非金属材料&#xff0c;具有耐高温、耐磨损、绝缘、化学稳定等特性&#xff0c;因此在许多领域得到广泛应用。 本案针对陶瓷件尺寸长25mm*宽11mm*高2mm的产品的外观检…

物联网实战--驱动篇之(五)TEA和AES加密算法

目录 一、前言 二、TEA算法 三、AES算法 四、加解密测试 五、安全性保障 一、前言 物联网的安全性是经常被提及的一个点&#xff0c;如果你的设备之间通讯没有加密的话&#xff0c;那么攻击者很容易就能获取并解析出报文的协议&#xff0c;从而根据攻击者的需要进行设备操…

运行gitHub中的vue项目,遇到三个报错解决方案

报错1&#xff1a;解决npm run serve启动报错npm ERR Missing script:"serve" 启动项目的时候用npm run serve发现报了以下的错误 npm ERR! Missing script: "serve" npm ERR! npm ERR! To see a list of scripts, run: npm ERR! npm runnpm ERR! A co…

Linux安装Oracle11g(无图形界面下的静默安装)

Oracle11g安装文档-Linux静默安装 环境准备安装数据库配置监听器创建数据库测试打开防火墙 环境准备 创建组和用户 [rootlocalhost ~]# groupadd oinstall #创建oinstall组 [rootlocalhost ~]# groupadd dba  #创建dba组 [rootlocalhost ~]# useradd -g oinstall -G dba -m…

window2003 中cmd提权到system

打开cmd&#xff0c;输入命令&#xff1a; sc Create syscm2 binPath "cmd /K start" type own type interact 注意&#xff01;等号左边是有空格然后才是引号的&#xff0c;三个等号都是&#xff0c;否则会失败 成功提示&#xff1a;[SC] CreateService 成功 然后…

Junit单元测试基础

目录 配置xml文件&#xff0c;注入依赖 常用注释 1.Test 2.BeforeAll和AfterAll 3.BeforeEach和AfterEach 4.TestMethodOrder 参数化 1.单参数 2.多参数 3.通过方法生成参数 测试用例执行管理 JUnit 是一个流行的 Java 单元测试框架&#xff0c;它为开发者提供了一…

题目 2694: 蓝桥杯2022年第十三届决赛真题-最大数字【暴力解法】

最大数字 原题链接 &#x1f970;提交结果 思路 对于每一位&#xff0c;我我们都要尽力到达 9 所以我们去遍历每一位, 如果是 9 直接跳过这一位 如果可以上调到 9 我们将这一位上调到 9 &#xff0c;并且在a 中减去对应的次数 同样的&#xff0c;如果可以下调到 9&#xff0c;我…

参数仅有0.049M!基于Mamba的医学图像分割新SOTA来了!

目前&#xff0c;基于CNN和Transformer的医学图像分割面临着许多挑战。比如CNN在长距离建模能力上存在不足&#xff0c;而Transformer则受到其二次计算复杂度的制约。 相比之下&#xff0c;Mamba的设计允许模型在保持线性计算复杂度的同时&#xff0c;仍然能够捕捉到长距离的依…

【AIGC】训练数据入库(Milvus)

之前的文章有写如何获取数据、如何补充数据&#xff0c;也有说如何对数据进行清洗、如何使用结构化数据进行训练。但好像没有说如何将训练数据“入库”。这里说的入库不是指 MySQL 数据库&#xff0c;而是指向量检索库 Milvus。 众所周知&#xff0c;人工智能多用向量数据进行…

人民网至顶科技:《开启智能新时代:2024中国AI大模型产业发展报告发布》

3月26日&#xff0c;人民网财经研究院与至顶科技联合发布《开启智能新时代&#xff1a;2024年中国AI大模型产业发展报告》。该报告针对AI大模型产业发展背景、产业发展现状、典型案例、挑战及未来趋势等方面进行了系统全面的梳理&#xff0c;为政府部门、行业从业者以及社会公众…

渗透知识贴

文章目录 基础知识同源策略 常见web漏洞SQL注入漏洞 web中间件 基础知识 同源策略 同源策略是目前所有浏览器都实行的一种安全政策。A网页设置的 Cookie&#xff0c;B网页不能打开&#xff0c;除非这两个网页同源。所谓同源&#xff0c;是指&#xff1a;协议、端口、域名相同…

蓝桥杯刷题--RDay5

清理水域--枚举 8.清理水域 - 蓝桥云课 (lanqiao.cn)https://www.lanqiao.cn/problems/2413/learning/?page1&first_category_id1&second_category_id3&tags2023 小蓝有一个n m大小的矩形水域&#xff0c;小蓝将这个水域划分为n行m列&#xff0c;行数从1…