--
-- Common Interface Components
--
-- (C) 2006 Alpha Data
-- 
-- Entities for Common Interface components
--
-- control_register
-- status_register
-- interrupt_register
-- internal_memory
-- external_memory
-- locallink

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;

library work;
use work.common_interface.all;

entity control_register is
  
  generic (
    width     : integer := 32;
    addr      : integer := 0;
    sys_width : integer := system_width);
  port (
    clk          : in  std_logic;
    rst          : in  std_logic;
    system_in    : in  std_logic_vector(sys_width-1 downto 0);
    system_out   : out std_logic_vector(sys_width-1 downto 0);
    control_data : out std_logic_vector(width-1 downto 0);
    control_wstb : out std_logic);

end control_register;

architecture rtl of control_register is

  signal lclk       : std_logic;
  signal ctrl_bus   : std_logic_vector(ctrl_bus_width-1 downto 0);
  signal status_bus : std_logic_vector(status_bus_width-1 downto 0);
  signal irq_bus    : std_logic_vector(interrupt_bus_width-1 downto 0);
  signal bram_bus   : std_logic_vector(bram_bus_width-1 downto 0);
  signal locallinks : std_logic_vector(4*locallink_type_width-1 downto 0);
  signal extrams    : std_logic_vector(6*extmem_type_width-1 downto 0);

  signal ctrl_bus_sig : ctrl_bus_type;

  signal wstb_reg,wstb_reg1,wstb_reg2 : std_logic;

  signal control_reg : std_logic_vector(width-1 downto 0);
  
begin  -- rtl

  split0 : split_system_signal(
    system     => system_in,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus,
    locallinks => locallinks,
    extrams    => extrams);

  merge0 : build_system_signal (
    system     => system_out,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus,
    locallinks => locallinks,
    extrams    => extrams);

  ctrl_bus_sig <= slv_to_ctrl_bus (ctrl_bus);

  ctrl_reg : process (clk, rst)
  begin  -- process ctrl_reg
    if rst = '1' then                   -- asynchronous reset (active low)
      control_data <= (others => '0');
      control_wstb <= '0';
      wstb_reg2 <= '0';
      wstb_reg1 <= '0';
    elsif clk'event and clk = '1' then  -- rising clock edge
      control_data <= control_reg;
      wstb_reg1 <= wstb_reg;
      wstb_reg2 <= wstb_reg1;
      control_wstb <= wstb_reg1 and not wstb_reg2;
    end if;
  end process ctrl_reg;

  decode_addr: process (lclk)
  begin  -- process decode_addr
    if lclk'event and lclk = '1' then  -- rising clock edge
      if ctrl_bus_sig.addr = CONV_STD_LOGIC_VECTOR(addr, reg_addr_width) and ctrl_bus_sig.wstb = '1' then        
        wstb_reg <= '1';
        control_reg <= ctrl_bus_sig.data(width-1 downto 0);
      else
        wstb_reg <= '0';
      end if;
    end if;
  end process decode_addr;
  

end rtl;


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;

library work;
use work.common_interface.all;

entity status_register is
  
  generic (
    width     : integer := 32;
    addr      : integer := 0;
    sys_width : integer := system_width);
  port (
    clk         : in  std_logic;
    rst         : in  std_logic;
    system_in   : in  std_logic_vector(sys_width-1 downto 0);
    system_out  : out std_logic_vector(sys_width-1 downto 0);
    status_data : in  std_logic_vector(width-1 downto 0));

end status_register;

architecture rtl of status_register is

  signal lclk       : std_logic;
  signal ctrl_bus   : std_logic_vector(ctrl_bus_width-1 downto 0);
  signal status_bus : std_logic_vector(status_bus_width-1 downto 0);
  signal irq_bus    : std_logic_vector(interrupt_bus_width-1 downto 0);
  signal bram_bus   : std_logic_vector(bram_bus_width-1 downto 0);
  signal locallinks : std_logic_vector(4*locallink_type_width-1 downto 0);
  signal extrams    : std_logic_vector(6*extmem_type_width-1 downto 0);

  signal status_bus_in                         : std_logic_vector(status_bus_width-1 downto 0);
  signal status_bus_sig_in, status_bus_sig_out : status_bus_type;

  signal status_signal : std_logic_vector(width-1 downto 0);

  
