Search code examples
vhdlmodelsim

Booth multiplier puts a 1 in the high 32 bits for a 64 bit register


I am multiplying the following numbers contained in registers A and B respectively using the booth multiplier algorithm: 308 and 165. The result is stored into zlo and zhi, where zlo is the lower 32 bits and zhi is the upper 32 bits. Here is the VHDL code:

variable M : std_logic_vector(64 downto 0);
variable S : std_logic_vector(64 downto 0);
variable P : std_logic_vector(64 downto 0);

-- Input A is in most significant bits of M
M(64 downto 33) := A(31 downto 0);
M(32 downto 0) := B"00000000_00000000_00000000_00000000_0";
-- -Input A is in most significant bits of S
S(64 downto 33) := std_logic_vector(NOT signed(A) + 1);
S(32 downto 0) := B"00000000_00000000_00000000_00000000_0";
-- P contains the product
P(64 downto 33) := B"00000000_00000000_00000000_00000000";
P(32 downto 1) := B(31 downto 0);
P(0) := '0';
-- check the last two bits and perform appropriate operation and shift
for i in 0 to 31 loop
    if P(1 downto 0) = "01" then
        P(64 downto 0) := std_logic_vector(signed(P) + signed(M));
    elsif P(1 downto 0) = "10" then
        P(64 downto 0) := std_logic_vector(signed(P) + signed(S));
    end if;
    P := std_logic_vector(signed(P) srl 1);
end loop;
zhi <= P(64 downto 33);
zlo <= P(32 downto 1);

The result of the waveform in ModelSim is shown below. As you can see 308 is loaded onto the bus, followed by 165. The result, 50820 is then stored on the bus (zlo), and then a 1 is stored on the bus (zhi). Why is there a 1? 50820 doesn't go into the upper 32 bits.

enter image description here


Solution

  • Hmmm, When I copied you code, it also did not work for me. So I cleaned it up a lot, and now it works... But I don't know what I changed which made it to work. Maybe someone else can help? It's probably has to do with the arithmetic.

    library ieee; use ieee.std_logic_1164.all;

    entity booth_mult is
        generic(
            nr_of_bits : positive := 32
            );
        port(
            clk : in  std_logic;
            A   : in  integer;
            B   : in  integer;
            zhi : out std_logic_vector(nr_of_bits-1 downto 0);
            zlo : out std_logic_vector(nr_of_bits-1 downto 0)
            );
    end entity booth_mult;
    
    library ieee;
    use ieee.numeric_std.all;
    
    architecture behavior of booth_mult is
        signal M : signed((2*nr_of_bits) downto 0) := (others => '0');
        signal S : signed((2*nr_of_bits) downto 0) := (others => '0');
        signal P : signed((2*nr_of_bits) downto 0) := (others => '0');
    
        signal index : natural := 0;
    begin
    -- check the last two bits and perform appropriate operation and shift
        clk_booth : process(clk)
            variable P_temp : signed(P'range);
        begin
            if rising_edge(clk) then
                if index = 0 then
                    M((2*nr_of_bits) downto nr_of_bits+1) <= to_signed(A, nr_of_bits);
                    S((2*nr_of_bits) downto nr_of_bits+1) <= to_signed(-A, nr_of_bits);
                    P(nr_of_bits downto 1) <= to_signed(B, nr_of_bits);
                elsif index < (nr_of_bits+1) then
                    P_temp := P;
                    if P(1 downto 0) = "01" then
                        P_temp := P + M;
                    elsif P(1 downto 0) = "10" then
                        P_temp := P + S;
                    end if;
                    P <= shift_right(P_temp, 1);
                end if;
                index <= index + 1;
            end if;
        end process;
    
        zhi <= std_logic_vector(P((2*nr_of_bits) downto nr_of_bits+1));
        zlo <= std_logic_vector(P(nr_of_bits downto 1));
    end architecture;
    

    and testbench

    entity booth_mult_tb is
    end entity booth_mult_tb;
    
    library ieee;
    use ieee.std_logic_1164.all;
    
    architecture behavior of booth_mult_tb is
        signal clk : std_logic := '0';
    
        constant nr_of_bits : positive := 32;
    
        constant A : integer := 308;
        constant B : integer := 165;
    
        signal zhi : std_logic_vector(nr_of_bits-1 downto 0);
        signal zlo : std_logic_vector(nr_of_bits-1 downto 0);
    begin
        dut : entity work.booth_mult
            generic map(
                nr_of_bits => nr_of_bits
                )
            port map(
                clk => clk,
                A   => A,
                B   => B,
                zhi => zhi,
                zlo => zlo
                );
    
        clk_proc : process
        begin
            loop
                clk <= '0', '1' after 1 ns;
                wait for 2 ns;
            end loop;
        end process;
    end architecture;