[验证百花筒] systemverilog中高精度浮点运算的一种求解思路

文章介绍了在SystemVerilog中处理80bit时间数据结构,通过转换、符号位处理和函数设计解决高精度浮点运算的问题,以求取计时器之间的差值。

systemverilog中高精度浮点运算的一种求解思路

1. 问题背景

设计中有一个计时器,包含48bit的s和32bit的ns共同组成80 bit的时间数据存放在以下数据结构中

reg [79:0] timer;

该计时器允许存入一个负数值,符号位由s所在的48bit表示
现在有两个这样类型的计时器timer1和timer2,实时计算这两个计时器之间的时间差值,并填入到计时器offset中。
想要实现的算法如下所示:

bit [79:0] timer1;
bit [79:0] timer2; 
bit [79:0] offset; 

//求解offset为timer1与timer2的差值
//需要对其中的s和ns分别进行运算,还要考虑符号位,所以不能简单的进行相减

2. 问题难点

  • 这里的时间由两部分构成,分别是s和ns,ns跟s之间的进制关系是10^9,因而无法直接用这两个80bit的数进行加减运算
  • SystemVerilog数据结构中很难找到这么一种数据类型来描述48bit的s和32bit的ns的组合值,SystemVerilog中能够记录的最大的有符号数类型为real,所占空间也仅仅只有64bit

3. 解题思路

由于bit类型是无符号的,所以我们在进行bit类型的运算时最好将其转化为无符号之间的运算,同时符号位单独计算。

3.1 统一度量衡

原有的80 bit timer即包含了s又包含了ns,那么我们要进行运算首先得统一单位,同时还需要将符号位进行处理,进而得到一个符号位和以ns为单位的无符号正整数的组合,为后面的运算打好基础。
这里我们写了这么一个函数array_to_time进行转换,输入为

SystemVerilog 中,由于 `real` 类型无法被综合工具直接映射为硬件电路,因此必须采用其他方法来实现浮点运算。以下是一些可行的替代方案: ### 使用定点数表示法 最常见且资源效率较高的方法是使用定点数进行计算。通过将浮点数值乘以一个固定比例因子并转换为整数形式,可以在硬件中模拟浮点运算[^2]。 例如,若需要表示 `3.14` 的值,可以将其转换为 `314` 并在后续计算中维护小数点位置。SystemVerilog 支持使用 `int`、`logic` 或 `bit` 类型数组来存储这些缩放后的数值,并通过移位操作实现加减乘除等运算。 示例代码如下: ```systemverilog module fixed_point_example; typedef logic signed [31:0] fixed_point_t; fixed_point_t a, b, result; initial begin a = 314_000; // 表示 3.14 b = 271_000; // 表示 2.71 result = a + b; $display("Sum: %d (实际值应为 5.85)", result); end endmodule ``` ### 使用 IEEE 754 浮点 IP 核 对于需要高精度浮点运算的应用场景,可以使用 FPGA 厂商提供的 IEEE 754 浮点运算 IP 核。这些 IP 核支持加法、乘法、比较等基本操作,并能以固定时钟周期完成运算。 例如,在 Xilinx Vivado 中可以调用 `floating_point` IP 模块来执行浮点加法或乘法操作。SystemVerilog 代码中可以通过接口连接这些模块,并将输入输出信号绑定到相应的端口上。 ### 使用联合(Union)类型进行数据共享 SystemVerilog 提供了 `union` 类型,允许在同一内存空间中存储不同类型的数据。这种方式可用于实现不同数据格式之间的灵活切换,例如整数与浮点数之间的共享存储。 示例代码如下: ```systemverilog typedef union { int I; real f; } num_u; num_u un; initial begin un.f = 0.0; // 将数值设为浮点形式 $display("Floating-point value: %f", un.f); un.I = 32'h40490FDB; // 设置为 π 的单精度近似值 $display("Integer representation of π: %h", un.I); end ``` ### 使用自定义结构体结合位数组 对于需要更高灵活性的应用,可以通过定义包含符号位、指数部分和尾数部分的结构体来实现自定义浮点格式。这种结构体可以使用 `bit` 数组来表示每个字段,并通过组合逻辑实现加法、乘法等运算。 例如,定义一个简单的 32 位浮点数结构体: ```systemverilog typedef struct packed { bit [7:0] exponent; bit [22:0] mantissa; bit sign; } custom_float_t; custom_float_t float_val; initial begin float_val.sign = 0; float_val.exponent = 8'h7F; float_val.mantissa = 23'h0; $display("Custom floating-point value: sign=%b, exponent=%h, mantissa=%h", float_val.sign, float_val.exponent, float_val.mantissa); end ``` ### 在测试平台中使用 `real` 类型 尽管 `real` 类型不能用于可综合的模块,但在测试平台中仍然具有重要价值。例如,可以使用 `real` 类型生成高精度激励信号,并将其转换为定点数输入到 DUT 中进行验证[^4]。 示例代码如下: ```systemverilog module tb_real_conversion; real voltage; logic [31:0] voltage_fixed; initial begin voltage = 3.3; voltage_fixed = $rtoi(voltage * 1000); // 转换为毫伏单位的整数 $display("Voltage in fixed-point: %0d mV", voltage_fixed); end endmodule ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值