begin  -- rtl

  split0 : split_system_signal(
    system     => system_in,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus_in,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus,
    locallinks => locallinks,
    extrams    => extrams);

  merge0 : build_system_signal (
    system     => system_out,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus,
    locallinks => locallinks,
    extrams    => extrams);



  status_bus_sig_in <= slv_to_status_bus (status_bus_in);
  status_bus        <= status_bus_to_slv(status_bus_sig_out);

  status_bus_sig_out.addr <= status_bus_sig_in.addr;
  status_bus_sig_out.data <= EXT(status_signal, reg_width) when status_bus_sig_in.addr = CONV_STD_LOGIC_VECTOR(addr,reg_addr_width) else status_bus_sig_in.data;

  status_reg : process (lclk, rst)
  begin  -- process ctrl_reg
    if rst = '1' then                     -- asynchronous reset (active low)
      status_signal <= (others => '0');
    elsif lclk'event and lclk = '1' then  -- rising clock edge
      status_signal <= status_data;
    end if;
  end process status_reg;
  

end rtl;


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;

library work;
use work.common_interface.all;

entity readable_control_register is
  
  generic (
    width     : integer := 32;
    addr      : integer := 0;
    sys_width : integer := system_width);
  port (
    clk          : in  std_logic;
    rst          : in  std_logic;
    system_in    : in  std_logic_vector(sys_width-1 downto 0);
    system_out   : out std_logic_vector(sys_width-1 downto 0);
    control_data : out std_logic_vector(width-1 downto 0);
    control_wstb : out std_logic);

end readable_control_register;

architecture rtl of readable_control_register is

  signal system_int : std_logic_vector(sys_width-1 downto 0);
  signal data : std_logic_vector(width-1 downto 0);
  signal status_data : std_logic_vector(width-1 downto 0);
  
begin  -- rtl

  creg0 : control_register
    generic map (
      width => width, addr => addr)
    port map (
      clk          => clk, rst => rst, system_in => system_in, system_out => system_int,
      control_data => data, control_wstb => control_wstb);
  
  sreg0 : status_register
    generic map (
      width => width, addr => addr)
    port map (
      clk         => clk, rst => rst, system_in => system_int, system_out => system_out,
      status_data => status_data);

  process (clk)
  begin  -- process
    if clk'event and clk = '1' then  -- rising clock edge
      status_data <= data;
    end if;
  end process;
  
  control_data <= data;
  
end rtl;



library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;

library work;
use work.common_interface.all;

entity interrupt_register is
  
  generic (
    width     : integer := 32;
    sys_width : integer := system_width);
  port (
    clk               : in  std_logic;
    rst               : in  std_logic;
    system_in         : in  std_logic_vector(sys_width-1 downto 0);
    system_out        : out std_logic_vector(sys_width-1 downto 0);
    interrupt_enable  : out std_logic_vector(width-1 downto 0);
    interrupt_trigger : in  std_logic_vector(width-1 downto 0));

end interrupt_register;

architecture rtl of interrupt_register is

  signal lclk       : std_logic;
  signal ctrl_bus   : std_logic_vector(ctrl_bus_width-1 downto 0);
  signal status_bus : std_logic_vector(status_bus_width-1 downto 0);
  signal irq_bus_in : std_logic_vector(interrupt_bus_width-1 downto 0);
  signal bram_bus   : std_logic_vector(bram_bus_width-1 downto 0);
  signal locallinks : std_logic_vector(4*locallink_type_width-1 downto 0);
  signal extrams    : std_logic_vector(6*extmem_type_width-1 downto 0);

  signal irq_bus_out     : std_logic_vector(interrupt_bus_width-1 downto 0);
  signal irq_in, irq_out : interrupt_bus_type;

  signal interrupt_reg : std_logic_vector(width-1 downto 0);

  
