---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 13:07:12 11/08/2007 -- Design Name: -- Module Name: Mboard - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: Top module -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. library UNISIM; use UNISIM.VComponents.all; entity Mboard is Port ( -- Global clock for initialisation -------------------------------------------- OSC_CLK: in std_logic; EXT_RST: in std_logic; -------------------------------------------- -- ADC 0 -------------------------------------------- PD0: out std_logic; SCLK0: out std_logic; DIN0: in std_logic_vector(9 downto 0); -------------------------------------------- -- ADC 1 -------------------------------------------- PD1: out std_logic; SCLK1: out std_logic; DIN1: in std_logic_vector(9 downto 0); -------------------------------------------- -- Beetle fast control (common to both ASICs) -------------------------------------------- B_CLK: out std_logic; B_RST: out std_logic; B_TRIGGER: out std_logic; B_TESTPULSE: out std_logic; DATAVALID0: in std_logic; DATAVALID1: in std_logic; -------------------------------------------- -- Digital delay line -------------------------------------------- SCLK: out std_logic; SI: out std_logic; AE: out std_logic; TRIGGER_OUT: out std_logic; -------------------------------------------- -- Beetle slow control -------------------------------------------- SDA: inout std_logic; SCL: out std_logic; -------------------------------------------- -- USB / telescope BUS -------------------------------------------- nTXE: in std_logic; nRFX: in std_logic; nPWEN: in std_logic; nRD: out std_logic; WR: out std_logic; USB_DATA: inout std_logic_vector(7 downto 0); -------------------------------------------- -- Indicator LEDs -------------------------------------------- GREEN_LED: out std_logic; RED_LED: out std_logic; -------------------------------------------- -- Clock, trigger and reset pulses -------------------------------------------- SIN1P: in std_logic; SIN1N: in std_logic; SIN2P: in std_logic; SIN2N: in std_logic; PPOSP: in std_logic; PPOSN: in std_logic; PNEGP: in std_logic; PNEGN: in std_logic; -------------------------------------------- -- TDC (not in use) -------------------------------------------- ALE: out std_logic; RDN: out std_logic; WRN: out std_logic; CSN: out std_logic; INT_FLAG: in std_logic; START: out std_logic; STOP1: out std_logic; ENSTOP1: out std_logic; RSTN: out std_logic; CLK_REF: out std_logic; DATA: inout std_logic_vector(7 downto 0); -------------------------------------------- -- Threshold DACs -------------------------------------------- DAC_NCS: out std_logic; DAC_SDI: out std_logic; DAC_CLK: out std_logic; NLDACS: out std_logic; DAC_NRST: out std_logic; -------------------------------------------- -- Temperature sensor -------------------------------------------- T_NCS: out std_logic; T_SCLK: out std_logic; T_SO: in std_logic; -------------------------------------------- -- Data RAM (not used) -------------------------------------------- ADR_SDRAM: out std_logic_vector(12 downto 0); BA_SDRAM: out std_logic_vector(1 downto 0); DQ_SDRAM: inout std_logic_vector(7 downto 0); nCAS_SDRAM: out std_logic; nRAS_SDRAM: out std_logic; nCS_SDRAM: out std_logic; nWE_SDRAM: out std_logic; DQM_SDRAM: out std_logic_vector(0 downto 0); CKE_SDRAM: out std_logic; CLK_SDRAM_FB: in std_logic; CLK_SDRAM: out std_logic -------------------------------------------- ); end Mboard; architecture Behavioral of Mboard is -- LVDS buffer -------------------------------------------- component IBUFDS port (O: out std_logic; I: in std_logic; IB: in std_logic); end component; -------------------------------------------- -- PLL component -------------------------------------------- component pll port (CLKIN_IN: in std_logic; RST_IN: in std_logic; CLKFX_OUT: out std_logic; CLK0_OUT: out std_logic; CLK90_OUT: out std_logic; CLK180_OUT: out std_logic; CLK270_OUT: out std_logic); end component; -------------------------------------------- -- system control -------------------------------------------- signal EXT_CLK: std_logic; signal EXT_TRG: std_logic; signal EXT_RES: std_logic; -------------------------------------------- -- Readout clock management -------------------------------------------- signal DCM_RES: std_logic; signal PLL_CLK: std_logic; signal FE_CLK: std_logic; signal FE_DEL: std_logic; signal CLK_FX: std_logic; signal CLK_000: std_logic; signal CLK_090: std_logic; signal CLK_180: std_logic; signal CLK_270: std_logic; -------------------------------------------- -- Trigger and calibration pulse -------------------------------------------- signal FE_TRG: std_logic; signal INT_TRG: std_logic; signal CAL_CNT: natural range 0 to 131071; signal LAT_CNT: natural range 0 to 511; signal LAT_CNV: std_logic_vector(8 downto 0); signal LAT_REG: std_logic_vector(8 downto 0); signal LAT_RND: std_logic_vector(8 downto 0); signal TRG_EOF: std_logic; signal TRG_PUL: std_logic; signal CAL_PUL: std_logic; -------------------------------------------- -- Event handler -------------------------------------------- signal RUN_ENA: std_logic; signal TRG_BLK: std_logic; signal EVT_CNT: natural range 0 to 2147483647; signal EVT_NUM: std_logic_vector(31 downto 0); signal EVT_ERR: std_logic; -------------------------------------------- -- Reset module -------------------------------------------- signal FE_RES: std_logic; signal BUT_RES: std_logic; signal BUT_STP: std_logic; signal BUT_CNT: natural range 0 to 16777215; signal SIN_CYC: std_logic; signal MUL_CYC: std_logic; signal SIN_CNT: natural range 0 to 7; signal MUL_CNT: natural range 0 to 7; signal SIN_EOF: std_logic; signal MUL_EOF: std_logic; signal SIN_RES: std_logic; signal MUL_RES: std_logic; signal PC_RES: std_logic; -------------------------------------------- -- Communication port -------------------------------------------- -- control signal RF_CYC: std_logic; signal RF_CLK: std_logic; signal RF_STB: std_logic; signal RF_ADV: natural range 0 to 511; signal RF_CNT: natural range 0 to 511; -- readout signal TX_SOF: std_logic; signal TX_EOF: std_logic; signal RF_SOF: std_logic; signal RF_EOF: std_logic; signal TX_SCN: natural range 0 to 3; signal TX_ECN: natural range 0 to 3; signal RF_SCN: natural range 0 to 3; signal RF_ECN: natural range 0 to 3; signal TX_CYC: std_logic; signal TX_CLK: std_logic; signal TX_RA0: std_logic_vector(7 downto 0); signal TX_RA1: std_logic_vector(7 downto 0); signal WAT_DOG: std_logic; signal TX_STB: std_logic; signal TX_ADV: natural range 0 to 7; signal TX_CNT: natural range 0 to 7; signal DAT_CNT: natural range 0 to 1023; -- max 404 signal MUX_CNT: natural range 0 to 1023; signal DAT_CNV: std_logic_vector(9 downto 0); signal RPL_REG: std_logic_vector(9 downto 0); -- data multiplexors signal MUX_DAT: std_logic_vector(9 downto 0); signal EVT_DAT: std_logic_vector(7 downto 0); -- IO signal USB_OUT: std_logic_vector(7 downto 0); signal USB_INP: std_logic_vector(7 downto 0); -------------------------------------------- -- Input commands -------------------------------------------- signal ADR_CNT: natural range 0 to 255; signal ADR_BUF: std_logic_vector(7 downto 0); signal LEN_REG: std_logic_vector(7 downto 0); signal LEN_BUF: std_logic_vector(7 downto 0); signal COM_REG: std_logic_vector(7 downto 0); signal COM_DEL: std_logic_vector(7 downto 0); signal CTR_REG: std_logic_vector(7 downto 0); signal SEQ_REG: std_logic_vector(7 downto 0); signal STA_REG: std_logic_vector(7 downto 0); -------------------------------------------- -- Sequencer -------------------------------------------- signal SEQ_GTE: std_logic; -------------------------------------------- -- ASICs control -------------------------------------------- signal SDA_INP: std_logic; signal SDA_OUT: std_logic; signal SCL_OUT: std_logic; signal SDA_RW: std_logic; signal ACK_WRD: std_logic_vector(31 downto 0); signal ACK_DAT: std_logic_vector(7 downto 0); -------------------------------------------- -- TDC variables -------------------------------------------- signal TRG_090: std_logic; signal TRG_180: std_logic; signal TRG_270: std_logic; signal CNT_000: natural range 0 to 255; signal CNT_090: natural range 0 to 255; signal CNT_180: natural range 0 to 255; signal CNT_270: natural range 0 to 255; signal TDC_000: std_logic_vector(7 downto 0); signal TDC_090: std_logic_vector(7 downto 0); signal TDC_180: std_logic_vector(7 downto 0); signal TDC_270: std_logic_vector(7 downto 0); signal TDC_COR: std_logic; -------------------------------------------- -- ADC variables -------------------------------------------- -- clock phase signal ADC_PH0: std_logic_vector(3 downto 0); signal ADC_PH1: std_logic_vector(3 downto 0); -- clock frequency signal ADC_CL0: std_logic; signal ADC_CL1: std_logic; -- clock error flag -- signal ADC_ER0: std_logic; -- signal ADC_ER1: std_logic; -- address counter signal ADC_CN0: natural range 0 to 255; signal ADC_CN1: natural range 0 to 255; -- data valid signal ADC_DV0: std_logic; signal ADC_DV1: std_logic; -- data valid (phase adjusted) signal ADC_DS0: std_logic; signal ADC_DS1: std_logic; -- end of sampling phase signal ADC_EP0: std_logic; signal ADC_EP1: std_logic; -- RAM write address signal ADC_WA0: std_logic_vector(7 downto 0); signal ADC_WA1: std_logic_vector(7 downto 0); -------------------------------------------- -- Data RAM component -------------------------------------------- component ram port ( clka: in std_logic; wea: in std_logic_vector(0 downto 0); addra: in std_logic_vector(7 downto 0); dina: in std_logic_vector(9 downto 0); douta: out std_logic_vector(9 downto 0)); end component; -------------------------------------------- -- RAM variables -------------------------------------------- -- memory write enable signal RAM_WE0: std_logic_vector(0 downto 0); signal RAM_WE1: std_logic_vector(0 downto 0); -- multiplexed address signal RAM_AD0: std_logic_vector(7 downto 0); signal RAM_AD1: std_logic_vector(7 downto 0); -- multiplexed clock signal RAM_CL0: std_logic; signal RAM_CL1: std_logic; -- output data signal DOUT0: std_logic_vector(9 downto 0); signal DOUT1: std_logic_vector(9 downto 0); -------------------------------------------- -- NTC component -------------------------------------------- signal NTC_DAT: std_logic_vector(10 downto 0); -------------------------- component NTC port ( Clock: in std_logic; nCS : out std_logic; SCLK : out std_logic; SO : in std_logic; Data : out std_logic_vector(10 downto 0)); end component; -------------------------------------------- -- Indicators -------------------------------------------- signal RW_CYC: std_logic; signal LED_OFF: std_logic; signal LED_GTE: std_logic; signal LED_CNT: natural range 0 to 4194303; -------------------------------------------- -- IO attributes for Leonardo Spectrum -------------------------------------------- attribute IOSTANDARD : string; attribute IOSTANDARD of CLK_BUF : label is "LVPECL_25"; attribute IOSTANDARD of TRG_BUF : label is "LVPECL_25"; attribute IOSTANDARD of RES_BUF : label is "LVPECL_25"; -------------------------------------------- -- OK, here the entity starts... begin -------------------------------------------- -- Permanent assignments -------------------------------------------- -- ADCs (permanently ON) -------------------------------------------- PD0 <= '0'; PD1 <= '0'; -------------------------------------------- -- DRAM (not in use) -------------------------------------------- ADR_SDRAM <= (others => '0'); BA_SDRAM <= (others => '0'); DQ_SDRAM <= (others => 'Z'); nCAS_SDRAM <= '1'; nRAS_SDRAM <= '1'; nCS_SDRAM <= '1'; nWE_SDRAM <= '1'; DQM_SDRAM <= (others => '0'); CKE_SDRAM <= '0'; CLK_SDRAM <= '0'; -------------------------------------------- -- TDC (not in use) -------------------------------------------- ALE <= '0'; RDN <= '1'; WRN <= '1'; CSN <= '1'; START <= '0'; STOP1 <= '0'; ENSTOP1 <= '0'; RSTN <= '1'; CLK_REF <= '0'; DATA <= (others => 'Z'); -------------------------------------------- -------------------------------------------- -- Differential receives -------------------------------------------- -- clock frequency -------------------------- CLK_BUF : IBUFDS port map ( O => EXT_CLK, I => PPOSP, IB => PPOSN); -------------------------- -- trigger pulse -------------------------- TRG_BUF : IBUFDS port map ( O => EXT_TRG, I => SIN1P, IB => SIN1N); -------------------------- -- reset command -------------------------- RES_BUF : IBUFDS port map ( O => EXT_RES, I => SIN2P, IB => SIN2N); -------------------------------------------- -------------------------------------------- -- Synchronisation module -------------------------------------------- -- Clock source -------------------------------------------- process(CTR_REG, EXT_CLK, OSC_CLK) begin case CTR_REG(0) is when '1' => PLL_CLK <= OSC_CLK; when others => PLL_CLK <= EXT_CLK; end case; end process; -------------------------------------------- -- Phase management -------------------------------------------- U0: pll port map ( CLKIN_IN => PLL_CLK, RST_IN => DCM_RES, CLKFX_OUT => CLK_FX, CLK0_OUT => CLK_000, CLK90_OUT => CLK_090, CLK180_OUT => CLK_180, CLK270_OUT => CLK_270); -------------------------- B_CLK <= CLK_000; FE_CLK <= CLK_000; -------------------------------------------- -------------------------------------------- -- Trigger module -------------------------------------------- -- Select trigger source for the front-end -------------------------------------------- process(CTR_REG, EXT_TRG, INT_TRG) begin case CTR_REG(1) is when '1' => FE_TRG <= INT_TRG; when others => FE_TRG <= not EXT_TRG; end case; end process; -------------------------------------------- -- 300 Hz pacer -------------------------------------------- process(FE_CLK) begin if (FE_CLK'event and FE_CLK = '0') then CAL_CNT <= CAL_CNT + 1; end if; end process; -------------------------------------------- -- Internal trigger -------------------------------------------- process(FE_CLK, CAL_CNT) begin if (FE_CLK'event and FE_CLK = '1') then case CAL_CNT is when 1 => INT_TRG <= '1'; when 2 => INT_TRG <= '0'; when others => null; end case; end if; end process; -------------------------- TRIGGER_OUT <= FE_TRG; -------------------------------------------- -- 10us Calibration pulse -------------------------------------------- process(FE_CLK, CAL_CNT) begin if (FE_CLK'event and FE_CLK = '1') then case CAL_CNT is when 1 => CAL_PUL <= '1'; when 2 => CAL_PUL <= '0'; when 400 => CAL_PUL <= '1'; when 401 => CAL_PUL <= '0'; when others => null; end case; end if; end process; -------------------------- B_TESTPULSE <= CTR_REG(3) and CAL_PUL; -------------------------------------------- -- Block further trigger pulses during -- event processing and readout (CLK ->) -------------------------------------------- process(FE_RES, FE_TRG, RUN_ENA) begin if (FE_RES = '1') then TRG_BLK <= '0'; elsif (FE_TRG'event and FE_TRG = '1') then if (RUN_ENA = '1') then TRG_BLK <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Latency counter (CLK <-) -------------------------------------------- process(FE_CLK, TRG_BLK, TRG_EOF) begin if (FE_CLK'event and FE_CLK = '0') then if (TRG_BLK = '0') then LAT_CNT <= 0; elsif (TRG_EOF = '0') then LAT_CNT <= LAT_CNT + 1; else null; end if; end if; end process; -------------------------- LAT_CNV <= conv_std_logic_vector(LAT_CNT, 9); -------------------------------------------- -- End of trigger frame including: -- a.) latency (0...187) bunch Xs -- b.) cable delay (2x5 ns/m) ~1 bX -- c.) offset between Trigger in -- and Data valid out (4 bX) -- d.) event processing (0...255 bX) -- e.) ADC latency (6 bX) -------------------------------------------- process(FE_CLK, LAT_CNT) begin if (FE_CLK'event and FE_CLK = '1') then if (LAT_CNT = 500) then TRG_EOF <= '1'; else TRG_EOF <= '0'; end if; end if; end process; -------------------------------------------- -- Delayed trigger pulse (should match -- Beetle latency) -------------------------------------------- LAT_RND(8 downto 2) <= "0000000"; LAT_RND(1 downto 0) <= EVT_NUM(1 downto 0); -------------------------- process(FE_CLK, LAT_CNV, LAT_REG, LAT_RND) begin if (FE_CLK'event and FE_CLK = '1') then if (LAT_CNV = (LAT_REG + LAT_RND)) then TRG_PUL <= '1'; else TRG_PUL <= '0'; end if; end if; end process; -------------------------- B_TRIGGER <= TRG_PUL; -------------------------------------------- -- Beetle pipeline reset -------------------------------------------- process(COM_REG, SIN_RES) begin if (COM_REG = x"08") then B_RST <= SIN_RES; else B_RST <= '0'; end if; end process; -------------------------- -- process(FE_CLK, LAT_CNT) -- begin -- if (FE_CLK'event and FE_CLK = '1') then -- case LAT_CNT is -- when 1 => -- B_RST <= '1'; -- when others => -- B_RST <= '0'; -- end case; -- end if; -- end process; -------------------------------------------- -- Prepare the run (SCK_CLK <-) -------------------------------------------- process(FE_RES, RF_CYC, COM_REG) begin if (FE_RES = '1') then RUN_ENA <= '1'; elsif (RF_CYC'event and RF_CYC = '0') then if (COM_REG = x"08") then RUN_ENA <= '0'; else null; end if; end if; end process; -------------------------------------------- -- Event counter -------------------------------------------- process(RUN_ENA, TRG_BLK) begin if (RUN_ENA = '0') then EVT_CNT <= 0; elsif (TRG_BLK'event and TRG_BLK = '1') then EVT_CNT <= EVT_CNT + 1; end if; end process; -------------------------- EVT_NUM <= conv_std_logic_vector(EVT_CNT, 31); -------------------------------------------- -- Report read attempt during -- uncompleted event processing -------------------------------------------- process(MUL_RES, TX_CYC, TRG_BLK, TRG_EOF) begin if (MUL_RES = '1') then EVT_ERR <= '0'; elsif (TX_CYC'event and TX_CYC = '1') then if (TRG_BLK = '1' and TRG_EOF = '0') then EVT_ERR <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Status register. LAM is needed to launch -- the readout if neither of ASICs responds -------------------------------------------- STA_REG(7) <= TRG_EOF; -- "look at me" STA_REG(6) <= '0'; STA_REG(5) <= ADC_EP1; -- ASIC 1 ready STA_REG(4) <= ADC_EP0; -- ASIC 0 ready STA_REG(3) <= '0'; --ADC_ER1; -- synchronisation error STA_REG(2) <= '0'; --ADC_ER0; -- synchronisation error STA_REG(1) <= TDC_COR; STA_REG(0) <= EVT_ERR; -- read during event processing -------------------------------------------- -------------------------------------------- -- Communication module -------------------------------------------- -- Bi-directional IO for the USB-like port -------------------------------------------- process(TX_CYC, USB_OUT) begin if (TX_CYC = '1') then USB_DATA <= USB_OUT; else USB_DATA <= (others => 'Z'); end if; end process; -------------------------- USB_INP <= USB_DATA; -------------------------------------------- -- Write /Read cycles, resolving -- conflicts on the USB_DATA bus -- nRFX - write data into Xilinx -- nTXE - write data into MC -------------------------------------------- -- Monoflope "A" launched by the -- leading edge of the RF signal -------------------------------------------- process(OSC_CLK, nRFX, RF_SOF) begin if(OSC_CLK'event and OSC_CLK = '1') then if (nRFX = '1') then RF_SCN <= 0; elsif (RF_SOF = '0') then RF_SCN <= RF_SCN + 1; else null; end if; end if; end process; -------------------------------------------- -- Monoflope "B" launched by the -- trailing edge of the RF signal -------------------------------------------- process(OSC_CLK, nRFX, RF_EOF) begin if(OSC_CLK'event and OSC_CLK = '1') then if (nRFX = '0') then RF_ECN <= 0; elsif (RF_EOF = '0') then RF_ECN <= RF_ECN + 1; else null; end if; end if; end process; -------------------------------------------- -- Monoflope "C" launched by the -- leading edge of the TX signal -------------------------------------------- process(OSC_CLK, nTXE, TX_SOF) begin if(OSC_CLK'event and OSC_CLK = '1') then if (nTXE = '1') then TX_SCN <= 0; elsif (TX_SOF = '0') then TX_SCN <= TX_SCN + 1; else null; end if; end if; end process; -------------------------------------------- -- Monoflope "D" launched by the -- trailing edge of the TX signal -------------------------------------------- process(OSC_CLK, nTXE, TX_EOF) begin if(OSC_CLK'event and OSC_CLK = '1') then if (nTXE = '0') then TX_ECN <= 0; elsif (TX_EOF = '0') then TX_ECN <= TX_ECN + 1; else null; end if; end if; end process; -------------------------------------------- -- Terminate monoflope "A" -------------------------------------------- process(OSC_CLK, RF_SCN) begin if(OSC_CLK'event and OSC_CLK = '0') then if (RF_SCN = 3) then RF_SOF <= '1'; else RF_SOF <= '0'; end if; end if; end process; -------------------------------------------- -- Terminate monoflope "B" -------------------------------------------- process(OSC_CLK, RF_ECN) begin if(OSC_CLK'event and OSC_CLK = '0') then if (RF_ECN = 3) then RF_EOF <= '1'; else RF_EOF <= '0'; end if; end if; end process; -------------------------------------------- -- Terminate monoflope "C" -------------------------------------------- process(OSC_CLK, TX_SCN) begin if(OSC_CLK'event and OSC_CLK = '0') then if (TX_SCN = 3) then TX_SOF <= '1'; else TX_SOF <= '0'; end if; end if; end process; -------------------------------------------- -- Terminate monoflope "D" -------------------------------------------- process(OSC_CLK, TX_ECN) begin if(OSC_CLK'event and OSC_CLK = '0') then if (TX_ECN = 3) then TX_EOF <= '1'; else TX_EOF <= '0'; end if; end if; end process; -------------------------------------------- -- RF cycle to write data into Xilinx -------------------------------------------- process(OSC_CLK, RF_ECN, RF_SCN) begin if (OSC_CLK'event and OSC_CLK = '0') then if (RF_ECN = 2) then RF_CYC <= '0'; elsif (RF_SCN = 2) then RF_CYC <= '1'; else null; end if; end if; end process; -------------------------------------------- -- TX cycle to read data from Xilinx -------------------------------------------- process(OSC_CLK, TX_ECN, RF_SCN, TX_SCN) begin if (OSC_CLK'event and OSC_CLK = '0') then if (TX_ECN = 2 or RF_SCN = 2) then TX_CYC <= '0'; elsif (TX_SCN = 2) then TX_CYC <= '1'; else null; end if; end if; end process; -------------------------------------------- -------------------------------------------- -- Control module -------------------------------------------- -- 100 kHz Clock division for Write cycle -------------------------------------------- process(OSC_CLK, RF_CYC) begin if (OSC_CLK'event and OSC_CLK = '1') then if (RF_CYC = '1') then RF_ADV <= RF_ADV + 1; else RF_ADV <= 0; end if; end if; end process; -------------------------- process(OSC_CLK, RF_ADV) begin if (OSC_CLK'event and OSC_CLK = '0') then RF_CNT <= RF_ADV; end if; end process; -------------------------------------------- -- Write clock -------------------------------------------- process(OSC_CLK, RF_CYC, RF_CNT) begin if (OSC_CLK'event and OSC_CLK = '1') then if (RF_CYC = '0') then RF_CLK <= '1'; elsif (RF_CNT = 127) then RF_CLK <= '0'; elsif (RF_CNT = 383) then RF_CLK <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Get data from the MC -------------------------------------------- process(RF_CYC, OSC_CLK, RF_CNT) begin if (OSC_CLK'event and OSC_CLK = '1') then if (RF_CYC = '0') then RF_STB <= '1'; elsif (RF_CNT = 255) then RF_STB <= '0'; elsif (RF_CNT = 511) then RF_STB <= '1'; else null; end if; end if; end process; -------------------------- process(RF_CYC, ADR_CNT, RF_STB) begin if (RF_CYC = '1') then if (ADR_CNT = 0) then nRD <= '1'; else nRD <= RF_STB; end if; else nRD <= 'Z'; end if; end process; -------------------------------------------- -- Register address -------------------------------------------- process(RF_CYC, RF_CLK, ADR_BUF, LEN_BUF) begin if (RF_CYC = '0') then ADR_CNT <= 0; elsif (RF_CLK'event and RF_CLK = '0') then if (ADR_BUF = LEN_BUF) then ADR_CNT <= 0; else ADR_CNT <= ADR_CNT + 1; end if; end if; end process; -------------------------- process(RF_CYC, RF_STB, ADR_CNT) begin if (RF_CYC = '0') then ADR_BUF <= (others => '1'); elsif (RF_STB'event and RF_STB = '1') then ADR_BUF <= conv_std_logic_vector(ADR_CNT, 8); end if; end process; -------------------------------------------- -- Latch input data -------------------------------------------- process(RF_CLK, ADR_CNT, USB_INP) begin if (RF_CLK'event and RF_CLK = '1') then case ADR_CNT is when 1 => LEN_REG <= USB_INP; when others => null; end case; end if; end process; process(RF_STB, ADR_CNT, LEN_REG) begin if (RF_STB'event and RF_STB = '1') then if (ADR_CNT = 1) then LEN_BUF <= LEN_REG; else null; end if; end if; end process; process(RF_CLK, ADR_CNT, USB_INP) begin if (RF_CLK'event and RF_CLK = '1') then case ADR_CNT is when 2 => COM_REG <= USB_INP; when others => null; end case; end if; end process; process(RF_CLK, ADR_CNT, USB_INP) begin if (RF_CLK'event and RF_CLK = '1') then -- case ADR_CNT is -- when 0 to 2 => -- SEQ_REG <= -- null; -- when others => SEQ_REG <= USB_INP; -- end case; end if; end process; -------------------------- process(RF_CLK, COM_REG) begin if (RF_CLK'event and RF_CLK = '0') then COM_DEL <= COM_REG; end if; end process; -------------------------------------------- -- DCM reset when attempting to write -- the control register -------------------------------------------- process(RF_CLK, ADR_CNT, USB_INP) begin if (RF_CLK'event and RF_CLK = '1') then if (ADR_CNT = 2 and USB_INP = x"01") then DCM_RES <= '1'; elsif (ADR_CNT = 3) then DCM_RES <= '0'; else null; end if; end if; end process; -------------------------------------------- -- Load control register -------------------------------------------- process(RF_CLK, ADR_CNT, COM_DEL, USB_INP) begin if (RF_CLK'event and RF_CLK = '1') then if (ADR_CNT = 3 and COM_DEL = x"01") then CTR_REG <= USB_INP; else null; end if; end if; end process; -------------------------------------------- -------------------------------------------- -- Gate for peripherials -------------------------------------------- process(RF_CYC, RF_CLK, ADR_CNT, USB_INP) begin if (RF_CYC = '0') then SEQ_GTE <= '0'; elsif (RF_CLK'event and RF_CLK = '1') then case ADR_CNT is when 0 to 2 => SEQ_GTE <= '0'; when others => SEQ_GTE <= '1'; end case; end if; end process; -------------------------------------------- -- Load threshold DACs (write only) -------------------------------------------- process(COM_REG, SEQ_GTE, SEQ_REG) begin if (COM_REG = x"02" and SEQ_GTE = '1') then DAC_SDI <= SEQ_REG(0); DAC_CLK <= SEQ_REG(1); DAC_NCS <= SEQ_REG(2); NLDACS <= SEQ_REG(3); DAC_NRST <= SEQ_REG(4); else DAC_SDI <= '1'; DAC_CLK <= '1'; DAC_NCS <= '1'; NLDACS <= '1'; DAC_NRST <= '1'; end if; end process; -------------------------------------------- -------------------------------------------- -- Load Beetle ASICs (read and write) -------------------------------------------- process(COM_REG, SEQ_GTE, SEQ_REG) begin if (COM_REG = x"03" and SEQ_GTE = '1') then SDA_OUT <= SEQ_REG(0); SCL_OUT <= SEQ_REG(1); SDA_RW <= SEQ_REG(2); else SDA_OUT <= '1'; SCL_OUT <= '1'; SDA_RW <= '1'; end if; end process; -------------------------- SCL <= SCL_OUT; -------------------------------------------- -- Bi-directional IO for the I2C port -------------------------------------------- process(SDA_RW, SDA_OUT) begin if (SDA_RW = '0') then SDA <= SDA_OUT; else SDA <= 'Z'; end if; end process; -------------------------- SDA_INP <= SDA; -------------------------------------------- -- Latch ASIC data -------------------------------------------- process(RF_CLK, SDA_RW, SCL_OUT, SEQ_REG, SDA_INP) begin if (RF_CLK'event and RF_CLK = '0') then if (SDA_RW = '1' and SCL_OUT = '1') then case SEQ_REG(7 downto 3) is when "00000" => ACK_WRD(0) <= SDA_INP; when "00001" => ACK_WRD(1) <= SDA_INP; when "00010" => ACK_WRD(2) <= SDA_INP; when "00011" => ACK_WRD(3) <= SDA_INP; when "00100" => ACK_WRD(4) <= SDA_INP; when "00101" => ACK_WRD(5) <= SDA_INP; when "00110" => ACK_WRD(6) <= SDA_INP; when "00111" => ACK_WRD(7) <= SDA_INP; when "01000" => ACK_WRD(8) <= SDA_INP; when "01001" => ACK_WRD(9) <= SDA_INP; when "01010" => ACK_WRD(10) <= SDA_INP; when "01011" => ACK_WRD(11) <= SDA_INP; when "01100" => ACK_WRD(12) <= SDA_INP; when "01101" => ACK_WRD(13) <= SDA_INP; when "01110" => ACK_WRD(14) <= SDA_INP; when "01111" => ACK_WRD(15) <= SDA_INP; when "10000" => ACK_WRD(16) <= SDA_INP; when "10001" => ACK_WRD(17) <= SDA_INP; when "10010" => ACK_WRD(18) <= SDA_INP; when "10011" => ACK_WRD(19) <= SDA_INP; when "10100" => ACK_WRD(20) <= SDA_INP; when "10101" => ACK_WRD(21) <= SDA_INP; when "10110" => ACK_WRD(22) <= SDA_INP; when "10111" => ACK_WRD(23) <= SDA_INP; when "11000" => ACK_WRD(24) <= SDA_INP; when "11001" => ACK_WRD(25) <= SDA_INP; when "11010" => ACK_WRD(26) <= SDA_INP; when "11011" => ACK_WRD(27) <= SDA_INP; when "11100" => ACK_WRD(28) <= SDA_INP; when "11101" => ACK_WRD(29) <= SDA_INP; when "11110" => ACK_WRD(30) <= SDA_INP; when others => ACK_WRD(31) <= SDA_INP; end case; else null; end if; end if; end process; -------------------------------------------- -- Output ASIC data -------------------------------------------- process(TX_CLK, DAT_CNT, ACK_WRD) begin if (TX_CLK'event and TX_CLK = '1') then case DAT_CNT is when 0 => ACK_DAT <= ACK_WRD(7 downto 0); when 1 => ACK_DAT <= ACK_WRD(15 downto 8); when 2 => ACK_DAT <= ACK_WRD(23 downto 16); when others => ACK_DAT <= ACK_WRD(31 downto 24); end case; end if; end process; -------------------------------------------- -------------------------------------------- -- Load delay line (write only) -------------------------------------------- process(COM_REG, SEQ_GTE, SEQ_REG) begin if (COM_REG = x"04" and SEQ_GTE = '1') then SI <= SEQ_REG(0); SCLK <= SEQ_REG(1); AE <= SEQ_REG(2); else SI <= '0'; SCLK <= '0'; AE <= '0'; end if; end process; -------------------------------------------- -- Load latency register -------------------------------------------- process(RF_CLK, ADR_CNT, COM_DEL, USB_INP) begin if (RF_CLK'event and RF_CLK = '1') then if (ADR_CNT = 3 and COM_DEL = x"05") then LAT_REG(7 downto 0) <= USB_INP; else null; end if; end if; end process; -------------------------- LAT_REG(8) <= '0'; -------------------------------------------- -- Load event readout packet length register -------------------------------------------- process(RF_CLK, ADR_CNT, COM_DEL, USB_INP) begin if (RF_CLK'event and RF_CLK = '1') then if (ADR_CNT = 3 and COM_DEL = x"07") then RPL_REG(9 downto 8) <= USB_INP(1 downto 0); elsif (ADR_CNT = 4 and COM_DEL = x"07") then RPL_REG(7 downto 0) <= USB_INP; else null; end if; end if; end process; -------------------------------------------- -------------------------------------------- -- ADC module -------------------------------------------- -- Synchronize Data Valid with clock -------------------------------------------- process(RUN_ENA, DATAVALID0, CLK_000, CLK_090, CLK_180, CLK_270) begin if (RUN_ENA = '0') then ADC_PH0 <= (others => '0'); elsif (DATAVALID0'event and DATAVALID0 = '1') then ADC_PH0(0) <= CLK_000; ADC_PH0(1) <= CLK_090; ADC_PH0(2) <= CLK_180; ADC_PH0(3) <= CLK_270; end if; end process; -------------------------- process(RUN_ENA, DATAVALID1, CLK_000, CLK_090, CLK_180, CLK_270) begin if (RUN_ENA = '0') then ADC_PH1 <= (others => '0'); elsif (DATAVALID1'event and DATAVALID1 = '1') then ADC_PH1(0) <= CLK_000; ADC_PH1(1) <= CLK_090; ADC_PH1(2) <= CLK_180; ADC_PH1(3) <= CLK_270; end if; end process; -------------------------------------------- -- Adjust clock phase for ADCs -- (trailing edge is required) -------------------------------------------- process(ADC_PH0, CTR_REG, CLK_000, CLK_090, CLK_180, CLK_270, FE_CLK) begin case ADC_PH0(1 downto 0) is when "01" => case CTR_REG(5 downto 4) is when "00" => ADC_CL0 <= CLK_090; when "01" => ADC_CL0 <= CLK_180; when "10" => ADC_CL0 <= CLK_270; when others => ADC_CL0 <= CLK_000; end case; when "11" => case CTR_REG(5 downto 4) is when "00" => ADC_CL0 <= CLK_180; when "01" => ADC_CL0 <= CLK_270; when "10" => ADC_CL0 <= CLK_000; when others => ADC_CL0 <= CLK_090; end case; when "10" => case CTR_REG(5 downto 4) is when "00" => ADC_CL0 <= CLK_270; when "01" => ADC_CL0 <= CLK_000; when "10" => ADC_CL0 <= CLK_090; when others => ADC_CL0 <= CLK_180; end case; when others => case CTR_REG(5 downto 4) is when "00" => ADC_CL0 <= CLK_000; when "01" => ADC_CL0 <= CLK_090; when "10" => ADC_CL0 <= CLK_180; when others => ADC_CL0 <= CLK_270; end case; end case; end process; -------------------------- process(ADC_PH1, CTR_REG, CLK_000, CLK_090, CLK_180, CLK_270, FE_CLK) begin case ADC_PH1(1 downto 0) is when "01" => case CTR_REG(5 downto 4) is when "00" => ADC_CL1 <= CLK_090; when "01" => ADC_CL1 <= CLK_180; when "10" => ADC_CL1 <= CLK_270; when others => ADC_CL1 <= CLK_000; end case; when "11" => case CTR_REG(5 downto 4) is when "00" => ADC_CL1 <= CLK_180; when "01" => ADC_CL1 <= CLK_270; when "10" => ADC_CL1 <= CLK_000; when others => ADC_CL1 <= CLK_090; end case; when "10" => case CTR_REG(5 downto 4) is when "00" => ADC_CL1 <= CLK_270; when "01" => ADC_CL1 <= CLK_000; when "10" => ADC_CL1 <= CLK_090; when others => ADC_CL1 <= CLK_180; end case; when others => case CTR_REG(5 downto 4) is when "00" => ADC_CL1 <= CLK_000; when "01" => ADC_CL1 <= CLK_090; when "10" => ADC_CL1 <= CLK_180; when others => ADC_CL1 <= CLK_270; end case; end case; end process; -------------------------- SCLK0 <= ADC_CL0; SCLK1 <= ADC_CL1; -------------------------------------------- -- Latch data valid -------------------------------------------- process(FE_RES, DATAVALID0) begin if (FE_RES = '1') then ADC_DV0 <= '0'; elsif (DATAVALID0'event and DATAVALID0 = '1') then ADC_DV0 <= '1'; end if; end process; -------------------------- process(FE_RES, DATAVALID1) begin if (FE_RES = '1') then ADC_DV1 <= '0'; elsif (DATAVALID1'event and DATAVALID1 = '1') then ADC_DV1 <= '1'; end if; end process; -------------------------------------------- -- Data sampling (CLK <-) -------------------------------------------- process(ADC_CL0, ADC_DV0) begin if (ADC_CL0'event and ADC_CL0 = '0') then ADC_DS0 <= ADC_DV0; end if; end process; -------------------------- process(ADC_CL1, ADC_DV1) begin if (ADC_CL1'event and ADC_CL1 = '0') then ADC_DS1 <= ADC_DV1; end if; end process; -------------------------------------------- -- End of ADC frame (CLK <-) -------------------------------------------- process(ADC_CL0, ADC_CN0) begin if (ADC_CL0'event and ADC_CL0 = '0') then if (ADC_CN0 > 160) then ADC_EP0 <= '1'; else ADC_EP0 <= '0'; end if; end if; end process; -------------------------- process(ADC_CL1, ADC_CN1) begin if (ADC_CL1'event and ADC_CL1 = '0') then if (ADC_CN1 > 160) then ADC_EP1 <= '1'; else ADC_EP1 <= '0'; end if; end if; end process; -------------------------------------------- -- Incrementing RAM address (CLK ->) -------------------------------------------- process(ADC_CL0, ADC_DS0, ADC_EP0) begin if (ADC_CL0'event and ADC_CL0 = '1') then if (ADC_DS0 = '0') then ADC_CN0 <= 0; elsif (ADC_EP0 = '0') then ADC_CN0 <= ADC_CN0 + 1; else null; end if; end if; end process; -------------------------- process(ADC_CL1, ADC_DS1, ADC_EP1) begin if (ADC_CL1'event and ADC_CL1 = '1') then if (ADC_DS1 = '0') then ADC_CN1 <= 0; elsif (ADC_EP1 = '0') then ADC_CN1 <= ADC_CN1 + 1; else null; end if; end if; end process; -------------------------- ADC_WA0 <= conv_std_logic_vector(ADC_CN0, 8); ADC_WA1 <= conv_std_logic_vector(ADC_CN1, 8); -------------------------------------------- -------------------------------------------- -- Data storage unit -------------------------------------------- -- RAM address and clock multiplexor -------------------------------------------- process(RAM_WE0, ADC_WA0, TX_RA0, ADC_CL0, TX_CLK) begin if (RAM_WE0 = "1") then RAM_AD0 <= ADC_WA0; RAM_CL0 <= not ADC_CL0; else RAM_AD0 <= TX_RA0; RAM_CL0 <= TX_CLK; end if; end process; -------------------------- process(RAM_WE1, ADC_WA1, TX_RA1, ADC_CL1, TX_CLK) begin if (RAM_WE1 = "1") then RAM_AD1 <= ADC_WA1; RAM_CL1 <= not ADC_CL1; else RAM_AD1 <= TX_RA1; RAM_CL1 <= TX_CLK; end if; end process; -------------------------------------------- -- RAM write enable (CLK->) -------------------------------------------- process(ADC_CN0) begin case ADC_CN0 is when 0 to 160 => RAM_WE0 <= "1"; when others => RAM_WE0 <= "0"; end case; end process; -------------------------- process(ADC_CN1) begin case ADC_CN1 is when 0 to 160 => RAM_WE1 <= "1"; when others => RAM_WE1 <= "0"; end case; end process; -------------------------------------------- -- Memory for amplitudes (CLK <-) -- Address, Data and WE (CLK ->) -------------------------------------------- U2: ram port map ( clka => RAM_CL0, wea => RAM_WE0, addra => RAM_AD0, dina => DIN0, douta => DOUT0); -------------------------- U3: ram port map ( clka => RAM_CL1, wea => RAM_WE1, addra => RAM_AD1, dina => DIN1, douta => DOUT1); -------------------------------------------- -------------------------------------------- -- TDC module -------------------------------------------- -- Gates for counters -------------------------------------------- process(CLK_090, TRG_PUL) begin if (CLK_090'event and CLK_090 = '1') then TRG_090 <= TRG_PUL; end if; end process; -------------------------- process(CLK_180, TRG_PUL) begin if (CLK_180'event and CLK_180 = '1') then TRG_180 <= TRG_PUL; end if; end process; -------------------------- process(CLK_270, TRG_PUL) begin if (CLK_270'event and CLK_270 = '1') then TRG_270 <= TRG_PUL; end if; end process; -------------------------------------------- -- 000 phase counter -------------------------------------------- process(CLK_000, TRG_BLK) begin if (CLK_000'event and CLK_000 = '1') then if (TRG_BLK = '0') then CNT_000 <= 0; else CNT_000 <= CNT_000 + 1; end if; end if; end process; -------------------------------------------- -- 090 phase counter -------------------------------------------- process(CLK_090, TRG_BLK) begin if (CLK_090'event and CLK_090 = '1') then if (TRG_BLK = '0') then CNT_090 <= 0; else CNT_090 <= CNT_090 + 1; end if; end if; end process; -------------------------------------------- -- 180 phase counter -------------------------------------------- process(CLK_180, TRG_BLK) begin if (CLK_180'event and CLK_180 = '1') then if (TRG_BLK = '0') then CNT_180 <= 0; else CNT_180 <= CNT_180 + 1; end if; end if; end process; -------------------------------------------- -- 270 phase counter -------------------------------------------- process(CLK_270, TRG_BLK) begin if (CLK_270'event and CLK_270 = '1') then if (TRG_BLK = '0') then CNT_270 <= 0; else CNT_270 <= CNT_270 + 1; end if; end if; end process; -------------------------------------------- -- Keep counter results -------------------------------------------- process(CLK_000, TRG_PUL) begin if (CLK_000'event and CLK_000 = '0') then if (TRG_PUL = '1') then TDC_000 <= conv_std_logic_vector(CNT_000, 8); else null; end if; end if; end process; -------------------------- process(CLK_090, TRG_090) begin if (CLK_090'event and CLK_090 = '0') then if (TRG_090 = '1') then TDC_090 <= conv_std_logic_vector(CNT_090, 8); else null; end if; end if; end process; -------------------------- process(CLK_180, TRG_180) begin if (CLK_180'event and CLK_180 = '0') then if (TRG_180 = '1') then TDC_180 <= conv_std_logic_vector(CNT_180, 8); else null; end if; end if; end process; -------------------------- process(CLK_270, TRG_270) begin if (CLK_270'event and CLK_270 = '0') then if (TRG_270 = '1') then TDC_270 <= conv_std_logic_vector(CNT_270, 8); else null; end if; end if; end process; -------------------------------------------- -- Correction bit -------------------------------------------- process(TRG_BLK, CLK_FX) begin if (TRG_BLK'event and TRG_BLK = '1') then TDC_COR <= CLK_FX; end if; end process; -------------------------------------------- -------------------------------------------- -- NTC module (temperature measurement) -------------------------------------------- U4: ntc port map ( Clock => OSC_CLK, nCS => T_NCS, SCLK => T_SCLK, SO => T_SO, Data => NTC_DAT); -------------------------------------------- -------------------------------------------- -- Transmitter module -------------------------------------------- -- Clock division for Read cycle -------------------------------------------- process(OSC_CLK, TX_CYC) begin if (OSC_CLK'event and OSC_CLK = '1') then if (TX_CYC = '1') then TX_ADV <= TX_ADV + 1; else TX_ADV <= 0; end if; end if; end process; -------------------------- process(OSC_CLK, TX_ADV) begin if (OSC_CLK'event and OSC_CLK = '0') then TX_CNT <= TX_ADV; end if; end process; -------------------------------------------- -- Send data to the MC -- (2 strobes for each RAM address) -------------------------------------------- process(OSC_CLK, WAT_DOG, TX_CNT) begin if (OSC_CLK'event and OSC_CLK = '1') then if (WAT_DOG = '0') then TX_STB <= '1'; else case TX_CNT is when 1 => TX_STB <= '0'; when 3 => TX_STB <= '1'; when 5 => TX_STB <= '0'; when 7 => TX_STB <= '1'; when others => null; end case; end if; end if; end process; -------------------------------------------- -- Connect Xilinx read strobes to the USB -- bus when the Motherboard is addressed -------------------------------------------- process(TX_CYC, TX_STB) begin if (TX_CYC = '1') then WR <= TX_STB; else WR <= 'Z'; end if; end process; -------------------------------------------- -- Watchdog is needed to skip the first -- strobe when the data are not yet ready -------------------------------------------- process(OSC_CLK, TX_CYC, TX_CNT) begin if (OSC_CLK'event and OSC_CLK = '1') then if (TX_CYC = '0') then WAT_DOG <= '0'; elsif (TX_CNT = 4) then WAT_DOG <= '1'; else null; end if; end if; end process; -------------------------------------------- -- RAM read address -------------------------------------------- process(FE_RES, TX_CLK) begin if (FE_RES = '1') then DAT_CNT <= 0; elsif (TX_CLK'event and TX_CLK = '0') then DAT_CNT <= DAT_CNT + 1; end if; end process; -------------------------- TX_RA0 <= conv_std_logic_vector((DAT_CNT-5), 8); TX_RA1 <= conv_std_logic_vector((DAT_CNT-165), 8); -------------------------------------------- -- RAM read clock -------------------------------------------- process(OSC_CLK, TX_CYC, TX_CNT) begin if (OSC_CLK'event and OSC_CLK = '1') then if (TX_CYC = '1') then case TX_CNT is when 1 => TX_CLK <= '1'; when 5 => TX_CLK <= '0'; when others => null; end case; else TX_CLK <= '0'; end if; end if; end process; -------------------------------------------- -- Data output multiplexor -------------------------------------------- process(TX_CLK, DAT_CNT) begin if (TX_CLK'event and TX_CLK = '1') then MUX_CNT <= DAT_CNT; end if; end process; -------------------------------------------- -- Compile output data packet -------------------------------------------- process(OSC_CLK, MUX_CNT, TX_CNT, STA_REG, ADC_PH1, ADC_PH0, EVT_NUM, TDC_000, TDC_090, TDC_180, TDC_270, DOUT0, DOUT1, NTC_DAT) begin if (OSC_CLK'event and OSC_CLK = '1') then case MUX_CNT is when 0 => case TX_CNT is when 3 => EVT_DAT <= STA_REG; when 7 => EVT_DAT(7 downto 4) <= ADC_PH1; EVT_DAT(3 downto 0) <= ADC_PH0; when others => null; end case; when 1 => case TX_CNT is when 3 => EVT_DAT <= EVT_NUM(31 downto 24); when 7 => EVT_DAT <= EVT_NUM(23 downto 16); when others => null; end case; when 2 => case TX_CNT is when 3 => EVT_DAT <= EVT_NUM(15 downto 8); when 7 => EVT_DAT <= EVT_NUM(7 downto 0); when others => null; end case; when 3 => case TX_CNT is when 3 => EVT_DAT <= TDC_000; when 7 => EVT_DAT <= TDC_090; when others => null; end case; when 4 => case TX_CNT is when 3 => EVT_DAT <= TDC_180; when 7 => EVT_DAT <= TDC_270; when others => null; end case; when 5 to 164 => case TX_CNT is when 3 => EVT_DAT(7 downto 2) <= "000000"; EVT_DAT(1 downto 0) <= DOUT0(9 downto 8); when 7 => EVT_DAT <= DOUT0(7 downto 0); when others => null; end case; when 165 to 324 => case TX_CNT is when 3 => EVT_DAT(7 downto 2) <= "000000"; EVT_DAT(1 downto 0) <= DOUT1(9 downto 8); when 7 => EVT_DAT <= DOUT1(7 downto 0); when others => null; end case; when 325 => case TX_CNT is when 3 => EVT_DAT(7 downto 3) <= "00000"; EVT_DAT(2 downto 0) <= NTC_DAT(10 downto 8); when 7 => EVT_DAT <= NTC_DAT(7 downto 0); when others => null; end case; when others => EVT_DAT <= (others => '0'); end case; end if; end process; -------------------------------------------- -- event / control data readout -------------------------------------------- process(COM_REG, ACK_DAT, EVT_DAT) begin if (COM_REG = x"03") then USB_OUT <= ACK_DAT; else USB_OUT <= EVT_DAT; end if; end process; -------------------------------------------- -------------------------------------------- -- Manual control -------------------------------------------- -- 100 ns latency for the "reset" button -------------------------------------------- process(FE_CLK, EXT_RST, BUT_STP) begin if (FE_CLK'event and FE_CLK = '0') then if (EXT_RST = '1') then if (BUT_STP = '0') then BUT_CNT <= BUT_CNT + 1; else null; end if; else BUT_CNT <= 0; end if; end if; end process; -------------------------------------------- -- Single action -------------------------------------------- process(FE_CLK, BUT_CNT) begin if (FE_CLK'event and FE_CLK = '1') then if (BUT_CNT > 16777200) then BUT_STP <= '1'; else BUT_STP <= '0'; end if; end if; end process; -------------------------------------------- -- Manual reset pulse -------------------------------------------- process(FE_CLK, BUT_CNT) begin if (FE_CLK'event and FE_CLK = '1') then if (BUT_CNT = 16777198) then BUT_RES <= '1'; elsif (BUT_CNT = 16777200) then BUT_RES <= '0'; else null; end if; end if; end process; -------------------------------------------- -- Automatic reset will be used for -- a stand-alone motherboard -------------------------------------------- -- Reset counters -------------------------------------------- process(FE_CLK, RF_CYC, SIN_EOF) begin if (FE_CLK'event and FE_CLK = '0') then if (RF_CYC = '1') then SIN_CNT <= 0; elsif (SIN_EOF = '0') then SIN_CNT <= SIN_CNT + 1; else null; end if; end if; end process; -------------------------- process(FE_CLK, TX_CYC, MUL_EOF) begin if (FE_CLK'event and FE_CLK = '0') then if (TX_CYC = '1') then MUL_CNT <= 0; elsif (MUL_EOF = '0') then MUL_CNT <= MUL_CNT + 1; else null; end if; end if; end process; -------------------------------------------- -- Counter silencers -------------------------------------------- process(FE_CLK, SIN_CNT) begin if (FE_CLK'event and FE_CLK = '1') then if (SIN_CNT = 5) then SIN_EOF <= '1'; else SIN_EOF <= '0'; end if; end if; end process; -------------------------- process(FE_CLK, MUL_CNT) begin if (FE_CLK'event and FE_CLK = '1') then if (MUL_CNT = 5) then MUL_EOF <= '1'; else MUL_EOF <= '0'; end if; end if; end process; -------------------------------------------- -- Reset strobes -------------------------------------------- process(FE_CLK, SIN_CNT) begin if (FE_CLK'event and FE_CLK = '1') then if (SIN_CNT = 2) then SIN_RES <= '1'; elsif (SIN_CNT = 4) then SIN_RES <= '0'; else null; end if; end if; end process; -------------------------- process(FE_CLK, MUL_CNT) begin if (FE_CLK'event and FE_CLK = '1') then if (MUL_CNT = 2) then MUL_RES <= '1'; elsif (MUL_CNT = 4) then MUL_RES <= '0'; else null; end if; end if; end process; -------------------------------------------- -- Combined reset: single after run start -- and repetitive after each event readout -------------------------------------------- DAT_CNV(9 downto 1) <= conv_std_logic_vector(DAT_CNT, 9); DAT_CNV(0) <= '0'; -------------------------- process(COM_REG, DAT_CNV, RPL_REG, SIN_RES, MUL_RES) begin if (COM_REG = x"08") then if (DAT_CNV >= RPL_REG) then PC_RES <= SIN_RES or MUL_RES; else PC_RES <= SIN_RES; end if; else PC_RES <= '0'; end if; end process; -------------------------------------------- -- Select between external / automatic reset -------------------------------------------- process(CTR_REG, BUT_RES, PC_RES, EXT_RES) begin case CTR_REG(2) is when '1' => FE_RES <= BUT_RES or PC_RES; when others => FE_RES <= BUT_RES or (not EXT_RES); end case; end process; -------------------------------------------- -- LED indicators -- green = trigger and reset activity -- read = clock and access -------------------------------------------- -- Read / write Access -------------------------------------------- RW_CYC <= RF_CYC or TX_CYC; -------------------------- process(LED_OFF, RW_CYC) begin if (LED_OFF = '1') then LED_GTE <= '0'; elsif (RW_CYC'event and RW_CYC = '1') then LED_GTE <= '1'; end if; end process; -------------------------------------------- -- Lit duration counter -------------------------------------------- process(FE_CLK, LED_GTE) begin if (FE_CLK'event and FE_CLK = '1') then if (LED_GTE = '1') then LED_CNT <= LED_CNT + 1; else LED_CNT <= 0; end if; end if; end process; -------------------------------------------- -- LED switch off -------------------------------------------- process(FE_CLK, LED_CNT) begin if (FE_CLK'event and FE_CLK = '0') then if (LED_CNT = 4194303) then LED_OFF <= '1'; else LED_OFF <= '0'; end if; end if; end process; -------------------------------------------- -- LED drivers -------------------------------------------- RED_LED <= LED_GTE; GREEN_LED <= TRG_BLK; -------------------------------------------- end Behavioral;