-- 
-- esefir5.vhd
--   5 Tap FIR low-pass filter (cutoff=20000Hz)
--   Revision 1.00
-- 
-- Copyright (c) 2006 Mitsutaka Okazaki (ESE Artists' factory)
-- All rights reserved.
-- 
-- Redistribution and use of this source code or any derivative works, are 
-- permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice, 
--    this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright 
--    notice, this list of conditions and the following disclaimer in the 
--    documentation and/or other materials provided with the distribution.
-- 3. Redistributions may not be sold, nor may they be used in a commercial 
--    product or activity without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
-- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
-- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
-- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- 
--------------------------------------------------------------------------------
-- Description
--------------------------------------------------------------------------------
--   This component is an implementation of 5 tap FIR low-pass
--   simulation circut for ESE-MSX system II. 
--   21MHz rate is assumed for an input clock. 3.58MHz is 
--   assumed for streaming sample rate of 'wavin' and 'wavout'. 
--------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity esefir5 is
  generic (
    MSBI : integer
  );
  port ( 
    clk    : in std_logic;
    reset  : in std_logic;
    wavin  : in std_logic_vector ( MSBI downto 0 );
    wavout : out std_logic_vector ( MSBI downto 0 )  
  );
end esefir5;

architecture RTL of esefir5 is

  component tapram is
    generic (
      MSBI : integer
    );
    port ( clk    : in std_logic;
           tapidx : in integer range 0 to 4;
           wr     : in std_logic;
           tapin  : in std_logic_vector(MSBI downto 0);
           tapout : out std_logic_vector(MSBI downto 0));
  end component;

  signal tapidx : integer range 0 to 4;
  subtype H_TYPE is std_logic_vector(7 downto 0);
  type H_ARRAY is array (0 to 4) of H_TYPE;
  constant h : H_ARRAY := ( X"09", X"3d", X"72", X"3d", X"09" );
  signal wr : std_logic;
  signal tapout : std_logic_vector(MSBI downto 0);
  signal tapin  : std_logic_vector(MSBI downto 0);

begin

  process (clk, reset)
    variable tmp : std_logic_vector(H_TYPE'high + wavin'length downto 0);
    variable state : std_logic_vector(2 downto 0);

  begin

    if reset = '1' then

      state  := "000";
      tmp    := (others=>'0');
      wavout <= (others=>'0');
      wr     <= '0';
    
    elsif clk'event and clk = '1' then

      if state = "101" then
        wavout <= tmp( tmp'high downto H_TYPE'length);
        tmp    := (others=>'0');
        wr     <= '1';
        tapin  <= wavin;      
        state  := "000";
      else
        tmp   := tmp + (tapout * h(CONV_INTEGER(state)));
        wr    <='0';
        state := state + 1;
      end if;

      if tapidx = 4 then
        tapidx <= 0;
      else
        tapidx <= tapidx + 1;
      end if;

    end if;

  end process;  

  U0 : tapram generic map ( MSBI ) port map ( clk, tapidx, wr, tapin, tapout );

end RTL;
