---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2008
--
-- Filename: SIPOCtrl.vhd
-- Language: VHDL '93
-- Project:  NDTS2100
--
-- Design Description:
-- Control of SIPO registers used to control the input selection and filters
--
-- The clock will be 2*gHCycle input clock cycles long
---------------------------------------------------------------------------

library IEEE;
use IEEE.Std_Logic_1164.all;
use IEEE.Std_Logic_Arith.all;

entity SIPOCtrl is
  generic(gHCycle: integer := 2);
  port (nReset        : in  std_ulogic;
        Clk           : in  std_ulogic;
        Update        : in  std_ulogic;
        IpSelReg      : in  std_logic_vector(31 downto 0);
        FilterCtrlReg : in  std_logic_vector(15 downto 0);
        Bea           : in  std_ulogic;
        --
        FSerData      : out std_ulogic;
        nFSerOE       : out std_ulogic;
        FSerRClk      : out std_ulogic;
        FSerClk       : out std_ulogic;
        FSel0db       : out std_ulogic;
        FSelN20db     : out std_ulogic;
        FSelN40db     : out std_ulogic;
        FSelP20db     : out std_ulogic);
end entity SIPOCtrl;


architecture Rtl of SIPOCtrl is
  signal ClkCount : integer range 0 to gHCycle*2;
  signal BitCount : integer range 0 to 40;
  signal ShiftReg : std_logic_vector(39 downto 0);
  signal DOutLat  : std_ulogic;
  signal UpdatePending: std_ulogic;
begin

  StateM: process(nReset, Clk)
  begin
    if nReset = '0' then
      ClkCount <= 0;
      BitCount <= 0;
      ShiftReg <= (others => '0');
      DOutLat <= '0';
      UpdatePending <= '0';
      FSerData <= '0';
      nFSerOE <= '1';
      FSerRClk <= '0';
      FSerClk <= '0';
    elsif rising_edge(Clk) then
      if BitCount /= 0 then
        if Update = '1' then
          UpdatePending <= '1';
        end if;

        if ClkCount = 0 then
          FSerClk <= '0';
          FSerData <= ShiftReg(39);
          ShiftReg <= ShiftReg(38 downto 0) & '0';
        end if;
        if ClkCount = gHCycle then
          FSerClk <= '1';
        end if;
        if ClkCount = (gHCycle*2)-1 then
          ClkCount <= 0;
          BitCount <= BitCount - 1;
        else
          ClkCount <= ClkCount + 1;
        end if;
        DOutLat <= '1';
      elsif Update = '1' or updatePending = '1' then
        UpdatePending <= '0';
        BitCount <= 40;
        ShiftReg <= FilterCtrlReg & IpSelReg(23 downto 0);
      else
        if DOutLat = '1' then
          ClkCount <= ClkCount + 1;
          if ClkCount = gHCycle then
            FSerRClk <= '1';
          end if;
          if ClkCount = (gHCycle*2)-1 then
            FSerRClk <= '0';
            ClkCount <= 0;
            DOutLat <= '0';
            nFSerOE <= '0';
          end if;
        end if;
      end if;
    end if;
  end process StateM;

  FiltSel: process(nReset, Clk)
  begin
    if nReset = '0' then
      FSel0db   <= '0';
      FSelN20db <= '0';
      FSelN40db <= '0';
      FSelP20db <= '0';
    elsif rising_edge(Clk) then
      if Bea = '0' then
        FSel0db   <= IpSelReg(24);
        FSelN20db <= IpSelReg(25);
        FSelN40db <= IpSelReg(26);
        FSelP20db <= IpSelReg(27);
      else
        FSel0db   <= IpSelReg(28);
        FSelN20db <= IpSelReg(29);
        FSelN40db <= IpSelReg(30);
        FSelP20db <= IpSelReg(31);
      end if;
    end if;
  end process FiltSel;

end architecture rtl;
