-- Version V2 - kja --3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 ------------------------------------------------------------------------------------------ -- Filename : glink_asic.vhdl -- -- AUTHORS : Haifeng Wu, University of Chicago -- -- Ambreesh Gupta, University of Chicago -- -- Kelby Anderson, U of Chicago -- -- DESCRIPTION: -- -- Interface Card Controller VHDL code. -- -- -- -- VERSION HISTORY: -- -- 7/6/2000 : Version 0.01; -- -- 7/12/2000 : Version 0.02; -- -- 7/17/2000 : Version 1.0, for each frame, data number is set at first -- -- data frame; -- -- 7/18/2000 : Version 2.0, data number is changable on event base; -- -- HP_FLAG is delayed. -- -- 7/20/2000 : Version 3.0, use dff to set data number -- -- 7/21/2000 : Version 4.0, ctrl word is corrected by force -- -- HP_D(16) <= HP_FLAG; -- -- 7/24/2000 : Version 5.0, add slink start word:0x11111110, and -- -- stop word:0xfffffff0. -- -- 7/25/2000 : Version 6.0, enable flow control and TTC channel -- -- selection. -- -- 7/26/2000 : Version 7.0, add fifo auto reset function. -- -- 7/28/2000 : Version 8.0, enhance TTC channel selection. -- -- 7/31/2000 : Version 9.0, enhance data format -- -- 8/03/2000 : Version 9.1, enable succesive event -- -- 8/09/2000 : Version 9.9, correct dmu consequencesx -- -- 26/11/2000: link_reset implemented, and channels within dmu are -- -- corrected -- -- 26/11/2000: flow_ctrl function was removed. -- -- 28/11/2000: test mode implemented. -- -- 12/12/2000: muti confirmation of start and end of event; it needs at -- -- least 3 digital board -- -- 1/23/2001 : code for 16 bit 3.3v glink chip -- -- 2/14/2001 : Initial steps to move to 3.3v glink chip - -- -- Implement 16 bit CRC checksum. -- -- -- -- 1/15/2001 : lots of clocking changes. -- -- Address clocks and memory fetchs are now clocked on different edges -- -- signal names changed to correspond to 3.3v serializer convension -- -- vote change to allow one active board to start -- -- clocking through memory input now done with digitizer (TTC) -- -- clock selected from board 3,2,or 5 -- -- logic improved for choosing which TTC clock to send to digitizers -- -- global CRC and digitizer serial stream CRC checking made to work -- -- start ctrl word = 51115110 since only 14 bits sent by serializer -- -- for control words 11111110 ends up 51115110 at the LDC anyway -- -- -- kja -- ------------------------------------------------------------------------------------------ library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library lpm; use lpm.lpm_components.all; entity glink_asic is port( DataIN : in std_logic_vector(31 downto 0); WenIN : in std_logic_vector(7 downto 0); CtrlIN : in std_logic_vector(7 downto 0); ClkIN : in std_logic_vector(7 downto 0); TestIN : in std_logic_vector(5 downto 0); ResetIN : in std_logic_vector(5 downto 0); TTC_chkb: in std_logic; TTC_chka: in std_logic; TTC_en: out std_logic; Flow_ctrl: out std_logic; TX : out std_logic_vector(15 downto 0); TXCNTL : out std_logic; TXDATA : out std_logic; TXFLAG : out std_logic; TXFLGENB : out std_logic; TXCLK : out std_logic; LOCKED: in std_logic; TXDIV0: out std_logic; TXDIV1: out std_logic; ESMPXENB : out std_logic; TCLKENB : out std_logic; Ready : in std_logic; -------------------------------------------------------------------------------- --***************************************************************************** -- some signal for test --------------------------------------------------------------------------------- TP1: out std_logic; TP2: out std_logic; TP3: out std_logic; TP4: out std_logic; TP5: out std_logic; TP6: out std_logic; TP7: out std_logic; TP8: out std_logic; TP9: out std_logic; ----------------------------------------- end of test point---------------------- Clock : in std_logic); end glink_asic; architecture a of glink_asic is ------------------------------------------------------------------------------------------ -- Initialize components ------------------------------------------------------------------------------------------ COMPONENT s2p_sort PORT( clki, di0, di1, weni, clr, data_now : in STD_LOGIC; dready : out STD_LOGIC; do : out std_logic_vector(31 downto 0)); END COMPONENT; COMPONENT CRC16 PORT( crc_clk, crc_step, crc_start : in std_logic; crc_data : in std_logic_vector(31 downto 0); crc_error : out std_logic_vector(31 downto 0)); END COMPONENT; COMPONENT vote PORT( poll : in std_logic_vector(5 downto 0); result : out STD_LOGIC); END COMPONENT; COMPONENT e2o PORT( reset : in std_logic; en : in std_logic; data1 : in std_logic_vector(31 downto 0); data2 : in std_logic_vector(31 downto 0); data3 : in std_logic_vector(31 downto 0); data4 : in std_logic_vector(31 downto 0); data5 : in std_logic_vector(31 downto 0); data6 : in std_logic_vector(31 downto 0); data7 : in std_logic_vector(31 downto 0); data8 : in std_logic_vector(31 downto 0); data_out : out std_logic_vector(31 downto 0); data_en : out std_logic; clk_op : in std_logic); END COMPONENT; COMPONENT crctx PORT( CLK : in std_logic; TX_D_IN : in std_logic_vector (15 downto 0); TX_D : out std_logic_vector (15 downto 0); TX_DATA_IN : in std_logic; TX_DATA : out std_logic; TX_CNTL_IN : in std_logic; TX_CNTL : out std_logic; TX_FLAG_IN : in std_logic; TX_FLAG : out std_logic ); END COMPONENT; type op_state is (idle, startHI, startLO, txingHI, txingLO, cmd_tx, crc_tx, txeflg1, txeflg2, stopHI, stopLO); type ttc_state is (wait1_ttc, chk_ttc, wait2_ttc); type dclk_state is (wait1_dclk, chk_dclk, wait2_dclk); signal current_state: op_state; signal next_state : op_state; signal now_ttc : ttc_state; signal next_ttc : ttc_state; signal now_dclk : dclk_state; signal next_dclk : dclk_state; signal reset_all: std_logic; signal data_read_num: std_logic_vector(9 downto 0); signal mem1_raddr: std_logic_vector(9 downto 0); signal mem2_raddr: std_logic_vector(9 downto 0); signal mem1_waddr: std_logic_vector(9 downto 0); signal mem2_waddr: std_logic_vector(9 downto 0); signal rden: std_logic; signal wren: std_logic_vector(7 downto 0); signal fifo_data: std_logic_vector(31 downto 0); signal data_num2: std_logic_vector(10 downto 0); signal data_num3: std_logic_vector(10 downto 0); signal data_num4: std_logic_vector(10 downto 0); signal clk_out: std_logic; signal clkb_out: std_logic; signal clk2_out: std_logic; signal clk2b_out: std_logic; signal clk4_out: std_logic; signal clk4b_out: std_logic; signal clk_pipe: std_logic; signal clk2: std_logic; signal clk4: std_logic; signal clk2b: std_logic; signal clk4b: std_logic; signal ctrl_n: std_logic; signal ctrl_n1: std_logic; signal ctrl_n2: std_logic; signal ctrl_n3: std_logic; signal ctrl_n4: std_logic; signal ctrl_n5: std_logic; signal data_end: std_logic; signal ctrl_count: std_logic; signal ctrl_countb: std_logic; signal data_now: std_logic; signal data_set: std_logic_vector(3 downto 0); signal data_set_clr: std_logic; signal data_num_av: std_logic; signal data4read: std_logic_vector( 9 downto 0); signal data_count_en: std_logic; signal reg_in1: std_logic_vector( 31 downto 0); signal reg_in2: std_logic_vector( 31 downto 0); signal reg_in3: std_logic_vector( 31 downto 0); signal reg_in4: std_logic_vector( 31 downto 0); signal reg_in5: std_logic_vector( 31 downto 0); signal reg_in6: std_logic_vector( 31 downto 0); signal reg_in7: std_logic_vector( 31 downto 0); signal reg_in8: std_logic_vector( 31 downto 0); signal reg_in9: std_logic_vector( 31 downto 0); signal reg_in10: std_logic_vector( 31 downto 0); signal reg_in11: std_logic_vector( 31 downto 0); signal reg_in12: std_logic_vector( 31 downto 0); signal reg_in13: std_logic_vector( 31 downto 0); signal reg_in14: std_logic_vector( 31 downto 0); signal reg_in15: std_logic_vector( 31 downto 0); signal reg_in16: std_logic_vector( 31 downto 0); signal data_en: std_logic_vector( 15 downto 0); signal fifo_in_data1: std_logic_vector(31 downto 0); signal fifo_in_data2: std_logic_vector(31 downto 0); signal fifo_in_data2x: std_logic_vector(31 downto 0); signal fifo_out_data1: std_logic_vector(31 downto 0); signal fifo_out_data2: std_logic_vector(31 downto 0); signal reg_out: std_logic_vector(31 downto 0); signal fifo_wren1: std_logic; signal fifo_wren2: std_logic; signal fifo_wren1_delay: std_logic; signal fifo_wren2_delay: std_logic; signal fifo_rden1: std_logic; signal fifo_rden2: std_logic; signal pack_txed: std_logic; signal packw_num: std_logic_vector(2 downto 0); signal packr_num: std_logic_vector(3 downto 0); signal pack_ready: std_logic; signal reading: std_logic; signal tx_en: std_logic; signal read_ready: std_logic; signal reading1: std_logic; signal reading2: std_logic; signal reading3: std_logic; signal reading1b: std_logic; signal reading2b: std_logic; signal reading3b: std_logic; signal reading4: std_logic; signal tmp_clk: std_logic; signal data_txed: std_logic; signal data_read_clr: std_logic; signal buff_out: std_logic_vector(15 downto 0); signal buff_crc: std_logic_vector(31 downto 0); signal packr_num0: std_logic; signal packr_num1: std_logic; signal packr_num0b: std_logic; signal link_reset: std_logic; signal data_end3: std_logic; signal clkb_pipe: std_logic; signal ttc_enable: std_logic; constant startwHI : std_logic_vector := "0101000100010001"; -- 5111 constant startwLO : std_logic_vector := "0101000100010000"; -- 5110 -- using 51115110 for start word 11111110 does not work as serializer -- only sends 16 bits in control mode and 11111110 becomes 51115110 at LDC -- so I send 51115110 in the first place to avoid confusion - kja constant stopwHI : std_logic_vector := "1111111111111111"; -- word to send constant stopwLO : std_logic_vector := "1111111111110000"; -- these words. constant crc_cnst: std_logic_vector := "0000000000000000"; constant cmd_word: std_logic_vector := "0000000000000011"; signal crc_word: std_logic_vector(31 downto 0); signal crc_rst: std_logic; signal crc_cal: std_logic; signal cha_count: std_logic_vector(5 downto 0); signal chb_count: std_logic_vector(5 downto 0); signal clk3_count: std_logic_vector(5 downto 0); signal clk2_count: std_logic_vector(5 downto 0); signal clk5_count: std_logic_vector(5 downto 0); signal b3s2 : std_logic; signal b3s5 : std_logic; signal b2s3 : std_logic; signal b2s5 : std_logic; signal b5s2 : std_logic; signal b5s3 : std_logic; signal clk3_ok : std_logic; signal clk2_ok : std_logic; signal clk5_ok : std_logic; signal period: std_logic_vector(5 downto 0); signal period2: std_logic_vector(5 downto 0); signal cha_ok: std_logic; signal chb_ok: std_logic; signal ttc_done : std_logic; signal csel_enable : std_logic; signal fifo_clr: std_logic; signal wide1: std_logic_vector(9 downto 0); signal wide2: std_logic_vector(9 downto 0); signal out_num1: std_logic_vector(9 downto 0); signal out_num2: std_logic_vector(9 downto 0); signal addr_used1: std_logic_vector(6 downto 0); signal addr_used: std_logic_vector(9 downto 0); signal up_count1: std_logic_vector(2 downto 0); signal bot_count1: std_logic_vector(6 downto 0); signal up_count2: std_logic_vector(2 downto 0); signal bot_count2: std_logic_vector(6 downto 0); signal up1: std_logic; signal up2: std_logic; signal bot_clr1: std_logic; signal bot_clr2: std_logic; signal up_clr1: std_logic; signal up_clr2: std_logic; signal temp_count1: std_logic_vector(1 downto 0); signal temp_count2: std_logic_vector(3 downto 0); signal temp_clr2: std_logic; signal temp_clr1: std_logic; signal ttc_clkb: std_logic_vector(7 downto 0); signal dig_start: std_logic_vector(5 downto 0); signal dig_stop: std_logic_vector(5 downto 0); signal dig_now: std_logic_vector(5 downto 0); signal event_coming: std_logic; signal event_end: std_logic; signal event_now: std_logic; signal dig_dnum2: std_logic_vector(6 downto 0); signal dig_dnum3: std_logic_vector(6 downto 0); signal dig_dnum4: std_logic_vector(6 downto 0); signal data_enx: std_logic; signal HP_DATA_IN, HP_CNTL_IN, HP_FLAG_IN : std_logic; signal reading1c,reading1d : std_logic; signal Data : std_logic_vector(31 downto 0); signal Wen : std_logic_vector(7 downto 0); signal Ctrl : std_logic_vector(7 downto 0); signal Clk : std_logic_vector(7 downto 0); signal Reset: std_logic_vector(5 downto 0); signal Test : std_logic_vector(5 downto 0); signal cstart : std_logic; signal cstep : std_logic; signal cerror : std_logic_vector(31 downto 0); begin --- --- FOR the prototype version of INTERFACE card, first input of the LVDS drivers -- are inverted. Below is a temporary correction for that. --- -- DATA Data(0) <= DataIN(0); Data(1) <= DataIN(1); Data(2) <= DataIN(2); Data(3) <= DataIN(3); Data(4) <= DataIN(4); Data(5) <= DataIN(5); Data(6) <= DataIN(6); Data(7) <= DataIN(7); Data(8) <= DataIN(8); Data(9) <= DataIN(9); Data(10) <= DataIN(10); Data(11) <= DataIN(11); Data(12) <= DataIN(12); Data(13) <= DataIN(13); Data(14) <= DataIN(14); Data(15) <= DataIN(15); Data(16) <= DataIN(16); Data(17) <= DataIN(17); Data(18) <= DataIN(18); Data(19) <= DataIN(19); Data(20) <= DataIN(20); Data(21) <= DataIN(21); Data(22) <= DataIN(22); Data(23) <= DataIN(23); Data(24) <= DataIN(24); Data(25) <= DataIN(25); Data(26) <= DataIN(26); Data(27) <= DataIN(27); Data(28) <= DataIN(28); Data(29) <= DataIN(29); Data(30) <= DataIN(30); Data(31) <= DataIN(31); -- WEN Wen(0) <= WenIN(0); Wen(1) <= WenIN(1); Wen(2) <= WenIN(2); Wen(3) <= WenIN(3); Wen(4) <= WenIN(4); Wen(5) <= WenIN(5); Wen(6) <= WenIN(6); Wen(7) <= WenIN(7); -- CTRL Ctrl(0) <= CtrlIN(0); Ctrl(1) <= CtrlIN(1); Ctrl(2) <= CtrlIN(2); Ctrl(3) <= CtrlIN(3); Ctrl(4) <= CtrlIN(4); Ctrl(5) <= CtrlIN(5); Ctrl(6) <= CtrlIN(6); Ctrl(7) <= CtrlIN(7); --CLOCK Clk(0) <= not ClkIN(0); Clk(1) <= not ClkIN(1); Clk(2) <= not ClkIN(2); Clk(3) <= not ClkIN(3); Clk(4) <= not ClkIN(4); Clk(5) <= not ClkIN(5); Clk(6) <= not ClkIN(6); Clk(7) <= not ClkIN(7); -- RESET Reset(0) <= ResetIN(0); Reset(1) <= ResetIN(1); Reset(2) <= ResetIN(2); Reset(3) <= ResetIN(3); Reset(4) <= ResetIN(4); Reset(5) <= ResetIN(5); -- TEST Test(0) <= TestIN(0); Test(1) <= TestIN(1); Test(2) <= TestIN(2); Test(3) <= TestIN(3); Test(4) <= TestIN(4); Test(5) <= TestIN(5); ----------------------------------------------------------------------------------------- -- Generate active high signals for lpm lib, since most of lpm lib use active high level ----------------------------------------------------------------------------------------- wren(0) <= not Wen(0); wren(1) <= not Wen(1); wren(2) <= not Wen(2); wren(3) <= not Wen(3); wren(4) <= not Wen(4); wren(5) <= not Wen(5); wren(6) <= not Wen(6); wren(7) <= not Wen(7); ----------------------------------------------------------------------------------------- -- Mark the start of digitizers - use 3 digitizers that can supply global clock -- Before every data frame the digitizer send a control signal with data bits set high ----------------------------------------------------------------------------------------- dig_start(0) <= wren(2) and (not Ctrl(2)) and Data(8) and Data(9); dig_start(1) <= wren(2) and (not Ctrl(2)) and Data(10) and Data(11); dig_start(2) <= wren(3) and (not Ctrl(3)) and Data(12) and Data(13); dig_start(3) <= wren(3) and (not Ctrl(3)) and Data(14) and Data(15); dig_start(4) <= wren(5) and (not Ctrl(5)) and Data(20) and Data(21); dig_start(5) <= wren(5) and (not Ctrl(5)) and Data(22) and Data(23); ----------------------------------------------------------------------------------------- -- Mark the stop of digitizers - use 3 digitizers that can supply global clock -- At the end of data frame, the digitizer sends a control signal with data bits set low ----------------------------------------------------------------------------------------- process (Clk(2)) begin if(Clk(2)'event and Clk(2) = '1') then dig_stop(0) <= wren(2) and (not Ctrl(2)) and (not Data(8)) and (not Data(9)); end if; end process; process (Clk(2)) begin if(Clk(2)'event and Clk(2) = '1') then dig_stop(1) <= wren(2) and (not Ctrl(2)) and (not Data(10)) and (not Data(11)); end if; end process; process (Clk(3)) begin if(Clk(3)'event and Clk(3) = '1') then dig_stop(2) <= wren(3) and (not Ctrl(3)) and (not Data(12)) and (not Data(13)); end if; end process; process (Clk(3)) begin if(Clk(3)'event and Clk(3) = '1') then dig_stop(3) <= wren(3) and (not Ctrl(3)) and (not Data(14)) and (not Data(15)); end if; end process; process (Clk(5)) begin if(Clk(5)'event and Clk(5) = '1') then dig_stop(4) <= wren(5) and (not Ctrl(5)) and (not Data(20)) and (not Data(21)); end if; end process; process (Clk(5)) begin if(Clk(5)'event and Clk(5) = '1') then dig_stop(5) <= wren(5) and (not Ctrl(5)) and (not Data(22)) and (not Data(23)); end if; end process; ----------------------------------------------------------------------------------------- -- Mark the event of digitizers ----------------------------------------------------------------------------------------- process (dig_stop, dig_start) begin if (dig_stop(0) = '1' or reset_all = '1') then dig_now(0) <= '1'; elsif dig_start(0) = '1' then dig_now(0) <= '0'; -- effictive low; end if; if (dig_stop(1) = '1' or reset_all = '1') then dig_now(1) <= '1'; elsif dig_start(1) = '1' then dig_now(1) <= '0'; -- effictive low; end if; if (dig_stop(2) = '1' or reset_all = '1') then dig_now(2) <= '1'; elsif dig_start(2) = '1' then dig_now(2) <= '0'; -- effictive low; end if; if (dig_stop(3) = '1' or reset_all = '1') then dig_now(3) <= '1'; elsif dig_start(3) = '1' then dig_now(3) <= '0'; -- effictive low; end if; if (dig_stop(4) = '1' or reset_all = '1') then dig_now(4) <= '1'; elsif dig_start(4) = '1' then dig_now(4) <= '0'; -- effictive low; end if; if (dig_stop(5) = '1' or reset_all = '1') then dig_now(5) <= '1'; elsif dig_start(5) = '1' then dig_now(5) <= '0'; -- effictive low; end if; end process; -- 2 of 6 inputs are low event_coming=0 otherwise event_coming=1 slink_evnt: vote port map (poll => dig_now(5 downto 0), result => event_coming); event_now <= not event_coming; -- effective high. ----------------------------------------------------------------------------------------- -- time_controller provide global control signal -- ctrl_n is used as global ctrl signals -- ctrl_n1, ctrl_n2, ctrl_n3, ctrl_n4 and ctrl_n5 are delays of original ctrl_n signal ----------------------------------------------------------------------------------------- ctrl_n <= event_now; process ( clk_pipe, ctrl_n ) begin if ( clk_pipe'event and clk_pipe = '1') then ctrl_n1 <= ctrl_n; ctrl_n2 <= ctrl_n1; ctrl_n3 <= ctrl_n2; ctrl_n4 <= ctrl_n3; ctrl_n5 <= ctrl_n4; end if; end process; ---------------------------------------------------------------------------------------- -- generate reset singal for the chip; -- reset_all is the global reset signal; ---------------------------------------------------------------------------------------- slink_reset: vote port map (poll => Reset(5 downto 0), result => link_reset); reset_all <= (not Ready) or (not link_reset); -- system reset = configuration done or link reset. data_end <= (not event_now) and (ctrl_n5 xor ctrl_n4); -- data_end indicates the end of data frame. -- data_end3 is used as clock to latch the data number data_end3 <= ( not event_now ) and (ctrl_n3 xor ctrl_n2) and (not read_ready); -- data_set_clr is the clear signal of counter of data_number_counter data_set_clr <= reset_all or data_end; -- fifo_clr is the clear signal for fifo; -- the chip reset the fifo at time of system reset or when there is no data in the fifo when -- signal ctrl_n5 or ctrl_n4 arrives. fifo_clr <= reset_all or (event_now and (ctrl_n5 xor ctrl_n4) and ( not (pack_ready or reading2))); ------------------------------------------------------------------------------------------ -- this block to generate data_now signal, data_now and data_end are used in s2p_sort component ------------------------------------------------------------------------------------------ data_begin_counter: lpm_counter generic map (LPM_WIDTH => 4) port map ( clock => clk_pipe, clk_en => event_now, aclr => data_set_clr, q => data_set); process ( data_set, data_set_clr) begin if ( data_set = "1100" ) then data_now <= '1'; elsif data_set_clr = '1' then data_now <= '0'; end if; end process; --------------end of data_now block ---------------------------------- ---------------------------------------------------------------------- -- this block counts the data numbers of a frame ---------------------------------------------------------------------- data_num_counter2: lpm_counter generic map (LPM_WIDTH =>11) port map ( clock => Clk(2), clk_en => wren(2), aclr => data_set_clr, q => data_num2); data_num_counter3: lpm_counter generic map (LPM_WIDTH =>11) port map ( clock => Clk(3), clk_en => wren(3), aclr => data_set_clr, q => data_num3); data_num_counter4: lpm_counter generic map (LPM_WIDTH =>11) port map ( clock => Clk(5), clk_en => wren(5), aclr => data_set_clr, q => data_num4); process ( data_end3, reset_all) begin if reset_all = '1' then dig_dnum2( 6 downto 0) <= "0000000"; dig_dnum3( 6 downto 0) <= "0000000"; dig_dnum4( 6 downto 0) <= "0000000"; elsif ( data_end3'event and data_end3 = '1' ) then dig_dnum2(6 downto 0) <= data_num2(10 downto 4); -- in each shift register (2 regs per tileDMU) dig_dnum3(6 downto 0) <= data_num3(10 downto 4); dig_dnum4(6 downto 0) <= data_num4(10 downto 4); end if; end process; data4read(2 downto 0) <= "000"; process(dig_dnum2, dig_dnum3, dig_dnum4) -- use boards 3, 2, 5, 6, 1 in that order begin if ( clk3_ok = '1' ) then data4read(9 downto 3) <= dig_dnum3(6 downto 0); --data_enx <= data_en(6) or data_en(7); data_enx <= data_en(6); elsif( clk2_ok = '1' ) then data4read(9 downto 3) <= dig_dnum2(6 downto 0); --data_enx <= data_en(4)or data_en(5); data_enx <= data_en(4); elsif(clk5_ok = '1' ) then data4read(9 downto 3) <= dig_dnum4(6 downto 0); --data_enx <= data_en(10) or data_en(11); data_enx <= data_en(10); else data4read(9 downto 3) <= dig_dnum3(6 downto 0); --data_enx <= data_en(6) or data_en(7); data_enx <= data_en(6); end if; end process; -------------- end of this block ------------------------------------------------ ----test point for debug TP1 <= b3s2; TP2 <= b3s5; TP3 <= b2s3; TP4 <= b2s5; TP5 <= b5s2; TP6 <= b5s3; TP7 <= clk3_ok; TP8 <= clk2_ok; TP9 <= clk5_ok; --TP1 <= dig_start(2); --TP2 <= dig_start(3); --TP3 <= dig_stop(2); --TP4 <= dig_stop(3); --TP5 <= event_now; --TP6 <= link_reset; --TP7 <= data_end; --TP8 <= dig_now(2); --TP9 <= dig_now(3); --********************************************************************************* -- following 16 input convert serial data from 16 DMU to paralell --*********************************************************************************** input1: s2p_sort port map ( clki => Clk(0), di0 => Data(0), di1 => Data(1), weni => wren(0), clr => data_end, data_now => data_now, dready => data_en(0), do => reg_in1); input2: s2p_sort port map ( clki => Clk(0), di0 => Data(2), di1 => Data(3), weni => wren(0), clr => data_end, data_now => data_now, dready => data_en(1), do => reg_in2); input3: s2p_sort port map ( clki => Clk(1), di0 => Data(4), di1 => Data(5), weni => wren(1), clr => data_end, data_now => data_now, dready => data_en(2), do => reg_in3); input4: s2p_sort port map ( clki => Clk(1), di0 => Data(6), di1 => Data(7), weni => wren(1), clr => data_end, data_now => data_now, dready => data_en(3), do => reg_in4); input5: s2p_sort port map ( clki => Clk(2), di0 => Data(8), di1 => Data(9), weni => wren(2), clr => data_end, data_now => data_now, dready => data_en(4), do => reg_in5); input6: s2p_sort port map ( clki => Clk(2), di0 => Data(10), di1 => Data(11), weni => wren(2), clr => data_end, data_now => data_now, dready => data_en(5), do => reg_in6); input7: s2p_sort port map ( clki => Clk(3), di0 => Data(12), di1 => Data(13), weni => wren(3), clr => data_end, data_now => data_now, dready => data_en(6), do => reg_in7); input8: s2p_sort port map ( clki => Clk(3), di0 => Data(14), di1 => Data(15), weni => wren(3), clr => data_end, data_now => data_now, dready => data_en(7), do => reg_in8); input9: s2p_sort port map ( clki => Clk(4), di0 => Data(16), di1 => Data(17), weni => wren(4), clr => data_end, data_now => data_now, dready => data_en(8), do => reg_in9); input10: s2p_sort port map ( clki => Clk(4), di0 => Data(18), di1 => Data(19), weni => wren(4), clr => data_end, data_now => data_now, dready => data_en(9), do => reg_in10); input11: s2p_sort port map ( clki => Clk(5), di0 => Data(20), di1 => Data(21), weni => wren(5), clr => data_end, data_now => data_now, dready => data_en(10), do => reg_in11); input12: s2p_sort port map ( clki => Clk(5), di0 => Data(22), di1 => Data(23), weni => wren(5), clr => data_end, data_now => data_now, dready => data_en(11), do => reg_in12); input13: s2p_sort port map ( clki => Clk(6), di0 => Data(24), di1 => Data(25), weni => wren(6), clr => data_end, data_now => data_now, dready => data_en(12), do => reg_in13); input14: s2p_sort port map ( clki => Clk(6), di0 => Data(26), di1 => Data(27), weni => wren(6), clr => data_end, data_now => data_now, dready => data_en(13), do => reg_in14); input15: s2p_sort port map ( clki => Clk(7), di0 => Data(28), di1 => Data(29), weni => wren(7), clr => data_end, data_now => data_now, dready => data_en(14), do => reg_in15); input16: s2p_sort port map ( clki => Clk(7), di0 => Data(30), di1 => Data(31), weni => wren(7), clr => data_end, data_now => data_now, dready => data_en(15), do => reg_in16); --***************************************************************************** -- two pipes line, pipe1 and pipe2 -- each pipe accepts data from one half of the draw --***************************************************************************** pipe1: e2o port map ( reset => reset_all, en => data_enx, data1 => reg_in2, data2 => reg_in1, data3 => reg_in4, data4 => reg_in3, data5 => reg_in6, data6 => reg_in5, data7 => reg_in8, data8 => reg_in7, data_out => fifo_in_data1, data_en => fifo_wren1, clk_op => clk2b); pipe2: e2o port map ( reset => reset_all, en => data_enx, data1 => reg_in15, data2 => reg_in16, data3 => reg_in13, data4 => reg_in14, data5 => reg_in11, data6 => reg_in12, data7 => reg_in9, data8 => reg_in10, data_out => fifo_in_data2, data_en => fifo_wren2, clk_op => clk2b); fifo1: lpm_ram_dp generic map ( LPM_WIDTH => 32, LPM_WIDTHAD => 10, LPM_NUMWORDS => 1024) port map ( data => fifo_in_data1, wren => fifo_wren1, wrclock => clk2, -- kja wraddress => mem1_waddr, rdaddress => mem1_raddr, rdclock => clk2_out, --kja rden => fifo_rden1, q => fifo_out_data1); fifo2: lpm_ram_dp generic map ( LPM_WIDTH => 32, LPM_WIDTHAD => 10, LPM_NUMWORDS => 1024) port map ( data => fifo_in_data2, wren => fifo_wren2, wrclock => clk2, -- kja wraddress => mem2_waddr, rdaddress => mem2_raddr, rdclock => clk2_out, --kja rden => fifo_rden2, q => fifo_out_data2 ); --------------------------------------------------------------------------------- -- address calculation of memory --------------------------------------------------------------------------------- width1_count: lpm_counter generic map (LPM_WIDTH =>10) port map (clock => clk2b, clk_en => fifo_wren1, aclr => fifo_clr, q => wide1); -- word count of e2o sending to memory 1 width2_count: lpm_counter generic map (LPM_WIDTH =>10) port map (clock => clk2b, clk_en => fifo_wren2, aclr => fifo_clr, q => wide2); -- word count of e2o sending to memory 2 mem1_waddr(9 downto 7) <= wide1(2 downto 0); -- TILEdmu address bits memory 1 mem2_waddr(9 downto 7) <= wide2(2 downto 0); -- TILEdmu address bits memory 2 mem1_waddr(6 downto 0) <= wide1(9 downto 3); -- word within a TILEdmu block memory 1 mem2_waddr(6 downto 0) <= wide2(9 downto 3); -- word within a TILEdmu block memory 2 mem1_raddr(9 downto 7) <= up_count1(2 downto 0); -- TILEdmu address bits memory 1 mem1_raddr(6 downto 0) <= bot_count1(6 downto 0) + addr_used1(6 downto 0); -- word within a TILEdmu memory 1 mem2_raddr(9 downto 7) <= up_count2(2 downto 0); -- TILEdmu address bits memory 2 mem2_raddr(6 downto 0) <= bot_count2(6 downto 0) + addr_used1(6 downto 0); -- word within a TILEdmu memory 2 mem1bot_count: lpm_counter generic map (LPM_WIDTH =>7) port map (clock => clk2b_out, clk_en => fifo_rden1, aclr => bot_clr1, q => bot_count1); mem1up_count: lpm_counter generic map (LPM_WIDTH =>3) port map (clock => up1, clk_en => fifo_rden1, aclr => up_clr1, q => up_count1); mem1_cmp: lpm_compare generic map ( LPM_WIDTH =>7) port map ( dataa => bot_count1, datab => data4read(9 downto 3), aeb => up1 ); mem2bot_count: lpm_counter generic map (LPM_WIDTH =>7) port map (clock => clk2b_out, clk_en => fifo_rden2, aclr => bot_clr2, q => bot_count2); mem2up_count: lpm_counter generic map (LPM_WIDTH =>3) port map (clock => up2, clk_en => fifo_rden2, aclr => up_clr2, q => up_count2); mem2_cmp: lpm_compare generic map ( LPM_WIDTH =>7) port map ( dataa => bot_count2, datab => data4read(9 downto 3), aeb => up2 ); bot_clr1 <= fifo_clr or up1; bot_clr2 <= fifo_clr or up2; up_clr1 <= fifo_clr; up_clr2 <= fifo_clr; base_addr_count: lpm_counter generic map (LPM_WIDTH =>10) -- count how many data read. port map (clock => clk2_out, clk_en => fifo_rden1, aclr => fifo_clr, q => addr_used); process(temp_count1(1), fifo_clr) begin if ( fifo_clr = '1' ) then addr_used1(6 downto 0) <= "0000000"; elsif ( temp_count1(1)'event and temp_count1(1) = '1') then addr_used1(6 downto 0) <= addr_used(9 downto 3); end if; end process; ---- end of this block ---------------------------------------------------------- ---******************************************************************* -- select ttc channel; TTC_en = 1 select channel a, 0 select channel b --******************************************************************** period_count: lpm_counter generic map (LPM_WIDTH =>6) port map (clock => clk4_out, clk_en => ttc_enable, aclr => reset_all, q => period); ttc_count1: lpm_counter generic map (LPM_WIDTH =>6) port map (clock => TTC_chka, clk_en => ttc_enable, aclr => reset_all, q => cha_count); ttc_count2: lpm_counter generic map (LPM_WIDTH =>6) port map (clock => TTC_chkb, clk_en => ttc_enable, aclr => reset_all, q => chb_count); ttc_comp1: lpm_compare generic map ( LPM_WIDTH =>6) port map ( dataa => cha_count, datab => chb_count, ageb => cha_ok, alb => chb_ok ); -- TTC select state machine process (reset_all,clk4_out) begin if(reset_all = '1') then now_ttc <= wait1_ttc; elsif(clk4_out'event and clk4_out = '1') then now_ttc <= next_ttc; end if; end process; process (now_ttc) begin case now_ttc is when wait1_ttc => ttc_enable <= '0'; ttc_done <= '0'; if(reset_all = '0') then ttc_done <= '0'; next_ttc <= chk_ttc; else next_ttc <= wait1_ttc; end if; when chk_ttc => ttc_enable <= '1'; if(period(2) = '0') then next_ttc <= chk_ttc; else ttc_done <= '1'; if(cha_ok = '1') then ttc_en <= '1'; -- select A elsif(chb_ok = '1') then ttc_en <= '0'; -- select B else ttc_en <= '0'; -- default to A end if; next_ttc <= wait2_ttc; end if; when wait2_ttc => next_ttc <= wait2_ttc; end case; end process; ---******************************************************************* -- select which digitizer clock to use for the pipeline --******************************************************************** period_count2: lpm_counter generic map (LPM_WIDTH =>6) port map (clock => clk_out, clk_en => csel_enable, aclr => reset_all, q => period2); dig_count3: lpm_counter generic map (LPM_WIDTH =>6) port map (clock => Clk(3), clk_en => csel_enable, aclr => reset_all, q => clk3_count); dig_count2: lpm_counter generic map (LPM_WIDTH =>6) port map (clock => Clk(2), clk_en => csel_enable, aclr => reset_all, q => clk2_count); dig_count5: lpm_counter generic map (LPM_WIDTH =>6) port map (clock => Clk(5), clk_en => csel_enable, aclr => reset_all, q => clk5_count); d32_comp: lpm_compare generic map ( LPM_WIDTH =>6) port map ( dataa => clk3_count, datab => clk2_count, ageb => b3s2, alb => b2s3); d26_comp: lpm_compare generic map ( LPM_WIDTH =>6) port map ( dataa => clk2_count, datab => clk5_count, ageb => b2s5, alb => b5s2); d36_comp: lpm_compare generic map ( LPM_WIDTH =>6) port map ( dataa => clk3_count, datab => clk5_count, ageb => b3s5, alb => b5s3); -- pipeline clock selection process(reset_all,ttc_done) begin if(reset_all = '1' or ttc_done = '0') then now_dclk <= wait1_dclk; elsif(clk_out'event and clk_out = '1') then now_dclk <= next_dclk; end if; end process; process(now_dclk) begin case now_dclk is when wait1_dclk => csel_enable <= '0'; if(ttc_done = '1') then next_dclk <= chk_dclk; else next_dclk <= wait1_dclk; end if; when chk_dclk => csel_enable <= '1'; if(period2(3) = '0') then next_dclk <= chk_dclk; else next_dclk <= wait2_dclk; end if; when wait2_dclk => csel_enable <= '0'; next_dclk <= wait2_dclk; end case; end process; clkset: process(b2s3,b2s5,b3s2,b3s5,b5s2,b5s3) begin if(b3s2 = '1' and b3s5 = '1') then clk3_ok <= '1'; clk2_ok <= '0'; clk5_ok <= '0'; clk_pipe <= not Clk(3); elsif(b2s3 = '1' and b2s5 = '1') then clk2_ok <= '1'; clk3_ok <= '0'; clk5_ok <= '0'; clk_pipe <= not Clk(2); elsif(b5s3 = '1' and b5s2 = '1') then clk5_ok <= '1'; clk2_ok <= '0'; clk3_ok <= '0'; clk_pipe <= not Clk(5); else -- default to Clk(3) clk3_ok <= '1'; clk2_ok <= '0'; clk5_ok <= '0'; clk_pipe <= not Clk(3); end if; -- clk_pipe <= not Clk(3); -- clk_pipe <= not Clk(5); end process clkset; -------------------end of this block --------------------------------------------- ------------------------------------------------------------------------------------------- -- output_controller: provide control signal for interface with glink ------------------------------------------------------------------------------------------- packw_count: lpm_counter generic map (LPM_WIDTH =>3) -- data frame write in counter port map (clock => data_end, aclr => reset_all, q => packw_num); packr_count: lpm_counter generic map (LPM_WIDTH =>4) -- data frame read out counter port map (clock => data_txed, aclr => reset_all, q => packr_num); pack_comp: lpm_compare generic map ( LPM_WIDTH =>3) -- compare the two counters port map ( dataa => packw_num, datab => packr_num(3 downto 1), aneb => pack_ready); -- if not equal, data is ready data_read_count: lpm_counter generic map (LPM_WIDTH =>10) -- count how many data read. port map (clock => clk2b_out, clk_en => reading, aclr => data_read_clr, q => data_read_num); package_comp: lpm_compare generic map ( LPM_WIDTH =>10) -- if data read equal data num port map ( dataa => data4read, -- then one fifo is read datab => data_read_num, aeb => data_txed); tx_en <= pack_ready and LOCKED; -- after data is ready and glink is locked, then enable transmittion. data_read_clr <= (reset_all or data_txed); delay_count1: lpm_counter generic map (LPM_WIDTH =>2) -- when temp_count1(1) = 1 port map (clock => data_txed, -- reading is held at 0 aclr => temp_clr1, q => temp_count1); delay_count2: lpm_counter generic map (LPM_WIDTH =>4) -- this counts the clock cycles port map (clock => clk2_out, -- to hold reading at zero aclr => temp_clr2, -- so crc and control words q => temp_count2); -- can get written before next -- event starts temp_clr2 <= reset_all or ( not temp_count1(1)); temp_clr1 <= reset_all or temp_count2(3); process ( packr_num1) begin if ( packr_num1 = '1' ) then reg_out <= fifo_out_data2; else reg_out <= fifo_out_data1; end if; end process; --******************************************************************************-- -- this block to control sending the data word and control word using state machine --******************************************************************************-- crcdig: CRC16 port map ( crc_clk => clk_out, crc_step => cstep, crc_start => cstart, crc_data => buff_crc, crc_error => cerror); process(reset_all, clk_out) begin if reset_all = '1' then current_state <= idle; elsif (clk_out'event and clk_out = '1' ) then current_state <= next_state; end if; end process; process (current_state) begin case current_state is when idle => cstart <= '0'; cstep <= '0'; HP_CNTL_IN <= '0'; HP_DATA_IN <= '0'; HP_FLAG_IN <= '0'; buff_out <= startwHI; if reading1b = '1' then next_state <= startHI; else next_state <= idle; end if; when startHI => cstart <= '1'; cstep <= '0'; HP_CNTL_IN <= '1'; HP_DATA_IN <= '1'; HP_FLAG_IN <= '0'; buff_out <= startwHI; next_state <= startLO; when startLO => HP_CNTL_IN <= '1'; HP_DATA_IN <= '1'; HP_FLAG_IN <= '0'; buff_out <= startwLO; cstart <= '1'; cstep <= '1'; next_state <= txingHI; when txingHI => cstart <= '0'; cstep <= '1'; HP_CNTL_IN <= '0'; HP_DATA_IN <= '1'; HP_FLAG_IN <= '0'; buff_out <= fifo_data(31 downto 16); buff_crc(31 downto 0) <= fifo_data(31 downto 0); next_state <= txingLO; when txingLO => cstep <= '0'; HP_CNTL_IN <= '0'; HP_DATA_IN <= '1'; HP_FLAG_IN <= '0'; buff_out <= fifo_data(15 downto 0); if ( reading3 = '1' and reading2 = '0' ) then next_state <= txeflg1; else next_state <= txingHI; end if; when txeflg1 => HP_CNTL_IN <= '0'; HP_DATA_IN <= '1'; HP_FLAG_IN <= '0'; buff_out <= cerror(31 downto 16); next_state <= txeflg2; when txeflg2 => HP_CNTL_IN <= '0'; HP_DATA_IN <= '1'; HP_FLAG_IN <= '0'; buff_out <= cerror(15 downto 0); next_state <= cmd_tx; when cmd_tx => HP_CNTL_IN <= '0'; HP_DATA_IN <= '0'; -- idle word with no crc calc HP_FLAG_IN <= '1'; buff_out <= cmd_word; next_state <= crc_tx; when crc_tx => HP_CNTL_IN <= '0'; HP_DATA_IN <= '1'; -- return the crc word HP_FLAG_IN <= '1'; buff_out <= crc_cnst; next_state <= stopHI; when stopHI => HP_CNTL_IN <= '1'; HP_DATA_IN <= '1'; HP_FLAG_IN <= '0'; buff_out <= stopwHI; next_state <= stopLO; when stopLO => HP_CNTL_IN <= '1'; HP_DATA_IN <= '1'; HP_FLAG_IN <= '0'; buff_out <= stopwLO; next_state <= idle; end case; end process; ------------------------------------------------------------------------------------------ -- delay signals ------------------------------------------------------------------------------------------ process ( clk2_out ) begin if ( clk2_out'event and clk2_out = '1') then fifo_data <= reg_out; read_ready <= tx_en; reading1 <= reading; reading2 <= reading1b; reading3 <= reading2b; reading4 <= reading3b; packr_num0 <= packr_num(0); packr_num1 <= packr_num0b; end if; end process; process ( clkb_out ) begin if ( clkb_out'event and clkb_out = '1') then reading1c <= reading1b; end if; end process; process ( clk_out ) begin if ( clk_out'event and clk_out = '1') then reading1d <= reading1b; end if; end process; process (clk2b_out) begin if ( clk2b_out'event and clk2b_out = '1') then reading1b <= reading1; reading2b <= reading2; reading3b <= reading3; packr_num0b <= packr_num0; end if; end process; -----------------------------------end of this block -------------------------------------- process ( tx_en, temp_count1(1), clk2b_out) begin if ((temp_count1(1) or reset_all) = '1') then reading <= '0'; elsif (clk2b_out'event and clk2b_out = '1' ) then reading <= tx_en; end if; end process; fifo_rden1 <= reading and (not packr_num(0)); fifo_rden2 <= reading and packr_num(0); ------------------------------------------------------------------------------------------- -- other logics ------------------------------------------------------------------------------------------- clkb_pipe <= not clk_pipe; process( clk_pipe) begin if( clk_pipe'event and clk_pipe = '1') then clk2 <= clk2b; end if; end process; clk2b <= not clk2; process( clk2) begin if(clk2'event and clk2 = '1') then clk4 <= clk4b; end if; end process; clk4b <= not clk4; -- kja clk_out <= Clock; clkb_out <= not clk_out; process( clk_out) begin if( clk_out'event and clk_out = '1') then clk2_out <= clk2b_out; end if; end process; clk2b_out <= not clk2_out; process( clk2_out) begin if(clk2_out'event and clk2_out = '1') then clk4_out <= clk4b_out; end if; end process; clk4b_out <= not clk4_out; -- kja ------------------------------------------------------------------------------------------- crccal : crctx port map ( CLK => clkb_out, TX_D_IN => buff_out, TX_D => TX, TX_DATA_IN => HP_DATA_IN, TX_DATA => TXDATA, TX_CNTL_IN => HP_CNTL_IN, TX_CNTL => TXCNTL, TX_FLAG_IN => HP_FLAG_IN, TX_FLAG => TXFLAG); TXFLGENB <= '1'; TXDIV0 <= '1'; TXDIV1 <= '0'; TXCLK <= clk_out; TCLKENB <='0'; ESMPXENB <='1'; -- kja end a;