You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在SV/UVM中绑定VHDL定点数类型SFIXED/UFIXED?

如何在SV/UVM中绑定VHDL定点数类型SFIXED/UFIXED?

我太懂这种卡壳的感觉了——用VHDL fixed_pkg里的sfixed/ufixed定点类型做设计时,SV/UVM环境里的绑定、调试一直是个头疼的点:端口套wrapper转std_logic_vector只能解决外部接口的问题,内部信号想观测或者在验证环境里直接用,要么零散加debug信号太乱,要么根本没法直接访问。

下面是我实际项目里用过的几个可行方案,从简单优化到进阶绑定,按需选就行:

1. 优化Debug信号方案:结构化批量导出

如果不想动仿真器配置,最务实的优化就是把零散的debug信号改成结构化的导出,用VHDL的generate块批量处理内部定点信号,比手动加信号高效得多:

-- 在VHDL设计内部,先把需要观测的定点信号打包成记录
type fixed_debug_t is record
  sig1 : sfixed(7 downto -4);
  sig2 : ufixed(3 downto -2);
end record;
signal fixed_debug : fixed_debug_t;

-- 把内部信号赋值到debug记录
fixed_debug.sig1 <= internal_sfixed_sig1;
fixed_debug.sig2 <= internal_ufixed_sig2;

-- 再把整个记录转成单条slv导出
signal fixed_debug_slv : std_logic_vector( (7 - (-4) +1) + (3 - (-2)+1) -1 downto 0);
fixed_debug_slv <= std_logic_vector(fixed_debug.sig1) & std_logic_vector(fixed_debug.sig2);

然后在SV里拆分这个slv,转成可直接观测的数值:

logic [11:0] sig1_slv; // 对应sfixed(7 downto -4):12位
logic [5:0]  sig2_slv; // 对应ufixed(3 downto -2):6位

assign {sig1_slv, sig2_slv} = top.dut.fixed_debug_slv;

// 转成real值方便观测和计算
real sig1_real = $itor($signed(sig1_slv)) / (2.0**4); // 小数部分4位
real sig2_real = $itor($unsigned(sig2_slv)) / (2.0**2); // 小数部分2位

这种方法不用改验证环境架构,只是把debug信号的导出结构化了,后期维护也方便。

2. 跨语言直接绑定:利用仿真器类型兼容支持

如果用的是Mentor Questa这类对跨语言类型互操作支持较好的仿真器,其实可以直接在SV里声明匹配位宽的定点类型,用bind语句直接绑定VHDL的sfixed/ufixed信号,完全不用转slv

-- 在SV里声明和VHDL定点位宽完全匹配的类型
typedef logic signed [7:-4] sv_sfixed_7to_neg4; // 对应VHDL的sfixed(7 downto -4)
typedef logic unsigned [3:-2] sv_ufixed_3to_neg2; // 对应VHDL的ufixed(3 downto -2)

-- 用bind语句直接绑定DUT内部的定点信号
bind my_vhdl_design fixed_signal_bind : begin
  sv_sfixed_7to_neg4 internal_sig1;
  sv_ufixed_3to_neg2 internal_sig2;

  assign internal_sig1 = top.dut.internal_sfixed_sig1;
  assign internal_sig2 = top.dut.internal_ufixed_sig2;
end

绑定后,你可以在UVM的virtual interface里直接引用这些SV定点类型的信号,甚至在波形窗口里右键选「Radix->Fixed Point」,就能直接显示定点的实际数值,不用自己换算。

注意:这个方法依赖仿真器的跨语言支持,VCS等其他仿真器可能需要额外编译选项或不支持,要先确认你的仿真器版本。

3. 转整数导出:适合UVM数值比较场景

如果核心需求是在UVM的scoreboard或sequence里做数值验证,而非单纯观测波形,可以把VHDL定点信号转成整数类型导出,SV里处理起来更简单:

signal internal_sfixed : sfixed(7 downto -4);
signal internal_sfixed_int : std_logic_vector(11 downto 0); -- 位宽和sfixed一致

-- 转成有符号整数再转slv
internal_sfixed_int <= std_logic_vector(to_signed(to_integer(internal_sfixed), 12));

然后在SV里转成real,直接和预期值比较:

int internal_sfixed_int;
real actual_value;
real expected_value;

assign internal_sfixed_int = top.dut.internal_sfixed_int;
assign actual_value = $itor(internal_sfixed_int) / (2.0**4); // 小数部分4位

-- 在scoreboard里做精度范围内的比较
if (abs(actual_value - expected_value) > 1e-3) begin
  `uvm_error("SCOREBOARD", $sformatf("Value mismatch: actual=%.3f, expected=%.3f", actual_value, expected_value))
end

这个方法不用处理复杂的定点类型映射,整数转real的计算直观,非常适合验证场景。

额外小技巧:波形窗口直接看定点值

很多人忽略了,仿真器的波形工具本身就支持直接显示VHDLsfixed/ufixed的实际数值。比如在Questa里:

  • 选中波形里的定点信号
  • 右键选「Radix」->「Fixed Point」
  • 弹出窗口里设置整数位宽(如7 downto 0)和小数位宽(如-1 downto -4)
  • 确认后波形就会直接显示定点的实际数值,省掉大量转码工作!

最后总结:如果追求效率,先试试波形工具的定点显示;如果要在UVM里直接用信号,优先看仿真器支持的跨语言绑定;如果要兼容多仿真器,就用结构化debug导出或转整数的方法。

火山引擎 最新活动