引言在数字计算中,加、减、乘、除常用。 在FPGA中,有加法、减法、乘法、除法的算法命令,但是在除法运算中除数必须是2的乘方,所以不能实现除数为任意数的除法运算; 二进制除法算法包括减法、乘法、数的分解与合成、试商的判断等多个操作过程。 因此,除法的过程非常复杂,很难用VHDL写出除法。 因此,作者根据二进制乘法的原理,用被除数和除数倒数相乘的方法实现了二进制除法。
16位二进制乘法
二进制乘法是通过逐项移位相加的原理实现的。 被乘数从最低有效位开始为1时,乘数向左移动并送入寄存器进行加法运算。 0时,向左移动,然后全零相加。 这样往复,达到被乘数的最高位。 乘法运算结束后,此时累加器的输出值为最后的乘积。 图1表示乘法的原理框图。
图1乘法的原理框图
根据上述原理,设计VHDL算法,实现16位二进制乘法。 乘法运算在1个时钟脉冲内完成。
库IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
实体多重
端口(clk : instd _ logic;
a : instd _ logic _ vector (15 down to0);
//乘数
b : instd _ logic _ vector (15 down to0);
//被乘数
START:IN STD_LOGIC;
ch:out STD _ logic _ vector (15 down to0);
cl : out STD _ logic _ vector (15 downtoo );
结束多重;
ARCHITECTURE BEHAV OF MULTIPLY IS
signall 8: STD _ logic _ vector (15 down to );
比根
是进程(clk )
variable ACC : STD _ logic _ vector (31 down to0);
variable n : STD _ logic _ vector (7down to 0;
variable q : STD _ logic _ vector (31 down to );
variable ma : STD _ logic _ vector (31 downtoo );
比根
IF START='1'THEN
IF CLK'EVENT AND CLK='1'THEN
ma(31downto0) :=(000000000000 ) a ) 15
DOWNTO 0;
ACC :=' 000000000000000 ';
FOR I IN 0 TO 15 LOOP
FOR JIN 0 TO 31 LOOP
q(j ) :=B(I ) I ) AND MA(J ) j; //b(I )和MA相(和) )。
结束环路;
ACC:=ACC Q; //累积
ma(31downto0) :=ma (30 down to0) ma ) 31;
//左移
结束环路;
ch=ACC(31downto16; //积的高度16位
cl=ACC(15downto0; //积的后16位
ENDIF;
ENDIF;
结束进程;
END BEHAV;
合并后生成的乘法器宏如图2所示。
图2二进制乘法器
改进二进制除法由于在FPGA中实现二进制除法的算法非常复杂,我们在实现二进制除法时,采取被除数和除数的倒数相乘的方法。 因此,在给定除数的同时必须计算除数的倒数。 除数的倒数是小数形式。 如果除数为1,则倒数为1。 因此,将此倒数小数部分的16位和整数部分的最后1位(主要考虑除数为1时,倒数的整数部分为1 )记录为17位的二进制数。 这样就可以将被除数和二进制乘法运算。 的后16位是商品的小数部分。 前面是商品的整数部分。
在FPGA中,将除数作为寄存器的地址,将其倒数的小数部分作为寄存器的内容。 这样,重新计算除数的倒数就相当于1次寄存器的寻址。 图3是改进除法原理的框图。
图3除法原理框图的改进
用VHDL设计的查找表程序如下。 (将除数b以1个时钟周期转换为1/B,输出结果m的后16位为倒数的小数部分,m的第17位为倒数的整数部分)。
库IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
实体表is
端口(
N:IN STD_
LOGIC_VECTOR (7 downto 0);CLK:IN STD_LOGIC;
READ:IN STD_LOGIC;
M:out STD_LOGIC_VECTOR(16 downto 0)//倒数的
//整数M(16)和小数部分M(15:0)
);
END TABLE;
ARCHITECTURE TABLE_ARCH OF TABLE IS
SIGNAL L8:STD_LOGIC_VECTOR(16 DOWNTO 0);
BEGIN
PROCESS(CLK,READ)
IF READ='l'THEN
IF CLK'EVENT AND CLK='l'THEN
WHEN"00000001"=>L8<="10000000000000000";
WHEN"00000010"=>L8<="01000000000000000";
WHEN"00000011"=>L8<="00101010101010101";
WHEN"00000100"=>L8<="00100000000000000";
WHEN"00000101"=>L8<="00011001100110011";
WHEN"00000110"=>L8<="00010101010101010";
WHEN"00000111"=>L8<="00010010010010010";
WHEN"11111001"=>L8<="00000000100000111";
WHEN"11111010"=>L8<="00000000100000110";
WHEN"11111011"=>L8<="00000000100000101";
WHEN"11111100"=>L8<="00000000100000100";
WHEN"11111101"=>L8<="00000000100000011";
WHEN"11111110"=>L8<="00000000100000010";
WHEN"11111111"=>L8<="00000000100000001";
WHEN OTHERS=>L8<="ZZZZZZZZZZZZZZZZZ";
//以上为1-255的倒数
END CASE;
M<=L8;
ENDIF;
ENDIF;
END PROCESS;
END TABLE_ARCH;
综合后生成倒数转换寄存器的宏如图4所示。
图4除数转化其倒数寄存器
用原理图将上面所生成的宏连接成完整的除法器如图5所示。其中A[15:0]为被除数,B[7:0]为除数,c[31:16]为商的整数部分,C[15:0]为商的小数部分。
图5 完整的二进制除法器
我们选择几对被除数和除数进行了仿真,其结果如图6和表1所示。
表1部分仿真结果
被除数
除数
商的整数部分
商的小数部分
0450
68
000A
9CE0
0036
68
0000
84E4
0256
68
0005
BFA4
0256
39
000A
7BFE
0168
17
000F
A668
结语
应用上述的二进制乘法和二进制除法,我们解决了工程中所需的乘法和除法运算问题。其中除法运算的商可以精确到小数点后面16位,达到了工程中对运算精度的要求。二进制乘法可以扩展到任意位数,二进制除法中被除数可以为任意位数。由于本方法中除数转换为其倒数的过程是由作者手工输入,并作为寄存器的内容进行存储的, 因此只考虑了除数为8位的情况,当然,也可以完成更高位的寄存器寻址,但工作量很大。