begin  -- rtl

  split0 : split_system_signal(
    system     => system_in,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus_in,
    bram_bus   => bram_bus,
    locallinks => locallinks,
    extrams    => extrams);

  merge0 : build_system_signal (
    system     => system_out,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus_out,
    bram_bus   => bram_bus,
    locallinks => locallinks,
    extrams    => extrams);

  irq_in      <= slv_to_irq_bus (irq_bus_in);
  irq_bus_out <= irq_bus_to_slv(irq_out);

  irq_out.ier <= (others => '0');

  status_reg : process (lclk, rst)
  begin  -- process ctrl_reg
    if rst = '1' then                     -- asynchronous reset (active low)
      interrupt_reg    <= (others => '0');
      interrupt_enable <= (others => '0');
      irq_out.isr      <= (others => '0');
    elsif lclk'event and lclk = '1' then  -- rising clock edge
      for i in 0 to width-1 loop
        if irq_in.ier(i) = '1' then
          if irq_in.isr(i) = '1' then     -- write '1' to clear interrupt
            irq_out.isr(i) <= '0';
          else
            if interrupt_reg(i) = '1' then
              irq_out.isr(i) <= '1';
            end if;
          end if;
        end if;
      end loop;  -- i
      interrupt_reg    <= interrupt_trigger;
      interrupt_enable <= irq_in.ier(width-1 downto 0);
    end if;
  end process status_reg;
  

end rtl;






--
-- 64 bit wide block RAM, selectable depth
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;


-- synthesis translate_off
library UNISIM;
use UNISIM.all;
-- synthesis translate_on


entity ramb16_64_64 is
  
  generic (
    depth : natural := 14);

  port (
    wea   : in  std_logic_vector(7 downto 0);
    ena   : in  std_logic;
    ssra  : in  std_logic;
    clka  : in  std_logic;
    addra : in  std_logic_vector(depth-1 downto 0);
    dia   : in  std_logic_vector(63 downto 0);
    doa   : out std_logic_vector(63 downto 0);
    web   : in  std_logic_vector(7 downto 0);
    enb   : in  std_logic;
    ssrb  : in  std_logic;
    clkb  : in  std_logic;
    addrb : in  std_logic_vector(depth-1 downto 0);
    dib   : in  std_logic_vector(63 downto 0);
    dob   : out std_logic_vector(63 downto 0));

end ramb16_64_64;

