LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

entity signed_mult is
generic 
(
	latency		: natural := 2;
	data_width	: natural := 16
);
port
(
	clk			: in std_logic;
	ce			: in std_logic;
	a			: in signed (data_width-1 downto 0);
	b			: in signed (data_width-1 downto 0);
	result		: out signed (2*data_width-1 downto 0)
);
end signed_mult;

architecture rtl of signed_mult is
	
	constant in_latency		: natural := latency - 1;
	constant out_latency	: natural := latency - in_latency;
	
	subtype in_t is signed (data_width-1 downto 0);
	subtype out_t is signed (2*data_width-1 downto 0);
	type in_pipe_t is array (in_latency downto 1) of in_t;
	type out_pipe_t is array (out_latency downto 1) of out_t;

	signal a_pipe	: in_pipe_t;
	signal b_pipe	: in_pipe_t;
	signal out_pipe	: out_pipe_t;

begin

	result	<= out_pipe(out_latency);
	
input_pipe_reg: 
	process(clk)
	begin
	if rising_edge(clk) then
		if ce = '1' then
			a_pipe	<= a_pipe(in_latency-1 downto 1) & a;
			b_pipe	<= b_pipe(in_latency-1 downto 1) & b;
		end if;	
	end if;	
	end process;
	
mult_pipe_reg: 
	process (clk)
	variable res : out_t;
	begin
	if rising_edge(clk) then
		res := a_pipe(in_latency) * b_pipe(in_latency);
		if ce = '1' then
			out_pipe	<= out_pipe(out_latency-1 downto 1) & res;
		end if;
	end if;
	end process;

end rtl;
