调用IP实现数据加速

news2024/9/20 16:58:28

前言

        在数字系统设计中,提升数据处理速度和效率是关键目标。本实验着眼于利用双端口RAM和异步FIFO对IP核ROM中的数据进行加速处理,通过这两种硬件组件的有效结合来优化数据访问和传输。双端口RAM允许同时进行读写操作,提高数据处理的并行性和吞吐量,而异步FIFO则解决了不同时钟域之间的数据传输问题,实现了高效的数据缓冲和同步。设计一个集成了双端口RAM和异步FIFO的FPGA系统,验证其在加速数据处理方面的性能。

正文

一、调用IP实现数据加速

        1.项目需求

        通过ROM,RAM,FIFO与锁相环四个ip核结合起来进行一个综合设计,本设计主要是利用双端口ram和异步fifo对Ip核rom中的数据进行加速处理。

        2.技术介绍

        双端口RAM:拥有两个独立的读写端口,可同时进行读写操作。提供了更高的数据吞吐量和更低的访问延迟,适用于需要并行处理的应用场景。

        异步FIFO:通过内部的读写指针和状态标志位,实现了数据的无缝缓冲和处理,有效解决了数据传输中的速率不匹配问题。是一种先进先出(FIFO)的数据缓存器,能够跨时钟域进行数据传输。

        RAM(Random Access Memory,随机访问存储器):RAM是一种易失性存储器,即断电后存储的数据会丢失。它支持随机读写,这意味着可以跳过前面的内存地址,直接对任何地址上的数据进行访问。RAM通常用于快速存储正在被CPU使用的程序和数据,以提高响应速度和效率。它通常用于操作系统和应用程序的内存分配,因为它能够以非常快的速度进行读写操作。

        ROM(Read-Only Memory,只读存储器):ROM是一种非易失性存储器,即使电源关闭,其中存储的数据也可以保持不变。它只能进行读操作,不能进行写操作,或者是写操作受到限制,需要特殊的硬件或软件条件才能进行。ROM通常用于存储固件或固化的代码,这些信息不应当被修改,或者是在设备启动的时候需要使用这些数据。例如,BIOS(基本输入输出系统)就是一种ROM,它储存了计算机启动和检测硬件所需的基本指令。mif文件保存正弦波数据。

        FIFO(First-In First-Out,先进先出队列):FIFO是一种数据结构,遵循先进先出的原则,即最早进入队列的数据或元素是第一个被处理的。FIFO在软件中是一种算法,而在硬件中则可能是一个专门的组件。在FPGA中,FIFO通常由专门的硬件逻辑实现,它可以跨越不同的时钟域工作,支持不同速度的数据源和使用者之间的高效数据传输。FIFO用于在数据处理的不同阶段之间缓冲数据,保证数据流不受速度差异的影响,避免数据丢失或乱序。在多任务系统和实时系统中,FIFO是一种常见的数据交互机制。

        在实际的数字系统设计中,RAM、ROM和FIFO可以通过不同的搭配方式来提高数据处理的效率和性能。进行数据预取与缓存流程为

1.ROM读取:从ROM中读取数据或指令。

2.数据存储:将数据存储到RAM中,以便进行快速访问和处理。

3.FIFO缓冲:将数据从RAM通过FIFO传输到处理单元,FIFO在数据传输过程中进行缓冲,避免由于处理速度不匹配而导致的数据丢失。

基于IP核,本章将讲述如何实现利用双端口ram和异步fifo对Ip核rom中的数据进行加速处理。

        3.顶层架构

        数据保存在rom中通过ram写控制模块读出数据并写入到ram中,ram的数据通过ram读控制模块读出并通过fifo写控制模块写入到fifo中,数据最终通过fifo读控制模块读出。

        4.端口描述

clk系统时钟
rst_n复位按键(低电平有效)
data[7:0]读出数据

二、代码验证

        rd_fifo_ctrl模块:

module rd_fifo_ctrl(
 
	input clk,
	input rst_n,
	input empty,//标志信号,指示FIFO是否为空。为空时,无法进行读操作。
	input full,//标志信号,指示FIFO是否已满。FIFO满时,无法进行写操作。
	
	output reg rdreq//读请求信号,表示请求从FIFO中读取数据。
);
 
