DUTInterfaces_rtl.vhd 11.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
--=============================================================================
--! @file DUTInterfaces_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- VHDL Architecture fmc_mTLU_lib.DUTInterfaces.rtl
--
--! @brief \n
--! \n
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 15:09:50 11/09/12
--
--! @version v0.1
--
--! @details
--! Address map:\n
--! 5-bit decoded
--! 0x00000000 - DUT interface mode, two bits per DUT. Up to 12 inputs XXXXXXXXBBAA99887766554433221100\n
--!            - mode: 0 = EUDET mode , 1 = synchronous ( LHC / Timepix ) , 2,3=reserved
--! 
--
--!
--! <b>Dependencies:</b>\n
--!
--! <b>References:</b>\n
--!
--! <b>Modified by:</b>\n
--! Author: 
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
-------------------------------------------------------------------------------
--! @todo <next thing to do> Indicate if the DUT works under AIDA/EUDET style\n
--! <another thing to do> \n
--
--------------------------------------------------------------------------------
-- 
-- Created using using Mentor Graphics HDL Designer(TM) 2010.3 (Build 21)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

USE work.ipbus.all;
use work.ipbus_reg_types.all;

library unisim;
use unisim.VComponents.all;


ENTITY DUTInterfaces IS
   GENERIC( 
      g_NUM_DUTS    : positive := 3;
      g_IPBUS_WIDTH : positive := 32
   );
   PORT( 
      busy_from_dut_n_i       : IN     std_logic_vector (g_NUM_DUTS-1 DOWNTO 0);     -- BUSY input from DUTs
      busy_from_dut_p_i       : IN     std_logic_vector (g_NUM_DUTS-1 DOWNTO 0);     -- BUSY input from DUTs
      clk_4x_logic_i          : IN     std_logic;
      ipbus_clk_i             : IN     std_logic;
      ipbus_i                 : IN     ipb_wbus;                                     -- Signals from IPBus core to slave
      ipbus_reset_i           : IN     std_logic;
      strobe_4x_logic_i       : IN     std_logic;                                    -- ! goes high every 4th clock cycle
      --trigger_counter_i       : IN     std_logic_vector (g_IPBUS_WIDTH-1 DOWNTO 0);
      trigger_i               : IN     std_logic;                                    -- goes high when trigger logic issues a trigger
      clk_to_dut_i				: IN     std_logic ;											-- ! clock to DUT
		reset_or_clk_to_dut_i	: IN		std_logic;
		AIDAhandshake_i			: IN 		std_logic;												-- AIDA/EUDET handshake
		ipbus_o                 : OUT    ipb_rbus;                                     -- signals from slave to IPBus core
      clk_to_dut_n_o        	: INOUT  std_logic_vector (g_NUM_DUTS-1 DOWNTO 0);     -- clocks trigger data when in EUDET mode
      clk_to_dut_p_o        	: INOUT  std_logic_vector (g_NUM_DUTS-1 DOWNTO 0);     -- clocks trigger data when in EUDET mode
		reset_or_clk_to_dut_n_o : OUT    std_logic_vector (g_NUM_DUTS-1 DOWNTO 0);     -- ! Either reset line or trigger
      reset_or_clk_to_dut_p_o : OUT    std_logic_vector (g_NUM_DUTS-1 DOWNTO 0);     -- ! Either reset line or trigger
      trigger_to_dut_n_o      : OUT    std_logic_vector (g_NUM_DUTS-1 DOWNTO 0);     -- ! Trigger output
      trigger_to_dut_p_o      : OUT    std_logic_vector (g_NUM_DUTS-1 DOWNTO 0);     -- ! Trigger output
      veto_o                  : OUT    std_logic                                     -- goes high when one or more DUT are busy
   );

-- Declarations

END ENTITY DUTInterfaces ;

--
ARCHITECTURE rtl OF DUTInterfaces IS

  signal s_intermediate_busy_or : std_logic_vector(g_NUM_DUTS downto 0);  -- OR tree
  signal s_veto : std_logic;
  signal s_strobe_4x_logic_d1 : std_logic;
  signal s_clk_to_DUT , s_busy_from_dut , s_reset_or_clk_to_dut , s_trigger_to_dut : std_logic_vector(g_NUM_DUTS-1 downto 0);
  signal s_DUT_mask : std_logic_vector(g_NUM_DUTS-1 downto 0) := (others => '0');   	--! Mask for the DUTs not used
  signal s_clk_is_input, s_clk_is_input_b : std_logic := '0'; 					--! Indicates the direction of the clock in the RJ45 DUT
  signal s_clk_to_tlu : std_logic := '0';
  
  constant c_N_CTRL : positive := 1;
  constant c_N_STAT : positive := 1;
  signal s_status_to_ipbus, s_sync_status_to_ipbus : ipb_reg_v(c_N_STAT-1 downto 0);
  signal s_control_from_ipbus,s_sync_control_from_ipbus : ipb_reg_v(c_N_CTRL-1 downto 0);
