--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:    12:16:14 10/02/05
-- Design Name:    
-- Module Name:    fir_parallel - Behavioral
-- Project Name:   
-- Target Device:  
-- Tool versions:  
-- Description:
--
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL;
USE ieee.numeric_std.ALL;

library ieee_proposed;
use ieee_proposed.fixed_float_types.all;
use ieee_proposed.fixed_pkg.all;

library work;
use work.utils_pkg.all;
use work.fixed_util_pkg.all;

entity delay_line is
Generic
(
	nbits				: integer := 12;
	nbits_frac			: integer := 11;
	ntaps				: integer := 4;
	delay_fix			: integer := 1
);
Port
(
	rst			: in std_logic;
	clk			: in std_logic;
	shift_en	: in std_logic;
	delay		: in natural range 0 to ntaps-1;
	din			: in sfixed;
	dout		: out sfixed
);
end delay_line;

architecture ram_based of delay_line is

	-------------------------------------------------------------------------------
	signal count : natural range 0 to ntaps-1;
	signal addr_w : unsigned(NextExpBaseTwo(ntaps)-1 downto 0);
	signal addr_r : unsigned(NextExpBaseTwo(ntaps)-1 downto 0);
	signal ram_w : unsigned(nbits-1 downto 0);
	signal ram_r : unsigned(nbits-1 downto 0);

	-------------------------------------------------------------------------------
begin

	addr_w	<= to_unsigned(count, addr_w'length);
	addr_r	<= addr_w + not to_unsigned(delay, addr_w'length);
	
	ram_w	<= unsigned(din);
	dout	<= sfixed(ram_r);

counter:
	process(clk)
	begin
		if rising_edge(clk) then
			if rst = '1' then
				count <= 0;
			elsif shift_en = '1' then
				if count /= ntaps-1 then
					count <= count + 1;
				else
					count <= 0;
				end if;
			end if;
		end if;
	end process;

	inst_dpram_1w1r: entity work.dpram_1w1r2c_ro
	GENERIC MAP
	(
		addr_width	=> NextExpBaseTwo(ntaps),
		data_width	=> nbits
	)
	PORT MAP (
		clk_a	=> clk,
		clk_b	=> clk,
		we_a	=> shift_en,
		re_b	=> '1',
		addr_a	=> addr_w,
		addr_b	=> addr_r,
		din_a	=> ram_w,
		dout_b	=> ram_r
	);
	
end ram_based;

architecture reg_based of delay_line is

	-------------------------------------------------------------------------------
	subtype word_t is sfixed(shi(nbits, nbits_frac) downto slo(nbits, nbits_frac));
	type delay_pipe_t is array (ntaps-1 downto 0) of word_t;
	type delay_fix_pipe_t is array (delay_fix downto 0) of word_t;
	
	-------------------------------------------------------------------------------
begin

shift_register:
	process(clk)
	variable delay_pipe	: delay_pipe_t;
	begin
		if rising_edge(clk) then
			dout			<= delay_pipe(delay);
			if shift_en = '1' then
				delay_pipe		:= delay_pipe(delay_pipe'left-1 downto 0) & din;
			end if;
		end if;
	end process;

end reg_based;

