我需要将一个长数作为固定点转换为双说唱演示。 定点数学用于合成过程,实数数据类型仅用于验证和模拟。
如果我在具有多种数据类型的链中进行多次转换以调整格式,那么这还不够或完全错误。
在我的情况下,44位的定点尾数我有3位整数+符号位。Q 表示法,如"sfix_44_48"
例如,我这样做是为了将定点整数转换为实数值(获取数字 0.5f(:
logic signed [47:0] fp_number = 48'h0800_0000_0000; // it should be 0.5f
real r_val;
real rr_val;
real rrr_val;
real tmp;
initial
begin
r_val = $itor(fp_number)/(2**44); // doesn't solve the problem.
rr_val = real'{fp_number}/(2**44); // doesn't solve the problem.
$cast(tmp,fp_number>>>44); // doesn't solve the problem
rrr_val = tmp;
end
$itor(...( 限制为 32 位整数部分。 由于上述结果,我在Modelsim模拟上得到零或NaN。
在所有这些皈依中都没有运气。 SV LRM似乎没有明确的方法来进行这种转换。
SV 解决方法是什么,允许模拟轻松分析大于 32 位大小的数据? 请。
三.
你想使用
rr_val = real'(fp_number)/(2.0**44);
请勿使用 Verilog 中的任何$TtoT
功能。它们具有固定的数据类型输入和输出。
2**44
计算为 32 位 2 补码值并溢出,得到 0。您可以改用2.0
或real'(2)
。
感谢@dave_59我发布了这段代码,它显示了转换的混乱。
logic signed [47:0] fp_number = 48'h0800_0000_0000; // it should be 0.5f
logic signed [31:0] fp_number2 = 32'h0800_0000; // it should be 0.5f
real r_val;
real rr_val;
real rrr_val;
real rrrr_val;
initial
begin
$display("48bit fp convertion sfix_44_48");
r_val = real'{fp_number}/(2**44); // doesn't solve the problem (curly braces valid sintax but wrong convertion + wrong convertion on the denominator).
rr_val = real'{fp_number}/(2.0**44); // doesn't solve the problem (curly braces valid sintax but wrong convertion + denominator convertion OK).
rrr_val = real'(fp_number)/(2**44); // doesn't solve the problem (numerator OK + the power operation is not properly converted to a Real number as result).
rrrr_val = real'(fp_number)/(2.0**44); // solve the problem with long integer fixed points convertion (the braces are not curly anymore).
$display("r_val[%08f]",r_val,", rr_val[%08f]",rr_val,", rrr_val[%08f]",rrr_val,", rrrr_val[%08f]",rrrr_val); // it should be 0.5 on the fourth data
$display("32bit fp convertion sfix_28_32");
r_val = real'{fp_number2}/(2**28); // result totally different than previous 48bit operation, doesn't solve the problem (curly braces valid sintax but wrong convertion + wrong convertion on the denominator).
rr_val = real'{fp_number2}/(2.0**28); // doesn't solve the problem (curly braces valid sintax but wrong convertion + denominator convertion OK).
rrr_val = real'(fp_number2)/(2**28); // with a 32bit range it apparently solve the problem (numerator OK + the power operation is OK with this range).
rrrr_val = real'(fp_number2)/(2.0**28); // solve the problem with long integer fixed points convertion (the braces are not curly anymore).
$display("r_val[%08f]",r_val,", rr_val[%08f]",rr_val,", rrr_val[%08f]",rrr_val,", rrrr_val[%08f]",rrrr_val); // it should be 0.5 on the fourth data
end
48位唯一有效的转换是第四种情况。 对于 32 位,第三种情况有效,第四种情况也有效。
- 首先:经典的
pow(...)
操作必须使用此语法完成,(2.0**BIT)
当应用缩放固定点时,它将使用(2**BIT)
创建一个实数除法,而不是整数除法。
在这种情况下,上述操作被管理为浮点/双精度(C 样式(或实数(SystemVerilog( * 第二:real'()
铸造操作必须与无大括号一起使用。 我没有 Linting 工具来正确检查语法,因此由于使用大括号的操作的有效性,我希望收到警告。
- 第三:如果 INTEGER 分母限制在 32 位操作,则子结果是可以的。 结果如下所示:
SIM START.
# 48bit fp convertion sfix_44_48
# ** Error (suppressible): (vsim-8604) ./blocks/sim/test_tb.sv(141): NaN (not a number) resulted from a division operation.
# ** Error (suppressible): (vsim-8630) Infinity results from division operation.
# Time: 0 ps Iteration: 0 Process: /test_tb/#INITIAL#138 File: ./blocks/sim/test_tb.sv Line: 143
# r_val[-1.#IND00], rr_val[0.000000], rrr_val[1.#INF00], rrrr_val[0.500000]
# 32bit fp convertion sfix_28_32
SIM END.
# r_val[0.000000], rr_val[0.000000], rrr_val[0.500000], rrrr_val[0.500000]
解决方案是避免任何不受保护的强制转换,例如带有大括号边界的强制转换:
r_val = real'{ byteU,byteH,byteL} / (2.0**44) ; // WRONG
rr_val = real'({byteU,byteH,byteL}) / (2.0**44) ; // CORRECT
如果出现比例因子,则操作(通常/
(必须使用相同类型的操作数(实数/实数(来完成。
不安全的方式是(真实的/长期的(,这会导致一场噩梦。