BEGIN


  -- Dummy code.
  s_intermediate_busy_or(0) <= '0';
   --s_busy_from_dut(g_NUM_DUTS-1 downto 0) <= (others=>'0');
  
  -----------------------------------------------------------------------------
  -- IPBus interface 
  -----------------------------------------------------------------------------
  ipbus_registers: entity work.ipbus_ctrlreg_v
    generic map(
      N_CTRL => c_N_CTRL,
      N_STAT => c_N_STAT
      )
    port map(
      clk => ipbus_clk_i,
      reset=> '0',--ipbus_reset_i ,
      ipbus_in=>  ipbus_i,
      ipbus_out=> ipbus_o,
      d=>  s_sync_status_to_ipbus,
      q=>  s_control_from_ipbus,
      stb=>  open
      );

  -- Synchronize registers from logic clock to ipbus.
    sync_status: entity work.synchronizeRegisters
    generic map (
      g_NUM_REGISTERS => c_N_STAT )
    port map (
      clk_input_i => clk_4x_logic_i,
      data_i      =>  s_status_to_ipbus,
      data_o      => s_sync_status_to_ipbus,
      clk_output_i => ipbus_clk_i);

    -- Synchronize registers from logic clock to ipbus.
    sync_ctrl: entity work.synchronizeRegisters
    generic map (
      g_NUM_REGISTERS => c_N_CTRL )
    port map (
      clk_input_i => ipbus_clk_i,
      data_i      =>  s_control_from_ipbus,
      data_o      => s_sync_control_from_ipbus,
      clk_output_i => clk_4x_logic_i);

  -- Map the control registers
  s_DUT_mask <= s_sync_control_from_ipbus(0)(g_NUM_DUTS-1 downto 0);

  -- Map the status registers
  s_status_to_ipbus(0) <= std_logic_vector(to_unsigned(0,g_IPBUS_WIDTH-g_NUM_DUTS)) & s_DUT_mask;
  
  
  -- These instances need to be out of the loop because the RJ45 permits a bidirectional clock
  clk_to_DUT_OBUFDS_inst_0 : OBUFDS
      generic map (
        IOSTANDARD => "LVDS_25")
      port map (
        O =>  clk_to_dut_p_o(0),    	-- Diff_p output (connect directly to top-level port)
        OB => clk_to_dut_n_o(0),   	-- Diff_n output (connect directly to top-level port)
        I =>  s_clk_to_dut(0)					-- Buffer output
      );
	clk_to_DUT_OBUFDS_inst_1 : OBUFDS
      generic map (
        IOSTANDARD => "LVDS_25")
      port map (
        O =>  clk_to_dut_p_o(1),    	-- Diff_p output (connect directly to top-level port)
        OB => clk_to_dut_n_o(1),   	-- Diff_n output (connect directly to top-level port)
        I =>  s_clk_to_dut(1)					-- Buffer output
      );
  clk_to_DUT_OBUFDS_inst_2 : IOBUFDS
		generic map (
			IOSTANDARD => "BLVDS_25")
		port map (
			O => s_clk_to_tlu,     -- Buffer output
			IO => clk_to_dut_p_o(2),   -- Diff_p inout (connect directly to top-level port)
			IOB => clk_to_dut_n_o(2), -- Diff_n inout (connect directly to top-level port)
			I => s_clk_to_dut(2),     -- Buffer input
			T => s_clk_is_input_b      -- 3-state enable input, high=input, low=output
			);
	s_clk_is_input <= not AIDAhandshake_i;
	
								
	--When an ODDR2 primitive is used in conjunction with a 3-state output, the T control pin must
	--also use an ODDR2 primitive configured in the same mode as the ODDR2 primitive used for data
	--output.
	ddr_for_clk_to_DUT_tristate : ODDR2
   generic map(
      DDR_ALIGNMENT => "NONE", -- Sets output alignment to "NONE", "C0", "C1" 
      INIT => '0', -- Sets initial state of the Q output to '0' or '1'
      SRTYPE => "SYNC") -- Specifies "SYNC" or "ASYNC" set/reset
   port map (
      Q => s_clk_is_input_b, -- 1-bit output data
      C0 => clk_to_dut_i, -- 1-bit clock input
      C1 => not clk_to_dut_i, --not s_clk160_internal, -- 1-bit clock input
      CE => '1',  -- 1-bit clock enable input
      D0 => s_clk_is_input,   -- 1-bit data input (associated with C0)
      D1 => s_clk_is_input,   -- 1-bit data input (associated with C1)
      R => '0',    -- 1-bit reset input
      S => '0'     -- 1-bit set input
   );
				
  duts: for dut in 1 to g_NUM_DUTS generate
    
    busy_IBUFDS_inst : IBUFDS
      generic map (
        DIFF_TERM => TRUE, -- Differential Termination 
        IBUF_LOW_PWR => TRUE, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
        IOSTANDARD => "LVDS_25")
      port map (
        O => s_busy_from_dut(dut-1),  -- Buffer output
        I => busy_from_dut_p_i(dut-1),  -- Diff_p buffer input (connect directly to top-level port)
        IB => busy_from_dut_n_i(dut-1) -- Diff_n buffer input (connect directly to top-level port)
      );
		
   
    trig_OBUFDS_inst : OBUFDS
      generic map (
        IOSTANDARD => "LVDS_25")
      port map (
        O =>  trigger_to_dut_p_o(dut-1),     						-- Diff_p output (connect directly to top-level port)
        OB => trigger_to_dut_n_o(dut-1),   							-- Diff_n output (connect directly to top-level port)
        I =>  s_trigger_to_dut(dut-1) and s_DUT_mask(dut-1)    -- Buffer input 
      );
     
    clk_rst_OBUFDS_inst : OBUFDS
      generic map (
        IOSTANDARD => "LVDS_25")
      port map (
        O =>  reset_or_clk_to_dut_p_o(dut-1),    							-- Diff_p output (connect directly to top-level port)
        OB => reset_or_clk_to_dut_n_o(dut-1),   							-- Diff_n output (connect directly to top-level port)
        I =>  reset_or_clk_to_dut_i 	--s_reset_or_clk_to_dut(dut-1) and s_DUT_mask(dut-1)     -- Buffer input 
      );
     
    s_intermediate_busy_or(dut) <= s_intermediate_busy_or(dut-1) or
                                   (s_busy_from_dut(dut-1) and
											  s_DUT_mask(dut-1));
   
	
	ddr_for_clk_output : ODDR2
   generic map(
      DDR_ALIGNMENT => "NONE", -- Sets output alignment to "NONE", "C0", "C1" 
      INIT => '0', -- Sets initial state of the Q output to '0' or '1'
      SRTYPE => "SYNC") -- Specifies "SYNC" or "ASYNC" set/reset
   port map (
      Q => s_clk_to_dut(dut-1), -- 1-bit output data
      C0 => clk_to_dut_i, -- 1-bit clock input
      C1 => not clk_to_dut_i, -- 1-bit clock input
      CE => '1',  -- 1-bit clock enable input
      D0 => '1',   -- 1-bit data input (associated with C0)
      D1 => '0',   -- 1-bit data input (associated with C1)
      R => '0',    -- 1-bit reset input
      S => '0'     -- 1-bit set input
   );
	 
  end generate duts;

    s_veto <=  s_intermediate_busy_or(g_NUM_DUTS);
  
  -- purpose: register for internal signals and output signals
  -- type   : combinational
  -- inputs : clk_4x_logic_i , strobe_4x_logic_i , s_veto
  -- outputs: veto_o
  register_signals: process (clk_4x_logic_i)-- , strobe_4x_logic_i , s_veto)
  begin  -- process register_signals
    if rising_edge(clk_4x_logic_i) then
      veto_o <= s_veto;
      s_strobe_4x_logic_d1 <= strobe_4x_logic_i;
      --s_reset_or_clk_to_dut <= ( others => (s_strobe_4x_logic_d1 or strobe_4x_logic_i));      
      s_trigger_to_dut <= ( others => trigger_i );
		  --shutter_to_dut <= ( others => shutter_i );
    end if;
  end process register_signals;
  
END ARCHITECTURE rtl;