问题描述
我基于“左移加法”原理制作了一个简单的乘法单元(16位操作数,32位结果),当需要考虑溢出位时,它在加法器部分中无法正常工作
我知道应该怎么做(制作一个17位的求和向量并向产品中添加一个溢出位),但是我不知道如何实现它。您可以在下面找到显示错误位置的波形文件和mpu.vhd文件。屏幕截图没有显示最终结果,但是很明显这是错误的。如何使用16位大数字?
mpu.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity mpu_OP is
port (C: in std_logic; -- Clock
RST : in std_logic; -- Reset
LAB : in std_logic; -- Load A and B,P <= 0
SHIFT : in std_logic; -- Shift B and P
OUTHL : in std_logic; -- Output most(0) or least(1) significant word P
DA : in std_logic_vector(15 downto 0); -- Data A
DB : in std_logic_vector(15 downto 0); -- Data B
DP : out std_logic_vector(15 downto 0)); -- Word result P
end entity;
architecture BEH of mpu_OP is
signal A,B : std_logic_vector(15 downto 0); -- A,B
signal Pi,Ai,Si : integer;
signal S : signed(15 downto 0); -- Sum
signal S2 : signed(16 downto 0);
signal P : signed(31 downto 0); -- Product
begin
RG_A : process(C,RST) -- Register for A
begin
if (RST = '1') then
A <= X"0000";
elsif rising_edge(C) then `-- Reg_A`
if LAB = '1' then
A <= DA;
end if;
end if;
end process;
RG_B : process(C,RST) -- Register for B
begin
if (RST = '1') then
B <= X"0000";
elsif rising_edge(C) then
if LAB = '1' then
B <= DB;
elsif (SHIFT = '1') then
B <= std_logic_vector(shift_left(unsigned(B),1)); `-- Reg_B`
end if;
end if;
end process;
Adder : process (C)
begin
Pi <= to_integer(unsigned(std_logic_vector(P(15 downto 0))));
Ai <= to_integer(unsigned(A));
if B(15) = '1' then
S <= P(15 downto 0) + signed(A); -- Adder
Si <= Pi + Ai;
else
S <= P(15 downto 0);
Si <= Pi;
S2 <= to_signed(Si,S2'length);
end if;
end process;
RG_P : process (C,RST,P) -- Register for P
begin
if RST = '1' then
P <= X"00000000";
elsif rising_edge(C) then
if LAB = '1' then
P <= X"00000000";
elsif SHIFT = '1' then
if B /= "1000000000000000" then
P <= P(30 downto 16) & S & '0'; -- Shift LEFT `-- Reg_Product`
else
P <= P(31 downto 16) & S;
end if;
end if;
end if;
end process;
MUX_P : DP <= std_logic_vector(P(15 downto 0)) when OUTHL = '1' else
std_logic_vector(P(31 downto 16));
end architecture;
下面是重现上述问题和测试平台的最小代码。
mpu.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity mpu_TEST is
port (C: in std_logic;
LAB : in std_logic;
SHIFT : in std_logic;
DA : in std_logic_vector(15 downto 0);
DB : in std_logic_vector(15 downto 0);
DP : out std_logic_vector(31 downto 0));
end entity;
architecture BEH of mpu_TEST is
signal A,B : std_logic_vector(15 downto 0);
signal S : signed(15 downto 0);
signal P : signed(31 downto 0);
begin
RG_A : process(C)
begin
if rising_edge(C) then
if LAB = '1' then
A <= DA;
end if;
end if;
end process;
RG_B : process(C)
begin
if rising_edge(C) then
if LAB = '1' then
B <= DB;
elsif (SHIFT = '1') then
B <= std_logic_vector(shift_left(unsigned(B),1));
end if;
end if;
end process;
Adder : process (C)
begin
if B(15) = '1' then
S <= P(15 downto 0) + signed(A);
else
S <= P(15 downto 0);
end if;
end process;
RG_P : process (C,P)
begin
if rising_edge(C) then
if LAB = '1' then
P <= X"00000000";
elsif SHIFT = '1' then
if B /= "1000000000000000" then
P <= P(30 downto 16) & S & '0';
else
P <= P(31 downto 16) & S;
end if;
end if;
end if;
end process;
DP <= std_logic_vector(P);
end architecture;
mpu_TB.vhd
library ieee;
use ieee.NUMERIC_STD.all;
use ieee.std_logic_1164.all;
entity mpu_test_tb is
end mpu_test_tb;
architecture TB_ARCHITECTURE of mpu_test_tb is
component mpu_test
port(
C : in STD_LOGIC;
LAB : in STD_LOGIC;
SHIFT : in STD_LOGIC;
DA : in STD_LOGIC_VECTOR(15 downto 0);
DB : in STD_LOGIC_VECTOR(15 downto 0);
DP : out STD_LOGIC_VECTOR(31 downto 0) );
end component;
signal C : STD_LOGIC;
signal LAB : STD_LOGIC;
signal SHIFT : STD_LOGIC;
signal DA : STD_LOGIC_VECTOR(15 downto 0);
signal DB : STD_LOGIC_VECTOR(15 downto 0);
signal DP : STD_LOGIC_VECTOR(31 downto 0);
begin
UUT : mpu_test
port map (
C => C,LAB => LAB,SHIFT => SHIFT,DA => DA,DB => DB,DP => DP
);
process
begin
C <= '0';
wait for 5 ns;
C <= '1';
wait for 5 ns;
end process;
LAB <= '1','0' after 10 ns;
SHIFT <= '0','1' after 10 ns,'0' after 170 ns;
DA <= X"1234";
DB <= X"F234";
end TB_ARCHITECTURE;
解决方法
我设法使其正常工作。移位产品时,我明确添加了“ 0”,并在 S 中添加了第17位以保持溢出位。同样,信号范围已更改,应将其存储在乘积和总和中。最终得到下面的代码。
MPU.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity MPU_TEST is
port (C: in std_logic;
LAB : in std_logic;
SHIFT : in std_logic;
DA : in std_logic_vector(15 downto 0);
DB : in std_logic_vector(15 downto 0);
DP : out std_logic_vector(31 downto 0));
end entity;
architecture BEH of MPU_TEST is
signal A,B : std_logic_vector(15 downto 0);
signal S : signed(16 downto 0);
signal P : signed(31 downto 0);
begin
RG_A : process(C)
begin
if rising_edge(C) then
if LAB = '1' then
A <= DA;
end if;
end if;
end process;
RG_B : process(C)
begin
if rising_edge(C) then
if LAB = '1' then
B <= DB;
elsif (SHIFT = '1') then
B <= std_logic_vector(shift_left(unsigned(B),1));
end if;
end if;
end process;
Adder : process (C)
begin
if B(15) = '1' then
S <= P(16 downto 0) + signed(A);
else
S <= P(16 downto 0);
end if;
end process;
RG_P : process (C,P)
begin
if rising_edge(C) then
if LAB = '1' then
P <= X"00000000";
elsif SHIFT = '1' then
if B /= "1000000000000000" then
P <= P(30 downto 17) & S & '0';
else
P <= P(31 downto 17) & S;
end if;
end if;
end if;
end process;
DP <= std_logic_vector(P);
end architecture;