MikeWazowski
MikeWazowski

Reputation: 1

Multiplier via Repeated Addition

I need to create a 4 bit multiplier as a part of a 4-bit ALU in VHDL code, however the requirement is that we have to use repeated addition, meaning if A is one of the four bit number and B is the other 4 bit number, we would have to add A + A + A..., B number of times. I understand this requires either a for loop or a while loop while also having a temp variable to store the values, but my code just doesn't seem to be working and I just don't really understand how the functionality of it would work.

PR and T are temporary buffer standard logic vectors and A and B are the two input 4 bit numbers and C and D are the output values, but the loop just doesn't seem to work. I don't understand how to loop it so it keeps adding the A bit B number of times and thus do the multiplication of A * B.

WHEN "010" =>
       PR <= "00000000";
       T <= "0000";
       WHILE(T < B)LOOP
       PR <= PR + A;
       T <= T + 1;
       END LOOP;
       C <= PR(3 downto 0);
       D <= PR(7 downto 4); 

Upvotes: 0

Views: 1378

Answers (2)

Harry
Harry

Reputation: 938

I advise you to try not to think in terms of "temporary variables", "for loops" and "while loops". These are software constructions that can be useful, but ultimately you are designing a piece of hardware. You need to try to think about what physical pieces of hardware can be connected together to achieve your design, then how you might describe them using VHDL. This is difficult at first.

You should provide more information about what exactly you want to achieve (and on what kind of hardware) to increase the probability of getting a good answer.

You don't mention whether your multiplier needs to operate on signed or unsigned inputs. Let's assume signed, because that's a bit harder.

As has been noted, this whole exercise makes little sense if implemented combinationally, so let's assume you want a clocked (sequential) implementation.

You also don't mention how often you expect new inputs to arrive. This makes a big difference in the implementation. I don't think either one is necessarily more difficult to write than the other, but if you expect frequent inputs (e.g. every clock cycle), then you need a pipelined implementation (which uses more hardware). If you expect infrequent inputs (e.g. every 16 or more clock cycles) then a cheaper serial implementation should be used.

Let's assume you want a serial implementation, then I would start somewhere along these lines:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity loopy_mult is
generic(
    g_a_bits    : positive := 4;
    g_b_bits    : positive := 4
);
port(
    clk         : in std_logic;
    srst        : in std_logic;
    -- Input
    in_valid    : in std_logic;
    in_a        : in signed(g_a_bits-1 downto 0);
    in_b        : in signed(g_b_bits-1 downto 0);
    -- Output
    out_valid   : out std_logic;
    out_ab      : out signed(g_a_bits+g_b_bits-1 downto 0)
);
end loopy_mult;

architecture rtl of loopy_mult is

    signal a            : signed(g_a_bits-1 downto 0);
    signal b_sign       : std_logic;

    signal countdown    : unsigned(g_b_bits-1 downto 0);
    signal sum          : signed(g_a_bits+g_b_bits-1 downto 0);
begin

    mult_proc : process(clk)
    begin
        if rising_edge(clk) then
            if srst = '1' then
                out_valid <= '0';
                countdown <= (others => '0');
            else
                if in_valid = '1' then -- (Initialize)
                    -- Record the value of A and sign of B for later
                    a <= in_a;
                    b_sign <= in_b(g_b_bits-1);

                    -- Initialize countdown
                    if in_b(g_b_bits-1) = '0' then
                        -- Input B is positive
                        countdown <= unsigned(in_b);
                    else
                        -- Input B is negative
                        countdown <= unsigned(-in_b);
                    end if;

                    -- Initialize sum
                    sum <= (others => '0');

                    -- Set the output valid flag if we're already finished (B=0)
                    if in_b = 0 then
                        out_valid <= '1';
                    else
                        out_valid <= '0';
                    end if;
                elsif countdown > 0 then -- (Loop)
                    -- Let's assume the target is an FPGA with efficient add/sub
                    if b_sign = '0' then
                        sum <= sum + a;
                    else
                        sum <= sum - a;
                    end if;

                    -- Set the output valid flag when we get to the last loop
                    if countdown = 1 then
                        out_valid <= '1';
                    else
                        out_valid <= '0';
                    end if;

                    -- Decrement countdown
                    countdown <= countdown - 1;
                else
                    -- (Idle)
                    out_valid <= '0';
                end if;
            end if;
        end if;
    end process mult_proc;

    -- Output
    out_ab <= sum;

end rtl;

This is not immensely efficient, but is intended to be relatively easy to read and understand. There are many, many improvements you could make depending on your requirements.

Upvotes: 0

Matthew
Matthew

Reputation: 13957

This will never work, because when a line with a signal assignment (<=) like this one:

PR <= PR + A;

is executed, the target of the signal assignment (PR in this case) is not updated immediately; instead an event (a future change) is scheduled. When is this event (change) actioned? When all processes have suspended (reached wait statements or end process statements).

So, your loop:

   WHILE(T < B)LOOP
     PR <= PR + A;
     T <= T + 1;
   END LOOP;

just schedules more and more events on PR and T, but these events never get actioned because the process is still executing. There is more information here.


So, what's the solution to your problem? Well, it depends what hardware you are trying to achieve. Are you trying to achieve a block of combinational logic? Or sequential? (where the multiply takes multiple clock cycles)

Upvotes: 1

Related Questions