---------------------------------------------------------------------------
-- The multiplier
---------------------------------------------------------------------------
entity multiply is
port (load, clock :in bit;
input1, input2 :in bit_vector(7 downto 0);
product :out bit_vector(15 downto 0);
output_valid :out bit);
end multiply;
--
entity adder is
port (a :in bit_vector(7 downto 0);
b :in bit_vector(7 downto 0);
ci :in bit;
s :out bit_vector(7 downto 0);
co :out bit);
end adder;
--
entity D_latch is
port (din :in bit_vector(7 downto 0);
dout :out bit_vector(7 downto 0);
enable :in bit);
end D_latch;
--
---------------------------------------------------------------------------
-- Simple Ripple Adder
---------------------------------------------------------------------------
architecture logic of adder is
signal cw, cx :bit_vector(7 downto 0);
begin
cw(0) <= ci;
cw(7 downto 1) <= cx(6 downto 0);
cx <= (a and b) or (a and cw) or (b and cw);
s <= a xor b xor cw;
co <= cx(7);
end logic;
--
---------------------------------------------------------------------------
-- Rising Edge triggered latch
--
-- ** IMPORTANT NOTICE **
-- Note that 'w <=' and 'qb <=' lines have delay(after 3 ns).
-- Since these two lines are cross coupled(w with z and ,dout with qb),
-- you MUST force them to have certain amount of delay to avoid simulator
-- jamming. If you don't, the 'vsim' simulator will lock up itself and
-- you will have to force it(like Control-C) to abort.
--
---------------------------------------------------------------------------
architecture edge of D_latch is
signal x, y, z, w, qb, e :bit_vector(7 downto 0);
begin
e <= 255 when enable else 0; -- vector hack
x <= din nand y;
y <= e nand (not w);
z <= e nand w;
w <= z nand x after 3ns; -- to avoid simulator jamming
dout <= z nand qb;
qb <= y nand dout after 3ns; -- same
end edge;
--
----------------------------------------------------------------------
-- Unsigned multiplier using edge triggered latches
----------------------------------------------------------------------
architecture latch of multiply is
signal mux1, mux2, mux3, mux4 :bit_vector(7 downto 0);
signal control, adder_out :bit_vector(7 downto 0);
signal accum :bit_vector(15 downto 0);
signal carry_out :bit;
label l1, l2, l3, l4;
component add
port (arg1, arg2: in bitvec;
c_in :in bit;
result :out bitvec;
c_out :out bit);
end component;
for l4: add use entity adder(logic);
component latch
port (xin :in bitvec; xout :out bitvec; enable :in bit);
end component;
for l1, l2, l3: latch use entity D_latch(edge);
begin
--
-- Synchronous load clears result and initializes system.
-- Use: with clock low: setup inputs, load high
-- clock 010
-- load low
-- clock 010 for eight counts, or until output valid
--
-- Control Section: Count by shifting 8 bits.
-- Shift with a latch and a mux in a feedback loop.
--
mux1(7 downto 0) <= "11111111" when load
else "0" & control(7 downto 1);
l1: latch port map (mux1, control, clock);
output_valid <= not(control(0));
--
-- The accumulator is done in two 8 bit sections for modularity.
-- adder output data (including the carry out) is right shifted
-- on its way back to the accumulator. We shift input2 (kept in
-- the low half of the accumulator) at the same time. Everything
-- happens on the rising edge of clock.
--
mux2 <= 0 when load
else carry_out & adder_out(7 downto 1);
l2: latch port map (mux2, accum(15 downto 8), clock);
--
mux3 <= input2 when load
else adder_out(0) & accum(7 downto 1);
l3: latch port map (mux3, accum(7 downto 0), clock);
--
-- We just need an 8 bit adder on the high order bits of the accumulator
-- and input1. Mux 4 is where we decide to add or not to add,
-- the copy of input1. We run through the adder and shift in any event.
-- Note, we are not using carry in to the adder.
--
mux4 <= input1 when accum(0) else 0;
l4: add port map (mux4, accum(15 downto 8), "0", adder_out, carry_out);
--
product <= accum when output_valid else 0;
end latch;
----------------------------------------------------------------------
-- Unsigned multiplier using guards
----------------------------------------------------------------------
architecture guard of multiply is
signal mux4 :bit_vector(7 downto 0);
signal control, cont_buf :bit_vector(7 downto 0);
signal adder_out :bit_vector(7 downto 0);
signal accum, accum_buf :bit_vector(15 downto 0);
signal carry_out :bit;
label l4;
component add
port (arg1, arg2: in bitvec;
c_in :in bit;
result :out bitvec;
c_out :out bit);
end component;
for l4: add use entity adder(logic);
--
begin
-- Synchronous load. Clock with 010.
-- Single clock: one block of circuts for each clock phase.
-- Master-Slave operation ensures no race conditions.
--
block(clock)
begin
control <= guarded "11111111" when load
else "0" & cont_buf(7 downto 1);
accum <= guarded "00000000" & input2 when load
else accum_buf;
end block;
--
block (not clock)
begin
cont_buf <= guarded control;
accum_buf <= guarded carry_out & adder_out & accum(7 downto 1);
end block;
--
output_valid <= not(cont_buf(0));
--
mux4 <= input1 when accum(0) else 0;
l4: add port map (mux4, accum(15 downto 8), "0", adder_out, carry_out);
--
block(output_valid)
begin
product <= guarded accum;
end block;
--
end guard;
----------------------------------------------------------------------
-- Unsigned multiplier using process statement
----------------------------------------------------------------------
architecture beh of multiply is
signal mux :bit_vector(7 downto 0);
signal control, adder_out :bit_vector(7 downto 0);
signal accum :bit_vector(15 downto 0);
signal carry_out :bit;
label l;
component add
port (arg1, arg2: in bit_vector(7 downto 0);
c_in :in bit;
result :out bit_vector(7 downto 0);
c_out :out bit);
end component;
for l: add use entity adder(logic);
begin
process (clock)
begin
if clock'rising then
if load then
control(7 downto 0) <= "11111111";
accum(15 downto 0) <= "00000000" & input2;
else
control(7 downto 0) <= "0" & control(7 downto 1);
accum(15 downto 0) <= carry_out & adder_out &
accum(7 downto 1);
end if;
end if;
end process;
mux <= input1 when accum(0) else 0;
l: add port map (mux, accum(15 downto 8), "0",
adder_out, carry_out);
output_valid <= not(control(0));
product <= accum when output_valid else 0;
end beh;