FPGA_学习_16_IP核_ROM

news2024/11/24 3:13:39

在寻找APD最合适的偏压的过程中,一般会用到厂商提供一条曲线,横坐标是温度的变化,纵坐标表示击穿偏压的变化,但每个产品真正的击穿偏压是有差异的。 为了能够快速的找到当前温度下真实的击穿偏压,我们可以这样做,我先根据温度,得到厂商提供的击穿偏压。 然后再用厂商提供的击穿偏压,减去几伏。 我们以此作为寻找真实击穿偏压的起点。以一个固定的步长提升APD的偏压,直到满足我们设定的击穿判断条件。 但是呢,在整个这个流程中,我们需要解决一个问题,就如何在FPGA程序中实时的去获取当前温度下对应的击穿偏压。 如果是dsp或者stm32等嵌入式平台,可以直接把温度-击穿偏压数据做成一个数据表存到一个数组,然后直接查表。 但是在FPGA中,我们不能用数组了,但可以选择用ROM IP核 去实现。 在FPGA中,一些固定的初始化参数也可以用ROM来保存。 本文记录ROM的使用方法。

1 ROM是什么

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

简单说就是FPGA的ROM你随便搞,不用担心一次写死后,后面再也不能改了。

2 .coe文件生成

ROM 作为只读存储器,在进行 IP 核设置时需要指定初始化文件,即写入存储器中的 数据,数据要以规定的格式才能正确写入 ROM,这种格式就是 coe 文件。coe Vivado 规定的一种文件格式,下图为文件格式示意图

 下面提供一个.coe文件的 MatLAB生成代码,一键即可生成你想要的.coe

clear;clear all;clc;

FileName=['mycoe','.coe']; 

fid = fopen(FileName,'w'); 

fprintf(fid,'memory_initialization_radix = 16;\n');
fprintf(fid,'memory_initialization_vector =\n');
% 位宽
Width = 16;
% 深度
Depth = 20;

Hexlen = Width / 4;

for i=1:Depth
    data = i;
    
    % 根据位宽补0
	HexCode = dec2hex(data);
	HexSize = size(HexCode,2);
	ZeroCode='';
    for j=1:(Hexlen-HexSize)
        ZeroCode=['0',ZeroCode];
    end
	str0 = [ZeroCode,HexCode];
    
    % 判断是否为最后一行
    if i < Depth
        Hexstr = [str0,','];
        fprintf(fid,'%s\n',Hexstr);
    elseif i==Depth
        Hexstr = [str0,';'];
        fprintf(fid,'%s',Hexstr);
    end
end
fclose(fid);

open(FileName);

3 ROM IP 配置

ROM分单口ROM和双口ROM,它们配置的区别仅仅只是Basic这一页Memory Type的选项的区别,其他的都是一样的。 所以本文仅以单口ROM的配置为例。

 傻瓜式截图,从最原始的IP Catalog开始

 

取名这里,还是关注一下,比如我是用的单口rom,深度20,位宽16位。我的IP核命名就可以是 s_rom_20x16b。 比如我是用双口rom,深度256,位宽8位呢,那IP核命名则为 d_rom_256x8b。 这样的命名,能做到一目了然。

 👆上面这个图有个值得关注的点: Totoal Port A Read Latency :1 Clock Cycle 。 意思是读的时候要输出要延迟一个时钟周期。👆

IP生成了,这个参数文件也被成功加载过来了。 

瞅一眼是怎么例化的。

 4 Modelsim仿真

ROM在读取数据的时候,要给ROM IP核输入你的ROM地址。 而ROM地址应该是从0开始的。 比如你Rom的深度是20(= 0x14),那你的ROM读地址就是 0x00 ~ 0x13(10进制是19)。那地址 0x00对应的是ROM存的第一个数据(本例中是0x0001)。 0x13对应的是ROM存的最后一个数据(本例中是0x0014)。

源码如下:

`timescale 1ns / 1ps

module lab_rom(
        input   wire    clk,
        input   wire    rst_n
);


//==================================================================
//                        Parameter define
//==================================================================
parameter       MAX_ADDRA       = 20 - 1;


//==================================================================
//                        Internal Signals
//==================================================================
reg     [4:0]   addra;
wire    [15:0]  douta;

//----------------------------- addra自增 -----------------------------
always @(posedge clk or negedge rst_n) begin
        if (rst_n == 1'b0) begin
            addra <= 'd0;        
        end
        else if(addra == MAX_ADDRA)begin
                addra <= 'd0;
        end
        else begin
                addra <= addra + 1'b1;
        end
end

//----------------------------- s_rom_20x16b例化 -----------------------------
s_rom_20x16b s_rom_20x16b_inst (
        .clka(clk),    // input wire clka
        .addra(addra),  // input wire [4 : 0] addra
        .douta(douta)  // output wire [15 : 0] douta
);

endmodule

 约束文件

create_clock	-period			20.000		[	get_ports	clk	]

set_property    PACKAGE_PIN		N18			[	get_ports	clk			]
set_property    PACKAGE_PIN		T12			[	get_ports	rst_n		]

set_property    IOSTANDARD      LVCMOS33	[	get_ports	clk			]  
set_property    IOSTANDARD      LVCMOS33	[	get_ports	rst_n		]  

仿真代码

`timescale 1ns/1ps
module tb_lab_rom (); /* this is automatically generated */

    // clock
    reg clk;
    initial begin
        clk = 1'b0;
        forever #(10) clk = ~clk;
    end

    // asynchronous reset
    reg rst_n;
    initial begin
        rst_n <= 1'b0;
        #10
        rst_n <= 1'b1;
    end

    // (*NOTE*) replace reset, clock, others
    parameter MAX_ADDRA = 20 - 1;

    lab_rom #(.MAX_ADDRA(MAX_ADDRA)) inst_lab_rom (.clk(clk), .rst_n(rst_n));

endmodule

 仿真结果

5 ila在线调试

本着再复习一下ila在线调试的原则,这里做一个在线调试的测试。

代码