always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		rdreq <= 1'b0;
	else
		if(full == 1)//FIFO已满
			rdreq <= 1'b1;//开始读
		else
			if(empty == 1)//FIFO为空
				rdreq <= 1'b0;//停止读
			else
				rdreq <= rdreq;
end 
endmodule 

        rd_ram_ctrl模块:

module rd_ram_ctrl(

	input clk,
	input rst_n,
	input wren,//ram写使能
	
	output reg rden,//ram读使能信号
	output reg [7:0] rd_addr//读地址
);

reg wren_r;
reg wren_rr;
wire neg_flag;

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		begin
			wren_r <= 1'b0;
			wren_rr <= 1'b0;
		end 
	else
		begin
			wren_r <= wren;//暂存写使能信号
			wren_rr <= wren_r;
		end 
end 

assign neg_flag = ~wren_r & wren_rr;//ram写使能信号下降沿检测

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		rden <= 1'b0;
	else
		if(neg_flag == 1)//写使能拉低
			rden <= 1'b1;//读使能有效
		else
			if(rd_addr == 255)
				rden <= 1'b0;
			else
				rden <= rden;
end 

always @(posedge clk,negedge rst_n)//地址切换逻辑
begin
	if(rst_n == 0)
		rd_addr <= 8'd0;
	else
		if(rden == 1)
			rd_addr <= rd_addr +8'd1;
		else
			rd_addr <= 8'd0;
end 

endmodule 

        wr_fifo_ctrl模块:

module wr_fifo_ctrl(

	input clk,
	input rst_n,
	input rden,//ram的读使能信号
	input [7:0] data,//写入FIFO的数据
	
	output reg wrreq,//fifo写使能
	output [7:0] fifo_data//fifo写数据
);

assign fifo_data = data;

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		wrreq <= 1'b0;
	else
		wrreq <= rden;//ram读使能时fifo写使能
end 

endmodule 

        wr_ram_ctrl模块:

module wr_ram_ctrl(

	input clk,
	input rst_n,
	input empty,//标志信号,指示FIFO是否为空。为空时,无法进行读操作。
	input [7:0] data,//rom读出的数据
	
	output reg [7:0] rom_addr,//rom的地址
	output reg wren,//ram写使能
	output reg [7:0] wr_addr,//ram写地址
	output [7:0] wr_data//ram写数据
);

reg rd_rom_en;//读rom使能信号
reg wren_r;

reg [1:0] state;
parameter s0 = 2'd0;//fifo数据是否读空状态
parameter s1 = 2'd1;//控制从rom中读取数据
parameter s2 = 2'd2;//判断fifo是否写入数据

//状态机
always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		begin
			state <= s0;
			rd_rom_en <= 1'b0;
		end 
	else
		case(state)
			s0	:	begin
						rd_rom_en <= 1'b0;//读rom使能信号停止
						if(empty == 1)//fifo为空,状态跳转
							state <= s1;
						else
							state <= s0;
					end 
			s1	:	begin
						if(rom_addr == 255)//rom的地址读完
							begin
								rd_rom_en <= 1'b0;
								state <= s2;
							end 
						else
							begin
								rd_rom_en <= 1'b1;
								state <= s1;
							end 
					end 
			s2	:	begin
						rd_rom_en <= 1'b0;
						if(empty == 0)//fifo不为空
							state <= s0;
						else
							state <= s2;
					end 
			default	:	begin rd_rom_en <= 1'b0;state <= s0; end 
		endcase
end 

always @(posedge clk,negedge rst_n)//地址递增
begin
	if(rst_n == 0)
		rom_addr <= 8'd0;
	else
		if(rd_rom_en == 1)
			rom_addr <= rom_addr + 8'd1;
		else
			rom_addr <= 8'd0;
end 

always @(posedge clk,negedge rst_n)//
begin
	if(rst_n == 0)
		wren <= 1'b0;
	else
		wren <= rd_rom_en;	//ram写使能=rom读使能
end 

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		wr_addr <= 8'd0;
	else
		wr_addr <= rom_addr;
end 

assign wr_data = data;//rom读出数据等于ram写入数据

