--! @file        eca_tlu_auto.vhd
--  DesignUnit   eca_tlu_auto
--! @author      Wesley W. Terpstra <w.terpstra@gsi.de>
--! @date        15/04/2016
--! @version     2.0
--! @copyright   2016 GSI Helmholtz Centre for Heavy Ion Research GmbH
--!

--! @brief AUTOGENERATED WISHBONE-SLAVE CORE FOR eca_tlu.vhd
--!
--------------------------------------------------------------------------------
--! This library is free software; you can redistribute it and/or
--! modify it under the terms of the GNU Lesser General Public
--! License as published by the Free Software Foundation; either
--! version 3 of the License, or (at your option) any later version.
--!
--! This library is distributed in the hope that it will be useful,
--! but WITHOUT ANY WARRANTY; without even the implied warranty of
--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--! Lesser General Public License for more details.
--!
--! You should have received a copy of the GNU Lesser General Public
--! License along with this library. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------

-- ***********************************************************
-- ** WARNING - THIS IS AUTO-GENERATED CODE! DO NOT MODIFY! **
-- ***********************************************************
--
-- If you want to change the interface,
-- modify eca_tlu.xml and re-run 'python wbgenplus.py eca_tlu.xml' !

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.wbgenplus_pkg.all;
use work.genram_pkg.all;
use work.eca_tlu_auto_pkg.all;

entity eca_tlu_auto is
generic(
  g_num_inputs  : natural := 0  --Total number of inputs attached to the TLU
);
Port(
  clk_sys_i       : std_logic;                            -- Clock input for sys domain
  rst_sys_n_i     : std_logic;                            -- Reset input (active low) for sys domain
  error_i         : in  std_logic_vector(1-1 downto 0);   -- Error control
  stall_i         : in  std_logic_vector(1-1 downto 0);   -- flow control
  enable_o        : out std_logic_vector(1-1 downto 0);   -- Will this input generate timing events on an edge
  event_hi_o      : out std_logic_vector(32-1 downto 0);  -- Timing Event to generate (high word)
  event_lo_o      : out std_logic_vector(32-1 downto 0);  -- Timing Event to generate (low word), lowest bit is replaced with the edge of the transition
  input_select_o  : out std_logic_vector(8-1 downto 0);   -- Write the configuration of this input
  stable_o        : out std_logic_vector(32-1 downto 0);  -- Signal must be high/low for stable cycles to be counted as a valid transition
  write_o         : out std_logic_vector(1-1 downto 0);   -- Write register contents to TLU configuration
  
  slave_i         : in  t_wishbone_slave_in;
  slave_o         : out t_wishbone_slave_out

  
);
end eca_tlu_auto;

architecture rtl of eca_tlu_auto is

  signal s_pop, s_push    : std_logic;
  signal s_empty, s_full  : std_logic;
  signal r_e_wait         : std_logic;
  signal s_stall          : std_logic;
  signal s_valid          : std_logic;
  signal r_ack            : std_logic;
  signal r_err            : std_logic;
  signal s_e, s_w         : std_logic;
  signal s_d              : std_logic_vector(32-1 downto 0);
  signal s_s              : std_logic_vector(4-1 downto 0);
  signal s_a              : std_logic_vector(3-1 downto 0);
  signal s_a_ext, r_a_ext : std_logic_vector(5-1 downto 0);
  signal r_error          : std_logic_vector(1-1 downto 0)  := std_logic_vector(to_unsigned(0, 1));             -- Error
  signal s_error_i        : std_logic_vector(1-1 downto 0)  := (others => '0');                                 -- Error control
  signal s_stall_i        : std_logic_vector(1-1 downto 0)  := (others => '0');                                 -- flow control
  signal r_num_inputs     : std_logic_vector(8-1 downto 0)  := std_logic_vector(to_unsigned(g_num_inputs, 8));  -- Total number of inputs attached to the TLU
  signal r_input_select   : std_logic_vector(8-1 downto 0)  := (others => '0');                                 -- Write the configuration of this input
  signal r_enable         : std_logic_vector(1-1 downto 0)  := (others => '0');                                 -- Will this input generate timing events on an edge
  signal r_stable         : std_logic_vector(32-1 downto 0) := (others => '0');                                 -- Signal must be high/low for stable cycles to be counted as a valid transition
  signal r_event_hi       : std_logic_vector(32-1 downto 0) := (others => '0');                                 -- Timing Event to generate (high word)
  signal r_event_lo       : std_logic_vector(32-1 downto 0) := (others => '0');                                 -- Timing Event to generate (low word), lowest bit is replaced with the edge of the transition
  signal r_write          : std_logic_vector(1-1 downto 0)  := (others => '0');                                 -- Write register contents to TLU configuration


