--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
--
library XilinxCoreLib;
--
use work.vlib_commonfunc_pkg.all;
use work.control_x_pkg.all;

entity shift is
  generic (MEMBLOCKS : integer := 16); -- Potencias de 2
  port (
    clk         : in  std_logic; 
    trigger     : in  std_logic;
    trgDelaySel : in  std_logic_vector(getBusLines(16*MEMBLOCKS)-1 downto 0);
    trg_dly     : out std_logic
  );
end entity;

architecture arch of shift is
  -- Array de enlaces entre bloques de memoria
  type trsh_arr is array(MEMBLOCKS-1 downto 0) of 
                   std_logic_vector(15 downto 0);

  signal trsh_feedbackIn  : trsh_arr;
  signal trsh_feedbackOut : trsh_arr;
  signal trsh_link        : std_logic_vector(MEMBLOCKS downto 0);
  -- Multiplexor de salida
  signal muxOut: std_logic_vector(MEMBLOCKS*16 - 1 downto 0);

begin
  -- El trigger se inserta en el primer bloque de registros de desplazamiento.
  trsh_link(0) <= trigger;

  U0 : for i in 0 to MEMBLOCKS-1 generate
    -- El MSb de salida de cada bloque es el LSb de la entrada del siguiente
    trsh_link(i+1) <= trsh_feedbackOut(i)(15);
    --
    -- Bloques de registros de desplazamiento. Cada entrada se realimenta con
    -- su salida, desplazada un bit y concatenada con el bit mas alto del 
    -- bloque anterior
    --
    trsh_feedbackIn(i) <= trsh_feedbackOut(i)(14 downto 0) & trsh_link(i);
    SHF : shft16x8 port map (
      CLK => clk, 
      D   => trsh_feedbackIn(i),
      Q   => trsh_feedbackOut(i)
    );

    -- Las salidas de cada bloque se llevan a un gran muliplexor
    muxOut((i+1)*16-1 downto i*16) <= trsh_feedbackOut(i);
  end generate;

  trg_dly <= muxOut(to_integer(unsigned(trgDelaySel)));
  
end architecture;