endmodule 

        data_speed_up模块:顶层连线

module data_speed_up(

	input clk,
	input rst_n,
	
	output [7:0] data
);

	wire wr_ram_clk;//20
	wire rd_ram_clk;//50
	wire rd_fifo_clk;//120
	wire locked;
	wire [7:0] rom_addr;
	wire [7:0] rom_data;
	wire empty;
	wire wren;
	wire [7:0] wr_addr;
	wire [7:0] wr_data;
	wire rden;
	wire [7:0] rd_addr;
	wire [7:0] rd_data;
	wire wrreq;
	wire [7:0] fifo_data;
	wire rdfull;
	wire rdreq;
	wire wrfull;
	wire wrempty;
	wire [7:0] wrusedw;
	wire [7:0] rdusedw;

my_pll	my_pll_inst (
	.areset ( ~rst_n ),
	.inclk0 ( clk ),
	.c0 ( wr_ram_clk ),
	.c1 ( rd_ram_clk ),
	.c2 ( rd_fifo_clk ),
	.locked ( locked )
);

my_rom	my_rom_inst (
	.address ( rom_addr ),
	.clock ( wr_ram_clk ),
	.q ( rom_data )
	);

wr_ram_ctrl wr_ram_ctrl_inst(

			.clk(wr_ram_clk),
			.rst_n(locked),
			.empty(empty),
			.data(rom_data),
			
			.rom_addr(rom_addr),
			.wren(wren),
			.wr_addr(wr_addr),
			.wr_data(wr_data)
);

double_ram	double_ram_inst (
	.data ( wr_data ),
	.rdaddress ( rd_addr ),
	.rdclock ( rd_ram_clk ),
	.rden ( rden ),
	.wraddress ( wr_addr ),
	.wrclock ( wr_ram_clk ),
	.wren ( wren ),
	.q ( rd_data )
	);
	
rd_ram_ctrl rd_ram_ctrl_inst(

			.clk(rd_ram_clk),
			.rst_n(locked),
			.wren(wren),
			
			.rden(rden),
			.rd_addr(rd_addr)
);

wr_fifo_ctrl wr_fifo_ctrl_inst(

			.clk(rd_ram_clk),
			.rst_n(locked),
			.rden(rden),
			.data(rd_data),
			
			.wrreq(wrreq),
			.fifo_data(fifo_data)
);

rd_fifo_ctrl rd_fifo_ctrl_inst(

			.clk(rd_fifo_clk),
			.rst_n(locked),
			.full(rdfull),
			.empty(empty),
			
			.rdreq(rdreq)
);

asyn_fifo	asyn_fifo_inst (

			.data ( wr_data ),//输入信号,将要写入FIFO的数据。
			.rdclk ( rd_clk ),//读操作的时钟信号,控制FIFO读操作的时序。
			.rdreq ( rdreq ),//读请求信号,表示请求从FIFO中读取数据。
			.wrclk ( wr_clk ),//写操作的时钟信号,控制FIFO写操作的时序。
			.wrreq ( wrreq ),//写请求信号,表示请求将数据写入FIFO。
			.q ( data ),//输出信号,从FIFO中读取的数据。
			.rdempty ( rdempty ),//标志信号,指示FIFO是否为空。为空时,无法进行读操作。
			.rdfull ( rdfull ),//标志信号,指示FIFO是否已满。FIFO满时,无法进行写操作。
			.rdusedw ( rdusedw ),//信号,指示当前FIFO中已被使用的单元数量。
			.wrempty ( wrempty ),//标志信号,指示FIFO在写操作时是否为空。
			.wrfull ( wrfull ),//标志信号,指示FIFO在写操作时是否已满。
			.wrusedw ( wrusedw )//信号,指示当前FIFO中已被写入的单元数量。
);

endmodule 

仿真文件