architecture rtl of ramb16_64_64 is

  component RAMB16_S9_S9
    generic (
      WRITE_MODE_A : string;
      WRITE_MODE_B : string);
    port (
      wea   : in  std_logic;
      ena   : in  std_logic;
      ssra  : in  std_logic;
      clka  : in  std_logic;
      addra : in  std_logic_vector(10 downto 0);
      dia   : in  std_logic_vector(7 downto 0);
      doa   : out std_logic_vector(7 downto 0);
      dipa  : in  std_logic_vector(0 downto 0);
      dopa  : out std_logic_vector(0 downto 0);
      web   : in  std_logic;
      enb   : in  std_logic;
      ssrb  : in  std_logic;
      clkb  : in  std_logic;
      addrb : in  std_logic_vector(10 downto 0);
      dib   : in  std_logic_vector(7 downto 0);
      dob   : out std_logic_vector(7 downto 0);
      dipb  : in  std_logic_vector(0 downto 0);
      dopb  : out std_logic_vector(0 downto 0)
      );
  end component;

  component RAMB16_S4_S4
    generic (
      WRITE_MODE_A : string;
      WRITE_MODE_B : string);
    port (
      wea   : in  std_logic;
      ena   : in  std_logic;
      ssra  : in  std_logic;
      clka  : in  std_logic;
      addra : in  std_logic_vector(11 downto 0);
      dia   : in  std_logic_vector(3 downto 0);
      doa   : out std_logic_vector(3 downto 0);
      web   : in  std_logic;
      enb   : in  std_logic;
      ssrb  : in  std_logic;
      clkb  : in  std_logic;
      addrb : in  std_logic_vector(11 downto 0);
      dib   : in  std_logic_vector(3 downto 0);
      dob   : out std_logic_vector(3 downto 0));
  end component;

  component RAMB16_S2_S2
    generic (
      WRITE_MODE_A : string;
      WRITE_MODE_B : string);
    port (
      wea   : in  std_logic;
      ena   : in  std_logic;
      ssra  : in  std_logic;
      clka  : in  std_logic;
      addra : in  std_logic_vector(12 downto 0);
      dia   : in  std_logic_vector(1 downto 0);
      doa   : out std_logic_vector(1 downto 0);
      web   : in  std_logic;
      enb   : in  std_logic;
      ssrb  : in  std_logic;
      clkb  : in  std_logic;
      addrb : in  std_logic_vector(12 downto 0);
      dib   : in  std_logic_vector(1 downto 0);
      dob   : out std_logic_vector(1 downto 0));
  end component;

  component RAMB16_S1_S1
    generic (
      WRITE_MODE_A : string;
      WRITE_MODE_B : string);
    port (
      wea   : in  std_logic;
      ena   : in  std_logic;
      ssra  : in  std_logic;
      clka  : in  std_logic;
      addra : in  std_logic_vector(13 downto 0);
      dia   : in  std_logic_vector(0 downto 0);
      doa   : out std_logic_vector(0 downto 0);
      web   : in  std_logic;
      enb   : in  std_logic;
      ssrb  : in  std_logic;
      clkb  : in  std_logic;
      addrb : in  std_logic_vector(13 downto 0);
      dib   : in  std_logic_vector(0 downto 0);
      dob   : out std_logic_vector(0 downto 0));
  end component;

  signal addra_int : std_logic_vector(19 downto 0);
  signal addrb_int : std_logic_vector(19 downto 0);
  
begin  -- rtl

  addra_int <= EXT(addra, 20);
  addrb_int <= EXT(addrb, 20);

  gen_depth_lt_12 : if depth < 12 generate
    gen_ramb99 : for i in 0 to 7 generate
      bram_i : RAMB16_S9_S9
        generic map (
          WRITE_MODE_A => "READ_FIRST",
          WRITE_MODE_B => "READ_FIRST")
        port map (
          wea   => wea(i),
          ena   => ena,
          ssra  => ssra,
          clka  => clka,
          addra => addra_int(10 downto 0),
          dia   => dia(8*i+7 downto 8*i),
          dipa  => "0",
          doa   => doa(8*i+7 downto 8*i),
          web   => web(i),
          enb   => enb,
          ssrb  => ssrb,
          clkb  => clkb,
          addrb => addrb_int(10 downto 0),
          dib   => dib(8*i+7 downto 8*i),
          dipb  => "0",
          dob   => dob(8*i+7 downto 8*i));
    end generate gen_ramb99;
  end generate gen_depth_lt_12;

  gen_depth_eq_12 : if depth = 12 generate
    gen_ramb44x2 : for i in 0 to 7 generate
      gen_ramb44 : for j in 0 to 1 generate
        bram_i : RAMB16_S4_S4
          generic map (
            WRITE_MODE_A => "READ_FIRST",
            WRITE_MODE_B => "READ_FIRST")
          port map (
            wea   => wea(i),
            ena   => ena,
            ssra  => ssra,
            clka  => clka,
            addra => addra_int(11 downto 0),
            dia   => dia(8*i+4*j+3 downto 8*i+4*j),
            doa   => doa(8*i+4*j+3 downto 8*i+4*j),
            web   => web(i),
            enb   => enb,
            ssrb  => ssrb,
            clkb  => clkb,
            addrb => addrb_int(11 downto 0),
            dib   => dib(8*i+4*j+3 downto 8*i+4*j),
            dob   => dob(8*i+4*j+3 downto 8*i+4*j));
      end generate gen_ramb44;
    end generate gen_ramb44x2;
  end generate gen_depth_eq_12;

  gen_depth_eq_13 : if depth = 13 generate
    gen_ramb22x4 : for i in 0 to 7 generate
      gen_ramb22 : for j in 0 to 3 generate
        bram_i : RAMB16_S2_S2
          generic map (
            WRITE_MODE_A => "READ_FIRST",
            WRITE_MODE_B => "READ_FIRST")
          port map (
            wea   => wea(i),
            ena   => ena,
            ssra  => ssra,
            clka  => clka,
            addra => addra_int(12 downto 0),
            dia   => dia(8*i+2*j+1 downto 8*i+2*j),
            doa   => doa(8*i+2*j+1 downto 8*i+2*j),
            web   => web(i),
            enb   => enb,
            ssrb  => ssrb,
            clkb  => clkb,
            addrb => addrb_int(12 downto 0),
            dib   => dib(8*i+2*j+1 downto 8*i+2*j),
            dob   => dob(8*i+2*j+1 downto 8*i+2*j));
      end generate gen_ramb22;
    end generate gen_ramb22x4;
  end generate gen_depth_eq_13;

  gen_depth_eq_14 : if depth = 14 generate
    gen_ramb11x8 : for i in 0 to 7 generate
      gen_ramb11 : for j in 0 to 7 generate
        bram_i : RAMB16_S1_S1
          generic map (
            WRITE_MODE_A => "READ_FIRST",
            WRITE_MODE_B => "READ_FIRST")
          port map (
            wea   => wea(i),
            ena   => ena,
            ssra  => ssra,
            clka  => clka,
            addra => addra_int(13 downto 0),
            dia   => dia(8*i+j downto 8*i+j),
            doa   => doa(8*i+j downto 8*i+j),
            web   => web(i),
            enb   => enb,
            ssrb  => ssrb,
            clkb  => clkb,
            addrb => addrb_int(13 downto 0),
            dib   => dib(8*i+j downto 8*i+j),
            dob   => dob(8*i+j downto 8*i+j));
      end generate gen_ramb11;
    end generate gen_ramb11x8;
  end generate gen_depth_eq_14;


