如何从模块外部初始化SystemVerilog模块内的内存块
SystemVerilog 模块外部配置内存初始值实现方案
核心是利用SystemVerilog支持的强类型参数特性,直接将数组作为参数传入模块,完全匹配预期的传参形式。
具体实现步骤
- 模块定义时声明和内存结构完全匹配的参数
首先在模块的参数列表里,定义和内部mem位宽、深度、维度完全一致的parameter,给一个默认初始值即可:
module my_mod #( // 参数类型、位宽、深度必须和内部mem完全对齐,默认值可按需修改 parameter logic [31:0] INITIAL_VALS [64] = '{default: '0} )( // 自定义端口省略 ); reg [31:0] mem [64]; // 初始化逻辑直接读取传入的参数 initial begin foreach (mem[idx]) begin mem[idx] = INITIAL_VALS[idx]; end // 其余模块初始化逻辑省略 end // 模块功能逻辑省略 endmodule
- 上层实例化时传入自定义初始值
上层环境中提前定义好同结构的多维数组存放初始值,实例化时直接把数组传入参数即可,完全符合预期的写法:
// 上层提前定义待传入的初始值集合,维度位宽和模块参数匹配 logic [31:0] multi_dimensional_reg [64]; initial begin // 这里可以按测试场景给multi_dimensional_reg赋不同值,比如从文件加载、随机生成等 for (int i=0; i<64; i++) begin multi_dimensional_reg[i] = $urandom; end end // 实例化模块,直接传参 my_mod #( .INITIAL_VALS(multi_dimensional_reg) ) mm ( // 端口连接省略 );
注意事项
- 传入的数组必须和参数定义的位宽、深度严格匹配,否则编译阶段会直接报类型不匹配错误,避免传参出错。
- 目前所有主流仿真器、支持SystemVerilog的综合工具都原生支持数组类型参数,如果你使用的是年代极久的老旧工具不支持该特性,可以退而求其次将数组拍平为一维位流(32*64=2048bit)作为parameter传入,模块内部再按位切片还原为二维数组即可,只是写法稍繁琐。
- 如果遇到初始值体量极大、直接写数组效率低的场景,可以额外加一个字符串类型的参数传初始化文件路径,模块内部判断路径非空时调用
$readmemh/$readmemb加载文件,两种初始化方式可以通过判断参数值共存。
内容的提问来源于stack exchange,提问作者Martel
相关产品推荐
相关产品推荐

