----------------------------------------------
-- MSS copyright 1999-2001
-- Filename: M11X8U_A.VHD
-- Author: Alain Zarembowitch / MSS
-- Inheritance: new
-- Edit date: 1-29-01
-- Revision: 0.024 
--
-- VHDL code for 12bit x 9bit = 10-bit multiplier, synchronous
--
-- Rev 0.025 az
-- Switched from active low to active high reset
-- 
-- Unsigned multipler. The two inputs are 11-bit and 8-bit wide respectively.
-- The output is truncated down to 9 bits. 
-- Input and output are unsigned numbers
-- Implementation: Wallace tree multiplier consisting of half adders and
-- full adders. Ref: pp758
-- This version is clocked. 
-- Latency between inputs and output is 4 CLK clocks
----------------------------------------------
Library ieee;
Use ieee.std_logic_1164.all;

entity M11x8U_A is
	port (
		A: in std_logic_vector(10 downto 0);
			-- input A, 11-bit wide, unsigned
		B: in std_logic_vector(7 downto 0);
			-- input B, 8-bit wide, unsigned
		CLK: in std_logic;
			-- reference clock
		ASYNC_RESET: in std_logic;
			-- reset, active low
		M: out std_logic_vector(8 downto 0)
			-- output, 9-bit wide, unsigned
	);
end M11x8U_A;

architecture BEHAVIOR of M11x8U_A is

-----------------------------------------------------------------
-- COMPONENTS
-----------------------------------------------------------------
-- full adder
component FA is
	port (
		A: in std_logic;	-- input A
		B: in std_logic;	-- input B
		CI: in std_logic;	-- carry in
		O: out std_logic;	-- added value
		CO: out std_logic	-- carry out
	);
end component;

-- half adder
component HA is
	port (
		A: in std_logic;	-- input A
		B: in std_logic;	-- input B
		O: out std_logic;	-- added value
		CO: out std_logic	-- carry out
	);
end component;

-- 16 bit look ahead adder 
component fcadd16_2 is
	port (
		ci: 	in std_logic;
		a15,a14,a13,a12,a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0:	in std_logic;
		b15,b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0:	in std_logic;
		sum15,sum14,sum13,sum12,sum11,sum10,sum9,sum8,sum7,sum6,sum5,sum4,sum3,sum2,sum1,sum0: out std_logic;
		co: out std_logic);
end component;


-----------------------------------------------------------------
-- SIGNALS
-----------------------------------------------------------------
-- _D denotes 1 CLK delay
signal zero: std_logic;
signal one: std_logic;

-- intermediate products
signal A_D: std_logic_vector(10 downto 0);
signal B_D: std_logic_vector(7 downto 0);


signal AB0: std_logic_vector(10 downto 0);
signal AB1: std_logic_vector(10 downto 0);
signal AB2: std_logic_vector(10 downto 0);
signal AB3: std_logic_vector(10 downto 0);
signal AB4: std_logic_vector(10 downto 0);
signal AB5: std_logic_vector(10 downto 0);

signal AB6: std_logic_vector(10 downto 0);
signal AB7: std_logic_vector(10 downto 0);
signal P0: std_logic_vector(12 downto 0);	-- partial products, stage 1
signal P1: std_logic_vector(16 downto 0);	-- partial products, stage 1

signal AB6_D: std_logic_vector(10 downto 0);
signal AB7_D: std_logic_vector(10 downto 0);
signal P0_D: std_logic_vector(12 downto 0);	-- partial products, stage 1
signal P1_D: std_logic_vector(16 downto 0);	-- partial products, stage 1


signal P3: std_logic_vector(14 downto 0);	-- partial products, stage 2
signal P4: std_logic_vector(18 downto 0);	-- partial products, stage 2
signal P5: std_logic_vector(17 downto 0);	-- partial products, stage 3
signal P6: std_logic_vector(17 downto 0);	-- partial products, stage 4

signal P6_D: std_logic_vector(17 downto 0);	-- partial products, stage 4

signal M0: std_logic_vector(8 downto 0); 	-- product before final pipeline
-----------------------------------------------------------------
-- IMPLEMENTATION
-----------------------------------------------------------------
begin

zero <= '0';
one <= '1';

-- pipeline
PIPELINE_000: process(ASYNC_RESET, CLK, A, B)
begin
	if(ASYNC_RESET = '1') then
		A_D <= "00000000000";
		B_D <= "00000000";
	elsif rising_edge(CLK) then
		A_D <= A;
		B_D <= B;
	end if;
end process;


