-- VME interface program for the standard (A24) -- supervisory and non-privileged data access. -- The full address = Base Address + Extension -- Registers: -------------------------- -- x0000 (IN0_REG, 4 bits) RM mask for the FTI_0_south, Channels 0..3; -- x0002 (IN1_REG, 4 bits) RM mask for the FTI_0_south, Channels 4..7; -- x0004 (IN2_REG, 4 bits) RM mask for the FTI_0_south, Channels 8..11; -- x0006 (IN3_REG, 4 bits) RM mask for the FTI_0_south, Channels 12..15; -- x0008 (EX0_REG, 4 bits) RM mask for the FTI_0_north, Channels 0..3; -- x000A (EX1_REG, 4 bits) RM mask for the FTI_0_north, Channels 4..7; -- x000C (EX2_REG, 4 bits) RM mask for the FTI_0_north, Channels 8..11; -- x000E (EX3_REG, 4 bits) RM mask for the FTI_0_north, Channels 12..15; -- x0010 (CLK_FT0, 4 bits) HERA clock tuning for the FTI_0 in 10 steps of 10 ns; -- x0012 (CLK_FT2, 4 bits) HERA clock tuning for the FTI_2 in 10 steps of 10 ns; -- x0014 (CLK_PAD, 4 bits) HERA clock tuning for the BSTP in 10 steps of 10 ns; -- x0016 (DEL_FT0, 4 bits) Delay (in HERA b.c.) for the FTI_0 signals -- x0018 (DEL_FT2, 4 bits) Delay (in HERA b.c.) for the FTI_2 signals -- x001A (PED_REG, 4 bits) Number * 1kHz subtracted from rad. monitor rate; -- -- x001C (ST_RATE, 1 bit) Bit_0 = '1' stucks the rad. monitor rate; -- x001E (RAD_ALM, 4 bit) Radiation level 0...5 MHz (250 kHz / unit); -- x0020 (WDG_REG, 5 bit) Power watchdog (Bit_X = '0' - alarm); -------------------------------------------- -- Copyright I.Tsurin, University of Antwerpen, -- on behalf of DESY. -------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.numeric_std.all; -- OK. Here the entity starts... -------------------------------------------- entity VMEinter is port( SysCLK: in std_logic; SEL_ADD: in std_logic_vector(7 downto 0); Reserve: in std_logic; -- Former RXD (input) Rdata: inout std_logic_vector(3 downto 0); Raddr: out std_logic_vector(3 downto 0); Write: out std_logic; -- Former TXD (input) RDstb: out std_logic; Spare: in std_logic_vector(7 downto 0); nSetFER: in std_logic; L2KPul: in std_logic; FERout: out std_logic; VME_ADD: in std_logic_vector(23 downto 1); nLWord: in std_logic; nWrite: in std_logic; VME_DAT: inout std_logic_vector(15 downto 0); DTACK: out std_logic; BError: out std_logic; VME_AM: in std_logic_vector(5 downto 0); nAS: in std_logic; nIACK: in std_logic; nSRes: in std_logic; Direct: out std_logic; nDatEN: out std_logic; nDS0: in std_logic; nDS1: in std_logic; Quartz: in std_logic; LAM0: in std_logic_vector(2 downto 0); LAM1: in std_logic_vector(2 downto 0); FERin: in std_logic_vector(1 downto 0); P18_Ok: in std_logic; P25_Ok: in std_logic; P33_Ok: in std_logic; N50_Ok: in std_logic; P50_Ok: in std_logic ); attribute pinnum: string; attribute pinnum of SysCLK: signal is "7"; attribute pinnum of SEL_ADD: signal is "10,9,8,144,14,13,12,11"; attribute pinnum of Reserve: signal is "17"; attribute pinnum of Raddr: signal is "20,21,22,23"; attribute pinnum of Rdata: signal is "26,27,28,29"; attribute pinnum of Write: signal is "18"; attribute pinnum of RDstb: signal is "19"; attribute pinnum of Spare: signal is "30,31,32,33,36,37,38,39"; attribute pinnum of nSetFER: signal is "41"; attribute pinnum of L2KPul: signal is "42"; attribute pinnum of FERout: signal is "43"; attribute pinnum of VME_ADD: signal is "82,81,80,79,78,73,72,70,69,68,67,65,64,63,62,60,59,51,49,48,47,46,44"; attribute pinnum of nLWord: signal is "54"; attribute pinnum of nWrite: signal is "56"; attribute pinnum of VME_DAT: signal is "83,86,87,88,89,90,91,92,95,96,97,98,99,100,101,102"; attribute pinnum of DTACK: signal is "119"; attribute pinnum of BError: signal is "120"; attribute pinnum of VME_AM: signal is "114,113,112,111,110,109"; attribute pinnum of nAS: signal is "116"; attribute pinnum of nIACK: signal is "117"; attribute pinnum of nSRes: signal is "118"; attribute pinnum of Direct: signal is "121"; attribute pinnum of nDatEN: signal is "122"; attribute pinnum of nDS1: signal is "126"; attribute pinnum of nDS0: signal is "124"; attribute pinnum of Quartz: signal is "125"; attribute pinnum of LAM0: signal is "131,130,128"; attribute pinnum of LAM1: signal is "135,133,132"; attribute pinnum of FERin: signal is "137,136"; attribute pinnum of P18_Ok: signal is "138"; attribute pinnum of P25_Ok: signal is "140"; attribute pinnum of P33_Ok: signal is "141"; attribute pinnum of N50_Ok: signal is "142"; attribute pinnum of P50_Ok: signal is "143"; end; architecture behavior of VMEinter is -- Initialization -------------------------------------------- signal DUM_RES: std_logic; signal RES_PUL: std_logic; signal INI_CNT: natural range 0 to 524287; -------------------------------------------- -- VME variables -------------------------------------------- signal nAS_CNT: natural range 0 to 3; signal nDS_CNT: natural range 0 to 7; signal nAS_BLK: std_logic; signal nDS_BLK: std_logic; signal BAS_SEL: std_logic_vector(7 downto 0); signal BAS_ADR: std_logic; signal VMD_INP: std_logic_vector(15 downto 0); signal VMD_OUT: std_logic_vector(15 downto 0); signal VMA_INP: std_logic_vector(23 downto 1); alias REG_ADR: std_logic_vector(5 downto 1) is VMA_INP(5 downto 1); signal VMM_INP: std_logic_vector(5 downto 0); signal NLN_WRD: std_logic; signal DAT_ACC: std_logic; signal RDY_EXE: std_logic; signal ACTION: std_logic; signal MOD_ACT: std_logic; signal DAT_ACK: std_logic; -------------------------------------------- -- Indicators -------------------------------------------- signal PWR_REG: std_logic_vector(4 downto 0); signal WDG_REG: std_logic_vector(4 downto 0); signal WDG_CLR: std_logic; -------------------------------------------- begin -- Permanent statements -------------------------------------------- FERout <= '1'; DUM_RES <= '0'; ------------------------- BAS_SEL(7) <= not SEL_ADD(7); BAS_SEL(6) <= not SEL_ADD(6); BAS_SEL(5) <= not SEL_ADD(5); BAS_SEL(4) <= not SEL_ADD(4); BAS_SEL(3) <= not SEL_ADD(3); BAS_SEL(2) <= not SEL_ADD(2); BAS_SEL(1) <= not SEL_ADD(1); BAS_SEL(0) <= not SEL_ADD(0); ------------------------- Write <= not nWrite; Raddr <= VMA_INP(4 downto 1); -------------------------------------------- -- Start-up counter -------------------------------------------- process(DUM_RES, SysCLK, RES_PUL) begin if (DUM_RES = '1') then INI_CNT <= 0; elsif (SysCLK'event and SysCLK = '1') then if (RES_PUL = '1') then INI_CNT <= INI_CNT + 1; else null; end if; end if; end process; -------------------------------------------- -- Start-up reset pulse (SysCLK <-) -------------------------------------------- process(DUM_RES, SysCLK, INI_CNT) begin if (DUM_RES = '1') then RES_PUL <= '1'; elsif (SysCLK'event and SysCLK = '0') then if (INI_CNT = 524287) then RES_PUL <= '0'; else RES_PUL <= '1'; end if; end if; end process; -------------------------------------------- -- Bidirectional port for the VME interface: -------------------------------------------- process(nWrite, VMD_OUT) begin if (nWrite = '0') then VME_DAT <= (others => 'Z'); else VME_DAT <= VMD_OUT; end if; end process; -------------------------- VMD_INP <= VME_DAT; -------------------------------------------- -- Biderectional ACEX <-> APEX port -------------------------------------------- process(nWrite, VMD_INP) begin if (nWrite = '0') then Rdata <= VMD_INP(3 downto 0); else Rdata <= (others => 'Z'); end if; end process; -------------------------------------------- -- Forming the output data -------------------------------------------- process(REG_ADR, WDG_REG, Rdata) begin case REG_ADR is when "10000" => VMD_OUT(15 downto 5) <= "00000000000"; VMD_OUT(4 downto 0) <= WDG_REG; when others => VMD_OUT(15 downto 4) <= "000000000000"; VMD_OUT(3 downto 0) <= Rdata; end case; end process; -------------------------------------------- -- Address strobe timer -------------------------------------------- process(RES_PUL, nAS, SysCLK, nAS_BLK) begin if (RES_PUL = '1' or nAS = '1') then nAS_CNT <= 0; elsif (SysCLK'event and SysCLK = '1') then if (nAS_BLK = '0') then nAS_CNT <= nAS_CNT + 1; else null; end if; end if; end process; -------------------------- process(nAS, SysCLK, nAS_CNT) begin if (nAS = '1') then nAS_BLK <= '0'; elsif (SysCLK'event and SysCLK = '0') then if (nAS_CNT = 3) then nAS_BLK <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Latching the input address and modifier -------------------------------------------- process(nAS, SysCLK, nAS_CNT, nLWord, VME_ADD, VME_AM) begin if (nAS = '1') then NLN_WRD <= '1'; VMA_INP <= (others => '0'); VMM_INP <= (others => '0'); elsif (SysCLK'event and SysCLK = '0') then if (nAS_CNT = 2) then NLN_WRD <= nLWord; VMA_INP <= VME_ADD; VMM_INP <= VME_AM; else null; end if; end if; end process; -------------------------------------------- -- Check for the base address matching -------------------------------------------- process(VMA_INP, BAS_SEL) begin if (VMA_INP(23 downto 16) = BAS_SEL(7 downto 0)) then BAS_ADR <= '1'; else BAS_ADR <= '0'; end if; end process; -------------------------------------------- -- Data access regime (SysCLK <-) -------------------------------------------- process(VMM_INP) begin case VMM_INP is when "111101" => DAT_ACC <= '1'; when "111001" => DAT_ACC <= '1'; when others => DAT_ACC <= '0'; end case; end process; -------------------------------------------- -- Operation decoding (SysCLK <-) -------------------------------------------- process(VMA_INP) begin if ("000000000000000" <= VMA_INP(15 downto 1) and VMA_INP(15 downto 1) <= "000000000010000") then RDY_EXE <= '1'; else RDY_EXE <= '0'; end if; end process; -------------------------------------------- -- VME module activation (SysCLK <-) -------------------------------------------- ACTION <= NLN_WRD and RDY_EXE and DAT_ACC; MOD_ACT <= BAS_ADR and ACTION and nIACK; -------------------------------------------- -- Enable data operation (SysCLK <-) -------------------------------------------- process(MOD_ACT, nDS0) begin if (MOD_ACT = '1' and nDS0 = '0') then nDatEN <= '0'; else nDatEN <= '1'; end if; end process; -------------------------------------------- -- VME data flow direction -------------------------------------------- process(nWrite) begin if (nWrite = '0') then Direct <= '0'; else Direct <= '1'; end if; end process; -------------------------------------------- -- Data strobe timer -------------------------------------------- process(nDS0, SysCLK, nDS_BLK) begin if (nDS0 = '1') then nDS_CNT <= 0; elsif (SysCLK'event and SysCLK = '0') then if (nDS_BLK = '0') then nDS_CNT <= nDS_CNT + 1; else null; end if; end if; end process; -------------------------- process(nDS0, SysCLK, nDS_CNT) begin if (nDS0 = '1') then nDS_BLK <= '0'; elsif (SysCLK'event and SysCLK = '1') then if (nDS_CNT = 5) then nDS_BLK <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Data acknowledge response (SysCLK ->) -------------------------------------------- process(nDS0, SysCLK, nDS_CNT, MOD_ACT) begin if (nDS0 = '1') then DAT_ACK <= '0'; elsif (SysCLK'event and SysCLK = '1') then if (nDS_CNT = 4 and MOD_ACT = '1') then DAT_ACK <= '1'; else null; end if; end if; end process; -------------------------- DTACK <= DAT_ACK; -------------------------------------------- -- Bus error response (SysCLK ->) -------------------------------------------- process(nDS0, SysCLK, nDS_CNT, BAS_ADR, ACTION) begin if (nDS0 = '1') then BError <= '0'; elsif (SysCLK'event and SysCLK = '1') then if (nDS_CNT = 3 and BAS_ADR = '1' and ACTION = '0') then BError <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Data strobe (SysCLK->) -------------------------------------------- process(SysCLK, MOD_ACT, nWrite, nDS_CNT) begin if (SysCLK'event and SysCLK = '1') then if (MOD_ACT = '1' and nWrite = '0') then if (nDS_CNT = 3) then RDstb <= '1'; elsif (nDS_CNT = 4) then RDstb <= '0'; else null; end if; else null; end if; end if; end process; -------------------------------------------- -- Power failure latch. The triggered -- watchdog will be cleared after the -- register readout. -------------------------------------------- process(P50_Ok, WDG_CLR) begin if (P50_Ok = '0') then PWR_REG(4) <= '0'; elsif (WDG_CLR'event and WDG_CLR = '0') then PWR_REG(4) <= '1'; end if; end process; -------------------------- process(P33_Ok, WDG_CLR) begin if (P33_Ok = '0') then PWR_REG(3) <= '0'; elsif (WDG_CLR'event and WDG_CLR = '0') then PWR_REG(3) <= '1'; end if; end process; -------------------------- process(P25_Ok, WDG_CLR) begin if (P25_Ok = '0') then PWR_REG(2) <= '0'; elsif (WDG_CLR'event and WDG_CLR = '0') then PWR_REG(2) <= '1'; end if; end process; -------------------------- process(P18_Ok, WDG_CLR) begin if (P18_Ok = '0') then PWR_REG(1) <= '0'; elsif (WDG_CLR'event and WDG_CLR = '0') then PWR_REG(1) <= '1'; end if; end process; -------------------------- process(N50_Ok, WDG_CLR) begin if (N50_Ok = '1') then PWR_REG(0) <= '0'; elsif (WDG_CLR'event and WDG_CLR = '0') then PWR_REG(0) <= '1'; end if; end process; -------------------------------------------- -- Latch status before readout (SysCLK->) -------------------------------------------- process(SysCLK, nDS_CNT, MOD_ACT, nWrite, REG_ADR, PWR_REG, FERin, LAM1, LAM0) begin if (SysCLK'event and SysCLK = '1') then if (nDS_CNT = 3 and MOD_ACT = '1' and nWrite = '1' and REG_ADR = "10000") then WDG_REG <= PWR_REG; else null; end if; end if; end process; -------------------------------------------- -- Clear power watchdogs (SysCLK ->) -------------------------------------------- process(nDS0, SysCLK, nDS_CNT, MOD_ACT, nWrite, REG_ADR) begin if (nDS0 = '1') then WDG_CLR <= '0'; elsif (SysCLK'event and SysCLK = '1') then if (nDS_CNT = 3 and MOD_ACT = '1' and nWrite = '1' and REG_ADR = "10000") then WDG_CLR <= '1'; else null; end if; end if; end process; -------------------------------------------- end;