library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity NCO is
  port (
    CLK    : in  std_logic;
    RESET  : in  std_logic;
    DELTA  : in  std_logic_vector(11 downto 0);  -- <12,-6,t>
    OFFSET : in  std_logic_vector(16 downto 0); -- <17, 0,u>
    COSOUT : out std_logic_vector(7 downto 0) ); -- <8,0,t>
end NCO;

architecture RTL of NCO is

component COSROM is
  port (
    DATA : out std_logic_vector(7 downto 0);
    ADDR : in  std_logic_vector(9 downto 0)
  );
end component;

signal sum    : std_logic_vector(16 downto 0); -- <17,0,u> 
signal accm   : std_logic_vector(16 downto 0); -- <17,0,u>
signal accm_d : std_logic_vector(16 downto 0); -- <17,0,u>
signal addr   : std_logic_vector(9 downto 0);  -- <10,0,u>
signal data   : std_logic_vector(7 downto 0);  -- <8,0,t>


begin
-- INPUT ADDER
  INPUT_SUM: process(OFFSET,DELTA) 
    variable var_vext : std_logic_vector(16 downto 0);   -- <17,-1,t>
    variable var_tsum : std_logic_vector(16 downto 0);   -- <17,-1,t>
  begin
    var_vext := DELTA(11)&DELTA(11)&DELTA(11)&DELTA(11)&DELTA(11)&DELTA;
    var_tsum := signed(OFFSET) + signed(var_vext);
    sum <= var_tsum;
  end process INPUT_SUM;

-- ACCUMULATOR
  accm <= unsigned(sum) + unsigned(accm_d);

  ACCM_DFF: process(CLK, RESET) begin 
    if(RESET = '1') then
        accm_d <= "00000000000000000";
    elsif(CLK'event and CLK = '1') then
        accm_d <= accm;
    end if;
  end process ACCM_DFF;

-- COSINE ROM
  addr <= accm(16 downto 7);
  U1: COSROM port map (data, addr);

-- OUTPUT FF
  OUT_FF: process(CLK) begin
    if(CLK'event and CLK='1') then
      COSOUT <= data;
    end if;
  end process OUT_FF;

end RTL;
