-- TLMUsend, top level to send out TLMU data -- Addr 0: Bit 4..0 select Trigger src 0..31, -- Bit 5: select no Trigger, switch Datain to Mask Register to load Dummydata -- Addr 1: load Dummydata (write 1=store, reads 0) -- Addr 2: clear FIFO -- Addr 3: Read FIFO Write Count. -- Addr 4: Read FIFO Flags -- Addr 5: set wrong CRC to test error handling -- Addr 6: Testmode: Number of packets to load in FIFO = R/W -- Addr 7: Testmode: number of cycles (= number of packets to send= -- Addr7*Addr6) R/W -- Addr 8: Testmode: start WO -- Addr 9: write 1: inc Phaseshift, write 0, dec Phaseshift: Read: "psdone" -- what about FIFO fill level (rdcnt - wrcnt)? library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.all; library UNISIM; use UNISIM.vcomponents.all; entity tlmusend is generic ( OutClockMultiplier : integer := 1; OutClockDivisor : integer := 10; Oserdes_factor : integer := 4; -- faktor betweenn output frequency and input frequency, number of parallel inputs of oserdes serw : integer := 8); -- number of output lines (1..8) port ( clk40 : in std_logic; reset_n : in std_logic; Tin : in std_logic_vector(31 downto 0); -- 32 (theoreticval) trigger sources (select like in outputswitch) to activate FIFO write Tout : out std_logic_vector(serw-1 downto 0); -- Trigger out, exact: Data output lines senddata : in std_logic_vector(575 downto 0); -- from synced TOF input simdata : in std_logic_vector(575 downto 0); -- from TLMU Mask to write dummydata (to save registers) time_counter : in std_logic_vector(47 downto 0); -- from SOR/EOR Counter ? start : in std_logic; -- external start signal (from CBB) active : out std_logic; -- signal to take over Trigger lines during active sending address : in std_logic_vector(3 downto 0); -- scsn we : in std_logic; -- scsn tlmusend_IBO : in std_logic_vector(31 downto 0); -- scsn tlmusend_OBI : out std_logic_vector(31 downto 0) -- scsn ); end tlmusend; architecture behv of tlmusend is constant idlew : integer := 32; -- sending ffffffff when idle constant headerw : integer := 32; constant counterw : integer := 48; constant padding : integer := 16; -- for serialsender must be divideable by 32 constant parw : integer := idlew + headerw + 576 + counterw + padding; -- Header, TOF Bits and Counter. component tsserdes generic ( OutClockMultiplier : integer; OutClockDivisor : integer; Oserdes_factor : integer; parw : integer; serw : integer); port ( reset_n : in std_logic; clk : in std_logic; psen : in std_logic; psincdec : in std_logic; psdone : out std_logic; locked : out std_logic; dclk : out std_logic; dclkdiv : out std_logic; pardata : in std_logic_vector(parw-1 downto 0); serdata : out std_logic_vector(serw-1 downto 0); spoilcrc : in std_logic; start : in std_logic; active : out std_logic; done : out std_logic); end component; component tsfifo generic ( width : integer); port ( inclk : in std_logic; outclk : in std_logic; reset_n : in std_logic; di : in std_logic_vector(width-1 downto 0); wren : in std_logic; full : out std_logic; wrerr : out std_logic; wrcount : out std_logic_vector(11 downto 0); do : out std_logic_vector(width-1 downto 0); rden : in std_logic; empty : out std_logic; rderr : out std_logic; rdcount : out std_logic_vector(11 downto 0)); end component; component clksync port ( reset_n : in std_logic; fastclk : in std_logic; slowclk : in std_logic; fastin : in std_logic; slowout : out std_logic); end component; -- DCM in tsserdes outputs signal dclk : std_logic; signal dclkdiv : std_logic; -- Data going to serdes incl header signal pardata : std_logic_vector(parw-1 downto 0); -- signals done from tserdes signal done : std_logic; -- Multiplex between real data and maskregister signal muxout : std_logic_vector(575 downto 0); -- sourceselect register signal sourceselect : std_logic; -- triggersource register, result in trigger signal tsel : std_logic_vector(4 downto 0); signal trigger : std_logic; -- sabotage_crc: send wrong CRC to check receiver signal sabotage_crc : std_logic; -- reset_fifo, address 2 or reset_n signal reset_fifo : std_logic; signal full : std_logic; signal wren : std_logic; -- from logic signal wren_i : std_logic; -- to FIFO combined with tst-fsm signal wrerr : std_logic; signal wrcount : std_logic_vector(11 downto 0); signal fifoout : std_logic_vector(576+counterw-1 downto 0); signal fifoin : std_logic_vector(576+counterw-1 downto 0); signal empty : std_logic; signal rderr : std_logic; signal rdcount : std_logic_vector(11 downto 0); -- test mode signal tst_start : std_logic; -- number of packets to load at once in FIFO signal tst_FIFOld : std_logic_vector(31 downto 0); -- counter for FIFO wren signal tst_FIFOldcnt : std_logic_vector(31 downto 0); signal tst_FIFOldcnt_en, tst_FIFOldcnt_ld : std_logic; signal tst_FIFOldcnt_zero : std_logic; -- number of cycles, how often to load the fifo and send signal tst_cycles : std_logic_vector(31 downto 0); signal tst_cycles_dec : std_logic; signal tst_cycles_zero : std_logic; -- FSM to control testcycles type STATE_TYPE is (idle, sFIFOld, sFIFOpre, sFIFOen, sFIFOld2, sSend, sWaitdone1, sWaitdone0, sDecFIFO, sCycle); signal state, nextstate : STATE_TYPE; -- start signal to tsserdes signal tst_actsender : std_logic; -- sync to clk40 from FSM signal start_internal : std_logic; -- sync to dclkdiv to tsserdes signal start_i : std_logic; -- combined with ext "start" to instance signal tst_ldfifosig : std_logic; -- from fsm to enable FIFO writes -- Phase shift signals signal psen_i : std_logic; signal psincdec_i : std_logic; signal psdone_i : std_logic; signal locked_i : std_logic; begin -- behv start_i <= start or start_internal; tsserdes_1 : tsserdes generic map ( OutClockMultiplier => OutClockMultiplier, OutClockDivisor => OutClockDivisor, Oserdes_factor => Oserdes_factor, parw => parw, serw => serw) port map ( reset_n => reset_n, clk => clk40, psen => psen_i, psincdec => psincdec_i, psdone => psdone_i, locked => locked_i, dclk => dclk, dclkdiv => dclkdiv, pardata => pardata, serdata => Tout, spoilcrc => sabotage_crc, start => start_i, active => active, done => done); -- Header: Version "0001" and readcounter pardata <= x"ffffffff" & x"0001" & empty & rderr & "00" & rdcount & fifoout & (padding-1 downto 0 => '0'); -- idle + Header + fifoout wren_i <= wren or tst_ldfifosig; tsfifo_1 : tsfifo generic map ( width => 576 + counterw) port map ( inclk => clk40, outclk => dclkdiv, reset_n => reset_fifo, di => fifoin, wren => wren_i, full => full, wrerr => wrerr, wrcount => wrcount, do => fifoout, rden => done, empty => empty, rderr => rderr, rdcount => rdcount); -- Generate Phasehift control combinatoric from SCSN inp psen_i <= '1' when address = "1001" and we = '1' else '0'; psincdec_i <= tlmusend_IBO(0); muxout <= simdata when sourceselect = '1' else senddata; fifoin <= muxout & time_counter; -- Address 0: select source, ... adr0p : process (clk40, reset_n) begin -- process adr0p if reset_n = '0' then -- asynchronous reset (active low) tsel <= "00000"; sourceselect <= '0'; elsif clk40'event and clk40 = '1' then -- rising clock edge if address = "0000" and we = '1' then tsel <= tlmusend_IBO(4 downto 0); sourceselect <= tlmusend_IBO(5); end if; end if; end process adr0p; trigger <= Tin(conv_integer(tsel)); -- Address 1: load dummydata in FIFO, write anything to address 1 fifowren_p : process (trigger, address, sourceselect, we) begin -- process fifowren_p if sourceselect = '0' then --senddata wren <= trigger; else if address = "0001" and we = '1' then wren <= '1'; else wren <= '0'; end if; end if; end process fifowren_p; -- Address 2: Reset FIFO reset_fifo_p : process (reset_n, address, we) begin -- process reset_fifo_p if address = "0010" and we = '1' then reset_fifo <= '0'; else reset_fifo <= reset_n; end if; end process reset_fifo_p; -- Address 5: Set wrong CRC sabotage_p : process (clk40, reset_n) begin -- process sabotage_p if reset_n = '0' then -- asynchronous reset (active low) sabotage_crc <= '0'; elsif clk40'event and clk40 = '1' then -- rising clock edge if address = "0101" and we = '1' then sabotage_crc <= tlmusend_IBO(0); end if; end if; end process sabotage_p; -- Address 6: FIFo load count addr6p : process (clk40, reset_n) begin -- process addr6p if reset_n = '0' then -- asynchronous reset (active low) tst_FIFOld <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge if address = "0110" and we = '1' then tst_FIFOld <= tlmusend_IBO; end if; end if; end process addr6p; -- Address 7: Number of cycles addr7p : process (clk40, reset_n) begin -- process addr6p if reset_n = '0' then -- asynchronous reset (active low) tst_cycles <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge if address = "0111" and we = '1' then tst_cycles <= tlmusend_IBO; elsif tst_cycles_dec = '1' then tst_cycles <= tst_cycles - '1'; end if; end if; end process addr7p; tst_cycles_zero <= '1' when tst_cycles = (31 downto 0 => '0') else '0'; -- read demux with address select tlmusend_OBI <= (tsel & sourceselect & (31 downto 6 => '0')) when "0000", ((31 downto 12 => '0') & wrcount) when "0011", ((31 downto 2 => '0') & full & wrerr) when "0100", ((31 downto 1 => '0') & sabotage_crc) when "0101", ((31 downto 2 => '0') & locked_i & psdone_i) when "1001", (31 downto 0 => '0') when others; -- Test load FIFO counter tst_FIFOldcnt_p : process (clk40, reset_n) begin -- process tst_FIFOldcnt_p if reset_n = '0' then -- asynchronous reset (active low) tst_FIFOldcnt <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge if tst_FIFOldcnt_ld = '1' then tst_FIFOldcnt <= tst_FIFOld; elsif tst_FIFOldcnt_en = '1' then tst_FIFOldcnt <= tst_FIFOldcnt - '1'; end if; end if; end process tst_FIFOldcnt_p; tst_FIFOldcnt_zero <= '1' when tst_FIFOldcnt = (31 downto 0 => '0') else '0'; tst_start <= '1' when address = "1000" and we = '1' else '0'; -- FSM: inputs: tst_start, tst_cycles_zero, tst_FIFOldcnt_zero -- outputs: tst_FIFOldcnt_en, tst_FIFOldcnt_ld, tst_cycles_dec fsm_sp : process (clk40, reset_n) begin -- process fsm_sp if reset_n = '0' then -- asynchronous reset (active low) state <= idle; elsif clk40'event and clk40 = '1' then -- rising clock edge state <= nextstate; end if; end process fsm_sp; -- fsm_comb : process (state, tst_start, tst_cycles_zero, tst_FIFOldcnt_zero, done) begin -- process fsm_comb case state is when idle => if tst_start = '1' then nextstate <= sFIFOld; else nextstate <= idle; end if; when sFIFOld => nextstate <= sFIFOpre; when sFIFOpre => nextstate <= sFIFOen; when sFIFOen => if tst_FIFOldcnt_zero = '1' then nextstate <= sFIFOld2; else nextstate <= sFIFOen; end if; when sFIFOld2 => nextstate <= sSend; when sSend => nextstate <= sWaitdone1; when sWaitdone1 => if done = '1' then nextstate <= sWaitdone0; else nextstate <= sWaitdone1; end if; when sWaitdone0 => if done = '0' then nextstate <= sDecFIFO; else nextstate <= sWaitdone0; end if; when sDecFIFO => nextstate <= sCycle; when sCycle => if tst_FIFOldcnt_zero = '1' and tst_cycles_zero = '1' then nextstate <= idle; elsif tst_FIFOldcnt_zero = '1' and tst_cycles_zero = '0' then nextstate <= sFIFOld; else nextstate <= sSend; end if; when others => null; end case; end process fsm_comb; tst_FIFOldcnt_ld <= '1' when (state = sFIFOld) or (state = sFIFOld2) else '0'; tst_FIFOldcnt_en <= '1' when (state = sFIFOen) or (state = sDecFIFO) or (state=sFIFOpre) else '0'; tst_cycles_dec <= '1' when state = sFIFOld else '0'; tst_actsender <= '1' when state = sSend else '0'; tst_ldfifosig <= '1' when state = sFIFOen else '0'; clksync_1 : clksync port map ( reset_n => reset_n, fastclk => clk40, slowclk => dclkdiv, fastin => tst_actsender, slowout => start_internal); end behv;