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

实现功能:

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

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

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

uart协议的1帧数据传输

uart_test系统框图

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框图

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

72小时内报告!美国发布关键基础设施网络攻击通报新规草案

美国网络安全和基础设施安全局(CISA)本周四发布了关键基础设施企业如何向政府报告网络攻击的规定草案。 新规基于拜登2022年3月15日签署的美国《关键基础设施网络事件报告法案》(简称CIRCIA)。这是美国联邦政府首次提出一套跨关键基础设施部门的全面网络安全规则。CISA正在就规…

计算机网络-HTTP相关知识-基础

HTTP基础 基本概念&#xff1a;HTTP是一种计算机之间交流通信的规范&#xff0c;它允许数据在两点之间传输&#xff0c;这个过程可以包括中转或接力。HTTP不仅仅包括文本&#xff0c;还可以包括图片、音频等超文本。状态码&#xff1a;HTTP状态码分为五类&#xff1a; 2xx&…

intellij idea 使用git撤销(取消)commit

git撤销(取消) 未 push的 commit Git&#xff0c;选择分支后&#xff0c;右键 Undo Commit &#xff0c;会把这个 commit 撤销。 git撤销(取消) 已经 push 的 commit 备份分支内容&#xff1a; 选中分支&#xff0c; 新建 分支&#xff0c;避免后续因为操作不当&#xff0c;导…

windows版本-idea中下载的java版本在哪

1、点击idea的file-projectStructure 进入&#xff1a; 通过电脑目录进入该目录 找到bin目录&#xff0c;copy该目录地址 copy下来之后设置到系统环境变量中

经济学 博弈论 行为经济学

四种市场结构&#xff1a; 划分依据&#xff1a;生产者的数量&#xff0c;对价格的控制力&#xff0c;进入市场的难度&#xff08;新的商家进入市场的困难难度&#xff09; 1.完全竞争市场&#xff08;大多数农业产品&#xff1a;草莓&#xff09; 个体商家对价格没有控制力&a…

Android屏幕自适应

Android屏幕自适应 Android屏幕适配出现的原因为什么Android需要进行屏幕适配&#xff1f; 屏幕基本概念屏幕尺寸屏幕分辨率和像素sppxdp 密度无关像素dpiDensity 屏幕方向横屏竖屏自动切换禁用自动切换屏幕方向 Android屏幕自适应1. dp原生方案2. 线形布局权重示例代码 3. Jav…

阿里云短信服务业务

一、了解阿里云用户权限操作 1.注册账号、实名认证&#xff1b; 2.使用AccessKey 步骤一 点击头像&#xff0c;权限安全的AccessKey 步骤二 设置子用户AccessKey 步骤三 添加用户组和用户 步骤四 添加用户组记得绑定短信服务权限 步骤五 添加用户记得勾选openApi访问 添加…

Higgsfield AI: 对飙Sora打造个性化视频新浪潮,重塑社交媒体内容创作

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

对于个人如何选择服务器是最适合的?

选择适合的服务器对于个人来说是一个重要的决策&#xff0c;因为它会直接影响到你的网站或应用的性能、稳定性和成本。以下是一些建议&#xff0c;帮助你选择最适合的服务器&#xff1a; 京东云服务器&#xff0c;一年2G2H3M只需要50元&#xff01;&#xff01; 进入活动会场…

isc-dhcp-server DNS配置

我遇到一个有趣的问题&#xff0c;我先在一台Ubuntu服务器上使用isc-dhcp-server在其其中一个网口运行DHCP服务&#xff0c;然后我自己的笔记本电脑直连到这个网口&#xff0c;来上网。 本来直接就应该能上网&#xff0c;但是我的电脑只有在打开Clash时才能访问互联网&#xf…

【御控物联】JavaScript JSON结构转换(18):数组To对象——多层属性重组

文章目录 一、JSON结构转换是什么&#xff1f;二、案例之《JSON数组 To JSON对象》三、代码实现四、在线转换工具五、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换&#xff0c;生成新的JS…

猫头虎分享已解决Bug: ERROR: Could not find a version that satisfies the requirement

猫头虎分享已解决Bug: ERROR: Could not find a version that satisfies the requirement &#x1f42f;&#x1f4bb; 摘要 &#x1f4c4; 大家好&#xff0c;我是猫头虎博主&#xff0c;今天我们要聊聊后端技术领域中的一个常见Bug&#xff1a;ERROR: Could not find a vers…

Linux第3课 Linux系统安装及换源方法

文章目录 Linux第3课 Linux系统安装及换源方法一、VMware虚拟机下系统的安装及配置&#xff08;一&#xff09;创建新的虚拟机 二、换源三、初次配置四、修改分辨率五、共享文件夹的实现&#xff08;一&#xff09;创建并查看共享文件夹 Linux第3课 Linux系统安装及换源方法 用…

java生成word

两种方案 一、poi-tl生成word <dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version> </dependency> public static void main(String[] args) throws Exception {String…

解决打印尺寸难题:精准打印证件复印件的软件

为什么打印复印件&#xff0c;尺寸总是不对&#xff0c;用尺子测量打印出来总是不一样。 每次打印复印件&#xff0c;不是大了就是小了&#xff0c;让人十分痛苦。收款牌和桌卡也总是尺寸不对&#xff0c;怎么办&#xff1f;打印的痛苦谁能懂&#xff1f;复印件、收款牌、桌卡…

DashOJ-8.奇偶统计

题目链接&#xff1a; 题目详情 - 奇偶统计 - DashOJ 思路&#xff1a; &#xff08;while循环加if分支语句&#xff09; 巧用死循环 while(1) 然后在里面第一句就判断输入的数字是否等于0 if(x0) &#xff0c;如果 等于0就直接break跳出循环 或者用 while(cin>>x) 代…

AI Kimi:帮助教师做好试卷命题

原文&#xff1a;https://www.toutiao.com/article/7353661304307778083/?log_fromcfd0a50014034_1712243146922 最近&#xff0c;Kimichat工具很火。这款软件不仅仅是一个聊天和阅读工具&#xff0c;还是一个强大的教学辅助工具。作为一位教师&#xff0c;尝试使用Kimichat&…

Flask-RESTful 分析

Flask-RESTful 是一个 Flask 扩展&#xff0c;它为构建 RESTful API 提供了方便的工具和资源。它简化了创建 RESTful 服务的过程&#xff0c;允许开发者专注于业务逻辑而不是 HTTP 协议的细节。 资源&#xff08;Resources&#xff09;&#xff1a; Resource 类&#xff1a;是…

【C++】模拟实现红黑树(插入)

目录 红黑树的概念 红黑树的性质 红黑树的调整情况 红黑树的模拟实现 枚举类型的定义 红黑树节点的定义 插入函数的实现 旋转函数的实现 左旋 右旋 自检函数的实现 红黑树类 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储…

数据结构进阶篇 之 【并归排序】(递归与非递归实现)详细讲解

都说贪小便宜吃大亏&#xff0c;但吃亏是福&#xff0c;那不就是贪小便宜吃大福了吗 一、并归排序 MergeSort 1.基本思想 2.实现原理 3.代码实现 4.归并排序的特性总结 二、非递归并归排序实现 三、完结撒❀ –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀…