----------------------------------------------------------------------------------
-- Company:        CERN, BE-CO-HT
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    14:07:55 11/28/2011 
-- Design Name:    Trigger registers
-- Module Name:    trigger - Behavioral 
-- Project Name:   CTDAH
-- Target Devices: Spartan 6
-- Tool versions: 
-- Description:    Trigger module registers for interfacing easily with
--                 wishbone modules
--
-----------------------------------------------------------
--  Configuration process 
-----------------------------------------------------------
--  1.- CTR0: disable EN, EN_T
--  2.- CTR1: set MinPL, MaxPL
--  3.- CTR0: set CGM, CPL
--  4.- RAM0: set CLR_TT
--  5.- CTR0: enable EN, EN_TT, disable CLR_TT
-----------------------------------------------------------
--  Recommended masks to use for the steps                  
--  CTR0_step1     X"xxxxxxYY"     where Y is "yyy0" 
--  CTR0_step2     X"xxxxxxYY"     where Y is "yyy0"
--  CTR1_step3     X"xxxxxxxx"
--  RAM0_step4     X"xxxxxxxZ"     where Z is "zz1z"
--  CTR0_step5     X"xxxxxxYY"     where Y is "yyy1"
-----------------------------------------------------------
--
-- Dependencies:   none
--
-- Revision: 
-- Revision 0.1
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

library work;
use work.ctdah_pkg.ALL;
use work.trigger_pkg.ALL;

entity trigger_regs is
port (
       wb_rst_i  : in   STD_LOGIC;
       wb_clk_i  : in   STD_LOGIC;
       wb_stb_i  : in   STD_LOGIC;
       wb_cyc_i  : in   STD_LOGIC;
       wb_ack_o  : out  STD_LOGIC;
       wb_err_o  : out  STD_LOGIC;
       wb_rty_o  : out  STD_LOGIC;
       wb_we_i   : in   STD_LOGIC;
       wb_sel_i  : in   STD_LOGIC_VECTOR (3  downto 0);
       wb_data_i : in   STD_LOGIC_VECTOR (31 downto 0);
       wb_data_o : out  STD_LOGIC_VECTOR (31 downto 0);
       wb_addr_i : in   STD_LOGIC_VECTOR (2  downto 0);

       utc_i     : in  STD_LOGIC_VECTOR(g_RAMTT_DATA_WIDTH*8 - 1 downto 0);

       CTR0_o    : out  r_CTR0;
       CTR1_o    : out  r_CTR1;
       CTR2_i    : in   r_CTR2;
       RAM0_o    : out  r_RAM0;
       RAM1_i    : in   r_RAM1;
       RAM2_o    : out  r_RAM2
     );
end trigger_regs;

architecture Behavioral of trigger_regs is


  type RAM_fsm is (R0_RESET,
                   S0_IDLE,
                   S1_READ_B0,
                   S2_READ_B1,
                   S3_READ_B2,
                   S4_READ_B3);

  signal RAMstate         : RAM_fsm;

  signal s_wb_ack    : STD_LOGIC;
  signal s_wb_err    : STD_LOGIC;
  signal s_wb_rty    : STD_LOGIC;
  signal s_wb_data_o : STD_LOGIC_VECTOR (31 downto 0);

  signal s_CTR0      : r_CTR0;
  signal s_CTR1      : r_CTR1;
  signal s_RAM0      : r_RAM0;
  signal s_RAM2      : r_RAM2;

begin

  CTR0_o      <=  s_CTR0;  
  CTR1_o      <=  s_CTR1;   
  RAM0_o      <=  s_RAM0;   
  RAM2_o      <=  s_RAM2;   

  wb_ack_o   <= s_wb_ack;
  wb_err_o   <= s_wb_err;
  wb_rty_o   <= s_wb_rty;
  wb_data_o  <= s_wb_data_o; 

  RAMTT_256: gc_RAM
  generic map(g_DATA_WIDTH => c_RAMTT_DATA_WIDTH,
              g_ADDR_WIDTH => c_RAM_ADDR_BITS)
  port map(
            clka        => wb_clk_i,
            wea         => s_RAM0.WER,
            addra       => s_RAM1.CWA(g_ADDR_WIDTH - 1 downto 0),
            dina        => utc_i,
            clkb        => clkb_s,
            rstb        => rstb_s,
            addrb       => s_RAM1.CRA(g_ADDR_WIDTH - 1 downto 0),
            doutb       => s_dout_RAMTT);

  RAMID_256: gc_RAM
  generic map(g_DATA_WIDTH => c_RAMID_DATA_WIDTH,
              g_ADDR_WIDTH => c_RAM_ADDR_BITS)
  port map(
            clka        => wb_clk_i,
            wea         => s_RAM0.WER,
            addra       => s_RAM1.CWA(g_ADDR_WIDTH - 1 downto 0),
            --! Change to data to read
            dina        => (others => '0'),
            clkb        => clkb_s,
            rstb        => rstb_s,
            addrb       => s_RAM1.CRA(g_ADDR_WIDTH - 1 downto 0),
            doutb       => s_dout_RAMID);


  process(wb_clk_i)
  begin
     if rising_edge(wb_clk_i) then
        if wb_rst_i = '1' then
           RAMstate   <= S0_IDLE;
           s_CTR0     <= c_CTR0_default;
           s_CTR1     <= c_CTR1_default;
           s_RAM0     <= c_RAM0_default;
           s_RAM2     <= c_RAM2_default;
           s_wb_ack   <= '0';
           s_wb_err   <= '0';
           s_wb_rty   <= '0';
           s_wb_data  <= (others => '0');
        elsif wb_stb_i = '1' and wb_cyc_i = '1' then
           wb_ack_s   <= '0';
           wb_err_s   <= '0';
           wb_rty_s   <= '0';
           if (wb_ack_s or wb_err_s or wb_rty_s) = '1' then
           else
              case wb_we_i is
                 when '0' =>
                    case wb_addr_i (2 downto 0) is
                       when CTR0_addr   =>
                          wb_data_o <= f_STD_LOGIC_VECTOR(s_CTR0);
                          wb_ack_s <= '1';
                       when CTR1_addr   =>
                          wb_data_o <= f_STD_LOGIC_VECTOR(s_CTR1);
                          wb_ack_s <= '1';
                       when CTR2_addr   =>
                          wb_data_o(r_CTR2'a_length - 1 downto 0)
                                                    <= f_STD_LOGIC_VECTOR(s_CTR2);
                          wb_data_o(31 downto r_CTR2'a_length) <= (others => '0');
                          wb_ack_s <= '1';
                       when RAM0_addr    =>
                          wb_data_o(r_RAM0'a_length - 1 downto 0)
                                                    <= f_STD_LOGIC_VECTOR(s_RAM0);
                          wb_data_o(31 downto r_RAM0'a_length) <= (others => '0');
                          wb_ack_s <= '1';
                       when RAM1_addr    =>
                          wb_data_o <= f_STD_LOGIC_VECTOR(s_RAM1);
                          wb_ack_s <= '1';
                       when RAM2_addr    =>
                          wb_data_o <= f_STD_LOGIC_VECTOR(s_RAM2);
                          wb_ack_s <= '1';
                       when others =>
                          wb_err_s <= '1';
                    end case;
                 when others =>
                 --! TODO implement writes
                    case wb_addr_i is
                       when CTR0_addr   =>
                       when CTR1_addr   =>
                       when CTR2_addr   =>
                       when RAM0_addr   =>
                       when RAM1_addr   =>
                       when RAM2_addr   =>
                       when others =>
                          wb_err_s <= '1';
                    end case;
              end case;
           end if;
        end if;
     end if;
  end process;

end Behavioral;
