【发布时间】:2018-03-02 13:58:14
【问题描述】:
我正在设计一个签名的 verilog 乘法器,我打算在另一个模块中多次使用它。
我的两个输入将始终为 s4.27 格式。 1 位有符号,4 位整数和 27 位小数。我的输出也必须是 s4.27 格式,我必须从中得到最准确的结果。
在 C 中,以下不是那么完美的代码 sn-p 完成了这项工作。
int32_t mul(int32_t x, int32_t y)
{
int64_t mul = x;
mul *= y;
mul >>= 27;
return (int32_t) mul;
}
在verilog中我的简单代码版本如下,
`timescale 1ns/1ps
module fixed_multiplier (
i_a,
i_b,
o_p,
clk
);
input clk;
input signed [31:0] i_a;
input signed [31:0] i_b;
output signed [31:0] o_p;
wire signed [63:0] out;
assign out = i_a*i_b;
assign o_p = out;
endmodule
上面提到的代码有我知道的错误,因为我根本没有得到想要的结果。
所以我的问题是,
(1) 作为这一行“assign o_result = out;”对我来说似乎很重要,我应该如何对最终输出进行分配,以便获得正确和最准确的 s4.27 格式输出?请注意,此输出将被馈送到加法器,加法器输出将再次成为乘法器的输入。
在提出上述问题时,我还尝试对两个输入的符号位进行异或运算,并将 [57:27] 位分配给最终输出。不适合我并导致溢出,而在 C 中相同的输入没有给出任何溢出错误。
(2) 在使用 C 语言时,定点乘法没有任何问题,而在 verilog 中,我想我正在苦苦挣扎,因为我还是个新手。有什么建议在处理带符号的乘法/加法时要记住什么?
下面是测试台代码,
`timescale 1ns / 1ps
module tb_mul;
// Inputs
reg clk;
reg [31:0] a;
reg [31:0] b;
// Outputs
wire [31:0] c;
fixed_multiplier mul_i (
.clk(clk),
.i_a(a),
.i_b(b),
.o_p(c)
);
initial begin
$dumpfile("test_mul.vcd");
$dumpvars(1);
$monitor ("a=%h,\tb=%h,\tc=%h",a,b,c);
a = 32'h10000000;
b = 32'h10000000;
$finish();
end
endmodule
提前谢谢你。
【问题讨论】:
-
它应该和你的'c'片段一样工作吗?如果是这样,
assign o_result = out >> 27;有什么问题? -
[57:27]将是 31 位,比您需要的少一点。assign o_result = out[58:27];应该可以工作。 -
@Greg
[57:27]将是 31 位,这是真的。另一位是来自两个输入的两个符号位的 x 或。所以总共 32 位。 -
@Serge 您的建议比我以前的任何其他解决方案都有效。非常感谢你。
-
x * y >> 27截断,most accurate result可能暗示舍入。
标签: verilog multiplication fixed-point