xor00: process (A_D,B_D)
variable i: integer;
begin
	for i in 10 downto 0 loop
		AB0(i) <= A_D(i) AND B_D(0);
		AB1(i) <= A_D(i) AND B_D(1);
		AB2(i) <= A_D(i) AND B_D(2);
		AB3(i) <= A_D(i) AND B_D(3);
		AB4(i) <= A_D(i) AND B_D(4);
		AB5(i) <= A_D(i) AND B_D(5);
		AB6(i) <= A_D(i) AND B_D(6);
		AB7(i) <= A_D(i) AND B_D(7);
	end loop;
end process;


-- instantiate half adders and full adders
-- Stage 1, top three rows
FA00: FA port map(A => AB0(6), B => AB1(5), CI => AB2(4) , O => P0(0) , CO => P0(1));
FA01: FA port map(A => AB0(7), B => AB1(6), CI => AB2(5) , O => P0(2) , CO => P0(3));
FA02: FA port map(A => AB0(8), B => AB1(7), CI => AB2(6) , O => P0(4) , CO => P0(5));
FA03: FA port map(A => AB0(9), B => AB1(8), CI => AB2(7) , O => P0(6) , CO => P0(7));
FA04: FA port map(A => AB0(10), B => AB1(9), CI => AB2(8) , O => P0(8) , CO => P0(9));
HA00: HA port map(A => AB1(10), B => AB2(9), O => P0(10) , CO => P0(11));
P0(12) <= AB2(10);

-- Stage 1, middle three rows
FA05: FA port map(A => AB3(4), B => AB4(3), CI => AB5(2) , O => P1(0) , CO => P1(1));
FA06: FA port map(A => AB3(5), B => AB4(4), CI => AB5(3) , O => P1(2) , CO => P1(3));
FA07: FA port map(A => AB3(6), B => AB4(5), CI => AB5(4) , O => P1(4) , CO => P1(5));
FA08: FA port map(A => AB3(7), B => AB4(6), CI => AB5(5) , O => P1(6) , CO => P1(7));
FA09: FA port map(A => AB3(8), B => AB4(7), CI => AB5(6) , O => P1(8) , CO => P1(9));
FA10: FA port map(A => AB3(9), B => AB4(8), CI => AB5(7) , O => P1(10) , CO => P1(11));
FA11: FA port map(A => AB3(10), B => AB4(9), CI => AB5(8) , O => P1(12) , CO => P1(13));
HA01: HA port map(A => AB4(10), B => AB5(9), O => P1(14) , CO => P1(15));
P1(16) <= AB5(10);


-- pipeline
PIPELINE_001: process(ASYNC_RESET, CLK, P0, P1, AB6, AB7)
begin
	if(ASYNC_RESET = '1') then
		AB6_D <= "00000000000";
		AB7_D <= "00000000000";
		P0_D <= "0000000000000";
		P1_D <= "00000000000000000";
	elsif rising_edge(CLK) then
		AB6_D <= AB6;
		AB7_D <= AB7;
		P0_D <= P0;
		P1_D <= P1;
	end if;
end process;



-- Stage 2, top three rows
FA12: FA port map(A => P0_D(2), B => P0_D(1), CI => P1_D(0) , O => P3(0) , CO => P3(1));
FA13: FA port map(A => P0_D(4), B => P0_D(3), CI => P1_D(2) , O => P3(2) , CO => P3(3));
FA14: FA port map(A => P0_D(6), B => P0_D(5), CI => P1_D(4) , O => P3(4) , CO => P3(5));
FA15: FA port map(A => P0_D(8), B => P0_D(7), CI => P1_D(6) , O => P3(6) , CO => P3(7));
FA16: FA port map(A => P0_D(10), B => P0_D(9), CI => P1_D(8) , O => P3(8) , CO => P3(9));
FA17: FA port map(A => P0_D(12), B => P0_D(11), CI => P1_D(10) , O => P3(10) , CO => P3(11));
P3(12) <= P1_D(12);
P3(13) <= P1_D(14);
P3(14) <= P1_D(16);