end rtl;


--
-- Dual Port Block RAM Interface
--


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;


library work;
use work.common_interface.all;


entity internal_memory is
  generic (
    width     : integer := 8;
    depth     : integer := 14;
    bank_id   : integer := 0;
    sys_width : integer := system_width);
  port (
    clk        : in  std_logic;
    rst        : in  std_logic;
    system_in  : in  std_logic_vector(sys_width-1 downto 0);
    system_out : out std_logic_vector(sys_width-1 downto 0);
    w          : in  std_logic;
    a          : in  std_logic_vector(depth-1 downto 0);
    d          : in  std_logic_vector(width-1 downto 0);
    q          : out std_logic_vector(width-1 downto 0));
end internal_memory;

architecture rtl of internal_memory is

  constant bram64_depth      : natural := depth-6+log2(width);
  constant addr_decode_width : natural := 6-log2(width);

  component ramb16_64_64
    generic (
      depth : natural := 14);

    port (
      wea   : in  std_logic_vector(7 downto 0);
      ena   : in  std_logic;
      ssra  : in  std_logic;
      clka  : in  std_logic;
      addra : in  std_logic_vector(depth-1 downto 0);
      dia   : in  std_logic_vector(63 downto 0);
      doa   : out std_logic_vector(63 downto 0);
      web   : in  std_logic_vector(7 downto 0);
      enb   : in  std_logic;
      ssrb  : in  std_logic;
      clkb  : in  std_logic;
      addrb : in  std_logic_vector(depth-1 downto 0);
      dib   : in  std_logic_vector(63 downto 0);
      dob   : out std_logic_vector(63 downto 0));
  end component;

  signal addra_int    : std_logic_vector(bram64_depth-1 downto 0);
  signal d_int, q_int : std_logic_vector(63 downto 0);
  signal addra_decode : std_logic_vector(addr_decode_width downto 0);
  signal wea          : std_logic_vector(7 downto 0);



  signal lclk         : std_logic;
  signal ctrl_bus     : std_logic_vector(ctrl_bus_width-1 downto 0);
  signal status_bus   : std_logic_vector(status_bus_width-1 downto 0);
  signal irq_bus      : std_logic_vector(interrupt_bus_width-1 downto 0);
  signal bram_bus_in  : std_logic_vector(bram_bus_width-1 downto 0);
  signal bram_bus_out : std_logic_vector(bram_bus_width-1 downto 0);
  signal locallinks   : std_logic_vector(4*locallink_type_width-1 downto 0);
  signal extrams      : std_logic_vector(6*extmem_type_width-1 downto 0);

  signal bbus_in, bbus_out : bram_bus_type;
  signal bwe               : std_logic_vector(7 downto 0);
  signal bq, q_reg         : std_logic_vector(bram_width-1 downto 0);
  
