试图理解 Booth 的乘法 radix-4 实现
Trying to understand a Booth's multiplication radix-4 implementation
我正在尝试理解一些描述 Booth 乘法与基数 4 实现的 VHDL 代码。我知道算法是如何工作的,但我似乎无法理解代码的某些部分具体做了什么。
这是整个实现:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
entity booth_mult is
port(
clk : in std_logic;
start : in std_logic;
n_reset : in std_logic;
mcand : in std_logic_vector(15 downto 0);
mplier : in std_logic_vector(15 downto 0);
done : out std_logic;
product : out std_logic_vector(31 downto 0)
);
end booth_mult;
architecture arch of booth_mult is
type state_type is(IDLE, BUSY);
attribute ENUM_ENCODING : string; -- used for explicit state machine encoding
attribute ENUM_ENCODING of state_type : type is "01 10";
signal state_reg, state_next : state_type;
signal q_reg, q_next : unsigned(6 downto 0);
signal mcand_reg : std_logic_vector(15 downto 0); -- registers for the multiplicand
signal prod_reg, prod_next : std_logic_vector(32 downto 0);
signal result_reg, result_next : std_logic_vector(32 downto 0); -- this holds the result before shift
signal q_add, q_reset : std_logic;
begin
-- increment sequential logic on rising clock edge process
process(clk, n_reset)
begin
if rising_edge(clk) then
if n_reset = '0' then
state_reg <= IDLE;
q_reg <= (others => '0');
prod_reg <= (others => '0');
else
q_reg <= q_next;
state_reg <= state_next;
prod_reg <= prod_next(32) & prod_next(32 downto 1); -- shift prod register each time
result_reg <= prod_next;
end if;
end if;
end process;
-- control unit process
process(state_reg, q_reg, result_reg, start, prod_reg, mplier, mcand )
begin
-- initialize signals and no register update
q_add <= '0';
q_reset <= '0';
done <= '0';
state_next <= state_reg;
prod_next <= prod_reg;
result_next <= result_reg;
case state_reg is
when IDLE =>
if (start = '1') then -- load numbers to multiply
mcand_reg <= mcand;
prod_next(32 downto 17) <= (others => '0'); -- prod_next reg = [0000...0000(mplier)0]
prod_next(16 downto 1) <= mplier;
prod_next(0) <= '0';
state_next <= BUSY;
end if;
when BUSY =>
q_add <= '1';
if (q_reg = '0' & conv_unsigned(16, 7)(6 downto 1) and start /= '1') then -- after 8 clock cycles multiplication is done
product <= prod_next(32) & prod_next(32 downto 2);
done <= '1' ;
q_add <= '0';
q_reset <= '1';
state_next <= IDLE;
end if;
-- radix-4 decoding
case result_reg(2 downto 0) is
when "001" | "010" => -- + mcand
prod_next <= ((prod_reg(32) & prod_reg(32 downto 17)) + (mcand_reg(16 - 1) & mcand_reg)) & prod_reg(16 downto 1);
when "011" => -- + 2*mcand
prod_next <= ((prod_reg(32) & prod_reg(32 downto 17)) + (mcand_reg & '0' )) & prod_reg(16 downto 1);
when "100" => -- - 2*mcand
prod_next <= ((prod_reg(32) & prod_reg(32 downto 17)) - (mcand_reg & '0' )) & prod_reg(16 downto 1);
when "101" | "110" => -- - mcand
prod_next <= ((prod_reg(32) & prod_reg(32 downto 17)) - (mcand_reg(16 - 1) & mcand_reg)) & prod_reg(16 downto 1); -- 2*mcand
when others => -- shift only
prod_next <= prod_reg(32) & prod_reg(32 downto 1);
end case;
end case;
end process;
-- timer/counter for timed logic
q_next <= (others => '0') when q_reset = '1' else -- reset q_next to bottom if q_reset is 1
q_reg + 1 when q_add = '1' else -- increment q_reg by 1 if q_add is 1
q_reg;
end arch;
我不明白的是:
if (q_reg = '0' & conv_unsigned(16, 7)(6 downto 1) and start /= '1') then -- after 8 clock cycles multiplication is done
.
该评论使其显而易见,但它到底做了什么? conv_unsigned
的文档说它应该 return 值 16 作为大小为 7(我猜它可能是)的无符号值(它是)。 conv_usigned
和 0
编辑的 return 不会 &ing 只是让整个事情变成 0 吗?
prod_next <= prod_reg(32) & prod_reg(32 downto 1);
再次参考评论,这应该只是一个转变。我所理解的实际发生的是 prod_reg
寄存器的第 32 位与第 32 位和第 1 位之间的同一寄存器的每一位进行 &ed,然后分配给 prod_next
。这究竟是怎样一种转变?
代码在测试时有效,所以这 100% 是我缺乏 VHDL 知识的问题,所以如果问题很愚蠢,请原谅我。
回答问题 1:'&' 是连接运算符,因此 '0' & seven_bit_number
构成一个 8 位数。
所以整个表达式 '0' & conv_unsigned(16, 7)(6 downto 1)
是 B"001000"
或 8 的冗长说法。我认为...
这是否来自混淆 VHDL 竞赛?
与类型系统进行如此费力的斗争通常意味着您缺少某些东西,或者设计存在严重错误。
我会删除这些非标准库:
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
赞成标准,
使用 ieee.numeric_std.all;
并简单地写
if q_reg = 8 and start /= '1' then
请注意,现在难以理解的评论不仅有道理,而且是多余的。
(可能还有其他非标准库依赖需要清理,所以这是否真的值得做取决于你)。
关于 Q2 的一个小提示:该操作不是一个班次:它似乎是一个带符号扩展的班次,所以那里可能有带符号的数字。同样,如果合适的话,将 prod_next
设为 numeric_std.signed
将使真正发生的事情变得清晰,还清一点技术债务。
我正在尝试理解一些描述 Booth 乘法与基数 4 实现的 VHDL 代码。我知道算法是如何工作的,但我似乎无法理解代码的某些部分具体做了什么。
这是整个实现:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
entity booth_mult is
port(
clk : in std_logic;
start : in std_logic;
n_reset : in std_logic;
mcand : in std_logic_vector(15 downto 0);
mplier : in std_logic_vector(15 downto 0);
done : out std_logic;
product : out std_logic_vector(31 downto 0)
);
end booth_mult;
architecture arch of booth_mult is
type state_type is(IDLE, BUSY);
attribute ENUM_ENCODING : string; -- used for explicit state machine encoding
attribute ENUM_ENCODING of state_type : type is "01 10";
signal state_reg, state_next : state_type;
signal q_reg, q_next : unsigned(6 downto 0);
signal mcand_reg : std_logic_vector(15 downto 0); -- registers for the multiplicand
signal prod_reg, prod_next : std_logic_vector(32 downto 0);
signal result_reg, result_next : std_logic_vector(32 downto 0); -- this holds the result before shift
signal q_add, q_reset : std_logic;
begin
-- increment sequential logic on rising clock edge process
process(clk, n_reset)
begin
if rising_edge(clk) then
if n_reset = '0' then
state_reg <= IDLE;
q_reg <= (others => '0');
prod_reg <= (others => '0');
else
q_reg <= q_next;
state_reg <= state_next;
prod_reg <= prod_next(32) & prod_next(32 downto 1); -- shift prod register each time
result_reg <= prod_next;
end if;
end if;
end process;
-- control unit process
process(state_reg, q_reg, result_reg, start, prod_reg, mplier, mcand )
begin
-- initialize signals and no register update
q_add <= '0';
q_reset <= '0';
done <= '0';
state_next <= state_reg;
prod_next <= prod_reg;
result_next <= result_reg;
case state_reg is
when IDLE =>
if (start = '1') then -- load numbers to multiply
mcand_reg <= mcand;
prod_next(32 downto 17) <= (others => '0'); -- prod_next reg = [0000...0000(mplier)0]
prod_next(16 downto 1) <= mplier;
prod_next(0) <= '0';
state_next <= BUSY;
end if;
when BUSY =>
q_add <= '1';
if (q_reg = '0' & conv_unsigned(16, 7)(6 downto 1) and start /= '1') then -- after 8 clock cycles multiplication is done
product <= prod_next(32) & prod_next(32 downto 2);
done <= '1' ;
q_add <= '0';
q_reset <= '1';
state_next <= IDLE;
end if;
-- radix-4 decoding
case result_reg(2 downto 0) is
when "001" | "010" => -- + mcand
prod_next <= ((prod_reg(32) & prod_reg(32 downto 17)) + (mcand_reg(16 - 1) & mcand_reg)) & prod_reg(16 downto 1);
when "011" => -- + 2*mcand
prod_next <= ((prod_reg(32) & prod_reg(32 downto 17)) + (mcand_reg & '0' )) & prod_reg(16 downto 1);
when "100" => -- - 2*mcand
prod_next <= ((prod_reg(32) & prod_reg(32 downto 17)) - (mcand_reg & '0' )) & prod_reg(16 downto 1);
when "101" | "110" => -- - mcand
prod_next <= ((prod_reg(32) & prod_reg(32 downto 17)) - (mcand_reg(16 - 1) & mcand_reg)) & prod_reg(16 downto 1); -- 2*mcand
when others => -- shift only
prod_next <= prod_reg(32) & prod_reg(32 downto 1);
end case;
end case;
end process;
-- timer/counter for timed logic
q_next <= (others => '0') when q_reset = '1' else -- reset q_next to bottom if q_reset is 1
q_reg + 1 when q_add = '1' else -- increment q_reg by 1 if q_add is 1
q_reg;
end arch;
我不明白的是:
if (q_reg = '0' & conv_unsigned(16, 7)(6 downto 1) and start /= '1') then -- after 8 clock cycles multiplication is done
.
该评论使其显而易见,但它到底做了什么?conv_unsigned
的文档说它应该 return 值 16 作为大小为 7(我猜它可能是)的无符号值(它是)。conv_usigned
和0
编辑的 return 不会 &ing 只是让整个事情变成 0 吗?prod_next <= prod_reg(32) & prod_reg(32 downto 1);
再次参考评论,这应该只是一个转变。我所理解的实际发生的是prod_reg
寄存器的第 32 位与第 32 位和第 1 位之间的同一寄存器的每一位进行 &ed,然后分配给prod_next
。这究竟是怎样一种转变?
代码在测试时有效,所以这 100% 是我缺乏 VHDL 知识的问题,所以如果问题很愚蠢,请原谅我。
回答问题 1:'&' 是连接运算符,因此 '0' & seven_bit_number
构成一个 8 位数。
所以整个表达式 '0' & conv_unsigned(16, 7)(6 downto 1)
是 B"001000"
或 8 的冗长说法。我认为...
这是否来自混淆 VHDL 竞赛? 与类型系统进行如此费力的斗争通常意味着您缺少某些东西,或者设计存在严重错误。
我会删除这些非标准库:
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
赞成标准, 使用 ieee.numeric_std.all; 并简单地写
if q_reg = 8 and start /= '1' then
请注意,现在难以理解的评论不仅有道理,而且是多余的。
(可能还有其他非标准库依赖需要清理,所以这是否真的值得做取决于你)。
关于 Q2 的一个小提示:该操作不是一个班次:它似乎是一个带符号扩展的班次,所以那里可能有带符号的数字。同样,如果合适的话,将 prod_next
设为 numeric_std.signed
将使真正发生的事情变得清晰,还清一点技术债务。