-- ************************************************************************ -- Copyright (C) 1992 - University of Pittsburgh, Dept. Elect. Engr. -- PICALAB: Pittsburgh Integrated Circuits Analysis Laboratory -- ************************************************************************ -- Title: Eight-bit shift and add multiplier(s) -- Created: Wed Jan 29 04:54:30 1992 -- Author: Dr. Steven Levitan -- -- Compile: vcomp -e multiply.latch mult.vhdl --> for Latch -- vcomp -e multiply.guard mult.vhdl --> for Guard -- make_vsim multiply.beh mult.vhdl --> for Beh -- -- Description: -- This file contains the entity and architecture -- descriptions for three multipliers. All three are based on the -- same simple shift and add algorithm, and use the same ripple -- carry adder. The only difference is in the latching/feedback -- mechanisms: -- Latch - explicitly uses the edge triggered D-latches -- Guard - uses the guarded signal assignment construct -- Beh - uses the static variables inside the process statements -- NOTE THE USE OF THE NON-STANDARD ATRIBUTE S'RISING (S'FALLING) -- Modification History: -- started 3/89 -- Behavioral description by P.P. Hou, The Pennsylvania State University -- ************************************************************************ -- --------------------------------------------------------------------------- -- 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; --------------------------------------------------------------------------- -- end of file ---------------------------------------------------------------------------