begin

  sp : wb_skidpad
  generic map(
    g_adrbits   => 3
  )
  Port map(
    clk_i        => clk_sys_i,
    rst_n_i      => rst_sys_n_i,
    push_i       => s_push,
    pop_i        => s_pop,
    full_o       => s_full,
    empty_o      => s_empty,
    adr_i        => slave_i.adr(4 downto 2),
    dat_i        => slave_i.dat,
    sel_i        => slave_i.sel,
    we_i         => slave_i.we,
    adr_o        => s_a,
    dat_o        => s_d,
    sel_o        => s_s,
    we_o         => s_w
  );

  validmux: with to_integer(unsigned(s_a_ext)) select
  s_valid <= 
  '1' when others;
  
  s_a_ext           <= s_a & "00";
  s_stall           <= s_full;
  s_push            <= slave_i.cyc and slave_i.stb and not s_stall;
 -- push if wb op not stalled
  s_e               <= not (s_empty or  r_e_wait or stall_i(0)) ;-- op enable when skidpad not empty and not waiting for completion
  s_pop             <= (s_e or          r_e_wait) and s_valid; -- if op enabled or waiting for completion, pop on valid from entity
  slave_o.stall     <= s_stall;
  
  s_error_i       <= error_i;
  s_stall_i       <= stall_i;
  input_select_o  <= r_input_select;
  enable_o        <= r_enable;
  stable_o        <= r_stable;
  event_hi_o      <= r_event_hi;
  event_lo_o      <= r_event_lo;
  write_o         <= r_write;
  
  slave : process(clk_sys_i)
  begin
    if rising_edge(clk_sys_i) then
      if(rst_sys_n_i = '0') then
        r_e_wait <= '0';
        r_a_ext  <=  (others => '0');
        r_error       <= std_logic_vector(to_unsigned(0, 1));
        r_num_inputs  <= std_logic_vector(to_unsigned(g_num_inputs, 8));
        r_write       <= (others => '0');
      else
        r_a_ext  <= s_a_ext;
        r_e_wait <= (r_e_wait or s_e) and not s_valid;
        r_ack    <= s_pop and not (error_i(0) or r_error(0));
        r_err    <= s_pop and     (error_i(0) or r_error(0));
        slave_o.ack <= r_ack;
        slave_o.err <= r_err;
        
        r_error <= (others => '0');
        r_write <= (others => '0');
        
        
        if(s_e = '1') then
          if(s_w = '1') then
            -- WISHBONE WRITE ACTIONS
            case to_integer(unsigned(s_a_ext)) is
              when c_input_select_RW  => r_input_select <= f_wb_wr(r_input_select, s_d, s_s, "owr");  -- 
              when c_enable_RW        => r_enable       <= f_wb_wr(r_enable, s_d, s_s, "owr");        -- 
              when c_stable_RW        => r_stable       <= f_wb_wr(r_stable, s_d, s_s, "owr");        -- 
              when c_event_hi_RW      => r_event_hi     <= f_wb_wr(r_event_hi, s_d, s_s, "owr");      -- 
              when c_event_lo_RW      => r_event_lo     <= f_wb_wr(r_event_lo, s_d, s_s, "owr");      -- 
              when c_write_OWR        => r_write        <= f_wb_wr(r_write, s_d, s_s, "owr");         -- 
              when others             => r_error        <= "1";
            end case;
          else
            -- WISHBONE READ ACTIONS
            case to_integer(unsigned(s_a_ext)) is
              when c_num_inputs_GET   => null;
              when c_input_select_RW  => null;
              when c_enable_RW        => null;
              when c_stable_RW        => null;
              when c_event_hi_RW      => null;
              when c_event_lo_RW      => null;
              when others             => r_error <= "1";
            end case;
          end if; -- s_w
        end if; -- s_e
        
        case to_integer(unsigned(r_a_ext)) is
          when c_num_inputs_GET   => slave_o.dat  <= std_logic_vector(resize(unsigned(r_num_inputs), slave_o.dat'length));    -- 
          when c_input_select_RW  => slave_o.dat  <= std_logic_vector(resize(unsigned(r_input_select), slave_o.dat'length));  -- 
          when c_enable_RW        => slave_o.dat  <= std_logic_vector(resize(unsigned(r_enable), slave_o.dat'length));        -- 
          when c_stable_RW        => slave_o.dat  <= std_logic_vector(resize(unsigned(r_stable), slave_o.dat'length));        -- 
          when c_event_hi_RW      => slave_o.dat  <= std_logic_vector(resize(unsigned(r_event_hi), slave_o.dat'length));      -- 
          when c_event_lo_RW      => slave_o.dat  <= std_logic_vector(resize(unsigned(r_event_lo), slave_o.dat'length));      -- 
          when others             => slave_o.dat  <= (others => 'X');
        end case;

        
      end if; -- rst
    end if; -- clk edge
  end process;

end rtl;