`timescale 1ns / 1ps

module lab_rom(
        input   wire    clk,
        input   wire    rst_n
);


//==================================================================
//                        Parameter define
//==================================================================
parameter       MAX_ADDRA       = 20 - 1;


//==================================================================
//                        Internal Signals
//==================================================================
(* MARK_DEBUG="true" *) reg     [4:0]   addra;    // 修改🔺
(* MARK_DEBUG="true" *) wire    [15:0]  douta;    // 修改🔺

//----------------------------- addra自增 -----------------------------
always @(posedge clk or negedge rst_n) begin
        if (rst_n == 1'b0) begin
            addra <= 'd0;        
        end
        else if(addra == MAX_ADDRA)begin
                addra <= 'd0;
        end
        else begin
                addra <= addra + 1'b1;
        end
end

//----------------------------- s_rom_20x16b例化 -----------------------------
s_rom_20x16b s_rom_20x16b_inst (
        .clka(clk),    // input wire clka
        .addra(addra),  // input wire [4 : 0] addra
        .douta(douta)  // output wire [15 : 0] douta
);

endmodule

 Run Synthesis - Open Synthesized Design    运行综合 - 打开已综合的设计

 Set up Debug → Next   设置调试→下一步 

添加要观测的信号并设置时钟域

 由于项目比较简单,刚刚截图的瞬间,系统刚刚应该是自动Run synthesis了一遍,并且还Run完了。

 编译完之后直接 Open Hareware Manager 打开硬件管理器 - 直接烧写程序,刷新设备

 在线调试功能正常。

参考文献

Vivado 下 IP核 之ROM 读写_OliverH-yishuihan的博客-CSDN博客

在给rom IP核命名的时候,我发现FPGA的代码应该有一个统一遵循的规范,包括ip核 模块 变量 参数的命名规则、注释、缩进风格等都应该有一个规范, 后续应该会有一篇博客讲规范,不过目前初学阶段接触的FPGA相关内容还不够全面,因此这篇博客应该是在初学阶段的尾声部分。 另外,约束文件中关于时序部分的约束也是后续关注的一个重点。  

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

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

相关文章

C++之std::unordered_map<int, int, string>应用实例(一百八十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

小程序化,一种创新的HybirdApp开发模式

跨端框架的出现&#xff0c;弥补了传统移动应用开发中跨平台难题。开发者可以使用一套代码构建适用于多个平台的应用&#xff0c;既能在不同设备上保持一致的用户体验&#xff0c;又能更高效地进行开发和维护。这种开发模式不仅提升了开发效率&#xff0c;还为用户提供了更加一…

【K8S系列】Weave Net 故障排除的常见问题和解决方案

写在前面 当使用 Weave Net 进行容器网络配置时&#xff0c;可能会遇到一些常见的故障情况。以下是一些常见问题及其解决方案&#xff1a; 问题列表 1 节点无法加入 Weave Net 网络 解决方案 检查节点之间的网络连通性&#xff0c;确保可以通过 IP 地址相互访问。 检查节点的…

nodejs安装与卸载(高版本降为低版本)

初到公司发现电脑上面已经安装nodejs&#xff0c;但是版本是最新版本。但是问题来了&#xff0c;好像是不太支持vue3&#xff0c;所以查了一些资料&#xff0c;具体的也不是很清楚&#xff0c;反正就是nodejs的版本不能太高最好保持在16以下。好吧&#xff0c;那就重新卸载再来…

苹果手机怎么连接电脑?4招轻松连接!

“新买了一部苹果手机&#xff0c;想连接电脑传一些文件&#xff0c;但是不知道该如何操作。有没有朋友可以帮帮我呀&#xff1f;” 苹果手机作为一款智能手机&#xff0c;在市场上的应用越来越常见。苹果手机与电脑进行连接可以更好的进行文件的传输、备份以及进行其他操作。 …

FreeModbus——源码获取(一)

网站 About - Embedded Experts (embedded-experts.at) 下载v1.6版本&#xff0c;刚开始我还没找到&#xff0c;后面对照别人的截图才找到&#xff08;哈哈&#xff0c;感觉自己好二&#xff09;&#xff0c;把鼠标移过去&#xff0c;这个地方是才从黑变成这个绿色

基于X86六轮差速移动机器人运动控制器设计与实现(二)规划控制算法

带输入约束的 MPC 路径跟踪控制 MPC 算法是一种基于控制对象模型的控制方法&#xff0c;其优势在于在控制中考虑了 系统的多种物理约束&#xff0c;同时基于模型与当前机器人的反馈信息预估出未来机器人 位姿信息的处理方法可以解决控制迟滞的问题。 4.1 MPC 路径跟踪控…

压多少抗多少,滴滴全链路压测仿真度量体系建设

滴滴在重大节假日、活动前为保障线上系统稳定&#xff0c;需要通过全链路压测做多轮风险排查以及容量验收&#xff0c;我们经常听到这样的声音"你们全链路压测和线上业务场景有多大差异"、"是不是压测达到目标线上真的能抗这么大量"、"我的某某个模块…

iPhone15即将发布,苹果赔偿5亿美元,但再次不包括中国用户

苹果的iPhone15即将发布&#xff0c;就在此时苹果的“电池门”再次被翻出&#xff0c;这次美国的法院判决苹果给每名用户赔偿65美元&#xff0c;合计大约5亿美元&#xff0c;只是独独不包括中国用户&#xff0c;这就有点歧视中国用户了吧&#xff1f; 事件的起因在于2017年很多…

c++11 标准模板(STL)(std::basic_stringbuf)(六)

定义于头文件 <sstream> template< class CharT, class Traits std::char_traits<CharT>, class Allocator std::allocator<CharT> > class basic_stringbuf : public std::basic_streambuf<CharT, Traits> std::basic_stringbu…

C++新经典02--编译预处理

编译预处理 编译阶段会做如下几件事&#xff1a; (1)预处理。 (2)编译。包括词法分析、语法分析、目标代码生成、优化等。 (3)汇编。产生.o(.obj)目标文件。 C语言一般提供三种预处理功能&#xff1a;宏定义、 文件包含、条件编译。这三种预处理功能也是通过在源程序文件写入…

5G智能网关助力打造数字乡村物联网

乡村振兴&#xff0c;网络先行&#xff0c;信息通信技术赋能农业农村现代化发展的作用日益彰显&#xff0c;也成为实施乡村振兴战略的重要力量。 截止今年三月&#xff0c;我国5G网络已经覆盖全国所有地级市、县城城区及数万行政村&#xff0c;农村光纤平均下载速率超过100Mb/s…

C#之枚举中的按位与()按位或(|)。

一些基础定义&#xff1a; 按位或运算符&#xff08;|&#xff09;是一种位运算符&#xff0c;用来对两个二进制数进行操作。对于每个位上的1&#xff0c;如果至少有一个二进制数中的对应位为1&#xff0c;则结果为1&#xff1b;否则&#xff0c;结果为0。按位与运算符&#x…

秒懂算法 | 汉诺塔问题与木棒三角形

在数学与计算机科学中&#xff0c;递归(recursion)是指一个过程或函数在其定义或说明中又直接或间接调用自身的一种方法。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算&#x…

JAVA权限管理 助力企业精细化运营

在企业的日常经营中&#xff0c;企业人数达到一定数量之后&#xff0c;就需要对企业的层级和部门进行细分&#xff0c;建立企业的树形组织架构。围绕着树形组织架构&#xff0c;企业能够将权限落实到个人&#xff0c;避免企业内部出现管理混乱等情况。权限管理是每个企业管理中…

【3Ds Max】弯曲命令的简单使用

简介 在3ds Max中&#xff0c;"弯曲"&#xff08;Bend&#xff09;是一种用于在平面或曲面上创建弯曲效果的建模命令。使用弯曲命令&#xff0c;您可以将对象沿特定轴向弯曲&#xff0c;从而创建出各种弯曲的几何形状。以下是使用3ds Max中的弯曲命令的基本步骤&…

多数据源项目serviceImpl中使用了@PostConstruct注解导致项目启动时报“表不存在”的解决办法

背景&#xff1a; 原多数据源项目一直运行好好的&#xff0c;这两天开发定时任务调度功能&#xff0c;开发完了调用定时任务一直提示找不到定时任务&#xff0c;调查半天发现没有提前把表中定义的定时任务加载到ScheduleJob&#xff0c;也就是需要执行以下操作&#xff1a; Pos…

获取屏幕共享视频流

文章目录 1.增加 html 的一行代码2. 在 static 目录下创建 js 文件夹&#xff0c;并在 js 文件夹下面创建 screen_share.js 文件3. 访问 htpps 的网址3.1 点击开始推流3.2 选择要分享的窗口3.3 停止推流 1.增加 html 的一行代码 <script src"/static/js/screen_share.…

不会吧,小红书竟然也偷用户作品训练自家AI模型?

图片来源&#xff1a;由无界AI生成 “画手在小红书发的图是可以随意被拿去炼的吗&#xff1f;” 最近一个月&#xff0c;有关“小红书偷用户作品炼自家AI模型”的话题不断发酵&#xff0c;用户在小红书以及其他社交平台发起抵制行动。一部分画师停止在小红书更新作品&#xff0…

安装nodejs

1.下载nodejs的压缩包 https://nodejs.org/download/release/latest-v16.x/ 这个是v16版本的&#xff0c;可以根据自己需求下载对应的版本&#xff1a; https://nodejs.org/download/release/ 2.解压&#xff0c;将nodejs放到固定的路径下 注意&#xff1a;不要包含中文路径 3.…