-- **************************************************
--
-- Entity: GMTBoard_tb
--
-- Description: Testbench for GMT Board
--
-- The entire GMT board is simulated. Test data are read from file and fed
-- into the Input FPGAs and MIP/ISO Assingment units. Results at the output
-- of the sort chip are compared to the results from the test file.
--
-- In parallel, the readout system is tested. Three L1 accepts are generated,
-- the output on the channel link is saved to file chlink1.out (in the
-- simulation directory)
--
--
-- $Date: 2005/01/20 18:24:12 $
-- $Revision: 1.5 $
--
-- Author :
-- H. Sakulin CERN EP
--
-- **************************************************
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
use WORK.GMTTypes.all;
use work.GMTHWTestFile.all;
use STD.TEXTIO.all;
--use work.GMTBoard_cfg.all; -- switch beh/time simu
use work.ieee_to_string.all;
entity GMTBoard_tb is
end;
architecture Bench of GMTBoard_tb is
-- purpose: calculate xor of all bits in d
function parity (
constant d : std_logic_vector)
return std_logic is
variable result : std_logic;
begin -- function parity
result := '0';
for i in d'RANGE loop
result := result xor d(i);
end loop; -- i
return result;
end function parity;
-----------------------------------------------------------------------------
-- LATENCIES (in half cycles)
-----------------------------------------------------------------------------
constant LAT_TOTAL : integer := 19;
-- LAT_TOTAL_CYCLES is the the number of delays of the input event
-- there is no delay if the actual latency of an output was 0 or 1
-- there is a 1bx delay if the latency of an output was 2 or 3
constant LAT_TOTAL_CYCLES : integer := LAT_TOTAL / 2;
-- input latencies give the number of half-cycles from setting the earliest
-- signals to setting the respective delayed signals
constant LAT_IN_MIPISO : integer := 4;
-- output latencies give the number of half-cycles from setting the earliest
-- inputs to reading the respective output. (actually the time until the
-- outputs are read is even longer as signals are checked just before the
-- falling edge of a main cycle).
--
-- i.e. latency for OUT_CANCELDTCSC is same as for IN_CANCELDTCSC to other chip
--
-- With an input and an outpt FF in
-- the chip, the minimum output latency of any signal is 2.
constant LAT_OUT_DTCSCISMATCHED : integer := 5;--4;x
constant LAT_OUT_CANCELDTCSC : integer := 7;--7;
constant LAT_OUT_PM_DEBUG : integer := 6;
constant LAT_OUT_COU_DEBUG : integer := 8;
-----------------------------------------------------------------------------
constant t_period : time := 25 ns;
constant t_halfperiod : time := t_period / 2;
constant t_inbefore : time := 7 ns;
constant t_afterck : time := t_halfperiod - t_inbefore;
-----------------------------------------------------------------------------
-- OUTPUTS from chip
-- signal sOutMuons_flat : TFourGMTMu_flat;
-- signal sOutMuons : TGMTMu_vector (0 to 3);
-- signal sSortRanks : TSortRank_vector(0 to 3);
-- signal sIdxBits : TIndexBits_vector(0 to 3);
-- signal sDTCSCisMatched : std_logic_vector (0 to 3);
-- signal sCancelOtherDTCSC : std_logic_vector (0 to 3);
-- signal sPairMatrix : TPairMatrix;
-- signal sPairMatrix1 : TPairMatrix;
-- signal sPairMatrix2 : TPairMatrix;
-- signal sMQMatrix : TMQMatrix;
-- signal sCancelBits1 : std_logic_vector(0 to 7);
-- signal sCancelBits2 : std_logic_vector(0 to 7);
-- -- OUTPUTS delayed
-- signal sDTCSCisMatched_d : std_logic_vector (0 to 3);
-- signal sCancelOtherDTCSC_d : std_logic_vector (0 to 3);
-- signal sPairMatrix_d : TPairMatrix;
-- signal sPairMatrix1_d : TPairMatrix;
-- signal sPairMatrix2_d : TPairMatrix;
-- -- signal sMQMatrix_d : TMQMatrix;
-- signal sCancelBits1_d : std_logic_vector(0 to 7);
-- signal sCancelBits2_d : std_logic_vector(0 to 7);
-- Clock, control, VME
signal ck : std_logic := '0'; -- the clock
signal ck_inputs : std_logic := '0'; -- shifted clock for inputs
signal vme_addr_board_i : std_logic_vector (23 downto 1);
signal vme_data_i : std_logic_vector (15 downto 0);
signal dcm_locked_i : std_logic;
signal reset_dcm_i : std_logic;
signal inactive_i : std_logic;
signal reset_i : std_logic;
-- Input muons
signal sDTMu : TInMuons_vec(0 to 3);
signal sCSCMu : TInMuons_vec(0 to 3);
signal sbRPCMu : TInMuons_vec(0 to 3);
signal sfRPCMu : TInMuons_vec(0 to 3);
-- Flat version
signal sDTMu_flat : TFourInMuons_flat;
signal sCSCMu_flat : TFourInMuons_flat;
signal sbRPCMu_flat : TFourInMuons_flat;
signal sfRPCMu_flat : TFourInMuons_flat;
-- Input MQ bits
signal sfMQbits : TCaloRing_vector (0 to 9);
signal sbMQbits : TCaloRing_vector (0 to 9);
-- flat version
signal sfMQbits_flat : std_logic_vector(0 to 10*18-1);
signal sbMQbits_flat : std_logic_vector(0 to 10*18-1);
-- flat delayed version
signal sfMQbits_flat_d : std_logic_vector(0 to 10*18-1);
signal sbMQbits_flat_d : std_logic_vector(0 to 10*18-1);
-- Output muons
signal sMuon12 : TGMTMu_flat;
signal sMuon34 : TGMTMu_flat;
signal oPairMatrix_LFF_i : TPairMatrix;
signal oPairMatrix1_LFF_i : TPairMatrix;
signal oPairMatrix2_LFF_i : TPairMatrix;
signal oMQMatrix_LFF_i : TMQMatrix;
signal oCancelBits1_LFF_i : std_logic_vector(0 to 7);
signal oCancelBits2_LFF_i : std_logic_vector(0 to 7);
signal oPairMatrix_LFB_i : TPairMatrix;
signal oPairMatrix1_LFB_i : TPairMatrix;
signal oPairMatrix2_LFB_i : TPairMatrix;
signal oCancelBits1_LFB_i : std_logic_vector(0 to 7);
signal oCancelBits2_LFB_i : std_logic_vector(0 to 7);
signal oMQMatrix_LFB_i : TMQMatrix;
signal oPhiSelBits_AUF_i : TPhiSelBits_vec (0 to 15);
signal oEtaSelBits_AUF_i : TEtaSelBits_vec (0 to 15);
signal oPhiSelBits_AUB_i : TPhiSelBits_vec (0 to 15);
signal oEtaSelBits_AUB_i : TEtaSelBits_vec (0 to 15);
signal DTACK_EXT_i : std_logic;
signal SINGLE_ACCESS_i : std_logic;
signal BLT_ACCESS_i : std_logic;
signal DSPULS_i : std_logic;
signal DSCYC_i : std_logic;
signal DSSYNC_i : std_logic;
signal WRITE_I_i : std_logic := '0';
signal vme_en_i : std_logic := '0';
signal vme_en_i_d : std_logic := '0';
signal ch_link1_i : std_logic_vector(27 downto 0);
signal ch_link1_clk_i : std_logic;
signal en_link1_i : std_logic;
signal l1a_i : std_logic := '0';
signal bcreset_i : std_logic := '0';
signal l1reset_i : std_logic := '0';
signal ro_bus_i : std_logic_vector(11 downto 0);
signal ro_strobe_i : std_logic_vector(2 downto 0);
signal ro_rdrqst_i : std_logic;
begin
-------------------------------------------------------------------------------
-- instantiate the chip
-------------------------------------------------------------------------------
sDTMu_flat <= InMuons_vec_to_flat (sDTMu);
sCSCMu_flat <= InMuons_vec_to_flat (sCSCMu);
sbRPCMu_flat <= InMuons_vec_to_flat (sbRPCMu);
sfRPCMu_flat <= InMuons_vec_to_flat (sfRPCMu);
sfMQbits_flat <= CaloRing_vec_to_flat(sfMQbits);
sbMQbits_flat <= CaloRing_vec_to_flat(sbMQbits);
theBoard: entity work.GMTBoard
port map (
DTMu => sDTMu_flat,
CSCMu => sCSCMu_flat,
bRPCMu => sbRPCMu_flat,
fRPCMu => sfRPCMu_flat,
fMQbits => sfMQbits_flat_d,
bMQbits => sbMQbits_flat_d,
Muon12 => sMuon12,
Muon34 => sMuon34,
oPairMatrix_LFF => oPairMatrix_LFF_i,
oPairMatrix1_LFF => oPairMatrix1_LFF_i,
oPairMatrix2_LFF => oPairMatrix2_LFF_i,
oMQMatrix_LFF => oMQMatrix_LFF_i,
oCancelBits1_LFF => oCancelBits1_LFF_i,
oCancelBits2_LFF => oCancelBits2_LFF_i,
oPairMatrix_LFB => oPairMatrix_LFB_i,
oPairMatrix1_LFB => oPairMatrix1_LFB_i,
oPairMatrix2_LFB => oPairMatrix2_LFB_i,
oCancelBits1_LFB => oCancelBits1_LFB_i,
oCancelBits2_LFB => oCancelBits2_LFB_i,
oMQMatrix_LFB => oMQMatrix_LFB_i,
oPhiSelBits_AUF => oPhiSelBits_AUF_i,
oEtaSelBits_AUF => oEtaSelBits_AUF_i,
oPhiSelBits_AUB => oPhiSelBits_AUB_i,
oEtaSelBits_AUB => oEtaSelBits_AUB_i,
vme_addr_board => vme_addr_board_i,
vme_data => vme_data_i,
BERR_EXT => open,
DTACK_EXT => DTACK_EXT_i,
SINGLE_ACCESS => SINGLE_ACCESS_i,
BLT_ACCESS => BLT_ACCESS_i,
DSPULS => DSPULS_i,
DSCYC => DSCYC_i,
DSSYNC => DSSYNC_i,
WRITE_I => WRITE_I_i,
VME_LED => open,
error_LED => open,
SET_RUNNING => open,
stat_GMT => open,
ch_link1 => ch_link1_i,
ch_link1_clk => ch_link1_clk_i,
en_link1 => en_link1_i,
ch_link2 => open,
ch_link2_clk => open,
en_link2 => open,
l1a => l1a_i,
bcreset => bcreset_i,
l1reset => l1reset_i,
ro_bus => ro_bus_i,
ro_strobe => ro_strobe_i,
ro_rdrqst => ro_rdrqst_i,
test_pins => open,
clk => ck,
reset => reset_i,
dcm_locked_LED => dcm_locked_i,
reset_dcm => reset_dcm_i,
inactive => inactive_i);
delay_b_MIP_ISO: entity work.DelayLine
generic map ( n_halfcycles => LAT_IN_MIPISO)
port map (sbMQbits_flat, sbMQbits_flat_d, ck_inputs);
delay_f_MIP_ISO: entity work.DelayLine
generic map ( n_halfcycles => LAT_IN_MIPISO)
port map (sfMQbits_flat, sfMQbits_flat_d, ck_inputs);
inactive_i <= '0';
------------------------------------------------------------------------------
-- testbench process
-------------------------------------------------------------------------------
runtb : process
file F : text open read_mode is "gmt_testfile.dat";
-- synchronized muons from input FPGA
variable L, LO : line; -- input file line
variable event : TGMTEvent;
-- in the event pipe the events are delayed until the can be compated with
-- the chip output
variable event_pipe : TGMTEvent_vec(0 to LAT_TOTAL_CYCLES-1);
variable vDTMu : TInMuons_vec(0 to 3);
variable vCSCMu : TInMuons_vec(0 to 3);
variable vbRPCMu : TInMuons_vec(0 to 3);
variable vfRPCMu : TInMuons_vec(0 to 3);
variable vOutMuons : TGMTMu_vector(0 to 3);
variable vMuon12 : TGMTMu;
variable vMuon34 : TGMTMu;
-- variable vSortRanks : TSortRank_vector(0 to 3);
variable bMatch : boolean;
variable bTestOk : boolean;
variable ntestfailed : integer := 0;
variable ievent : integer;
variable zz : TFourSyncedMu_flat;
begin -- process runtb
---------------------------------------------------------------------------
-- reset variables
---------------------------------------------------------------------------
ck <= '0';
ck_inputs <= '0';
for i in 0 to 3 loop
sDTMu(i) <= ( others => '0');
sCSCMu(i) <= ( others => '0');
sbRPCMu(i) <= ( others => '0');
sfRPCMu(i) <= ( others => '0');
end loop; -- i
reset_i <= '0';
reset_dcm_i <= '0';
l1reset_i <= '0';
bcreset_i <= '0';
---------------------------------------------------------------------------
-- wait
---------------------------------------------------------------------------
wait for 100 ns;
---------------------------------------------------------------------------
-- start clock & apply reset for 5 cycles
---------------------------------------------------------------------------
reset_dcm_i <= '1';
for i in 1 to 5 loop
wait for t_halfperiod;
ck <= '1';
wait for t_halfperiod;
ck <= '0';
end loop;
reset_dcm_i <= '0';
---------------------------------------------------------------------------
-- run a few cycles to allow DCM to lock
---------------------------------------------------------------------------
for i in 1 to 100 loop
wait for t_halfperiod;
ck <= '1';
wait for t_halfperiod;
ck <= '0';
end loop;
assert dcm_locked_i = '1' report "DCM did not lock !" severity failure;
reset_i <= '1';
for i in 1 to 5 loop
wait for t_halfperiod;
ck <= '1';
wait for t_halfperiod;
ck <= '0';
end loop;
reset_i <= '0';
for i in 1 to 5 loop
wait for t_halfperiod;
ck <= '1';
wait for t_halfperiod;
ck <= '0';
end loop;
l1reset_i <= '1';
wait for t_halfperiod;
ck <= '1';
wait for t_halfperiod;
ck <= '0';
l1reset_i <= '0';
for i in 1 to 5 loop
wait for t_halfperiod;
ck <= '1';
wait for t_halfperiod;
ck <= '0';
end loop;
bcreset_i <= '1';
wait for t_halfperiod;
ck <= '1';
wait for t_halfperiod;
ck <= '0';
bcreset_i <= '0';
for i in 1 to 2 loop
wait for t_halfperiod;
ck <= '1';
wait for t_halfperiod;
ck <= '0';
end loop;
-------------------------------------------------------------------------------
-- loop over events
-------------------------------------------------------------------------------
bTestOk := true;
write (LO, string'("******************* start of tests ********************** "));
writeline (OUTPUT, LO);
write (LO, string'("******************* start of tests ********************** "));
writeline (OUTPUT, LO);
write (LO, string'("******************* start of tests ********************** "));
writeline (OUTPUT, LO);
ievent := 0;
while not endfile(F) loop
--------------------------------------------------------------------------
-- read an event
--------------------------------------------------------------------------
ievent := ievent+1;
write (LO, string'("++++++++++++++++++++ reading event nr "));
write (LO, ievent);
write (LO, string'(" ++++++++++++++++++++"));
writeline (OUTPUT, LO);
ReadEvent(F, event);
DumpEvent( event );
-- convert input muons
for i in 0 to 3 loop
vDTMu(i) := "000000" & parity(SyncedMu_to_flat (event.DTMuons(i))) & SyncedMu_to_flat (event.DTMuons(i));
vCSCMu(i) := "000000" & parity(SyncedMu_to_flat (event.CSCMuons(i))) & SyncedMu_to_flat (event.CSCMuons(i));
vbRPCMu(i) := "000000" & parity(SyncedMu_to_flat (event.bRPCMuons(i))) & SyncedMu_to_flat (event.bRPCMuons(i));
vfRPCMu(i) := "000000" & parity(SyncedMu_to_flat (event.fRPCMuons(i))) & SyncedMu_to_flat (event.fRPCMuons(i));
end loop; -- i
-------------------------------------------------------------------------
-- set signals on rising edge (unless they are delayed, later)
-------------------------------------------------------------------------
wait for t_afterck;
-- input clock which is phase shifted to occur t_inbefore before the
-- main clock
-- all the input signals are set after the edge of the input clock
-- the next clock egde occurs 1/2 bx later which will be the next
-- time when data in the input delay pipelines are shifted
ck_inputs <= '1';
sDTMu <= vDTMu;
sCSCMu <= vCSCMu;
sbRPCMu <= vbRPCMu;
sfRPCMu <= vfRPCMu;
sbMQbits <= event.MIPbits( 2 to 11 );
sfMQbits <= event.MIPbits( 0 to 4 ) & event.MIPbits( 9 to 13);
-- read signals to be read after falling edge
vOutMuons(1) := GMTMu_from_flat(sMuon12);
vOutMuons(3) := GMTMu_from_flat(sMuon34);
wait for t_inbefore;
ck <= '1';
-------------------------------------------------------------------------
-- set signals on falling edge
-------------------------------------------------------------------------
wait for t_afterck;
ck_inputs <= '0';
sbMQbits <= event.Quietbits( 2 to 11 );
sfMQbits <= event.Quietbits( 0 to 4 ) & event.Quietbits ( 9 to 13);
-- read signals to be read after rising edge
vOutMuons(0) := vMuon12;
vOutMuons(2) := vMuon34;
vMuon12 := GMTMu_from_flat(sMuon12); -- save for next cycle
vMuon34 := GMTMu_from_flat(sMuon34); -- save for next cycle
wait for t_inbefore;
-------------------------------------------------------------------------
-- read output and check if it matches the ORCA output
-------------------------------------------------------------------------
if ievent > LAT_TOTAL_CYCLES then
write (LO, string'("-------------------- checking event nr "));
write (LO, ievent-LAT_TOTAL_CYCLES);
write (LO, string'(" --------------------"));
writeline (OUTPUT, LO);
----------------------------------------------------------------------
-- check GMT muons
----------------------------------------------------------------------
bMatch := true;
for i in 0 to 3 loop
if ( (vOutMuons(i).sysign /= event_pipe(0).GMTMuons(i).sysign) or
(vOutMuons(i).mip /= event_pipe(0).GMTMuons(i).mip ) or
(vOutMuons(i).isol /= event_pipe(0).GMTMuons(i).isol ) or
(vOutMuons(i).eta /= event_pipe(0).GMTMuons(i).eta ) or
(vOutMuons(i).phi /= event_pipe(0).GMTMuons(i).phi ) or
(vOutMuons(i).pt /= event_pipe(0).GMTMuons(i).pt ) ) then
bMatch := false;
end if;
-- do some basic quality check
if TO_INTEGER(UNSIGNED(event_pipe(0).GMTMuons(i).qual)) /= TO_INTEGER(UNSIGNED(vOutMuons(i).qual)) then
bMatch := false;
end if;
end loop; -- i
if bMatch = false then
write (LO, string'("******* disagreement in out muons ******** "));
writeline (OUTPUT, LO);
bTestOk := false;
ntestfailed := ntestfailed + 1;
end if;
write (LO, string'("Simulated Out muons : "));
writeline (OUTPUT, LO);
for i in 0 to 3 loop
write (LO, vOutMuons(i));
writeline (OUTPUT, LO);
end loop; -- i
write (LO, string'("from ORCA Out muons : "));
writeline (OUTPUT, LO);
for i in 0 to 3 loop
write (LO, event_pipe(0).GMTMuons(i));
writeline (OUTPUT, LO);
end loop; -- i
else
write (LO, string'("-------------------- skipping checks for event nr "));
write (LO, ievent-2);
write (LO, string'(" --------------------"));
writeline (OUTPUT, LO);
end if;
-------------------------------------------------------------------------
-- end of cycle
-------------------------------------------------------------------------
ck <= '0';
-- delay GMT event for checks
for i in event_pipe'low to event_pipe'high-1 loop
event_pipe(i) := event_pipe(i+1);
end loop; -- i
event_pipe(event_pipe'high) := event;
end loop;
for i in 1 to 700 loop
wait for t_afterck;
ck_inputs <= '1';
wait for t_inbefore;
ck <= '1';
wait for t_afterck;
ck_inputs <= '0';
wait for t_inbefore;
ck <= '0';
end loop;
if bTestOk then
write(LO,string'("**** all tests succeeded."));
else
write(LO,string'("**** some tests failed. ("));
write(LO, ntestfailed);
write(LO,string'(") "));
end if;
writeline (OUTPUT,LO);
wait;
end process runtb;
-----------------------------------------------------------------------------
-- Test the ROP (runs in parallel to the main test)
-----------------------------------------------------------------------------
test_ROP: process (ck_inputs, reset_i) is
variable ev_count : integer := 0;
begin -- process test_ROP
if (reset_i = '1') then
l1a_i <= '0';
elsif ck_inputs'event and ck_inputs = '1' then -- rising clock edge
-- generate three L1As
-- if (ev_count = 20 or ev_count = 23 or ev_count = 30) then
if (ev_count = 20 or ev_count = 25 or ev_count = 34) then
l1a_i <= '1';
else
l1a_i <= '0';
end if;
ev_count := ev_count + 1;
end if;
end process test_ROP;
-----------------------------------------------------------------------------
-- read the readout data from channel link and save to file
-----------------------------------------------------------------------------
read_chlink: process (ch_link1_clk_i) is
file F : text open write_mode is "chlink1.out";
-- synchronized muons from input FPGA
variable LO : line; -- input file line
variable chipnr,chip_nr_prev : integer;
variable second_round : boolean := false;
variable prev_data : std_logic_vector (23 downto 0);
variable imu : integer;
begin -- process read_chlink
if ch_link1_clk_i'event and ch_link1_clk_i = '1' then
-- rising clock edge
write (LO, to_string(ch_link1_i));
case (ch_link1_i(27 downto 24)) is
when "0000" => write (LO, string'(" I "));
when "1010" => write (LO, string'(" A "));
when "1011" => write (LO, string'(" B "));
when "1100" => write (LO, string'(" C "));
when "1101" => write (LO, string'(" D "));
when "0001" => write (LO, string'(" 1 "));
when "0010" => write (LO, string'(" 2 "));
when "0011" => write (LO, string'(" 3 "));
when "0100" => write (LO, string'(" 4 "));
when "0101" => write (LO, string'(" 5 "));
when "1110" => write (LO, string'(" E "));
when "1111" => write (LO, string'(" F "));
when others => null;
end case;
-- decode A and B fields
if (ch_link1_i(27 downto 24) = "1011") then
write (LO, string'(" BX errors: "));
write (LO, to_string(ch_link1_i(12 downto 8)));
write (LO, string'("; event number: "));
write (LO, to_integer(unsigned( ch_link1_i(7 downto 0) & prev_data(15 downto 0))));
end if;
-- decode C field
if (ch_link1_i(27 downto 24) = "1100") then
write (LO, string'(" BX in event: "));
write (LO, to_integer(signed( ch_link1_i(15 downto 12))));
write (LO, string'("; Reference BX count: "));
write (LO, to_integer(unsigned( ch_link1_i(11 downto 0))));
end if;
-- decode D field
if (ch_link1_i(27 downto 24) = "1101") then
write (LO, string'(" Board ID: "));
write (LO, to_integer(unsigned( ch_link1_i(15 downto 8))));
write (LO, string'("; Length of record(words): "));
write (LO, to_integer(unsigned( ch_link1_i(4 downto 0))));
end if;
case (ch_link1_i(27 downto 24)) is
when "0001" => chipnr := 1;
when "0010" => chipnr := 2;
when "0011" => chipnr := 3;
when "0100" => chipnr := 4;
when "0101" => chipnr := 5;
when others => chipnr := -1;
end case;
if chipnr >= 1 and chipnr <= 5 then
if chip_nr_prev /= chipnr then
imu := 0;
end if;
if (second_round) then
-- decode input muons
if (chipnr < 5) then
case (ch_link1_i(15 downto 14)) is
when "00" => write (LO, string'(" DT "));
when "01" => write (LO, string'(" BRPC "));
when "10" => write (LO, string'(" CSC "));
when "11" => write (LO, string'(" FRPC "));
when others => null;
end case;
-- remove inversion of lower 16 bits
write (lo,SyncedMu_from_flat(ch_link1_i(8 downto 0) & (not prev_data(15 downto 8)) & prev_data(7 downto 0)));
-- decode GMT muons and sort ranks
else
if (imu < 4) then
write (lo,string'(" BrlGMT "));
elsif (imu < 8) then
write (lo,string'(" FwdGMT "));
elsif (imu < 12) then
write (lo,string'(" GMT "));
else
write (lo,string'(" S-Rank "));
end if;
if (imu <12) then
write (lo,string'(" IsRPC:"));
write (lo,to_bit(ch_link1_i(15)));
write (lo,string'(" IsFwd:"));
write (lo,to_bit(ch_link1_i(14)));
write (lo,string'(" IdxRPC:"));
write (lo,to_integer(unsigned(ch_link1_i(13 downto 12))));
write (lo,string'(" IdxDTCSC:"));
write (lo,to_integer(unsigned(ch_link1_i(11 downto 10))));
write (lo,string'(" "));
write (lo,GMTMu_from_flat(ch_link1_i(9 downto 0) & prev_data(15 downto 0)));
else
for i in 1 downto 0 loop
write (lo, to_integer(unsigned(ch_link1_i(8*(i+1)-1 downto 8*i))));
write (lo, string'(" "));
end loop; -- i
for i in 1 downto 0 loop
write (lo, to_integer(unsigned(prev_data(8*(i+1)-1 downto 8*i))));
write (lo, string'(" "));
end loop; -- i
end if;
end if;
imu := imu+1;
end if;
second_round := not second_round;
chip_nr_prev := chipnr;
else
second_round := false;
chip_nr_prev := -1;
end if;
prev_data := ch_link1_i(23 downto 0);
writeline (F, LO);
end if;
end process read_chlink;
-------------------------------------------------------------------------------
-- VME signals
-------------------------------------------------------------------------------
vme_addr_board_i <= (others => 'L');
vme_data_i <= (others => 'Z');
SINGLE_ACCESS_i <= '1';
BLT_ACCESS_i <= '0';
DSPULS_i <= 'L';
DSCYC_i <= 'L';
DSSYNC_i <= 'L';
WRITE_I_i <= 'L';
vme_en_i <= 'L';
------------------------------------------------------------------------------
-- test the VME Spy (runs in parallel to the main test)
------------------------------------------------------------------------------
ds: process (ck_inputs) is
begin -- process ds
if ck_inputs'event and ck_inputs = '1' then -- rising clock edge
vme_en_i_d <= vme_en_i;
end if;
end process ds;
DSCYC_i <= vme_en_i;
DSSYNC_i <= vme_en_i;
DSPULS_i <= vme_en_i and (not vme_en_i_d);
test_VME: process (ck_inputs) is
procedure readVME (
variable start_ev : in integer;
variable curr_ev : in integer;
address : in integer;
signal vme_addr : out std_logic_vector;
signal vme_data : in std_logic_vector;
signal vme_en : out std_logic;
signal vme_wr : out std_logic;
signal vme_dtack : in std_logic;
file F : text;
variable finished : inout integer) is
variable data : std_logic_vector(15 downto 0);
variable LO : line;
-- variable finished : integer := 0;
variable addr_vec : std_logic_vector(23 downto 0);
begin
addr_vec := std_logic_vector(to_unsigned(address,24));
if (curr_ev = start_ev) then
-- apply read address
vme_addr(addr_vec'high downto 1) <= addr_vec(addr_vec'high downto 1);
vme_wr <= '0';
vme_en <= '1';
finished := 0;
write (LO,string'("+++ start read addr "));
write (LO,to_string(addr_vec));
write (LO,string'(" curr_ev = "));
write (LO,curr_ev);
writeline(F, LO);
elsif (curr_ev > start_ev) and (curr_ev < start_ev+9) then
if vme_dtack = '1' then
data := vme_data(data'range);
write (LO,string'("**** VME output at addr "));
write (LO,to_string(addr_vec));
write (LO,string'(": "));
write (LO,to_string(data));
write (LO,string'(" curr_ev = "));
write (LO,curr_ev);
writeline(F, LO);
vme_en <= '0';
vme_addr <= (others => 'Z');
finished := 1;
end if;
elsif (curr_ev = start_ev+9 and finished = 0) then
write (LO,string'(" ***** did not receive dtack"));
writeline(F, LO);
vme_en <= '0';
vme_addr <= (others => 'Z');
end if;
end;
procedure writeVME (
variable start_ev : in integer;
variable curr_ev : in integer;
address : in integer;
variable value : in std_logic_vector(15 downto 0);
signal vme_addr : out std_logic_vector;
signal vme_data : out std_logic_vector;
signal vme_en : out std_logic;
signal vme_wr : out std_logic;
signal vme_dtack : in std_logic;
file F : text;
variable finished : inout integer) is
variable data : std_logic_vector(15 downto 0);
variable LO : line;
-- variable finished : integer := 0;
variable addr_vec : std_logic_vector(23 downto 0);
begin
addr_vec := std_logic_vector(to_unsigned(address,24));
if (curr_ev = start_ev) then
-- apply read address
vme_addr(addr_vec'high downto 1) <= addr_vec(addr_vec'high downto 1);
vme_data <= value;
vme_wr <= '1';
vme_en <= '1';
finished := 0;
write (LO,string'("+++ start write addr "));
write (LO,to_string(addr_vec));
write (LO,string'(" data = "));
write (LO,to_string(value));
write (LO,string'(" curr_ev = "));
write (LO,curr_ev);
writeline(F, LO);
elsif (curr_ev > start_ev) and (curr_ev < start_ev+9) then
if vme_dtack = '1' then
write (LO,string'("**** write cycle completed "));
write (LO,string'(" curr_ev = "));
write (LO,curr_ev);
writeline(F, LO);
vme_en <= '0';
vme_addr <= (others => 'Z');
vme_data <= (others => 'Z');
finished := 1;
end if;
elsif (curr_ev = start_ev+9 and finished = 0) then
write (LO,string'(" ***** did not receive dtack"));
writeline(F, LO);
vme_en <= '0';
vme_addr <= (others => 'Z');
vme_data <= (others => 'Z');
end if;
end;
variable ev_count : integer := 0;
variable finished : integer := 0;
variable spy_base_IND : integer := 16#310000#; -- Spy RAM
variable etaconv_base_AUF : integer := 16#500400#; -- asynch LUT
variable phipro_base_AUF : integer := 16#510000#; -- synch LUT
variable reg_base_ROP : integer := 16#000000#; -- synch LUT
file F : text open write_mode is "vmetest.out";
begin -- process test_VME
if ck_inputs'event and ck_inputs = '1' then -- rising clock edge
if ev_count = 0 then
vme_en_i <= '0';
WRITE_I_i <= '0';
vme_data_i <= (others => 'Z');
vme_addr_board_i <= (others =>'0');
end if;
-- read SPY MEMORY
readVME(25, ev_count, spy_base_IND,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(35, ev_count, spy_base_IND+2,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(45, ev_count, spy_base_IND+4,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
-- write
writeVME(55, ev_count, spy_base_IND+6, "0000111100001111",
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
-- read it back
readVME(65, ev_count, spy_base_IND+6,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
-- read from nonexisting register - this should fail
readVME(75, ev_count, 16#30000A#,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
-- read from register
readVME(85, ev_count, 16#300010#,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(95, ev_count, spy_base_IND+14,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(105, ev_count,spy_base_IND+16,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(115, ev_count,etaconv_base_AUF,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(125, ev_count,etaconv_base_AUF+2,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(135, ev_count,etaconv_base_AUF+4,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(145, ev_count,etaconv_base_AUF+6,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(155, ev_count,phipro_base_AUF,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(165, ev_count,phipro_base_AUF+2,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(175, ev_count,phipro_base_AUF+4,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(185, ev_count,reg_base_ROP+16#60#, -- DCM locked reg
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(195, ev_count,reg_base_ROP+16#61#, -- status 0 reg
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
writeVME(205, ev_count,reg_base_ROP+16#40#, "0001110001110001", -- en-prog
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
-- read it back
readVME(215, ev_count, reg_base_ROP+16#40#, -- en_prog
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(225, ev_count,reg_base_ROP+26, -- JTAG mode reg 0
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(235, ev_count,reg_base_ROP+28, -- JTAG mode reg 1
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(245, ev_count,spy_base_IND+44,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(255, ev_count,spy_base_IND+46,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
readVME(265, ev_count,spy_base_IND+48,
vme_addr_board_i, vme_data_i, vme_en_i, WRITE_I_i, DTACK_EXT_i, F, finished);
ev_count := ev_count + 1;
end if;
end process test_VME;
end;