如何在RTL代码中利用外部文件初始化RAM内容

在Vivado中RTL中的RAM内容一般可以通过以下两种方式初始化:

  • 在HDL 源代码中指定RAM 初始内容

  • 在外部数据文件中指定RAM 初始内容

这里主要讨论一下如何在外部数据文件中指定RAM 初始内容。

我们使用的外部数据文件有以下特点:

  • 是任意名称的ASCII 文本文件

  • 每一行描述RAM 中某个地址位置处的初始内容

  • 行数必须与RAM 阵列中的行数一样多

  • 与给定线路相关的可寻址位置由对RAM 建模的信号主要范围的方向定义

  • 可以用二进制或十六进制表示RAM 内容,两者不能混合.

  • 对应的命令是readmemb readme

  • 不能包含任何其他内容,例如注释

手册中给出的Verilog例子如下

手册中给出的Verilog例子.png

在实际工程中,我们把初始化文件与对应的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.
从波形上也可以看到没有初始值

初始值.png

原因是仿真的工作目录比综合的深,所以两者的相对目录表达并不相同。

在仿真时,工作目录是: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开发者社区

最新文章

最新文章