begin  -- rtl
  
  assert width = 8 or width = 16 or width = 32 or width = 64 report "Illegal Memory Width (must be 8,16,32 or 64)" severity warning;
  
  split0 : split_system_signal(
    system     => system_in,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus_in,
    locallinks => locallinks,
    extrams    => extrams);

  merge0 : build_system_signal (
    system     => system_out,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus_out,
    locallinks => locallinks,
    extrams    => extrams);

  bbus_in      <= slv_to_bram_bus (bram_bus_in);
  bram_bus_out <= bram_bus_to_slv(bbus_out);


  gen_d_int : for i in 0 to 64/width-1 generate
    d_int((i+1)*width-1 downto i*width) <= d;
  end generate gen_d_int;

  gen_dout_width64 : if width = 64 generate
    q   <= q_int;
    wea <= (others => w);
  end generate gen_dout_width64;

  addra_int <= a(bram64_depth-1+addr_decode_width downto addr_decode_width);

  gen_dout_widthn64 : if width /= 64 generate
    process (clk)
    begin  -- process
      if clk'event and clk = '1' then   -- rising clock edge
        addra_decode(addr_decode_width-1 downto 0) <= a(addr_decode_width-1 downto 0);
      end if;
    end process;

    gen_wea : for i in 0 to width/8-1 generate
      gen_wea1 : for j in 0 to 64/width-1 generate
        wea(j*width/8+i) <= w when CONV_INTEGER(a(addr_decode_width-1 downto 0)) = j else '0';
      end generate gen_wea1;
    end generate gen_wea;
  end generate gen_dout_widthn64;

  gen_width_eq_32 : if width = 32 generate
    q <= q_int(31 downto 0) when addra_decode(0) = '0' else q_int(63 downto 32);
  end generate gen_width_eq_32;

  gen_width_eq_16 : if width = 16 generate
    mux_q : process (q_int, addra_decode)
    begin  -- process mux_q
      case addra_decode(1 downto 0) is
        when "00"   => q <= q_int(15 downto 0);
        when "01"   => q <= q_int(31 downto 16);
        when "10"   => q <= q_int(47 downto 32);
        when "11"   => q <= q_int(63 downto 48);
        when others => q <= (others => '0');
      end case;
    end process mux_q;
  end generate gen_width_eq_16;

  gen_width_eq_8 : if width = 8 generate
    mux_q : process (q_int, addra_decode)
    begin  -- process mux_q
      case addra_decode(2 downto 0) is
        when "000"  => q <= q_int(7 downto 0);
        when "001"  => q <= q_int(15 downto 8);
        when "010"  => q <= q_int(23 downto 16);
        when "011"  => q <= q_int(31 downto 24);
        when "100"  => q <= q_int(39 downto 32);
        when "101"  => q <= q_int(47 downto 40);
        when "110"  => q <= q_int(55 downto 48);
        when "111"  => q <= q_int(63 downto 56);
        when others => q <= (others => '0');
      end case;
    end process mux_q;
  end generate gen_width_eq_8;


  bram_i : ramb16_64_64
    generic map (
      depth => bram64_depth)
    port map (
      wea   => wea,
      ena   => '1',
      ssra  => rst,
      clka  => clk,
      addra => addra_int,
      dia   => d_int,
      doa   => q_int,
      web   => bwe,
      enb   => '1',
      ssrb  => rst,
      clkb  => lclk,
      addrb => bbus_in.addr(bram64_depth-1 downto 0),
      dib   => bbus_in.data,
      dob   => bq);


  bwe        <= "11111111" when CONV_STD_LOGIC_VECTOR(bank_id, bram_id_width) = bbus_in.id and bbus_in.wstb = '1' else (others => '0');
  bbus_out.q <= bq         when CONV_STD_LOGIC_VECTOR(bank_id, bram_id_width) = bbus_in.id else q_reg;


  reg_bram_bus0 : process (lclk, rst)
  begin  -- process reg_bram_bus0
    if rst = '1' then                     -- asynchronous reset (active low)
      bbus_out.data <= (others => '0');
      bbus_out.addr <= (others => '0');
      bbus_out.id   <= (others => '0');
      bbus_out.wstb <= '0';
      bbus_out.rstb <= '0';
      bbus_out.qv   <= '0';
      q_reg         <= (others => '0');
    elsif lclk'event and lclk = '1' then  -- rising clock edge
      bbus_out.data <= bbus_in.data;
      bbus_out.addr <= bbus_in.addr;
      bbus_out.id   <= bbus_in.id;
      bbus_out.wstb <= bbus_in.wstb;
      bbus_out.rstb <= bbus_in.rstb;
      q_reg         <= bbus_in.q;
      if CONV_STD_LOGIC_VECTOR(bank_id, bram_id_width) = bbus_in.id then
        bbus_out.qv <= bbus_in.rstb;
      else
        bbus_out.qv <=  bbus_in.qv;
      end if;
    end if;
  end process reg_bram_bus0;
  

