-- PDS3 VME interface for the standard (A24) -- supervisory and non-privileged data access. -- The full address = Base Address + Extension. -- Write / Read functions: -------------------------------------------- -- Extension = 0000 - Power supply control; -- Extension = 0002 - Front-end reboot; -- Extension = 0004 - JTAG address select; -- Extension = 0006 - Low voltage status (r-o); -- Extension = 0008 - INI status (read-only); -- Extension = 000A - LAM status (read-only); -------------------------------------------- -- JTAG address select: -------------------------------------------- -- Data = 0000 0000 0000 0ADR (binary); -- ADR - coded front-end board number 0...5; -------------------------------------------- -- Front-end reboot, INI status, -- power control and monitoring: -------------------------------------------- -- Data = 0000 0000 00FF FFFF (binary); -- F_i - front-end board 'i' = 0...5; -- -- F_i = '1' - Operate / ON; -- F_i = '0' - Reboot / OFF; -------------------------------------------- -- LAM Status -------------------------------------------- -- Data = 0000 00RR 00FF FFFF (binary); -- F_i - front-end board 'i' = 0...5; -- R_8 - Repater card 1; -- R_9 - Repater card 2; -- -- F_i, R_j = '1' = ON; -- F_i, R_j = '0' = OFF; -------------------------------------------- -- 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 PDSmod is port( -- VME signals -------------------------------------------- VME_ADD: in std_logic_vector(15 downto 1); -- VME address; nBase_Ok: in std_logic; -- Match higher Byte; VME_AM: in std_logic_vector(5 downto 0); -- Address modifier; nLWord: in std_logic; nDS0: in std_logic; -- nDS1: in std_logic; (missing in the hardware) VME_DAT: inout std_logic_vector(15 downto 0); -- VME data; nWrite: in std_logic; nDatEN: out std_logic; DTACK: out std_logic; BError: out std_logic; nAS: in std_logic; nIACK: in std_logic; nSRES: in std_logic; SysCLK: in std_logic; -------------------------------------------- -- JTAG signals -------------------------------------------- TDO: in std_logic_vector(5 downto 0); -- TDO route from the JTAG; TDI: out std_logic_vector(5 downto 0); -- TDI route to the JTAG; TCK: out std_logic_vector(5 downto 0); -- TCK route to the JTAG; TMS: out std_logic_vector(5 downto 0); -- TMS route to the JTAG; TDO_Ext: out std_logic; -- TDO route to the ByteBlaster MV; TDI_Ext: in std_logic; -- TDI route from the ByteBlaster MV; TCK_Ext: in std_logic; -- TCK route from the ByteBlaster MV; TMS_Ext: in std_logic; -- TMS route from the ByteBlaster MV; -------------------------------------------- -- Front-end controls -------------------------------------------- PS_CT: out std_logic_vector(5 downto 0); -- Low and high voltage control; nWstart: out std_logic_vector(5 downto 0); -- Front-end reboot; -------------------------------------------- -- Front-end indictors -------------------------------------------- LV_ON: in std_logic_vector(5 downto 0); TINI: in std_logic_vector(5 downto 0); LAM: in std_logic_vector(5 downto 0); FER: in std_logic_vector(1 downto 0); -------------------------------------------- -- LED indicators -------------------------------------------- nLED_INI: out std_logic_vector(5 downto 0); nLED_CAN: out std_logic; nLED_VME: out std_logic; nLED_FER: out std_logic; nLED_LAM: out std_logic ); attribute pinnum: string; attribute pinnum of VME_ADD: signal is "47,46,45,44,41,40,39,38,37,36,31,30,29,28,27"; attribute pinnum of nBase_Ok: signal is "202"; attribute pinnum of VME_AM: signal is "203,204,205,206,207,208"; attribute pinnum of nLWord: signal is "126"; attribute pinnum of nDS0: signal is "78"; attribute pinnum of VME_DAT: signal is "26,25,24,19,18,17,16,15,14,13,12,11,10,9,8,7"; attribute pinnum of nWrite: signal is "80"; attribute pinnum of nDatEN: signal is "73"; attribute pinnum of DTACK: signal is "122"; attribute pinnum of BError: signal is "191"; attribute pinnum of nAS: signal is "125"; attribute pinnum of nIACK: signal is "71"; attribute pinnum of nSRES: signal is "120"; attribute pinnum of SysCLK: signal is "79"; attribute pinnum of TDO: signal is "167,113,176,89,111,112"; attribute pinnum of TDI: signal is "141,139,172,92,140,90"; attribute pinnum of TCK: signal is "135,132,166,180,136,179"; attribute pinnum of TMS: signal is "83,133,144,134,131,97"; attribute pinnum of TDO_Ext: signal is "114"; attribute pinnum of TDI_Ext: signal is "168"; attribute pinnum of TCK_Ext: signal is "184"; attribute pinnum of TMS_Ext: signal is "182"; attribute pinnum of PS_CT: signal is "75,88,87,86,85,53"; attribute pinnum of nWstart: signal is "200,199,198,197,196,195"; attribute pinnum of LV_ON: signal is "96,95,94,93,74,55"; attribute pinnum of TINI: signal is "99,100,101,102,103,104"; attribute pinnum of LAM: signal is "62,63,64,65,67,68"; attribute pinnum of FER: signal is "70,69"; attribute pinnum of nLED_INI: signal is "158,159,160,161,162,163"; attribute pinnum of nLED_CAN: signal is "121"; attribute pinnum of nLED_VME: signal is "150"; attribute pinnum of nLED_FER: signal is "164"; attribute pinnum of nLED_LAM: signal is "157"; end; architecture behavior of PDSmod 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_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(15 downto 1); alias REG_ADR: std_logic_vector(3 downto 1) is VMA_INP(3 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; -------------------------------------------- -- Control registers -------------------------------------------- signal PWR_CTR: std_logic_vector(5 downto 0); signal FED_INI: std_logic_vector(5 downto 0); signal JTAG_AD: std_logic_vector(2 downto 0); -------------------------------------------- -- Indicators -------------------------------------------- signal LV_REG: std_logic_vector(5 downto 0); signal INI_REG: std_logic_vector(5 downto 0); signal FER_REG: std_logic_vector(1 downto 0); signal LAM_REG: std_logic_vector(5 downto 0); signal VME_CNT: natural range 0 to 524287; signal VME_BLK: std_logic; -------------------------------------------- begin -- Permanent statements -------------------------------------------- DUM_RES <= '0'; ------------------------- PS_CT <= PWR_CTR; nWstart <= FED_INI; ------------------------- -- JTAG download status indicators -- (individually for every sector) ------------------------- nLED_INI(0) <= not TINI(0); nLED_INI(1) <= not TINI(1); nLED_INI(2) <= not TINI(2); nLED_INI(3) <= not TINI(3); nLED_INI(4) <= not TINI(4); nLED_INI(5) <= not TINI(5); ------------------------- -- Auxiliary indicators ------------------------- nLED_CAN <= not TCK_Ext; -- Indicates the JTAG operation; nLED_FER <= not (FER(1) and FER(0)); -- Lights when Repeater cards are OK; nLED_LAM <= not (LAM(5) or LAM(4) or -- Lights when at least one sector has LAM(3) or LAM(2) or -- been configured for the data taking; LAM(1) or LAM(0)); -------------------------------------------- -- 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; -------------------------------------------- -- 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, nBase_Ok, nLWord, VME_ADD, VME_AM) begin if (nAS = '1') then BAS_ADR <= '0'; NLN_WRD <= '1'; VMA_INP <= (others => '0'); VMM_INP <= (others => '0'); elsif (SysCLK'event and SysCLK = '0') then if (nAS_CNT = 2) then BAS_ADR <= not nBase_Ok; NLN_WRD <= nLWord; VMA_INP <= VME_ADD; VMM_INP <= VME_AM; else null; end if; 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 and VMA_INP <= "000000000000101") 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; -------------------------------------------- -- 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; -------------------------------------------- -- Latch the control data (SysCLK ->) -------------------------------------------- process(RES_PUL, SysCLK, nDS_CNT, MOD_ACT, nWrite, REG_ADR, VMD_INP) begin if (RES_PUL = '1') then PWR_CTR <= (others => '0'); -- power OFF; FED_INI <= (others => '1'); -- enable boot during power ON; JTAG_AD <= (others => '1'); -- JTAG function disabled; elsif (SysCLK'event and SysCLK = '1') then if (nDS_CNT = 3 and MOD_ACT = '1' and nWrite = '0') then if (REG_ADR = "000") then PWR_CTR(5 downto 0) <= VMD_INP(5 downto 0); elsif (REG_ADR = "001") then FED_INI(5 downto 0) <= VMD_INP(5 downto 0); elsif (REG_ADR = "010") then JTAG_AD(2 downto 0) <= VMD_INP(2 downto 0); else null; end if; else null; end if; end if; end process; -------------------------------------------- -- Keep the readout data (SysCLK ->) -------------------------------------------- process(SysCLK, nDS_CNT, MOD_ACT, nWrite, REG_ADR, LV_ON, TINI, FER, LAM) begin if (SysCLK'event and SysCLK = '1') then if (nDS_CNT = 3 and MOD_ACT = '1' and nWrite = '1') then if (REG_ADR = "011") then LV_REG <= LV_ON; elsif (REG_ADR = "100") then INI_REG <= TINI; elsif (REG_ADR = "101") then FER_REG <= FER; LAM_REG <= LAM; else null; end if; else null; end if; end if; end process; -------------------------------------------- -- Forming the output data -------------------------------------------- process(REG_ADR, PWR_CTR, FED_INI, JTAG_AD, LV_REG, INI_REG, FER_REG, LAM_REG) begin case REG_ADR is when "000" => VMD_OUT(15 downto 6) <= "0000000000"; VMD_OUT(5 downto 0) <= PWR_CTR(5 downto 0); when "001" => VMD_OUT(15 downto 6) <= "0000000000"; VMD_OUT(5 downto 0) <= FED_INI(5 downto 0); when "010" => VMD_OUT(15 downto 3) <= "0000000000000"; VMD_OUT(2 downto 0) <= JTAG_AD(2 downto 0); when "011" => VMD_OUT(15 downto 6) <= "0000000000"; VMD_OUT(5 downto 0) <= LV_REG(5 downto 0); when "100" => VMD_OUT(15 downto 6) <= "0000000000"; VMD_OUT(5 downto 0) <= INI_REG(5 downto 0); when "101" => VMD_OUT(15 downto 10) <= "000000"; VMD_OUT(9 downto 8) <= FER_REG(1 downto 0); VMD_OUT(7 downto 6) <= "00"; VMD_OUT(5 downto 0) <= LAM_REG(5 downto 0); when others => VMD_OUT <= (others => '0'); end case; 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; -------------------------------------------- -- JTAG sector select -------------------------------------------- process(JTAG_AD, TDO, TDI_Ext, TCK_Ext, TMS_Ext) begin case JTAG_AD is when "000" => TDO_Ext <= TDO(0); TDI(0) <= TDI_Ext; TCK(0) <= TCK_Ext; TMS(0) <= TMS_Ext; when "001" => TDO_Ext <= TDO(1); TDI(1) <= TDI_Ext; TCK(1) <= TCK_Ext; TMS(1) <= TMS_Ext; when "010" => TDO_Ext <= TDO(2); TDI(2) <= TDI_Ext; TCK(2) <= TCK_Ext; TMS(2) <= TMS_Ext; when "011" => TDO_Ext <= TDO(3); TDI(3) <= TDI_Ext; TCK(3) <= TCK_Ext; TMS(3) <= TMS_Ext; when "100" => TDO_Ext <= TDO(4); TDI(4) <= TDI_Ext; TCK(4) <= TCK_Ext; TMS(4) <= TMS_Ext; when "101" => TDO_Ext <= TDO(5); TDI(5) <= TDI_Ext; TCK(5) <= TCK_Ext; TMS(5) <= TMS_Ext; when others => null; end case; end process; -------------------------------------------- -- VME activity indication -------------------------------------------- process(SysCLK, DAT_ACK, VME_BLK) begin if (SysCLK'event and SysCLK = '0') then if (DAT_ACK = '1') then VME_CNT <= 0; elsif (VME_BLK = '0') then VME_CNT <= VME_CNT + 1; else null; end if; end if; end process; -------------------------- process(SysCLK, VME_CNT) begin if (SysCLK'event and SysCLK = '1') then if (VME_CNT = 524287) then VME_BLK <= '1'; else VME_BLK <= '0'; end if; end if; end process; -------------------------- process(VME_CNT) begin case VME_CNT is when 524287 => nLED_VME <= '1'; when others => nLED_VME <= '0'; end case; end process; -------------------------------------------- end;