在Vivado中RTL中的RAM内容一般可以通过以下两种方式初始化:
在HDL 源代码中指定RAM 初始内容
在外部数据文件中指定RAM 初始内容
这里主要讨论一下如何在外部数据文件中指定RAM 初始内容。
我们使用的外部数据文件有以下特点:
是任意名称的ASCII 文本文件
每一行描述RAM 中某个地址位置处的初始内容
行数必须与RAM 阵列中的行数一样多
与给定线路相关的可寻址位置由对RAM 建模的信号主要范围的方向定义
可以用二进制或十六进制表示RAM 内容,两者不能混合.
对应的命令是readmemb readme
不能包含任何其他内容,例如注释
手册中给出的Verilog例子如下
在实际工程中,我们把初始化文件与对应的RTL文件保存在同一个文件夹中,结构如下
Top Dir -
| -> source:top.v, rams_20c.data
| -> vivado: vivado project dir
reg [31:0] test_ram [0:4];
Initial
begin
$readmemb("rams_20c.data", test_ram, 0 , 4);
end
直接在readmemb命令引用文件名,只把RTL文件加入工程,在综合时会看到以下Warning,表明无法找到初始化文件。
CRITICAL WARNING: [Synth 8-4445] could not open $readmem data file 'rams_20c.data'; please make sure the file is added to project and has read permission, ignoring [C:/XX/vivado/project_1/project_1.srcs/sources_1/imports/source/top.v:16]
如果工程只是在本地使用,不需要到其他环境运行,我们可以使用绝对路径来指定外部初始化文件。
initial
begin
$readmemb("C:\top_dir\XX\source\rams_20c.data", test_ram, 0,4);
end
此时在综合的log中会看到以下信息,表明外部初始化文件已经被成功读到:
INFO: [Synth 8-3876] $readmem data file 'C:/XX/source/rams_20c.data' is read successfully [C:/XX/vivado/project_1/project_1.srcs/sources_1/imports/source/top.v:21]
采用绝对路径的方式,在仿真中,也可以正确读取外部初始化文件,不过在仿真中读取成功时不会有信息报出。
但是当这个工程需要在其他环境运行时,使用绝对路径指定外部初始化文件的方式就比较繁琐了,需要一一更新这些绝对路径,因为在新的环境中,原来绝对路径指向的文件大概率是找不到的. 这时我们可以考虑使用相对路径来指定外部初始化文件。
在综合时,工作目录是runs目录下的synth_x目录(比如C:/XX/vivado/project_1/project_1.runs/synth_1), 相对目录会以此目录为基准去寻找外部初始化文件。
所以这时,外部初始化文件的相对路径要写成以下这样:
initial
begin
$readmemb("../../../../source/rams_20c.data", test_ram, 0,4);
end
和之前一样,可以在综合的Log中看到类似的信息,表明外部初始化文件已经被成功读到:
(此时在log中打印出的外部初始化文件也已经变成相对路径)
INFO: [Synth 8-3876] $readmem data file '../../../../source/rams_20c.data' is read successfully [C:/XX/vivado/project_1/project_1.srcs/sources_1/imports/source/top.v:26]
但在此时运行仿真时,会得到以下告警, 外部初始化文件没能在仿真中读到:
WARNING: File ../../../../source/rams_20c.data referenced from process on C:/XX/vivado/project_1/project_1.srcs/sources_1/imports/source/top.v at line 24 cannot be opened for reading. Please ensure that this file is available in the current working directory.
从波形上也可以看到没有初始值
原因是仿真的工作目录比综合的深,所以两者的相对目录表达并不相同。
在仿真时,工作目录是:C:\XX\vivado\project_1\project_1.sim\sim_1\behav\xsim
所以这时,外部初始化文件的相对路径要写成以下这样:
initial
begin
$readmemb("../../../../../../source/rams_20c.data", test_ram, 0,4);
end
综合和仿真的相对路径的不同表达在实际工程中会带来不便,用户可以选择在综合和仿真时使用不同的源文件,也可以在RTL文件中借助SYNTHESIS 宏定义(只在综合时生效)为综合和仿真在同一个源文件中生成不同的代码。
initial
begin
`ifdef SYNTHESIS
$readmemb("../../../../source/rams_20c.data", test_ram);
`else
$readmemb("../../../../../../source/rams_20c.data", test_ram);
`endif
end
在非工程模式中,工作目录由用户直接决定,不存在工程模式中的问题。
文章来源:AMD开发者社区