end rtl;



library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;

library work;
use work.common_interface.all;

entity external_memory is
  
  generic (
    width     : integer := 64;
    depth     : integer := 26;
    bank_id   : integer := 0;
    sys_width : integer := system_width);
  port (
    clk        : in  std_logic;
    rst        : in  std_logic;
    system_in  : in  std_logic_vector(sys_width-1 downto 0);
    system_out : out std_logic_vector(sys_width-1 downto 0);
    w          : in  std_logic;
    r          : in  std_logic;
    a          : in  std_logic_vector(depth-1 downto 0);
    d          : in  std_logic_vector(width-1 downto 0);
    q          : out std_logic_vector(width-1 downto 0);
    qv         : out std_logic;
    full       : out std_logic;
    req        : in  std_logic;
    gnt        : out std_logic);

end external_memory;

architecture rtl of external_memory is

  signal lclk        : std_logic;
  signal ctrl_bus    : std_logic_vector(ctrl_bus_width-1 downto 0);
  signal status_bus  : std_logic_vector(status_bus_width-1 downto 0);
  signal irq_bus     : std_logic_vector(interrupt_bus_width-1 downto 0);
  signal bram_bus    : std_logic_vector(bram_bus_width-1 downto 0);
  signal locallinks  : std_logic_vector(4*locallink_type_width-1 downto 0);
  signal extrams_in  : std_logic_vector(6*extmem_type_width-1 downto 0);
  signal extrams_out : std_logic_vector(6*extmem_type_width-1 downto 0);

  signal extram_in, extram_out : extmem_type;
  
