-------------------------------------------- -- Company: Liverpool University -- Engineer: Ilya Tsurin -- -- Create Date: 09:41:25 15/04/2015 -- Design Name: Master Card for the Telescope -- Module Name: Tboard - Behavioral -- Project Name: -- Target Devices: XC3S500E-4FG320 -- Tool versions: ISE 11.3 WebPacks -- Description: -- -- Dependencies: Top Module -- -- Revision 1.01 - New concept of communicating FE -- Additional Comments: -- System Latency: 800 * 25ns = 20us -- (maximum rate 50 kHz, => 0.6s to fill buffers) -- Readout Speed: 12.5 MHz / 5 / 2048 = 1.2kHz -- (26s to read full buffers) -- FE MAC address convention: -- SG:AF:II:II:NN:NN (hex) -- S = SSSS (bin) - MC selection switch -- G = MXLU (bin) - IEEE convention: locally (L=1) -- administered unicast (U=0) -- -- M = 0 - master card read and write operations -- (section A could be used for addressing -- different registers, currently A=XXXX, -- where X = 'don't care') -- Read-only registers are polled alltogether -- (byte number is a position in the outgoing -- Ethernet train): -- STA status register (byte 0) -- EVT event number (bytes 1..4) -- COI coincidence counter (bytes 5..8) -- PMT1 counter (bytes 9..12) -- PMT2 counter (bytes 13..16) -- DUT_1 temperature (bytes 17..20) -- ... -- DUT_13 temperature (bytes 39..42) -- Write-only registers are addressed individually -- (register address is the 1st byte in the incoming -- Ethernet train, register content is the 2nd byte): -- 0x00 RS232_REG I/O data byte -- 0x01..0x02 PAK_REG number of ethernet packets -- 0x03..0x04 LEN_REG length of ethernet packets -- 0x05..0x06 RUN_REG preset run number -- 0x07..0x0A EVT_REG # of events for each run -- 0x0B..0x0E TOT_REG length of sampling phase -- 0x0F LAT_REG trigger delay -- 0x10 CTR_REG MC steering -- Control register bits: -- Bit0: external (0) or internal (1) clock -- Bit1: external (0) or internal (1) BOS -- Bit2: external (0) or internal (1) run -- Bit3: external (0) or internal (1) trigger -- Bit5: Test output control -- M = 1 - font-end read and write operations: -- X = Don't care -- L = 1 Locally administered -- U = 0 Unicast -- A = 0000..1111 (bin) - Front-end (Motherboard) address -- F = X000 (bin) - reset front-end -- X001 (bin) - write front-end -- X010 (bin) - read front-end -- X011 (bin) - trigger enable (start data acquisition) -- X100 (bin) - poll (read and trigger enable) -- -- II:II (two bytes) - Packet ID: to distinguish ehternet -- packets in the network card buffer -- memory (random or incremental value) -- NN:NN (two bytes) - Packet Number (incremental value) -- to distinguish ehternet packets sent -- in the network card buffer memory -------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; --use IEEE.NUMERIC_STD.ALL; --library XilinxCoreLib; --use XilinxCoreLib.all; library UNISIM; use UNISIM.VComponents.all; entity tboard is Port ( Clock : in std_logic; OSC_40 : in std_logic; ETH_CRS : in std_logic; ETH_COL : in std_logic; ETH_RX_DV : in std_logic; ETH_RX_CLK : in std_logic; ETH_RX_ERR : in std_logic; ETH_RXD : in std_logic_vector (3 downto 0); ETH_TX_EN : out std_logic; ETH_TX_CLK : in std_logic; ETH_TX_ERR : out std_logic; ETH_TXD : out std_logic_vector (3 downto 0); ETH_MDC : out std_logic; ETH_MDIO : inout std_logic; USB_nTXE : out std_logic; -- Enable reading FE USB_nRXF : out std_logic; -- Enable writing FE USB_nRD : out std_logic; -- Clock to write FE USB_WR : out std_logic; -- Clock to read FE USB_DAT : inout std_logic_vector (7 downto 0); PMT : in std_logic_vector (1 downto 0); SIT : in std_logic_vector (3 downto 0); SITR : in std_logic; SYS_ADR : out std_logic_vector (3 downto 0); -- SYS_ADR(3) = LED(4) -- SYS_ADR(2) = LED(5) -- SYS_ADR(1) = LED(6) -- SYS_ADR(0) = LED(7) SYS_CLK : out std_logic_vector (3 downto 0); -- SYS_CLK(1) = LED(0) -- SYS_CLK(0) = LED(3) SYS_TRG : out std_logic_vector (3 downto 0); -- SYS_TRG(0) = LED(2) SYS_RES : out std_logic_vector (3 downto 0); -- SYS_RES(0) = LED(1) TST_SYN : out std_logic; TST_TRG : out std_logic; TST_DV0 : in std_logic; TST_PUL : out std_logic; TST_RES : out std_logic; TST_SCL : out std_logic; TST_SDA : in std_logic; SW : in std_logic_vector(3 downto 0); BTN : in std_logic; BTS : in std_logic; BTW : in std_logic; BTE : in std_logic; BTC : in std_logic; ROTA : in std_logic; ROTB : in std_logic; CLK_50MHZ: in std_logic; CLK_AUX: in std_logic; CLK_SMA: in std_logic; AD_CONV: out std_logic; AMP_CS: out std_logic; AMP_DOUT: in std_logic; AMP_SHDN: out std_logic; DAC_CLR: out std_logic; DAC_CS: out std_logic; DS_WIRE: inout std_logic; FPGA_M0: inout std_logic; FPGA_M1: inout std_logic; FPGA_M2: in std_logic; FPGA_INIT_B: out std_logic; -- ghost signals -- FPGA_RDWR_B: out std_logic; -- FPGA_HSWAP: in std_logic; LCD_E: out std_logic; LCD_RS: out std_logic; LCD_RW: out std_logic; PS2_CLK: out std_logic; PS2_DATA: out std_logic; RS232_DCE_RXD: in std_logic; -- PIC18F4550 RS232_DCE_TXD: out std_logic; RS232_DTE_RXD: in std_logic; RS232_DTE_TXD: out std_logic; -- PL155-P SD_A: out std_logic_vector(12 downto 0); SD_BA: out std_logic_vector(1 downto 0); SD_CAS: out std_logic; SD_CK_N: out std_logic; SD_CK_P: out std_logic; SD_CKE: out std_logic; SD_CS: out std_logic; SD_DQ: inout std_logic_vector(15 downto 0); SD_LDM: out std_logic; SD_LDQS: inout std_logic; SD_RAS: out std_logic; SD_UDM: out std_logic; SD_UDQS: inout std_logic; SD_WE: out std_logic; SD_CK_FB: in std_logic; -- SF_A(24) is shared with TST_RES SF_A1: inout std_logic_vector(23 downto 20); SF_A0: out std_logic_vector(19 downto 0); SF_BYTE: out std_logic; SF_CE0: out std_logic; SF_D: inout std_logic_vector(15 downto 1); SF_OE: out std_logic; SF_STS: in std_logic; SF_WE: out std_logic; SPI_MISO: in std_logic; SPI_MOSI: out std_logic; SPI_SCK: inout std_logic; SPI_SS_B: out std_logic; SPI_ALT_CS_JP11: out std_logic; VGA_BLUE: out std_logic; VGA_GREEN: out std_logic; VGA_HSYNC: out std_logic; VGA_RED: out std_logic; VGA_VSYNC: out std_logic -- ghost signals -- XC_CMD: out std_logic_vector(1 downto 0); -- XC_CPLD_EN: in std_logic; -- XC_D: inout std_logic_vector(2 downto 0); -- XC_TRIG: in std_logic; -- XC_GCK0: out std_logic; -- GCLK10: out std_logic ); attribute pinnum: string; attribute pinnum of Clock: signal is "C9"; attribute pinnum of OSC_40: signal is "E10"; attribute pinnum of ETH_CRS: signal is "U13"; attribute pinnum of ETH_COL: signal is "U6"; attribute pinnum of ETH_RX_DV: signal is "V2"; attribute pinnum of ETH_RX_CLK: signal is "V3"; attribute pinnum of ETH_RX_ERR: signal is "U14"; attribute pinnum of ETH_RXD: signal is "V14,U11,V8,U14"; attribute pinnum of ETH_TX_EN: signal is "P15"; attribute pinnum of ETH_TX_CLK: signal is "T7"; attribute pinnum of ETH_TX_ERR: signal is "R6"; attribute pinnum of ETH_TXD: signal is "T5,R5,T15,R11"; attribute pinnum of ETH_MDC: signal is "P9"; attribute pinnum of ETH_MDIO: signal is "U5"; attribute pinnum of USB_nTXE: signal is "E8"; attribute pinnum of USB_nRXF: signal is "B4"; attribute pinnum of USB_nRD: signal is "C7"; attribute pinnum of USB_WR: signal is "F8"; attribute pinnum of USB_DAT: signal is "B6,F7,E7,D5,D7,C5,A6,A4"; attribute pinnum of PMT: signal is "C12,D12"; attribute pinnum of SIT: signal is "A15,B15,C3,C15"; attribute pinnum of SITR: signal is "D9"; attribute pinnum of SYS_ADR: signal is "C11,D11,E9,F9"; attribute pinnum of SYS_CLK: signal is "B16,C14,B13,E12"; attribute pinnum of SYS_TRG: signal is "A16,B14,A13,E11"; attribute pinnum of SYS_RES: signal is "D14,A14,F12,F11"; attribute pinnum of TST_SYN: signal is "D10"; attribute pinnum of TST_TRG: signal is "G9"; attribute pinnum of TST_DV0: signal is "B11"; attribute pinnum of TST_PUL: signal is "A8"; attribute pinnum of TST_RES: signal is "A11"; attribute pinnum of TST_SCL: signal is "E13"; attribute pinnum of TST_SDA: signal is "C4"; attribute pinnum of SW: signal is "N17,H18,L14,L13"; attribute pinnum of BTN: signal is "V4"; attribute pinnum of BTS: signal is "K17"; attribute pinnum of BTW: signal is "D18"; attribute pinnum of BTE: signal is "H13"; attribute pinnum of BTC: signal is "V16"; attribute pinnum of ROTA: signal is "K18"; attribute pinnum of ROTB: signal is "G18"; end tboard; architecture Behavioral of tboard is -- System wake up -------------------------------------------- signal PLL_REG: std_logic_vector(3 downto 0); signal PLL_DEL: std_logic_vector(3 downto 0); signal RX_SOF : std_logic; -- RX (receive) frame signal DV_DEL : std_logic; -------------------------------------------- -- Ethernet input package -------------------------------------------- signal RXB_CLK: std_logic; signal RXB_CNT: natural range 0 to 2047; signal MAC_CHK: std_logic_vector(7 downto 0); signal FE_FLAG: std_logic; signal UNICAST: std_logic; -- MAC match, chip select signal DUM_RES: std_logic; signal COM_RES: std_logic; -- Common reset before loop signal FE_ADR: std_logic_vector(47 downto 0); -- FE_ADR(47 downto 44) switch -- FE_ADR(43 downto 40) unicast -- FE_ADR(39 downto 36) FE address -- FE_ADR(35 downto 32) command -- FE_ADR(31 downto 16) packet ID -- FE_ADR(15 downto 0) packet number signal HOST_ADR: std_logic_vector(47 downto 0); signal DAT_LEN: std_logic_vector(15 downto 0); signal LEN_REG: std_logic_vector(15 downto 0); signal DAT_ACT: std_logic_vector(15 downto 0); signal LIM_NUM: natural range 0 to 65535; signal LIM_DAT: natural range 0 to 65535; -------------------------------------------- -- Command flags for a single-loop processor -------------------------------------------- signal WR_ENA: std_logic; signal RD_ENA: std_logic; signal CL_ENA: std_logic; signal TR_ENA: std_logic; -------------------------------------------- -- Data router -------------------------------------------- signal WR_CYC: std_logic; signal WR_STB: std_logic; signal RD_CYC: std_logic; signal RD_STB: std_logic; -------------------------------------------- -- MC controls -------------------------------------------- signal MC_ADR: std_logic_vector(7 downto 0); -------------------------------------------- -- Ethernet output package -------------------------------------------- signal TX_SOF: std_logic; -- TX (transmit) frame signal TX_CNT: natural range 0 to 2047; signal TX_RES: std_logic; signal PAK_CNT: natural range 0 to 65535; signal PAK_NUM: std_logic_vector(15 downto 0); signal PAK_REG: std_logic_vector(15 downto 0); signal TX_CYCLE: std_logic; -- Output data valid -------------------------------------------- -- Checksum variables -------------------------------------------- signal CRC_CLK: std_logic; signal CRC_INI: std_logic; signal CRC_DAT: std_logic_vector(7 downto 0); signal CRC_CRC: std_logic_vector(31 downto 0); signal CRC_RES: std_logic_vector(31 downto 0); -------------------------------------------- -- Data buffers -------------------------------------------- signal RXB_DAT: std_logic_vector(7 downto 0); -- merging input nibbles signal OUT_DAT: std_logic_vector(7 downto 0); -- Ethernet output data signal USB_INP: std_logic_vector(7 downto 0); -- USB bi-dir buffer signal USB_OUT: std_logic_vector(7 downto 0); -- USB bi-dir buffer -------------------------------------------- -- gm2 controls -------------------------------------------- signal GM2_CLK: std_logic; signal GM2_BOS: std_logic; signal GM2_RUN: std_logic; signal GM2_TRG: std_logic; signal BOS_CNT: natural range 0 to 7; signal SPILL: std_logic; signal BOS_BLK: std_logic; signal RUN_CLR: std_logic; signal EVT_NUM: std_logic_vector(31 downto 0); signal EVT_REG: std_logic_vector(31 downto 0); signal BOS_NUM: std_logic_vector(15 downto 0); signal RUN_REG: std_logic_vector(15 downto 0); signal RUN_NUM: std_logic_vector(15 downto 0); signal TOT_REG: std_logic_vector(31 downto 0); signal TOT_CNT: std_logic_vector(31 downto 0); signal LAT_REG: std_logic_vector(7 downto 0); signal CTR_REG: std_logic_vector(7 downto 0); -------------------------------------------- -- Track trigger -------------------------------------------- signal TRG_RUN: std_logic; signal TRG_GEN: std_logic; signal TRG_AND: std_logic; signal TRG_RES: std_logic; signal LAT_CNT: natural range 0 to 1023; signal DIV_CLK: std_logic; signal TRG_STB: std_logic; signal TRG_STD: std_logic; signal TRG_FAN: std_logic; -------------------------------------------- -- Event counters -------------------------------------------- signal PM1_CNT: std_logic_vector(31 downto 0); signal PM2_CNT: std_logic_vector(31 downto 0); signal COI_CNT: std_logic_vector(31 downto 0); signal TRG_CNT: std_logic_vector(31 downto 0); -------------------------------------------- -- RAM for gm2 scalers -------------------------------------------- signal RUN_EOF: std_logic; signal RUN_CNT: natural range 0 to 15; signal RUN_DAT: natural range 0 to 255; signal CLK_CNT: std_logic_vector(31 downto 0); signal CNT_DAT: std_logic_vector(31 downto 0); signal RAM_WA: std_logic_vector(10 downto 0); signal RAM_RA: std_logic_vector(10 downto 0); signal RAM_INP: std_logic_vector(7 downto 0); signal RAM_OUT: std_logic_vector(7 downto 0); signal STB_TMP: std_logic; signal RAM_STB: std_logic; signal RAM_WE: std_logic_vector(0 downto 0); -------------------------------------------- -- MC data registers -------------------------------------------- signal PM1_REG: std_logic_vector(31 downto 0); signal PM2_REG: std_logic_vector(31 downto 0); signal COI_REG: std_logic_vector(31 downto 0); signal TRG_REG: std_logic_vector(31 downto 0); signal STA_REG: std_logic_vector(7 downto 0); -------------------------------------------- -- MC data gateway -------------------------------------------- signal MC_DATA: std_logic_vector(7 downto 0); -------------------------------------------- -- FE reset -------------------------------------------- signal RES_CNT: natural range 0 to 7; signal FE_RES: std_logic; -------------------------------------------- -- Temperature registers -------------------------------------------- signal Temp00: std_logic_vector(7 downto 0); signal Temp01: std_logic_vector(7 downto 0); signal Temp10: std_logic_vector(7 downto 0); signal Temp11: std_logic_vector(7 downto 0); signal Temp20: std_logic_vector(7 downto 0); signal Temp21: std_logic_vector(7 downto 0); signal Temp30: std_logic_vector(7 downto 0); signal Temp31: std_logic_vector(7 downto 0); signal Temp40: std_logic_vector(7 downto 0); signal Temp41: std_logic_vector(7 downto 0); signal Temp50: std_logic_vector(7 downto 0); signal Temp51: std_logic_vector(7 downto 0); signal Temp60: std_logic_vector(7 downto 0); signal Temp61: std_logic_vector(7 downto 0); signal Temp70: std_logic_vector(7 downto 0); signal Temp71: std_logic_vector(7 downto 0); signal Temp80: std_logic_vector(7 downto 0); signal Temp81: std_logic_vector(7 downto 0); signal Temp90: std_logic_vector(7 downto 0); signal Temp91: std_logic_vector(7 downto 0); signal TempA0: std_logic_vector(7 downto 0); signal TempA1: std_logic_vector(7 downto 0); signal TempB0: std_logic_vector(7 downto 0); signal TempB1: std_logic_vector(7 downto 0); signal TempC0: std_logic_vector(7 downto 0); signal TempC1: std_logic_vector(7 downto 0); -------------------------------------------- -- Emulate RS232 port (9600 baud) -------------------------------------------- signal RS232_SYN: std_logic; signal RS232_CNT: natural range 0 to 4095; signal RS232_PLL: std_logic; signal RS232_CLK: std_logic; signal RS232_EOF: std_logic; signal BIT_CNT: natural range 0 to 15; signal RS232_REG: std_logic_vector(7 downto 0); -------------------------------------------- -- Data type conversion: -- binary#10 -> natural -------------------------------------------- function BIT16_to_NUM(BIT_ARR: std_logic_vector(15 downto 0)) return natural is variable TEMP: natural range 0 to 65535; begin TEMP:=0; for I in BIT_ARR'range loop TEMP:= TEMP * 2; if (BIT_ARR(I) = '1') then TEMP:= TEMP + 1; else null; end if; end loop; return TEMP; end BIT16_to_NUM; -------------------------------------------- -- declaring Tlog component -------------------------------------------- component TLOG is port ( CLK: in std_logic; RXD: in std_logic; T0: out std_logic_vector(7 downto 0); T1: out std_logic_vector(7 downto 0); T2: out std_logic_vector(7 downto 0); T3: out std_logic_vector(7 downto 0); T4: out std_logic_vector(7 downto 0); T5: out std_logic_vector(7 downto 0); T6: out std_logic_vector(7 downto 0); T7: out std_logic_vector(7 downto 0); T8: out std_logic_vector(7 downto 0); T9: out std_logic_vector(7 downto 0); T10: out std_logic_vector(7 downto 0); T11: out std_logic_vector(7 downto 0); T12: out std_logic_vector(7 downto 0); T13: out std_logic_vector(7 downto 0); T14: out std_logic_vector(7 downto 0); T15: out std_logic_vector(7 downto 0); T16: out std_logic_vector(7 downto 0); T17: out std_logic_vector(7 downto 0); T18: out std_logic_vector(7 downto 0); T19: out std_logic_vector(7 downto 0); T20: out std_logic_vector(7 downto 0); T21: out std_logic_vector(7 downto 0); T22: out std_logic_vector(7 downto 0); T23: out std_logic_vector(7 downto 0); T24: out std_logic_vector(7 downto 0); T25: out std_logic_vector(7 downto 0) ); end component; -------------------------------------------- -- declaring CRC component -------------------------------------------- component CRC port ( Clock: in std_logic; Init : in std_logic; Data : in std_logic_vector(7 downto 0); CRC : out std_logic_vector(31 downto 0) ); end component; -------------------------------------------- -- declaring RAM component -------------------------------------------- component RAM port ( clka: in std_logic; wea: in std_logic_vector(0 downto 0); addra: in std_logic_vector(10 downto 0); dina: in std_logic_vector(7 downto 0); clkb: in std_logic; addrb: in std_logic_vector(10 downto 0); doutb: out std_logic_vector(7 downto 0) ); end component; -------------------------------------------- -- Test features -------------------------------------------- signal GLB_CNT: natural range 0 to 33554431; -- 0.8s BOS period signal LCL_CNT: natural range 0 to 1048575; -- 26 ms period, 20ms RUN active signal TST_CNT: natural range 0 to 4095; -- 100us Trigger period signal TST_BOS: std_logic; signal TST_RUN: std_logic; signal TST_EVT: std_logic; -------------------------------------------- -- OK, here the entity starts begin -- Permanent assignments -------------------------------------------- -- Resolve pin conflicts -------------------------------------------- AD_CONV <= '0'; AMP_CS <= '1'; AMP_SHDN <= '1'; DAC_CLR <= '0'; DAC_CS <= '1'; DS_WIRE <= 'Z'; -- M2..M0 are selected by jumpers FPGA_M0 <= 'Z'; FPGA_M1 <= 'Z'; -- FPGA_M2 <= 'Z'; FPGA_INIT_B <= '1'; LCD_E <= '0'; LCD_RS <= '0'; LCD_RW <= '0'; PS2_CLK <= '0'; PS2_DATA <= '0'; RS232_DCE_TXD <= '0'; SD_A <= (others => '0'); SD_BA <= "00"; SD_CAS <= '1'; -- NOP SD_CK_N <= '1'; SD_CK_P <= '0'; SD_CKE <= '0'; -- disable clock SD_CS <= '1'; -- disable command decoder SD_DQ <= (others => 'Z'); SD_LDM <= '0'; SD_LDQS <= 'Z'; SD_RAS <= '1'; -- NOP SD_UDM <= '0'; SD_UDQS <= 'Z'; SD_WE <= '1'; -- NOP SF_A1 <= (others => 'Z'); SF_A0 <= (others => '0'); SF_BYTE <= '0'; SF_CE0 <= '1'; SF_D <= (others => 'Z'); SF_OE <= '1'; SF_WE <= '1'; SPI_MOSI <= '0'; SPI_SCK <= '0'; SPI_SS_B <= '1'; SPI_ALT_CS_JP11 <= 'Z'; VGA_BLUE <='0'; VGA_GREEN <='0'; VGA_HSYNC <='0'; VGA_RED <='0'; VGA_VSYNC <='0'; -------------------------------------------- -- FE clock fanout -------------------------------------------- SYS_CLK <= (others => GM2_CLK); -------------------------------------------- -- Ethernet controls -------------------------------------------- ETH_TX_ERR <= '0'; ETH_MDIO <= 'Z'; ETH_MDC <= '0'; -------------------------------------------- -- !!! Wake up !!! -- Capture the frame delimiter (Result CLK <-) -------------------------------------------- process(ETH_RX_CLK, ETH_RXD) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '1') then PLL_DEL <= ETH_RXD; end if; end process; -------------- process(ETH_RX_CLK, PLL_DEL) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '0') then PLL_REG <= PLL_DEL; end if; end process; -------------------------------------------- -- Start of the RX frame (CLK ->) -------------------------------------------- process(ETH_RX_CLK, ETH_RX_DV, ETH_RXD, PLL_REG) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (ETH_RX_DV = '1') then if (ETH_RXD = x"D" and PLL_REG = x"5") then RX_SOF <= '1'; else null; end if; else RX_SOF <= '0'; end if; end if; end process; -------------------------------------------- -- Signal for the clock synchronisation (CLK ->) -------------------------------------------- process(ETH_RX_CLK, ETH_RX_DV) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '1') then DV_DEL <= ETH_RX_DV; end if; end process; -------------------------------------------- -- RX nibble swapper and data clock (CLK <-) -- (synchronize phase with RX_SOF signal) -------------------------------------------- process(ETH_RX_CLK, DV_DEL, RX_SOF) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '0') then if (DV_DEL = '1' and RX_SOF = '0') then RXB_CLK <= '0'; else RXB_CLK <= not RXB_CLK; end if; end if; end process; -------------------------------------------- -- RX byte counter (CLK ->) -------------------------------------------- process(RXB_CLK, RX_SOF) begin if (RXB_CLK'event and RXB_CLK = '1') then if (RX_SOF = '1') then RXB_CNT <= RXB_CNT + 1; else RXB_CNT <= 0; end if; end if; end process; -------------------------------------------- -- Compile bytes from nibbles. Data are -- ready for latching by (CLK ->) under -- NIR_SWP = '0' condition -------------------------------------------- process(ETH_RX_CLK, RXB_CLK, ETH_RXD) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (RXB_CLK = '1') then RXB_DAT(3 downto 0) <= ETH_RXD; else null; end if; end if; end process; -------------- RXB_DAT(7 downto 4) <= ETH_RXD; -------------------------------------------- -- Validate FE addressing (unicast) -------------------------------------------- process(ETH_RX_CLK, RXB_CNT, RXB_CLK, RXB_DAT, SW) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (RXB_CNT = 1 and RXB_CLK = '0') then MAC_CHK <= RXB_DAT; else null; end if; end if; end process; -------------------------------------------- -- Locally administered unicast -------------------------------------------- process(MAC_CHK) begin if ((MAC_CHK(7 downto 4) = SW) and (MAC_CHK(1 downto 0) = "10")) then UNICAST <= '1'; else UNICAST <= '0'; end if; end process; -------------------------------------------- -- Capture the RX data -------------------------------------------- process(ETH_RX_CLK, UNICAST, RXB_CLK, RXB_CNT, MAC_CHK, RXB_DAT) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (UNICAST = '1' and RXB_CLK = '0') then case RXB_CNT is when 2 => FE_ADR(47 downto 40) <= MAC_CHK; FE_ADR(39 downto 32) <= RXB_DAT; when 3 => FE_ADR(31 downto 24) <= RXB_DAT; when 4 => FE_ADR(23 downto 16) <= RXB_DAT; when 5 => FE_ADR(15 downto 8) <= RXB_DAT; when 6 => FE_ADR(7 downto 0) <= RXB_DAT; when 7 => HOST_ADR(47 downto 40) <= RXB_DAT; when 8 => HOST_ADR(39 downto 32) <= RXB_DAT; when 9 => HOST_ADR(31 downto 24) <= RXB_DAT; when 10 => HOST_ADR(23 downto 16) <= RXB_DAT; when 11 => HOST_ADR(15 downto 8) <= RXB_DAT; when 12 => HOST_ADR(7 downto 0) <= RXB_DAT; when 13 => DAT_LEN(15 downto 8) <= RXB_DAT; when 14 => DAT_LEN(7 downto 0) <= RXB_DAT; when others => USB_OUT <= RXB_DAT; end case; else null; end if; end if; end process; -------------------------------------------- -- Counter limits -------------------------------------------- LIM_NUM <= BIT16_to_NUM(LEN_REG); -------------- process(LIM_NUM) begin if (LIM_NUM <= 46) then LIM_DAT <= 46; elsif (1500 <= LIM_NUM) then LIM_DAT <= 1500; else LIM_DAT <= LIM_NUM; end if; end process; -------------- DAT_ACT <= conv_std_logic_vector(LIM_DAT, 16); -------------------------------------------- -- Master card addressing -------------------------------------------- FE_FLAG <= FE_ADR(43); -- OR MAC_CHK(3) -------------------------------------------- -- Select one Alibava board -------------------------------------------- SYS_ADR <= FE_ADR(39 downto 36); -------------------------------------------- -- Command decoding -------------------------------------------- process(FE_ADR) begin case FE_ADR(34 downto 32) is when "000" => WR_ENA <= '0'; RD_ENA <= '0'; CL_ENA <= '1'; TR_ENA <= '0'; when "001" => WR_ENA <= '1'; RD_ENA <= '0'; CL_ENA <= '0'; TR_ENA <= '0'; when "010" => WR_ENA <= '0'; RD_ENA <= '1'; CL_ENA <= '0'; TR_ENA <= '0'; when "011" => WR_ENA <= '0'; RD_ENA <= '0'; CL_ENA <= '0'; TR_ENA <= '1'; when "100" => WR_ENA <= '0'; RD_ENA <= '1'; CL_ENA <= '0'; TR_ENA <= '1'; when others => WR_ENA <= '0'; RD_ENA <= '0'; CL_ENA <= '0'; TR_ENA <= '0'; end case; end process; -------------------------------------------- -- Issue reset pulse -------------------------------------------- process(DUM_RES, ETH_RX_CLK, UNICAST, CL_ENA, RXB_CLK, RXB_CNT) begin if (DUM_RES = '1') then COM_RES <= '0'; elsif (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (UNICAST = '1' and CL_ENA = '1' and RXB_CLK = '1') then case RXB_CNT is when 16 => COM_RES <= '1'; when 17 => COM_RES <= '0'; when others => null; end case; else null; end if; end if; end process; -------------------------------------------- -- FE write cycle (needed to prepare -- data before issuing FE write strobe) -------------------------------------------- process(COM_RES, ETH_RX_CLK, UNICAST, WR_ENA, RXB_CLK, RXB_CNT) begin if (COM_RES = '1') then WR_CYC <= '0'; elsif (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (UNICAST = '1' and WR_ENA = '1' and RXB_CLK = '0') then case RXB_CNT is when 15 => WR_CYC <= '1'; when 17 => WR_CYC <= '0'; when others => null; end case; else null; end if; end if; end process; -------------- USB_nRXF <= not (WR_CYC and FE_FLAG); -------------------------------------------- -- Bi-directional IO for the FE bus -------------------------------------------- process(WR_CYC, FE_FLAG, USB_OUT) begin if (WR_CYC = '1' and FE_FLAG = '1') then USB_DAT <= USB_OUT; else USB_DAT <= (others => 'Z'); end if; end process; -------------- USB_INP <= USB_DAT; -------------------------------------------- -- Selecting between MC and FE data (CLK ->) -------------------------------------------- process(CRC_CLK, FE_FLAG, MC_DATA, USB_INP) begin if (CRC_CLK'event and CRC_CLK = '1') then if (FE_FLAG = '1') then OUT_DAT <= USB_INP; else OUT_DAT <= MC_DATA; end if; end if; end process; -------------------------------------------- -- FE write strobe -------------------------------------------- process(COM_RES, ETH_RX_CLK, UNICAST, WR_ENA, RXB_CLK, RXB_CNT) begin if (COM_RES = '1') then WR_STB <= '0'; elsif (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (UNICAST = '1' and WR_ENA = '1' and RXB_CLK = '1') then case RXB_CNT is when 16 => WR_STB <= '1'; when 17 => WR_STB <= '0'; when others => null; end case; else null; end if; end if; end process; -------------- USB_nRD <= not (WR_STB and FE_FLAG); -------------------------------------------- -- Strobe to activate readout -------------------------------------------- process(COM_RES, ETH_RX_CLK, UNICAST, RD_ENA, RXB_CLK, RXB_CNT) begin if (COM_RES = '1') then RD_STB <= '0'; elsif (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (UNICAST = '1' and RD_ENA = '1' and RXB_CLK = '1') then case RXB_CNT is when 16 => RD_STB <= '1'; when 17 => RD_STB <= '0'; when others => null; end case; else null; end if; end if; end process; -------------------------------------------- -- Transmission frame -------------------------------------------- process(COM_RES, TX_RES, RD_STB) begin if (COM_RES = '1' or TX_RES = '1') then TX_SOF <= '0'; elsif (RD_STB'event and RD_STB = '0') then TX_SOF <= '1'; end if; end process; -------------------------------------------- -- TX nibble swapper = CRC32 clock (CLK ->) -------------------------------------------- process(ETH_TX_CLK, RD_STB) begin if (ETH_TX_CLK'event and ETH_TX_CLK = '1') then if (RD_STB = '1') then CRC_CLK <= '0'; else CRC_CLK <= not CRC_CLK; end if; end if; end process; -------------- USB_WR <= CRC_CLK; -------------------------------------------- -- TX byte counter (CLK ->) -------------------------------------------- process(CRC_CLK, TX_SOF) begin if (CRC_CLK'event and CRC_CLK = '1') then if (TX_SOF = '1') then TX_CNT <= TX_CNT + 1; else TX_CNT <= 0; end if; end if; end process; -------------------------------------------- -- Count the number of transmitted -- complete ethernet packets -------------------------------------------- process(COM_RES, RD_STB, CRC_CLK, TX_CNT, LIM_DAT) begin if (COM_RES = '1' or RD_STB = '1') then PAK_CNT <= 0; elsif (CRC_CLK'event and CRC_CLK = '0') then -- if (TX_CNT = 1527) then if (TX_CNT = (22 + LIM_DAT + 4 + 1)) then PAK_CNT <= PAK_CNT + 1; else null; end if; end if; end process; -------------- PAK_NUM <= conv_std_logic_vector(PAK_CNT, 16); -------------------------------------------- -- End of transmission frame (CLK ->) -------------------------------------------- process(COM_RES, RD_STB, CRC_CLK, TX_CNT, LIM_DAT, PAK_NUM, PAK_REG) begin if (COM_RES = '1' or RD_STB = '1') then TX_RES <= '0'; elsif (CRC_CLK'event and CRC_CLK = '0') then if (TX_CNT = (22 + LIM_DAT + 4 + 2) and PAK_NUM = PAK_REG) then TX_RES <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Ethernet transmit cycle -------------------------------------------- process(ETH_TX_CLK, CRC_CLK, LIM_DAT, TX_CNT, PAK_NUM, PAK_REG) begin if (ETH_TX_CLK'event and ETH_TX_CLK = '0') then if (CRC_CLK = '1') then if (TX_CNT = (22 + LIM_DAT + 4 + 1)) then TX_CYCLE <= '0'; elsif (TX_CNT = 1 and PAK_NUM /= PAK_REG) then TX_CYCLE <= '1'; else null; end if; else null; end if; end if; end process; -------------- ETH_TX_EN <= TX_CYCLE; -------------------------------------------- -- Front-end readout -------------------------------------------- process(CRC_CLK, TX_CNT, LIM_DAT) begin if (CRC_CLK'event and CRC_CLK = '0') then if (TX_CNT = 22) then RD_CYC <= '1'; -- elsif (TX_CNT = 1523) then elsif (TX_CNT = (22 + LIM_DAT)) then RD_CYC <= '0'; else null; end if; end if; end process; -------------- USB_nTXE <= not (RD_CYC and FE_FLAG); -------------------------------------------- -- Initialize CRC variables (CLK <-) -------------------------------------------- process(ETH_TX_CLK, TX_CNT, CRC_CLK) begin if (ETH_TX_CLK'event and ETH_TX_CLK = '0') then if (TX_CNT = 9) then if (CRC_CLK = '1') then CRC_INI <= '1'; else CRC_INI <= '0'; end if; else null; end if; end if; end process; -------------------------------------------- -- compile the Ethernet output packet -------------------------------------------- process(ETH_TX_CLK, TX_CNT, CRC_CLK, HOST_ADR, FE_ADR, PAK_NUM, DAT_ACT, CRC_CRC, CRC_RES, OUT_DAT, LIM_DAT) begin if (ETH_TX_CLK'event and ETH_TX_CLK = '0') then -- Make it clear -------------------------------------------- if (TX_CNT = 0) then ETH_TXD <= x"0"; -- 6 times preamble 0x55 -------------------------------------------- elsif (TX_CNT = 1) then ETH_TXD <= x"5"; elsif (TX_CNT = 2) then ETH_TXD <= x"5"; elsif (TX_CNT = 3) then ETH_TXD <= x"5"; elsif (TX_CNT = 4) then ETH_TXD <= x"5"; elsif (TX_CNT = 5) then ETH_TXD <= x"5"; elsif (TX_CNT = 6) then ETH_TXD <= x"5"; elsif (TX_CNT = 7) then ETH_TXD <= x"5"; -- Delimiter 0xD5 -------------------------------------------- elsif (TX_CNT = 8) then if (CRC_CLK = '1') then ETH_TXD <= x"5"; else ETH_TXD <= x"D"; end if; -- Destination (Host) MAC address -------------------------------------------- elsif (TX_CNT = 9) then if (CRC_CLK = '1') then ETH_TXD <= HOST_ADR(43 downto 40); else ETH_TXD <= HOST_ADR(47 downto 44); end if; elsif (TX_CNT = 10) then if (CRC_CLK = '1') then ETH_TXD <= HOST_ADR(35 downto 32); else ETH_TXD <= HOST_ADR(39 downto 36); end if; elsif (TX_CNT = 11) then if (CRC_CLK = '1') then ETH_TXD <= HOST_ADR(27 downto 24); else ETH_TXD <= HOST_ADR(31 downto 28); end if; elsif (TX_CNT = 12) then if (CRC_CLK = '1') then ETH_TXD <= HOST_ADR(19 downto 16); else ETH_TXD <= HOST_ADR(23 downto 20); end if; elsif (TX_CNT = 13) then if (CRC_CLK = '1') then ETH_TXD <= HOST_ADR(11 downto 8); else ETH_TXD <= HOST_ADR(15 downto 12); end if; elsif (TX_CNT = 14) then if (CRC_CLK = '1') then ETH_TXD <= HOST_ADR(3 downto 0); else ETH_TXD <= HOST_ADR(7 downto 4); end if; -- Source (Front-end) address -------------------------------------------- elsif (TX_CNT = 15) then if (CRC_CLK = '1') then ETH_TXD <= FE_ADR(43 downto 40); else ETH_TXD <= FE_ADR(47 downto 44); end if; elsif (TX_CNT = 16) then if (CRC_CLK = '1') then ETH_TXD <= FE_ADR(35 downto 32); else ETH_TXD <= FE_ADR(39 downto 36); end if; elsif (TX_CNT = 17) then if (CRC_CLK = '1') then ETH_TXD <= FE_ADR(27 downto 24); else ETH_TXD <= FE_ADR(31 downto 28); end if; elsif (TX_CNT = 18) then if (CRC_CLK = '1') then ETH_TXD <= FE_ADR(19 downto 16); else ETH_TXD <= FE_ADR(23 downto 20); end if; elsif (TX_CNT = 19) then if (CRC_CLK = '1') then ETH_TXD <= PAK_NUM(11 downto 8); else ETH_TXD <= PAK_NUM(15 downto 12); end if; elsif (TX_CNT = 20) then if (CRC_CLK = '1') then ETH_TXD <= PAK_NUM(3 downto 0); else ETH_TXD <= PAK_NUM(7 downto 4); end if; -- Packet length -------------------------------------------- elsif (TX_CNT = 21) then if (CRC_CLK = '1') then ETH_TXD <= DAT_ACT(11 downto 8); else ETH_TXD <= DAT_ACT(15 downto 12); end if; elsif (TX_CNT = 22) then if (CRC_CLK = '1') then ETH_TXD <= DAT_ACT(3 downto 0); else ETH_TXD <= DAT_ACT(7 downto 4); end if; -- CRC32 -------------------------------------------- -- elsif (TX_CNT = 1523) then elsif (TX_CNT = (22 + LIM_DAT + 1)) then -- *** Important *** Use CRC_CRC Nibble here if (CRC_CLK = '1') then ETH_TXD <= CRC_CRC(3 downto 0); else ETH_TXD <= CRC_CRC(7 downto 4); end if; -- elsif (TX_CNT = 1524) then elsif (TX_CNT = (22 + LIM_DAT + 2)) then if (CRC_CLK = '1') then ETH_TXD <= CRC_RES(11 downto 8); else ETH_TXD <= CRC_RES(15 downto 12); end if; -- elsif (TX_CNT = 1525) then elsif (TX_CNT = (22 + LIM_DAT + 3)) then if (CRC_CLK = '1') then ETH_TXD <= CRC_RES(19 downto 16); else ETH_TXD <= CRC_RES(23 downto 20); end if; -- elsif (TX_CNT = 1526) then elsif (TX_CNT = (22 + LIM_DAT + 4)) then if (CRC_CLK = '1') then ETH_TXD <= CRC_RES(27 downto 24); else ETH_TXD <= CRC_RES(31 downto 28); end if; -- Data block -------------------------------------------- else if (CRC_CLK = '1') then ETH_TXD <= OUT_DAT(3 downto 0); else ETH_TXD <= OUT_DAT(7 downto 4); end if; end if; end if; end process; -------------------------------------------- -- CRC data -------------------------------------------- process(TX_CNT, HOST_ADR, FE_ADR, PAK_NUM, DAT_ACT, OUT_DAT) begin -- Destination (Host) MAC address -------------------------------------------- case TX_CNT is when 9 => CRC_DAT <= HOST_ADR(47 downto 40); when 10 => CRC_DAT <= HOST_ADR(39 downto 32); when 11 => CRC_DAT <= HOST_ADR(31 downto 24); when 12 => CRC_DAT <= HOST_ADR(23 downto 16); when 13 => CRC_DAT <= HOST_ADR(15 downto 8); when 14 => CRC_DAT <= HOST_ADR(7 downto 0); -- Source (Front-end) address -------------------------------------------- when 15 => CRC_DAT <= FE_ADR(47 downto 40); when 16 => CRC_DAT <= FE_ADR(39 downto 32); when 17 => CRC_DAT <= FE_ADR(31 downto 24); when 18 => CRC_DAT <= FE_ADR(23 downto 16); when 19 => CRC_DAT <= PAK_NUM(15 downto 8); when 20 => CRC_DAT <= PAK_NUM(7 downto 0); -- Packet length -------------------------------------------- when 21 => CRC_DAT <= DAT_ACT(15 downto 8); when 22 => CRC_DAT <= DAT_ACT(7 downto 0); -- Data block -------------------------------------------- when others => CRC_DAT <= OUT_DAT; end case; end process; -------------------------------------------- -------------------------------------------- -- Calculate CRC32 for transmitted data ------------------------------------------- U1:CRC port map ( Clock => CRC_CLK, Init => CRC_INI, Data => CRC_DAT, CRC => CRC_CRC); -------------------------------------------- -- Keep the CRC result (the last data byte) -------------------------------------------- process(CRC_CLK, TX_CNT, CRC_CRC, LIM_DAT) begin if (CRC_CLK'event and CRC_CLK = '0') then -- if (TX_CNT = 1523) then if (TX_CNT = (22 + LIM_DAT + 1)) then CRC_RES <= CRC_CRC; else null; end if; end if; end process; -------------------------------------------- -------------------------------------------- -- FE reset -------------------------------------------- process(GM2_CLK, UNICAST, CL_ENA, COM_RES) begin if (GM2_CLK'event and GM2_CLK = '0') then if (UNICAST = '1' and CL_ENA = '1' and COM_RES = '1') then RES_CNT <= RES_CNT + 1; else RES_CNT <= 0; end if; end if; end process; -------------- process(GM2_CLK, RES_CNT) begin if (GM2_CLK'event and GM2_CLK = '1') then case RES_CNT is when 1 => FE_RES <= '1'; when 3 => FE_RES <= '0'; when others => null; end case; end if; end process; -------------------------------------------- -------------------------------------------- -- Telescope Slave configuration -------------------------------------------- -- New mapping -------------- RUN_CLK <= SITR; RUN_BOS <= SIT(0); RUN_RUN <= SIT(1); RUN_EVT <= SIT(2); -- Select controls -------------------------------------------- process(CTR_REG) GM2_CLK <= SITR; GM2_BOS <= SIT(0); GM2_RUN <= SIT(1); GM2_TRG <= SIT(2); -------------------------------------------- -- Button ringing measure for Spill signal -------------------------------------------- process(GM2_CLK, GM2_BOS, TR_ENA, BOS_BLK, SPILL) begin if (GM2_CLK'event and GM2_CLK = '0') then if (GM2_BOS = '0' or TR_ENA = '0' or BOS_BLK = '1') then BOS_CNT <= 0; elsif (SPILL = '0') then BOS_CNT <= BOS_CNT + 1; else null; end if; end if; end process; -------------------------------------------- -- Initiate and terminate Spill -------------------------------------------- process(COM_RES, GM2_CLK, EVT_NUM, EVT_REG, TOT_REG, TOT_CNT, BOS_CNT) begin if (COM_RES = '1') then SPILL <= '0'; elsif (GM2_CLK'event and GM2_CLK = '1') then if ((EVT_NUM = EVT_REG) or (TOT_REG = TOT_CNT)) then SPILL <= '0'; elsif (BOS_CNT = 5) then SPILL <= '1'; else null; end if; end if; end process; -------------- SYS_RES <= (others => SPILL); -------------------------------------------- -- Lock next BOS until readout complete -------------------------------------------- process(COM_RES, SPILL) begin if (COM_RES = '1') then BOS_BLK <= '0'; elsif(SPILL'event and SPILL = '0') then BOS_BLK <= '1'; end if; end process; -------------------------------------------- -- BOS time-out -------------------------------------------- process(COM_RES, GM2_CLK, SPILL) begin if (COM_RES = '1') then TOT_CNT <= (others => '0'); elsif (GM2_CLK'event and GM2_CLK = '0') then if (SPILL = '1') then TOT_CNT <= TOT_CNT + '1'; else TOT_CNT <= (others => '0'); end if; end if; end process; -------------------------------------------- -- Calculate the run number -------------------------------------------- process(RUN_CLR, SPILL) begin if (RUN_CLR = '1') then BOS_NUM <= (others => '0'); elsif (SPILL'event and SPILL = '1') then BOS_NUM <= BOS_NUM + '1'; end if; end process; -------------- RUN_NUM <= RUN_REG + BOS_NUM; -------------------------------------------- -- Clear run number -------------------------------------------- process(WR_CYC, WR_STB, FE_FLAG, MC_ADR, USB_OUT) begin if (WR_CYC = '0') then RUN_CLR <= '0'; elsif (WR_STB'event and WR_STB = '0') then if (FE_FLAG = '0') then case MC_ADR is when x"05" => RUN_CLR <= '1'; when x"06" => RUN_CLR <= '1'; when others => null; end case; end if; end if; end process; -------------------------------------------- -------------------------------------------- -- Delay PMT(0) by ~10ns using RC circuit -- between free pins SCL (out) and SDA (inp) -------------------------------------------- TST_SCL <= PMT(0); -- TST_SDA <= 'Z'; -------------------------------------------- -- Coincidence of PMT(1) and delayed PMT(0) -------------------------------------------- process(COM_RES, TR_ENA, TRG_RES, TST_SDA, PMT, GM2_RUN) begin if ((COM_RES = '1') or (TR_ENA = '0') or (TRG_RES = '1')) then TRG_RUN <= '0'; elsif (TST_SDA'event and TST_SDA = '0') then if ((PMT(1) = '0') and (GM2_RUN = '1')) then TRG_RUN <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Generated trigger -------------------------------------------- process(COM_RES, TR_ENA, TRG_RES, GM2_RUN, GM2_TRG) begin if ((COM_RES = '1') or (TR_ENA = '0') or (TRG_RES = '1')) then TRG_GEN <= '0'; elsif (GM2_TRG'event and GM2_TRG = '1') then if (GM2_RUN = '1') then TRG_GEN <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Select trigger source -------------------------------------------- process(CTR_REG, TRG_RUN, TRG_GEN) begin if (CTR_REG(3) = '0') then TRG_AND <= TRG_RUN; else TRG_AND <= TRG_GEN; end if; end process; -------------------------------------------- -- Frequency divider -------------------------------------------- process(GM2_CLK) begin if (GM2_CLK'event and GM2_CLK = '0') then DIV_CLK <= not DIV_CLK; end if; end process; -------------------------------------------- -- Trigger randomiser -------------------------------------------- process(DIV_CLK, LAT_REG, LAT_CNT) begin if (DIV_CLK'event and DIV_CLK = '1') then if (LAT_REG = conv_std_logic_vector(LAT_CNT, 8)) then TRG_STB <= '1'; elsif (LAT_REG = conv_std_logic_vector((LAT_CNT + 1), 8)) then TRG_STB <= '1'; else TRG_STB <= '0'; end if; end if; end process; -------------- process(TRG_STB, GM2_CLK) begin if (TRG_STB = '0') then TRG_STD <= '0'; elsif(GM2_CLK'event and GM2_CLK = '1') then TRG_STD <= '1'; end if; end process; -------------------------------------------- -- Trigger fanout -------------------------------------------- process(TRG_STD, TRG_AND) begin if (TRG_STD = '1') then TRG_FAN <= '0'; elsif (TRG_AND'event and TRG_AND = '1') then TRG_FAN <= '1'; end if; end process; -------------- SYS_TRG <= (others => TRG_FAN); -------------------------------------------- -- 2 Motherboard FADCs are running at 10 MHz -- producing 2 bytes each for every sampling -- clock period. The number of samples is 6 for -- pedestal + 16 for header + 128 for amplitudes -- resulting in 2x2x150 = 600 data bytes at 25ns -- (40 MHz) each. In addition there are 2 bytes -- for time, 2 bytes for temperature, 2 bytes for -- the run number and 4 bytes for the event number -- and 4 bytes for the clock period for the given -- event since the run start. Beetle pipeline depth -- of 160 clock cycles should be added to the system -- latency. -- Taking into account system latency: cable delay -- (2x * 5ns/m * 15 m = 6 clock cycles) and offset -- between "Trigger In" and "Data Valid out" of the -- Beetle chip (4 clock cycles) the latency should -- be 600+10+160+10 +20 (safety margin) = 800 clock -- cycles (40 MHz) -------------------------------------------- process(GM2_CLK, TRG_AND) begin if (GM2_CLK'event and GM2_CLK = '1') then if (TRG_AND = '1') then LAT_CNT <= LAT_CNT + 1; else LAT_CNT <= 0; end if; end if; end process; -------------- process(GM2_CLK, LAT_CNT) begin if (GM2_CLK'event and GM2_CLK = '0') then if (LAT_CNT = 0) then TRG_RES <= '0'; elsif (LAT_CNT = 800) then TRG_RES <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Scalers -------------------------------------------- -- PMT(0) -------------- process(COM_RES, PMT, TR_ENA, SPILL) begin if (COM_RES = '1') then PM1_CNT <= (others => '0'); elsif (PMT(0)'event and PMT(0) = '0') then if (TR_ENA = '1' and SPILL = '1') then PM1_CNT <= PM1_CNT + '1'; else null; end if; end if; end process; -------------- -- PMT(1) -------------- process(COM_RES, PMT, TR_ENA, SPILL) begin if (COM_RES = '1') then PM2_CNT <= (others => '0'); elsif (PMT(1)'event and PMT(1) = '0') then if (TR_ENA = '1' and SPILL = '1') then PM2_CNT <= PM2_CNT + '1'; else null; end if; end if; end process; -------------- -- Bare Coincidence -------------- process(COM_RES, TST_SDA, PMT, TR_ENA, SPILL) begin if (COM_RES = '1') then COI_CNT <= (others => '0'); elsif (TST_SDA'event and TST_SDA = '0') then if (PMT(1) = '0' and TR_ENA = '1' and SPILL = '1') then COI_CNT <= COI_CNT + '1'; else null; end if; end if; end process; -------------- -- Coincidence with trigger latency -------------- process(COM_RES, TRG_AND, SPILL) begin if (COM_RES = '1') then TRG_CNT <= (others => '0'); elsif (TRG_AND'event and TRG_AND = '0') then if (SPILL = '1') then TRG_CNT <= TRG_CNT + '1'; else null; end if; end if; end process; -------------- EVT_NUM <= TRG_CNT; -------------------------------------------- -- Store scalers data -------------------------------------------- process(RD_STB, FE_FLAG, BOS_BLK, PM1_CNT, PM2_CNT, COI_CNT, TRG_CNT) begin if (RD_STB'event and RD_STB = '1') then if (FE_FLAG = '0') then STA_REG(7 downto 1) <= (others => '0'); STA_REG(0) <= BOS_BLK; PM1_REG <= PM1_CNT; PM2_REG <= PM2_CNT; COI_REG <= COI_CNT; TRG_REG <= TRG_CNT; else null; end if; end if; end process; -------------------------------------------- -------------------------------------------- -- Temperature logger -------------------------------------------- U2:TLOG port map( CLK => OSC_40, RXD => RS232_DCE_RXD, T0 => Temp00, T1 => Temp01, T2 => Temp10, T3 => Temp11, T4 => Temp20, T5 => Temp21, T6 => Temp30, T7 => Temp31, T8 => Temp40, T9 => Temp41, T10 => Temp50, T11 => Temp51, T12 => Temp60, T13 => Temp61, T14 => Temp70, T15 => Temp71, T16 => Temp80, T17 => Temp81, T18 => Temp90, T19 => Temp91, T20 => TempA0, T21 => TempA1, T22 => TempB0, T23 => TempB1, T24 => TempC0, T25 => TempC1 ); -------------------------------------------- -- Output scalers data -------------------------------------------- process(CRC_CLK, TX_CNT, STA_REG, RUN_NUM, TRG_REG, COI_REG, PM1_REG, PM2_REG, Temp00, Temp01, Temp10, Temp11, Temp20, Temp21, Temp30, Temp31, Temp40, Temp41, Temp50, Temp51, Temp60, Temp61, Temp70, Temp71, Temp80, Temp81, Temp90, Temp91, TempA0, TempA1, TempB0, TempB1, TempC0, TempC1, RAM_OUT) begin if (CRC_CLK'event and CRC_CLK = '0') then case TX_CNT is when 22 => MC_DATA <= STA_REG; when 23 => MC_DATA <= RUN_NUM(15 downto 8); when 24 => MC_DATA <= RUN_NUM( 7 downto 0); when 25 => MC_DATA <= TRG_REG(31 downto 24); when 26 => MC_DATA <= TRG_REG(23 downto 16); when 27 => MC_DATA <= TRG_REG(15 downto 8); when 28 => MC_DATA <= TRG_REG( 7 downto 0); when 29 => MC_DATA <= COI_REG(31 downto 24); when 30 => MC_DATA <= COI_REG(23 downto 16); when 31 => MC_DATA <= COI_REG(15 downto 8); when 32 => MC_DATA <= COI_REG( 7 downto 0); when 33 => MC_DATA <= PM1_REG(31 downto 24); when 34 => MC_DATA <= PM1_REG(23 downto 16); when 35 => MC_DATA <= PM1_REG(15 downto 8); when 36 => MC_DATA <= PM1_REG( 7 downto 0); when 37 => MC_DATA <= PM2_REG(31 downto 24); when 38 => MC_DATA <= PM2_REG(23 downto 16); when 39 => MC_DATA <= PM2_REG(15 downto 8); when 40 => MC_DATA <= PM2_REG( 7 downto 0); when 41 => MC_DATA <= Temp00; when 42 => MC_DATA <= Temp01; when 43 => MC_DATA <= Temp10; when 44 => MC_DATA <= Temp11; when 45 => MC_DATA <= Temp20; when 46 => MC_DATA <= Temp21; when 47 => MC_DATA <= Temp30; when 48 => MC_DATA <= Temp31; when 49 => MC_DATA <= Temp40; when 50 => MC_DATA <= Temp41; when 51 => MC_DATA <= Temp50; when 52 => MC_DATA <= Temp51; when 53 => MC_DATA <= Temp60; when 54 => MC_DATA <= Temp61; when 55 => MC_DATA <= Temp70; when 56 => MC_DATA <= Temp71; when 57 => MC_DATA <= Temp80; when 58 => MC_DATA <= Temp81; when 59 => MC_DATA <= Temp90; when 60 => MC_DATA <= Temp91; when 61 => MC_DATA <= TempA0; when 62 => MC_DATA <= TempA1; when 63 => MC_DATA <= TempB0; when 64 => MC_DATA <= TempB1; when 65 => MC_DATA <= TempC0; when 66 => MC_DATA <= TempC1; when 67 => MC_DATA <= (others => '0'); -- Byte #46 is reserved for future use. -- The next block of data are 5*256 bytes: when 68 to 1347 => MC_DATA <= RAM_OUT; when others => MC_DATA <= (others => '0'); end case; end if; end process; -------------------------------------------- -------------------------------------------- -- Address MC registers -------------------------------------------- process(COM_RES, WR_STB, FE_FLAG, USB_OUT) begin if (COM_RES = '1') then MC_ADR <= (others => '0'); elsif (WR_STB'event and WR_STB = '1') then if (FE_FLAG = '0') then MC_ADR <= USB_OUT; else null; end if; end if; end process; -------------------------------------------- -- Access MC registers -------------------------------------------- process(WR_STB, FE_FLAG, MC_ADR, USB_OUT) begin if (WR_STB'event and WR_STB = '0') then if (FE_FLAG = '0') then case MC_ADR is when x"00" => RS232_REG <= USB_OUT; when x"01" => PAK_REG(15 downto 8) <= USB_OUT; when x"02" => PAK_REG( 7 downto 0) <= USB_OUT; when x"03" => LEN_REG(15 downto 8) <= USB_OUT; when x"04" => LEN_REG( 7 downto 0) <= USB_OUT; when x"05" => RUN_REG(15 downto 8) <= USB_OUT; when x"06" => RUN_REG( 7 downto 0) <= USB_OUT; when x"07" => EVT_REG(31 downto 24) <= USB_OUT; when x"08" => EVT_REG(23 downto 16) <= USB_OUT; when x"09" => EVT_REG(15 downto 8) <= USB_OUT; when x"0A" => EVT_REG( 7 downto 0) <= USB_OUT; when x"0B" => TOT_REG(31 downto 24) <= USB_OUT; when x"0C" => TOT_REG(23 downto 16) <= USB_OUT; when x"0D" => TOT_REG(15 downto 8) <= USB_OUT; when x"0E" => TOT_REG( 7 downto 0) <= USB_OUT; when x"0F" => LAT_REG <= USB_OUT; when x"10" => CTR_REG <= USB_OUT; when others => null; end case; else null; end if; end if; end process; -------------------------------------------- -------------------------------------------- -- Sync RS232 clock -------------------------------------------- process(WR_CYC, WR_STB, FE_FLAG, MC_ADR) begin if (WR_CYC = '0') then RS232_SYN <= '0'; elsif (WR_STB'event and WR_STB = '0') then if (FE_FLAG = '0' and MC_ADR = x"00") then RS232_SYN <= '1'; else null; end if; end if; end process; -------------------------------------------- -- 9600 baud clock synchronised to -- MC write command -------------------------------------------- process(ETH_RX_CLK, RS232_SYN, RS232_PLL) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '0') then if (RS232_SYN = '1' or RS232_PLL = '1') then RS232_CNT <= 0; else RS232_CNT <= RS232_CNT + 1; end if; end if; end process; -------------- process(ETH_RX_CLK, RS232_CNT) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (RS232_CNT = 2604) then RS232_PLL <= '1'; else RS232_PLL <= '0'; end if; end if; end process; -------------- process(ETH_RX_CLK, RS232_CNT) begin if (ETH_RX_CLK'event and ETH_RX_CLK = '1') then if (RS232_CNT = 1302) then RS232_CLK <= '1'; elsif (RS232_CNT = 2604) then RS232_CLK <= '0'; else null; end if; end if; end process; -------------------------------------------- -- Gate for one RS232 data package -------------------------------------------- process(RS232_CLK, RS232_EOF) begin if (RS232_CLK'event and RS232_CLK = '1') then if (RS232_EOF = '1') then BIT_CNT <= 0; else BIT_CNT <= BIT_CNT + 1; end if; end if; end process; -------------- process(RS232_SYN, RS232_CLK, BIT_CNT) begin if (RS232_SYN = '1') then RS232_EOF <= '0'; elsif (RS232_CLK'event and RS232_CLK = '0') then if (BIT_CNT = 11) then RS232_EOF <= '1'; else null; end if; end if; end process; -------------------------------------------- -- Output RS232 data -------------------------------------------- process(BIT_CNT, RS232_REG) begin case BIT_CNT is when 1 => RS232_DTE_TXD <= '0'; -- start bit when 2 => RS232_DTE_TXD <= RS232_REG(0); when 3 => RS232_DTE_TXD <= RS232_REG(1); when 4 => RS232_DTE_TXD <= RS232_REG(2); when 5 => RS232_DTE_TXD <= RS232_REG(3); when 6 => RS232_DTE_TXD <= RS232_REG(4); when 7 => RS232_DTE_TXD <= RS232_REG(5); when 8 => RS232_DTE_TXD <= RS232_REG(6); when 9 => RS232_DTE_TXD <= RS232_REG(7); when 10 => RS232_DTE_TXD <= '1'; -- stop bit when others => null; end case; end process; -------------------------------------------- -------------------------------------------- -- GM2 scaler control -------------------------------------------- process(GM2_RUN, GM2_CLK, RUN_EOF) begin if (GM2_RUN = '0') then RUN_CNT <= 0; elsif (GM2_CLK'event and GM2_CLK = '0') then if (RUN_EOF = '0') then RUN_CNT <= RUN_CNT + 1; else null; end if; end if; end process; -------------- process(GM2_CLK, RUN_CNT) begin if (GM2_CLK'event and GM2_CLK = '1') then case RUN_CNT is when 0 => RUN_EOF <= '0'; when 15 => RUN_EOF <= '1'; when others => null; end case; end if; end process; -------------------------------------------- -- Clock counter -------------------------------------------- process(GM2_CLK, SPILL) begin if (GM2_CLK'event and GM2_CLK = '0') then if (SPILL = '0') then CLK_CNT <= (others => '0'); else CLK_CNT <= CLK_CNT + '1'; end if; end if; end process; -------------------------------------------- -- Store clock counter value for the given -- GM2_RUN gate -------------------------------------------- process(GM2_CLK, RUN_CNT, CLK_CNT) begin if (GM2_CLK'event and GM2_CLK = '1') then if (RUN_CNT = 3) then CNT_DAT <= CLK_CNT; else null; end if; end if; end process; -------------------------------------------- -- Number of issued GM2_RUN gates -------------------------------------------- process(SPILL, GM2_CLK, RUN_CNT) begin if (SPILL = '0') then RUN_DAT <= 0; elsif (GM2_CLK'event and GM2_CLK = '1') then case RUN_CNT is when 3 => RUN_DAT <= RUN_DAT + 1; when others => null; end case; end if; end process; -------------------------------------------- -- RAM input -------------------------------------------- process(GM2_CLK, RUN_CNT, RUN_DAT, CNT_DAT) begin if (GM2_CLK'event and GM2_CLK = '1') then case RUN_CNT is when 4 => RAM_INP <= conv_std_logic_vector(RUN_DAT, 8); when 6 => RAM_INP <= CNT_DAT(31 downto 24); when 8 => RAM_INP <= CNT_DAT(23 downto 16); when 10 => RAM_INP <= CNT_DAT(15 downto 8); when 12 => RAM_INP <= CNT_DAT( 7 downto 0); when others => null; end case; end if; end process; -------------------------------------------- -- RAM write address -------------------------------------------- process(SPILL, GM2_CLK, RUN_CNT) begin if (SPILL = '0') then RAM_WA <= (others => '0'); elsif (GM2_CLK'event and GM2_CLK = '1') then case RUN_CNT is when 4 => RAM_WA <= RAM_WA + '1'; when 6 => RAM_WA <= RAM_WA + '1'; when 8 => RAM_WA <= RAM_WA + '1'; when 10 => RAM_WA <= RAM_WA + '1'; when 12 => RAM_WA <= RAM_WA + '1'; when others => null; end case; end if; end process; -------------------------------------------- -- RAM write strobe -------------------------------------------- process(GM2_CLK, RUN_CNT) begin if (GM2_CLK'event and GM2_CLK = '1') then case RUN_CNT is when 4 => STB_TMP <= '1'; when 6 => STB_TMP <= '1'; when 8 => STB_TMP <= '1'; when 10 => STB_TMP <= '1'; when 12 => STB_TMP <= '1'; when others => STB_TMP <= '0'; end case; end if; end process; -------------- process(GM2_CLK, STB_TMP) begin if (GM2_CLK'event and GM2_CLK = '0') then RAM_STB <= STB_TMP; end if; end process; -------------------------------------------- -- RAM write enable -------------------------------------------- process(GM2_CLK, RUN_CNT) begin if (GM2_CLK'event and GM2_CLK = '1') then case RUN_CNT is when 0 => RAM_WE <= "0"; when 4 => RAM_WE <= "1"; when 14 => RAM_WE <= "0"; when others => null; end case; end if; end process; -------------------------------------------- -- RAM read address -------------------------------------------- process(CRC_CLK, TX_CNT) begin if (CRC_CLK'event and CRC_CLK = '0') then RAM_RA <= conv_std_logic_vector((TX_CNT-66), 11); end if; end process; -------------------------------------------- -- RAM component -------------------------------------------- U3:RAM port map( clka => RAM_STB, -- CLK <- wea => RAM_WE, -- CLK -> addra => RAM_WA, -- CLK -> dina => RAM_INP, -- CLK -> clkb => CRC_CLK, addrb => RAM_RA, doutb => RAM_OUT); -------------------------------------------- -------------------------------------------- -- Test block for the telescope -------------------------------------------- -- BOS counter -------------------------------------------- process(OSC_40) begin if (OSC_40'event and OSC_40 = '0') then GLB_CNT <= GLB_CNT + 1; end if; end process; -------------------------------------------- -- Test BOS with ~0.8s period -------------------------------------------- process(OSC_40, GLB_CNT) begin if (OSC_40'event and OSC_40 = '1') then if (GLB_CNT = 1) then TST_BOS <= '1'; elsif (GLB_CNT = 10) then TST_BOS <= '0'; else null; end if; end if; end process; -------------------------------------------- -- GM2_RUN counter -------------------------------------------- process(OSC_40, TST_BOS) begin if (TST_BOS = '1') then LCL_CNT <= 0; elsif (OSC_40'event and OSC_40 = '0') then LCL_CNT <= LCL_CNT + 1; end if; end process; -------------------------------------------- -- 20ms GM2_RUN with ~26 ms period -------------------------------------------- process(OSC_40, LCL_CNT) begin if (OSC_40'event and OSC_40 = '1') then if (LCL_CNT = 20) then TST_RUN <= '1'; elsif (LCL_CNT = 800020) then TST_RUN <= '0'; else null; end if; end if; end process; -------------------------------------------- -- Trigger counter -------------------------------------------- process(Clock) begin if (Clock'event and Clock = '0') then TST_CNT <= TST_CNT + 1; end if; end process; -------------------------------------------- -- Test trigger 20ns wide with ~12kHz rate -------------------------------------------- process(Clock, TST_CNT) begin if (Clock'event and Clock = '1') then if (TST_CNT = 20) then TST_EVT <= '1'; elsif (TST_CNT = 21) then TST_EVT <= '0'; else null; end if; end if; end process; -------------------------------------------- -- Test output -------------------------------------------- process(CTR_REG, PMT, TST_SDA, TRG_AND, TST_EVT, TST_RUN, TST_BOS, OSC_40) begin if (CTR_REG(0) = '0') then -- run TST_TRG <= not GM2_CLK; TST_SYN <= not GM2_BOS; -- PMT(0) delayed TST_PUL <= not GM2_RUN; TST_RES <= not PMT(1); else -- test mode TST_TRG <= not TST_EVT; TST_SYN <= not TST_RUN; TST_PUL <= not TST_BOS; TST_RES <= not OSC_40; end if; end process; -------------------------------------------- end Behavioral;