Verilator仿真中如何通过C++修改SystemVerilog模块参数值
在C++测试平台中修改Verilator编译的SystemVerilog模块参数的方法
SystemVerilog模块的parameter是编译时确定的常量,Verilator会将参数值直接固化到生成的C++代码中,因此无法在运行时修改已实例化模块的参数值。但可以通过以下几种方式实现类似"配置参数"的效果:
方法1:编译时通过Verilator命令行指定参数值
如果只需要在测试前确定参数值,可以在Verilate阶段通过命令行参数覆盖默认值。比如要将WIDTH设为32,执行Verilator时添加:
verilator -cc my_module.sv -DWIDTH=32
这样生成的Vmy_module类会基于WIDTH=32编译。如果需要同时测试多个不同参数的实例,需要多次执行Verilator,每次指定不同的参数,并通过--prefix选项生成不同的类名:
# 生成WIDTH=16的模块类,前缀为Vmy_module_16 verilator -cc my_module.sv --prefix Vmy_module_16 # 生成WIDTH=32的模块类,前缀为Vmy_module_32 verilator -cc my_module.sv -DWIDTH=32 --prefix Vmy_module_32
之后在C++中可以分别实例化不同的类:
VerilatedContext* contextp = new VerilatedContext; // 实例化WIDTH=16的模块 Vmy_module_16* top16 = new Vmy_module_16{contextp}; // 实例化WIDTH=32的模块 Vmy_module_32* top32 = new Vmy_module_32{contextp};
方法2:将参数替换为运行时可配置的逻辑
如果需要在运行时动态调整参数相关行为,需要修改SystemVerilog模块,将编译时参数替换为运行时可控制的逻辑:
- 用输入端口控制行为:如果参数用于控制逻辑分支(而非信号位宽),可以将其改为输入端口。例如:
之后在C++中直接驱动module my_module ( input logic i_clk, input logic i_rst, input logic [3:0] i_width_cfg, // 运行时配置宽度(支持8/16/32位) output logic [31:0] o_out // 用最大宽度的输出信号 ); always_ff @(posedge i_clk or posedge i_rst) begin if (i_rst) begin o_out <= '0; end else begin case(i_width_cfg) 4'd8: o_out[7:0] <= o_out[7:0] + 1; 4'd16: o_out[15:0] <= o_out[15:0] + 1; 4'd32: o_out <= o_out + 1; endcase end end endmodulei_width_cfg端口即可模拟不同宽度的行为。
关于你尝试的方法的说明
/*verilator public*/标记参数:Verilator会将参数暴露为C++类的静态只读常量(比如Vmy_module::WIDTH),但只能读取,无法修改——因为参数值已经固化到编译后的代码中。- DPI接口:DPI仅用于运行时的信号交互,无法修改编译时确定的
parameter值,参数在Verilate阶段就已经确定了硬件结构,运行时无法更改。
内容的提问来源于stack exchange,提问作者gsm
相关产品推荐
相关产品推荐