-- Stage 2, lower three rows
FA18: FA port map(A => P1_D(1), B => AB6_D(2), CI => AB7_D(1) , O => P4(0) , CO => P4(1));
FA19: FA port map(A => P1_D(3), B => AB6_D(3), CI => AB7_D(2) , O => P4(2) , CO => P4(3));
FA20: FA port map(A => P1_D(5), B => AB6_D(4), CI => AB7_D(3) , O => P4(4) , CO => P4(5));
FA21: FA port map(A => P1_D(7), B => AB6_D(5), CI => AB7_D(4) , O => P4(6) , CO => P4(7));
FA22: FA port map(A => P1_D(9), B => AB6_D(6), CI => AB7_D(5) , O => P4(8) , CO => P4(9));
FA23: FA port map(A => P1_D(11), B => AB6_D(7), CI => AB7_D(6) , O => P4(10) , CO => P4(11));
FA24: FA port map(A => P1_D(13), B => AB6_D(8), CI => AB7_D(7) , O => P4(12) , CO => P4(13));
FA25: FA port map(A => P1_D(15), B => AB6_D(9), CI => AB7_D(8) , O => P4(14) , CO => P4(15));
HA02: HA port map(A => AB6_D(10), B => AB7_D(9), O => P4(16) , CO => P4(17));
P4(18) <= AB7_D(10);

-- Stage 3, top three rows
FA26: FA port map(A => P3(2), B => P3(1), CI => P4(0) , O => P5(0) , CO => P5(1));
FA27: FA port map(A => P3(4), B => P3(3), CI => P4(2) , O => P5(2) , CO => P5(3));
FA28: FA port map(A => P3(6), B => P3(5), CI => P4(4) , O => P5(4) , CO => P5(5));
FA29: FA port map(A => P3(8), B => P3(7), CI => P4(6) , O => P5(6) , CO => P5(7));
FA30: FA port map(A => P3(10), B => P3(9), CI => P4(8) , O => P5(8) , CO => P5(9));
FA31: FA port map(A => P3(12), B => P3(11), CI => P4(10) , O => P5(10) , CO => P5(11));
HA03: HA port map(A => P3(13), B => P4(12), O => P5(12) , CO => P5(13));
HA04: HA port map(A => P3(14), B => P4(14), O => P5(14) , CO => P5(15));
P5(16) <= P4(16);
P5(17) <= P4(18);

-- Stage 4, three rows
FA32: FA port map(A => P5(2), B => P5(1), CI => P4(1) , O => P6(0) , CO => P6(1));
FA33: FA port map(A => P5(4), B => P5(3), CI => P4(3) , O => P6(2) , CO => P6(3));
FA34: FA port map(A => P5(6), B => P5(5), CI => P4(5) , O => P6(4) , CO => P6(5));
FA35: FA port map(A => P5(8), B => P5(7), CI => P4(7) , O => P6(6) , CO => P6(7));
FA36: FA port map(A => P5(10), B => P5(9), CI => P4(9) , O => P6(8) , CO => P6(9));
FA37: FA port map(A => P5(12), B => P5(11), CI => P4(11) , O => P6(10) , CO => P6(11));
FA38: FA port map(A => P5(14), B => P5(13), CI => P4(13) , O => P6(12) , CO => P6(13));
FA39: FA port map(A => P5(16), B => P5(15), CI => P4(15) , O => P6(14) , CO => P6(15));
HA05: HA port map(A => P5(17), B => P4(17), O => P6(16) , CO => P6(17));


-- pipeline
PIPELINE_002: process(ASYNC_RESET, CLK, P6)
begin
	if(ASYNC_RESET = '1') then
		P6_D <= "000000000000000000";
	elsif rising_edge(CLK) then
		P6_D <= P6;
	end if;
end process;


-- Stage 5, final adder
ADD00: fcadd16_2 port map(ci => zero, a0 => P6_D(2), a1 => P6_D(4), a2 => P6_D(6), a3 => P6_D(8),
	a4 => P6_D(10), a5 => P6_D(12), a6 => P6_D(14), a7 => P6_D(16), a8 => zero, a9 => zero,
	a10 => zero, a11 => zero, a12 => zero, a13 => zero, a14 => zero, a15 => zero,
	b0 => P6_D(1), b1 => P6_D(3), b2 => P6_D(5), b3 => P6_D(7), b4 => P6_D(9), b5 => P6_D(11),
	b6 => P6_D(13), b7 => P6_D(15), b8 => P6_D(17), b9 => zero,
	b10 => zero, b11 => zero, b12 => zero, b13 => zero, b14 => zero, b15 => zero,
	sum0 => M0(0), sum1 => M0(1), sum2 => M0(2), sum3 => M0(3), sum4 => M0(4),
	sum5 => M0(5), sum6 => M0(6), sum7 => M0(7), sum8 => M0(8));		
	
	
-- pipeline
PIPELINE_003: process(ASYNC_RESET, CLK, M0)
begin
	if(ASYNC_RESET = '1') then
		M <= "000000000";
	elsif rising_edge(CLK) then
		M <= M0;
	end if;
end process;


end BEHAVIOR;