`timescale 1ns/1ps
module data_speed_up_tb;

	reg clk;
	reg rst_n;
	
	wire [7:0] data;

data_speed_up data_speed_up_inst(

	.clk(clk),
	.rst_n(rst_n),
	
	.data(data)
);

initial clk = 0;
always #10 clk = ~clk;

initial begin
	rst_n = 0;
	#200
	rst_n = 1;
	#30000
	$stop;
end 

endmodule 

三、仿真验证

        观看仿真波形图,数据可以正常读出:

调出中间数据进行分析,可以看到读rom/写ram,读ram/写fifo,读fifo三个阶段分别使用依次变慢的时钟,对数据进行降速处理。

三阶段数据均位有丢失。

既然依次变慢的时钟会对数据读取有减速效果,同理,将锁相环输出时钟依次变快

由此,数据加速完成,利用双端口ram和异步fifo对Ip核rom中的数据进行加速处理成功。

参考资料

IP核FIFO调用及验证(2)

IP核RAM调用及验证(2)

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

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

相关文章

中央空调常用风口的分类

中央空调常用风口的分类中央空调常用的风口类型有七类&#xff0c;包括百叶风口、散流器、喷口、旋流风口、条缝风口、格栅风口和专用风口。详细分类如下&#xff1a; 1&#xff09;百叶风口&#xff1a;单层百叶风口、双层百叶风口、连动百叶风口、固定斜百叶风口、地面固定斜…

How to tune agent _executor for better understanding of the database

题意&#xff1a;如何调整agent _executor以更好地理解数据库 问题背景&#xff1a; I have a database in which I have connected an agent too. However, I have noticed that it sometimes gets confused between whether or not it should return a column ID or persons…

5 mysql 查询语句

1.DML:对数据进行增删改查 提示:Execute执行 Execute and Suppress 执行并且抑制这个警告 person表的结构 /* DML:Data Manipulation Language 数据操作语言,对数据进行 增删改查操作,因为査询的操作太频繁和复杂,将查询的操作独立成为DQL */ use db1109;//person表在d…

智慧水务项目(二)django(drf)+angular 18 创建通用model,并对orm常用字段进行说明

一、说明 上一篇文章建立一个最简单的项目&#xff0c;现在我们建立一个公共模型&#xff0c;抽取公共字段&#xff0c;以便于后续模块继承&#xff0c;过程之中会对orm常用字段进行说明&#xff0c;用到的介绍一下 二、创建一个db.py 目录如下图 1、代码 from importlib im…

私域流量变迁与精细移动化趋势下的AI智能名片小程序源码应用探索

摘要&#xff1a;随着移动互联网技术的飞速发展&#xff0c;私域流量的价值日益凸显&#xff0c;成为企业营销战略的重要组成部分。私域流量的精细化和移动化趋势不仅改变了传统的营销格局&#xff0c;也为新兴技术的应用提供了广阔空间。本文深入探讨了私域流量的变迁历程&…

磁盘碎片整理工具IObit Smart Defrag PRO 绿色版

在数字化时代&#xff0c;电脑的性能直接影响到我们的工作效率和娱乐体验。随着使用时间的增长&#xff0c;硬盘上的文件碎片逐渐增多&#xff0c;导致电脑运行缓慢。今天&#xff0c;我为大家介绍一款强大的磁盘碎片整理工具——IObit Smart Defrag&#xff0c;它能有效解决这…

探索Python的聊天机器人世界:Errbot的魔力

文章目录 探索Python的聊天机器人世界&#xff1a;Errbot的魔力背景&#xff1a;为何选择Errbot&#xff1f;Errbot&#xff1a;Python中的聊天机器人框架安装Errbot&#xff1a;简单几步&#xff0c;即刻开始探索Errbot&#xff1a;五个简单函数的魔法1. 创建机器人2. 响应消息…

全球汽车用MEMS加速度计市场规划预测:未来六年CAGR为2.8%

随着汽车行业的持续发展和消费者对安全性能的需求增加&#xff0c;汽车用MEMS加速度计作为提升车辆安全性和稳定性的关键组件&#xff0c;正逐渐受到市场的广泛关注。本文旨在通过深度分析汽车用MEMS加速度计行业的各个维度&#xff0c;揭示行业发展趋势和潜在机会。 【市场趋…

ElementPlus 中el-select自定义指令实现触底加载请求options数据

1) 背景: 老项目翻新时&#xff0c;发现一个下拉框数据非常多&#xff0c;客户呢&#xff0c;希望全部数据一起展示&#xff0c;意思就是全部数据一起返回给前端用于展示。但这会造成明显的卡顿。~~明显的不合理! QAQ!~~ 于是压力给到前端&#xff0c;查询资料&#xff0c;各种…

论文阅读:Most Probable Densest Subgraphs

摘要 本文提出了一种在不确定图中发现最有可能稠密子图&#xff08;MPDS&#xff09;的新方法。不确定图中的每条边都有存在概率&#xff0c;使得计算稠密子图变得複杂。作者定义了稠密子图概率&#xff0c;并证明了计算该概率是#P难的。为了解决这个问题&#xff0c;设计了基…

算法通关:014_1:用栈实现队列

文章目录 题目总结代码运行结果 题目 用栈实现队列 leetcode :232 总结 时间复杂度 平均下来每个方式是O(1) 代码 class MyQueue {public Stack<Integer> in;public Stack<Integer> out;//初始化public MyQueue() {in new Stack<>();out new Stack<…

整体接口测试

文章目录 1.分类1.新增分类1.接口设计2.结果 2.更新分类1.接口设计2.结果 3.查询分类1.接口设计2.结果&#xff08;少了一个count字段暂时不改&#xff09; 4.查询大类下分类1.接口设计2.结果 5.删除分类1.接口设计2.结果 2.标签1.新增标签1.接口设计2.结果 2.更新标签1.接口设…

E5092A可配置的多端口测试仪

E5092A 可配置的多端口测试仪 多达 10 个端口的全交叉测量&#xff0c;或者最多 22 个端口的测量功能。 概述 E5092A 多端口测试仪可以灵活配置&#xff0c;并可与4 端口ENA 网络分析仪&#xff08;E5070B/E5071B/E5071C/E5080A&#xff09;结合使用&#xff0c;组成频率范…

信息安全管理中,文件销毁、硬盘销毁、数据销毁和物料销毁分别如何

文件销毁的方法主要有删除、覆盖、加密和物理破坏。硬盘销毁的方法主要有物理破坏、磁性破坏、化学破坏和高温破坏。数据销毁的方法主要有逻辑删除、物理破坏、磁性破坏和化学破坏。物料销毁的方法主要有回收利用、填埋处理、焚烧处理、生物降解和化学处理。 文件销毁的方法&a…

江协科技51单片机学习- p31 LCD1602液晶屏驱动

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

Frida挂钩Java层代码与协议分析

Hook类中普通方法 在本文中&#xff0c;我们继续以某嘟牛应用为例&#xff0c;在用户点击登录按钮后&#xff0c;哪个方法会被调用。我们在上一篇文章中提到&#xff0c;搜索关键词 “Encrypt” 后&#xff0c;发现两个包含该字符串的 Java 方法。接下来&#xff0c;我们通过 …

AGI思考探究的意义、价值与乐趣Ⅳ

探究in context或Prompt对于LLM来说其根本意义&#xff0c;in context & Prompt Learning带给我们更深一层的提示是什么&#xff1f; 文章里的探索希望能够将in context或Prompt置身于一个更全局的视角来看待&#xff1a;将其视为在真实世界中时空认知流形所映射为数据流形…

路由器IP互联无线对讲系统解决方案

一、项目概况 随着信息化的全面深入发展&#xff0c;各行各业的通信需求日益增长&#xff0c;传统的通信方式无法满足跨网络、跨系统、跨媒介的通信互联互通&#xff0c;打破信息孤岛、提高协同效率&#xff0c;成为当前各行业融合通信的首要任务。尤其大型企业、学校、医院等…

第14课 Scratch少儿编程 入门篇:抓蝴蝶

开车自驾去旅行 故事背景&#xff1a; 春天到了&#xff0c;让我们一起春游&#xff01;公园的草坪上有五颜六色的花朵和翩翩起舞的蝴蝶&#xff0c;让我们拿起工具&#xff0c;去捉蝴蝶吧&#xff01;&#xff01; 程序原理: 添加绿色的草地角色和蝴蝶的角色&#xff0c;给…

【C++程序设计】——利用数组处理批量数据(一)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-削好皮的Pineapple! &#x1f468;‍&#x1f4bb; hello 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 削好皮的Pineapple! 原创 &#x1f468;‍&#x1f4…