begin  -- rtl

  split0 : split_system_signal(
    system     => system_in,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus,
    locallinks => locallinks,
    extrams    => extrams_in);

  merge0 : build_system_signal (
    system     => system_out,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus,
    locallinks => locallinks,
    extrams    => extrams_out);

  gen_mem_routethrough : for i in 0 to 5 generate
    gen_through : if i /= bank_id generate
      extrams_out(extmem_type_width*(i+1)-1 downto extmem_type_width*i) <= extrams_in(extmem_type_width*(i+1)-1 downto extmem_type_width*i);
    end generate gen_through;
    gen_ram_if : if i = bank_id generate
      extram_in                                                         <= slv_to_extmem_type(extrams_in(extmem_type_width*(i+1)-1 downto extmem_type_width*i));
      extrams_out(extmem_type_width*(i+1)-1 downto extmem_type_width*i) <= extmem_type_to_slv(extram_out);
    end generate gen_ram_if;
  end generate gen_mem_routethrough;

  q    <= extram_in.q(width-1 downto 0);
  qv   <= extram_in.qv;
  full <= extram_in.full;
  gnt  <= extram_in.gnt;

  extram_out.w   <= w;
  extram_out.r   <= r;
  extram_out.a   <= EXT(a, extmem_addr_width);
  extram_out.d   <= EXT(d, extmem_width);
  extram_out.req <= req;
  
end rtl;




library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;

library work;
use work.common_interface.all;

entity locallink is
  
  generic (
    link_id   : integer := 0;
    sys_width : integer := system_width);
  port (
    clk        : in  std_logic;
    rst        : in  std_logic;
    system_in  : in  std_logic_vector(sys_width-1 downto 0);
    system_out : out std_logic_vector(sys_width-1 downto 0);
    tx_src_rdy : in  std_logic;
    tx_dst_rdy : out std_logic;
    tx_data    : in  std_logic_vector(link_width-1 downto 0);
    tx_sof     : in  std_logic;
    tx_eof     : in  std_logic;
    rx_data    : out std_logic_vector(link_width-1 downto 0);
    rx_src_rdy : out std_logic;
    rx_sof     : out std_logic;
    rx_eof     : out std_logic);

end locallink;

architecture rtl of locallink is

  signal lclk           : std_logic;
  signal ctrl_bus       : std_logic_vector(ctrl_bus_width-1 downto 0);
  signal status_bus     : std_logic_vector(status_bus_width-1 downto 0);
  signal irq_bus        : std_logic_vector(interrupt_bus_width-1 downto 0);
  signal bram_bus       : std_logic_vector(bram_bus_width-1 downto 0);
  signal locallinks_in  : std_logic_vector(4*locallink_type_width-1 downto 0);
  signal locallinks_out : std_logic_vector(4*locallink_type_width-1 downto 0);
  signal extrams        : std_logic_vector(6*extmem_type_width-1 downto 0);

  signal link_in, link_out : locallink_type;
  
begin  -- rtl

  split0 : split_system_signal(
    system     => system_in,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus,
    locallinks => locallinks_in,
    extrams    => extrams);

  merge0 : build_system_signal (
    system     => system_out,
    lclk       => lclk,
    ctrl_bus   => ctrl_bus,
    status_bus => status_bus,
    irq_bus    => irq_bus,
    bram_bus   => bram_bus,
    locallinks => locallinks_out,
    extrams    => extrams);

  gen_routethrough : for i in 0 to 3 generate
    gen_through : if i /= link_id generate
      locallinks_out(locallink_type_width*(i+1)-1 downto locallink_type_width*i) <= locallinks_in(locallink_type_width*(i+1)-1 downto locallink_type_width*i);
    end generate gen_through;
    gen_ram_if : if i = link_id generate
      link_in                                                                    <= slv_to_locallink_type(locallinks_in(locallink_type_width*(i+1)-1 downto locallink_type_width*i));
      locallinks_out(locallink_type_width*(i+1)-1 downto locallink_type_width*i) <= locallink_type_to_slv(link_out);
    end generate gen_ram_if;
  end generate gen_routethrough;

  tx_dst_rdy <= link_in.tx_dst_rdy;
  rx_data <= link_in.rx_data;
  rx_src_rdy <= link_in.rx_src_rdy;
  rx_sof <= link_in.rx_sof;
  rx_eof <= link_in.rx_eof;

  link_out.tx_src_rdy <= tx_src_rdy;
  link_out.tx_data <= tx_data;
  link_out.tx_sof <= tx_sof;
  link_out.tx_eof <= tx_eof;
  
  
end rtl;
