乘法器可以分为以下几种类型:
顺序乘法器(Sequential Multiplier
):顺序乘法器是最简单的乘法器类型,采用逐位相乘的方法实现。这种乘法器适用于小规模的乘法运算,但速度较慢。
(1) Booth
编码乘法器
并行乘法器(Parallel Multiplier
):
并行乘法器是采用并行计算的方法实现乘法运算,可以同时计算多个位的乘积。这种乘法器速度较快,适用于大规模的乘法运算。
(1) Wallace
树乘法器(Wallace Tree Multiplier
):
(2) Wallace
树带预编码的乘法器**(Wallace Tree with Pre-Encoding Multiplier
)
1 运算符 * 实现乘法器
运算符*表示乘法操作。实际上,乘法器的具体实现取决于所使用的FPGA
或ASIC
技术。不同的FPGA
或ASIC
可能使用不同的乘法器结构,以实现乘法操作。常见的乘法器结构包括布斯乘法器、士脑乘法器和Wallace树乘法器等。具体使用哪种乘法器结构取决于设计的要求和可用的资源。
在通常情况下,我们可能会定义无符号数来表示数据。然而,如果我们接收到的数据实际上是有符号数,而且在计算时默认按照无符号数进行计算(将读取到的8位二进制数视为原码进行计算),那么我们需要对符号位进行扩展来进行乘法计算。我们需要注意在这种情况下对符号位进行扩展来正确计算乘法。
设计
module signed_fixed_point_multiplier #(
parameter DATA_WIDTH = 32
) (
input signed [DATA_WIDTH-1:0] operand_a,
input signed [DATA_WIDTH-1:0] operand_b,
input wire clk,
output signed [2*DATA_WIDTH-1:0] result
);
//做符号位扩展,再相乘
assign result = {
{
32{
operand_a[31]}},operand_a} * {
{
32{
operand_b[31]}},operand_b};
endmodule
测试
module signed_fixed_point_multiplier_tb;
reg signed [31:0] operand_a;
reg signed [31:0] operand_b;
reg clk;
wire signed [63:0] result;
signed_fixed_point_multiplier #(.DATA_WIDTH(32)) uut (
.operand_a(operand_a),
.operand_b(operand_b),
.clk(clk),
.result(result)
);
// 时钟生成
initial begin
clk = 0;
operand_a = 5;
operand_b = 3;
#10;
operand_a = -7;
operand_b = -2;
#10;
operand_a = 10;
operand_b = -4;
#10;
// 可以继续添加更多的测试用例
$finish;
end
initial begin
$dumpfile("wave.vcd"); // 指定用作dumpfile的文件
$dumpvars; // dump all vars
end
endmodule
仿真结果
仿真结果符合预期。
Tips
: Reg
与 Wire
赋值区别?
reg
型变量必须在过程块内通过过程赋值语句赋值,而不能使用assign
语句进行赋值。过程赋值语句可以是非阻塞赋值语句(<=
)或阻塞赋值语句(=
),用于在时序逻辑中更新reg型变量的值。
相反,wire
型数据不能放在过程块内赋值。wire
型数据通常用于组合逻辑,其值由组合逻辑电路决定,而不是时钟驱动的。在组合逻辑中,可以使用assign
语句对wire
型数据进行赋值。
1 顺序乘法器
顺序乘法器(也叫串行乘法器)通过逐位相乘和累加的方式计算乘法结果。它需将被乘数和乘数进行二进制展开,然后逐位进行相乘和累加运算。最经典的例子是经典的Booth
乘法器。
1.1 Booth
编码乘法器
参考文献[2]
(Booth Encoder Multiplier
):Booth
编码乘法器是将乘法运算转化为加法运算的一种技术,通过对乘数进行编码,可以减少乘法器的硬件复杂度。
其中,HA
表示半加器,FA
表示全加器,虚线表示进位链
上图红色和紫色线表示最长路径,代表了组合逻辑深度, 在此基础上可进一步优化。乘法运算由2
部分组成:生成部分积、通过加法树对数据压缩。
部分积生成
Radix-2
编码
Radix-2
编码可以消除2bit
连续的“1
”,但是对于硬件电路来说,加法树的层级并没有得到减少,反而引入了编码电路,由此引出radix-4编码
Radix-4
编码
A*B
可以写为:
我们只需要对A进行取补码或者移位操作,就可完成部分积的计算
相比于Radix-2 Booth
编码,Radix-4 Booth
编码将使得乘法累积的部分和数减少一半,部分积只涉及到移位和补码计算。
设计思路
使用 Booth 算法实现乘法的模块。该模块具有以下输入和输出:
这是一个使用 Booth 算法实现乘法的模块。该模块具有以下输入和输出:
输入:
clk
:时钟信号rst_n
:复位信号,低电平有效start
:启动信号,用于触发乘法运算的开始mul_A
:被乘数,8 位无符号数mul_B
:乘数,8 位无符号数
输出:
done
:乘法运算完成信号Product
:乘法结果,16 位无符号数
内部信号:
state
:状态寄存器,用于控制乘法过程的状态转移mult_A
:mul_A
的补零扩展结果,用于 Booth 算法中的加法操作mult_B
:mul_B
的补零扩展结果,用于 Booth 算法中的移位操作inv_A
:mult_A
的补码结果,用于 Booth 算法中的加法操作result_tmp
:乘法结果的暂存器,用于 Booth 算法中的加法操作
具体实现思路如下:
- 通过
rst_n
信号将所有寄存器和输出信号重置为初始值。 - 当
start
信号为高电平时,进入状态机。 - 在状态 0 中,将
mul_A
进行补零扩展得到mult_A
,并计算出inv_A
。 - 在状态 1 中,根据
booth_code
的值选择加法操作的项,并进行加法操作。 - 每次加法操作后,将
mult_A
和inv_A
进行移位操作,将mult_B
进行右移操作。 - 判断是否需要跳转到下一个状态,如果需要,则跳转到状态 2,完成乘法运算。
- 在状态 2 中,将乘法结果赋值给输出信号,并将
done
置为高电平。 - 在状态 3 中,将
done
置为低电平,将状态机重置为状态 0,等待下一次启动。
这个模块使用 Booth 算法实现乘法,通过有符号数的运算规则减少乘法的位数。具体的 Booth 算法实现在状态 1 中,根据 booth_code
的值选择加法操作的项,以此减少加法的次数。这是一个使用 Booth 算法实现乘法的模块。该模块具有以下输入和输出:
输入:
clk
:时钟信号rst_n
:复位信号,低电平有效start
:启动信号,用于触发乘法运算的开始mul_A
:被乘数,8 位无符号数mul_B
:乘数,8 位无符号数
输出:
done
:乘法运算完成信号Product
:乘法结果,16 位无符号数
内部信号:
state
:状态寄存器,用于控制乘法过程的状态转移mult_A
:mul_A
的补零扩展结果,用于 Booth 算法中的加法操作mult_B
:mul_B
的补零扩展结果,用于 Booth 算法中的移位操作inv_A
:mult_A
的补码结果,用于 Booth 算法中的加法操作result_tmp
:乘法结果的暂存器,用于 Booth 算法中的加法操作
具体实现思路如下:
- 通过
rst_n
信号将所有寄存器和输出信号重置为初始值。 - 当
start
信号为高电平时,进入状态机。 - 在状态 0 中,将
mul_A
进行补零扩展得到mult_A
,并计算出inv_A
。 - 在状态 1 中,根据
booth_code
的值选择加法操作的项,并进行加法操作。 - 每次加法操作后,将
mult_A
和inv_A
进行移位操作,将