龙芯LoongArch CPU设计——基于vivado中的ip核实现RAM和ROM及性能比较

2023-10-11 16:30

本文主要是介绍龙芯LoongArch CPU设计——基于vivado中的ip核实现RAM和ROM及性能比较,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在计算机组成原理的课程学习中,很多同学(我也是)的RAM和ROM都是在代码中以数组的形式来表示。

例如:

reg [31:0] Ins[0:127];//定义一个名为Ins的reg类型数组,该数组有128个单元,每个单元32位

现在使用vivado中的ip核来对我们设计RAM和ROM进行改造,看看实例化之后的性能是否会发生变化。
 

ROM和RAM相关知识介绍

ROM 是只读存储器(Read Only Memory)的简称,是一种只能读出事先所存数据的固态半导体存储器。其特性是一旦储存数据就无法再将之改变或删除,且数据不会因为电源关闭而消失。而事实上在 FPGA 中通过 IP 核生成的 ROM 或 RAM 调用的都是 FPGA 内部的RAM 资源,掉电内容都会丢失(这也很容易解释,FPGA 芯片内部本来就没有掉电非易失存储器单元)。用 IP 核生成的 ROM 模块只是提前添加了数据文件(.coe 格式),在 FPGA 运行时通过数据文件给 ROM 模块初始化,才使得 ROM 模块像个“真正”的掉电非易失存储器;也正是这个原因,ROM 模块的内容必须提前在数据文件(.coe格式)中写好,并且无法在电路中修改。
 

RAM 是随机存取存储器(Random Access Memory)的简称,是一个易失性存储器。RAM 工作时可以随时从任何一个指定的地址写入或读出数据,同时我们还能修改其存储的数据,即写入新的数据,这是 ROM 所并不具备的功能。在 FPGA 中这也是其与 ROM 的最大区别。ROM 是只读存储器,而 RAM 是可写可读存储器,在我们 FPGA 中使用这两个存储器主要也是要区分这一点,因为这两个存储器使用的都是我们 FPGA 内部的 RAM 资源,不同的是 ROM 只用到了 RAM 资源的读数据端口,同时RAM也可以提前添加数据文件(.coe 格式)
 

IP核具体实现ROM

单击 IPCatalog,在右边窗口 Search 位置输入 ROMS,在 Memories & Storage Elements 下可以看到有两个与 RAM 创建的入口,一个是 Distributed Memory Generator(分布式),另一个是 Block Memory Generator(块式),两者最主要的差别是生成的 Core 所占用的 FPGA 资源不一样,从Distributed Memory Generator 生成的 ROM/RAM Core 占用的资源是 LUT(查找表,查找表本质就是一个小的 RAM),适用于所需存储空间较小的场景;从 Block Memory Generator 生成的 ROM/RAM Core 占用的资源是 Block Memory(嵌入式的硬件 RAM),适用于所需存储空间较大的场景。本人的ROM目前所需存储空间不大,为80×8bit,在此选择 Distributed Memory Generator。

由于LoongArch32采用的是按字节编址,所以Data Width设置为8,因为Depth的数值要求为2的次方,我的是80×8bit,所以Depth填128。Memory Type(存储器类型)选ROM即可。Component Name为自定义的名字,任取即可,我取的名字是dist。

用 IP 核生成的 ROM 模块需要提前添加数据文件,所以要配置Coefficients File,即添加.coe文件(提前写好),从而ROM实现了存储数据的功能。

 我的.coe文件如下

至此,用IP核配置ROM完成,若想使用该ROM,只需在设计文件中调用即可。要注意:.coe文件要和vivado中的设计文件配合好,不要犯逻辑上的错误。.coe文件中的数据是存在ROM中的。并且在.coe文件中,一个空格表示一个存储单元的结束,由于loongarch32的指令集为32位,按字节(8位)寻址,所以我在一个周期中,从基址开始,先得到在ROM中连续存储的四个8bit的存储单元,分别为data_out_instr1、data_out_instr2、data_out_instr3、data_out_instr4,由于采用小端模式(高字节存储在高地址,低字节存储在低地址),所以拼接成了一条32位的指令Instr。

Pc u0(offset,pc_inc,clk,rst,PCdata);
dist n1(.a(PCdata),.spo(data_out_instr1));
dist n2(.a(PCdata+1),.spo(data_out_instr2));
dist n3(.a(PCdata+2),.spo(data_out_instr3));
dist n4(.a(PCdata+3),.spo(data_out_instr4));
assign Instr={data_out_instr4,data_out_instr3,data_out_instr2,data_out_instr1};

IP核具体实现RAM

有了IP核实现ROM的基础,实现RAM就显得简单许多,因为RAM是可读可写入,所以可以不使用.coe文件,和IP核实现ROM一样,选择Distributed Memory Generator。

 我配置的Component Name取名为dist_ram,Depth为1024(存储单元数为1024),Data_Width为32(数据宽度为32位),Memory Type选择为Single Port RAM(单端口RAM),就得到了名为dist_ram的1024×32bit的单端口RAM,小伙伴们要根据你们所设计的实际情况来配置哈。

配置完成后,在设计文件中使用该RAM,要特别注意,形参和实参要正确对应。

dist_ram u7(.clk(clk),.we(MemWrEn),.a(AddResult),.d(busB),.spo(data_out));

用IP核实例化前后的性能比较 

 

 可以看到,实例化后较实例化前,综合时间(synth_design Time)减少了,确实提高了速度,但同时可以观察到,存储空间(Memory)变大了,想到了数据结构课程中的经典思想:拿空间换时间。

 

 可以看到,不管是Post-Synthesis还是Post-Implementation,实例化后的利用率都比实例化前要高,性能明显提高了。

 总结

使用vivado中的ip核来对我们设计RAM和ROM进行改造后,发现所设计CPU电路的性能明显提高。设计CPU就像一张拼图,把之前学过的零碎东西拼凑在一起,融会贯通。只有自己摸索和思考,实践和实现,才能体会其中的奥秘和乐趣。最后,与大家共勉:天下难事必作于易,天下大事必作于细。

参考阅读:https://blog.csdn.net/yifantan/article/details/127492786?ops_request_misc=&request_id=&biz_id=102&utm_term=%E4%BD%BF%E7%94%A8vivado%20ip%E6%A0%B8ram&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-127492786.142^v92^chatsearchT3_1&spm=1018.2226.3001.4187

这篇关于龙芯LoongArch CPU设计——基于vivado中的ip核实现RAM和ROM及性能比较的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/189350

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja