TITLE "CALTRG trigger"; % carla grosso-pilcher % % make individual OR of 10 single bit triggers and sum three set % % of double bit triggers from 12 cratesum boards % % outputs 20 trigger bits to the back plane for FRED % % !!!! Pin names and assignment fixed from the sumet chip. !!!!% % !!!! They have to be conserved on all pfred chip, even if not optimal. !!!!% FUNCTION lpm_add_sub (cin, dataa[LPM_WIDTH-1..0], datab[LPM_WIDTH-1..0], add_sub, clock, aclr) WITH (LPM_WIDTH, LPM_REPRESENTATION, LPM_DIRECTION, LPM_PIPELINE, ONE_INPUT_IS_CONSTANT) RETURNS (result[LPM_WIDTH-1..0], cout, overflow); FUNCTION lpm_shiftreg (data[LPM_WIDTH-1..0], clock, enable, shiftin, load, sclr, sset, aclr, aset) WITH (LPM_WIDTH, LPM_DIRECTION, LPM_AVALUE, LPM_SVALUE) RETURNS (Q[LPM_WIDTH-1..0], shiftout); FUNCTION lpm_mux (data[LPM_SIZE-1..0][LPM_WIDTH-1..0], sel[LPM_WIDTHS-1..0], clock, aclr) WITH (LPM_WIDTH, LPM_SIZE, LPM_WIDTHS, LPM_PIPELINE) RETURNS (result[LPM_WIDTH-1..0]); SUBDESIGN caltrg ( clk_66ns : INPUT; clk_132ns[2..0] : INPUT; % 132 ns clocks, separated by 22 ns; 1st one % % is in sync with CRATESUMs' incoming data % b0_delayed : INPUT; % B0 signal delayed by b0_offset % run : INPUT; vme_write : INPUT; % read (0) or write (1) request from VME % vme_dat[31..0] : BIDIR; % port used to download input mask % vme_address[13..2]: INPUT; % VME address bus % vme_proc_clk : INPUT; % clock to load masks from VME % vme_fifo_wen : INPUT; vme_version_ren : INPUT; % enables vme reading of the code version number % fred_delay[5..0] : INPUT; % alignment delay (constant) in units of 22 ns % thres_sel[1..0] : INPUT; % threshold selector for sumet pfred, % % here only used to define mask for bad channels % src_etin : INPUT; % What feeds this chip: % % 0=backplane (normal run), 1=VME_address bus % etin[11..0][9..0] : INPUT; % number of di-objects, single objects from CS % dataout_ren[1..0] : INPUT; % enables vme reading of dataout, i.e. trigword & % % to fred % dataout[55..0] : OUTPUT; sram_enable : OUTPUT; %**** the following signals are not used in this module, defined as input to keep pin assignment *****% % lut_address[5..0][11..0] : INPUT; % % output in sumet % lut_data[5..0][11..0] : INPUT; % bidir in sumet % vme_lut_en[2..0] : INPUT; ) VARIABLE _clk_132ns[2..0] : GLOBAL; load : NODE; vme_wen : NODE; % vme_write & load % vme_read : NODE; run_ : NODE; % run # src_etin % vme_data[31..0] : TRI_STATE_NODE; fake_etin[11..0][9..0] : TRI; fake_trigbits[19..0] : TRI; fake_b0delayed : TRI; datain[11..0][9..0] : TRI_STATE_NODE; etin_[11..0][9..0] : DFFE; % number of di-objects, single objects from CS % mask_et[11..0][9..0] : DFFE; % mask for bad etin data. Copy of individual cratesum mask for all inputs % tri_mask_et[11..0] : TRI; tri_b0delayed : TRI; tri_dataout[55..15] : TRI; tri_etin[11..0][9..0] : TRI; tri_trigbits[39..0] : TRI; % 19..0 are b0_delayed, 39..20 are the original ones % tri_version[7..0] : TRI; tri_dummy[2..0] : TRI; datout[55..15] : TRI_STATE_NODE; outpipe[20..0] : lpm_shiftreg WITH (LPM_WIDTH=8); % FRED alignment pipeline % align_mux : lpm_mux WITH (LPM_WIDTH=21, LPM_SIZE=8, LPM_WIDTHS=3); % picks the output with desired align delay % select_clk : lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=6, LPM_WIDTHS=3); sngtrg[9..0] : NODE; dbltrg_a[1..0] : NODE ; dbltrg_b[1..0] : NODE ; dbltrg_c[1..0] : NODE ; adder_a[10..0] : lpm_add_sub WITH (LPM_WIDTH=2,LPM_REPRESENTATION="UNSIGNED",LPM_DIRECTION="ADD"); adder_b[10..0] : lpm_add_sub WITH (LPM_WIDTH=2,LPM_REPRESENTATION="UNSIGNED",LPM_DIRECTION="ADD"); adder_c[10..0] : lpm_add_sub WITH (LPM_WIDTH=2,LPM_REPRESENTATION="UNSIGNED",LPM_DIRECTION="ADD"); adder_aof : NODE; adder_bof : NODE; adder_cof : NODE; trgbits_tmp[9..0] : DFFE; tofred[20..0] : DFFE; %20 trigger bits and b0delayed % trgbts[19..0] : DFFE; % trigger bits before Fred delay% version[7..0] : NODE; BEGIN _clk_132ns[] = !clk_132ns[]; etin_[][].clk = clk_66ns; trgbits_tmp[].clk = clk_132ns2; trgbts[].clk = _clk_132ns1; tri_dummy[].in = GND; tri_dummy[].oe = dataout_ren1; vme_data[23..21] = tri_dummy[2..0].out; % dummy assignment, 23..21 actually unused % run_ = run # src_etin; etin_[][].ena = run_; % I. LOAD mode % load = !run; vme_read = !vme_write; vme_wen = vme_write & load; version[] = 2; tri_version[].in = version[]; tri_version[].oe = vme_version_ren; vme_data[31..24] = tri_version[].out; mask_et[][].clk = vme_proc_clk; mask_et[][].ena = vme_wen & thres_sel0 & thres_sel1; mask_et[]_0.d = vme_dat[11..0]; mask_et[]_1.d = vme_dat[11..0]; mask_et[]_2.d = vme_dat[11..0]; mask_et[]_3.d = vme_dat[11..0]; mask_et[]_4.d = vme_dat[11..0]; mask_et[]_5.d = vme_dat[11..0]; mask_et[]_6.d = vme_dat[11..0]; mask_et[]_7.d = vme_dat[11..0]; mask_et[]_8.d = vme_dat[11..0]; mask_et[]_9.d = vme_dat[11..0]; tri_mask_et[].in = mask_et[]_0.q; tri_mask_et[].oe = vme_read & thres_sel0 & thres_sel1; vme_data[11..0] = tri_mask_et[].out; tri_trigbits[19..0].in = tofred[19..0].q; tri_trigbits[39..20].in = trgbts[19..0].q; tri_trigbits[19..0].oe = dataout_ren0; tri_trigbits[39..20].oe = dataout_ren1; vme_data[19..0] = tri_trigbits[19..0].out; vme_data[19..0] = tri_trigbits[39..20].out; tri_b0delayed.in = tofred20.q; tri_b0delayed.oe = dataout_ren0; vme_data20 = tri_b0delayed.out; vme_dat[] = vme_data[]; % this seems like an overkill, but kept for symmetry with sumet % fake_trigbits[19..0].in = vme_dat[19..0]; fake_trigbits[19..0].oe = vme_fifo_wen; % datout[50..35] = fake_trigbits[19..4].out; datout[54..51] = fake_trigbits[3..0].out; datout[34..15] = fake_trigbits[19..0].out; % fake_b0delayed.in = vme_dat20; fake_b0delayed.oe = vme_fifo_wen; datout55 = fake_b0delayed.out; fake_etin0_[].in = vme_address[11..2]; fake_etin1_[].in = (vme_address11,vme_address2,vme_address[10..3]); fake_etin2_[].in = (vme_address11,vme_address[3..2],vme_address[10..4]); fake_etin3_[].in = (vme_address11,vme_address[4..2],vme_address[10..5]); fake_etin4_[].in = (vme_address11,vme_address[5..2],vme_address[10..6]); fake_etin5_[].in = (vme_address11,vme_address[6..2],vme_address[10..7]); fake_etin6_[].in = (vme_address11,vme_address[7..2],vme_address[10..8]); fake_etin7_[].in = (vme_address11,vme_address[8..2],vme_address[10..9]); fake_etin8_[].in = (vme_address11,vme_address[9..2],vme_address10); fake_etin9_[].in = vme_address[11..2]; fake_etin10_[].in = (vme_address11,vme_address2,vme_address[10..3]); fake_etin11_[].in = (vme_address11,vme_address[3..2],vme_address[10..4]); fake_etin[][].oe = src_etin; datain[][] = fake_etin[][].out; % II. RUN mode: % tri_etin[][].in = etin[][]; tri_etin[][].oe = run; datain[][] = tri_etin[][].out; etin_[][].d = datain[][] & !mask_et[][]; % OR single bit triggers % sngtrg[] = etin_0_[].q#etin_1_[].q#etin_2_[].q#etin_3_[].q#etin_4_[].q#etin_5_[].q# etin_6_[].q#etin_7_[].q#etin_8_[].q#etin_9_[].q#etin_10_[].q#etin_11_[].q; %start adding double triggers bits % adder_a0.dataa[] = etin_0_[1..0].q; %bits 0 & 1 - first step % adder_a0.datab[] = etin_1_[1..0].q; adder_a1.dataa[] = etin_2_[1..0].q; adder_a1.datab[] = etin_3_[1..0].q; adder_a2.dataa[] = etin_4_[1..0].q; adder_a2.datab[] = etin_5_[1..0].q; adder_a3.dataa[] = etin_6_[1..0].q; adder_a3.datab[] = etin_7_[1..0].q; adder_a4.dataa[] = etin_8_[1..0].q; adder_a4.datab[] = etin_9_[1..0].q; adder_a5.dataa[] = etin_10_[1..0].q; adder_a5.datab[] = etin_11_[1..0].q; adder_a6.dataa[] = adder_a0.result[]; % second step % adder_a6.datab[] = adder_a1.result[]; adder_a7.dataa[] = adder_a2.result[]; adder_a7.datab[] = adder_a3.result[]; adder_a8.dataa[] = adder_a4.result[]; adder_a8.datab[] = adder_a5.result[]; adder_a9.dataa[] = adder_a6.result[]; % third step % adder_a9.datab[] = adder_a7.result[]; adder_a10.dataa[] = adder_a8.result[]; % final step % adder_a10.datab[] = adder_a9.result[]; adder_aof = adder_a0.overflow#adder_a1.overflow#adder_a2.overflow# adder_a3.overflow#adder_a4.overflow#adder_a5.overflow# adder_a6.overflow#adder_a7.overflow#adder_a8.overflow# adder_a9.overflow#adder_a10.overflow; dbltrg_a[] = adder_a10.result[]#adder_aof; %final sum bits 01 & 1% adder_b0.dataa[] = etin_0_[3..2].q; %bits 2 & 3% adder_b0.datab[] = etin_1_[3..2].q; adder_b1.dataa[] = etin_2_[3..2].q; adder_b1.datab[] = etin_3_[3..2].q; adder_b2.dataa[] = etin_4_[3..2].q; adder_b2.datab[] = etin_5_[3..2].q; adder_b3.dataa[] = etin_6_[3..2].q; adder_b3.datab[] = etin_7_[3..2].q; adder_b4.dataa[] = etin_8_[3..2].q; adder_b4.datab[] = etin_9_[3..2].q; adder_b5.dataa[] = etin_10_[3..2].q; adder_b5.datab[] = etin_11_[3..2].q; adder_b6.dataa[] = adder_b0.result[]; adder_b6.datab[] = adder_b1.result[]; adder_b7.dataa[] = adder_b2.result[]; adder_b7.datab[] = adder_b3.result[]; adder_b8.dataa[] = adder_b4.result[]; adder_b8.datab[] = adder_b5.result[]; adder_b9.dataa[] = adder_b6.result[]; adder_b9.datab[] = adder_b7.result[]; adder_b10.dataa[] = adder_b8.result[]; adder_b10.datab[] = adder_b9.result[]; adder_bof = adder_b0.overflow#adder_b1.overflow#adder_b2.overflow# adder_b3.overflow#adder_b4.overflow#adder_b5.overflow# adder_b6.overflow# adder_b7.overflow#adder_b8.overflow# adder_b9.overflow#adder_b10.overflow; dbltrg_b[] = adder_b10.result[]#adder_bof; %final sum bits 2 & 3% adder_c0.dataa[] = etin_0_[5..4].q; %bits 4 & 5% adder_c0.datab[] = etin_1_[5..4].q; adder_c1.dataa[] = etin_2_[5..4].q; adder_c1.datab[] = etin_3_[5..4].q; adder_c2.dataa[] = etin_4_[5..4].q; adder_c2.datab[] = etin_5_[5..4].q; adder_c3.dataa[] = etin_6_[5..4].q; adder_c3.datab[] = etin_7_[5..4].q; adder_c4.dataa[] = etin_8_[5..4].q; adder_c4.datab[] = etin_9_[5..4].q; adder_c5.dataa[] = etin_10_[5..4].q; adder_c5.datab[] = etin_11_[5..4].q; adder_c6.dataa[] = adder_c0.result[]; adder_c6.datab[] = adder_c1.result[]; adder_c7.dataa[] = adder_c2.result[]; adder_c7.datab[] = adder_c3.result[]; adder_c8.dataa[] = adder_c4.result[]; adder_c8.datab[] = adder_c5.result[]; adder_c9.dataa[] = adder_c6.result[]; adder_c9.datab[] = adder_c7.result[]; adder_c10.dataa[] = adder_c8.result[]; adder_c10.datab[] = adder_c9.result[]; adder_cof = adder_c0.overflow#adder_c1.overflow#adder_c2.overflow# adder_c3.overflow#adder_c4.overflow#adder_c5.overflow# adder_c6.overflow#adder_c7.overflow#adder_c8.overflow# adder_c9.overflow#adder_c10.overflow; dbltrg_c[] = adder_c10.result[]#adder_cof; %final sum bits 4 & 5% %save results temporarily to combine with next 66 ns cycle data % trgbits_tmp[1..0].d = dbltrg_a[] ; trgbits_tmp[3..2].d = dbltrg_b[] ; trgbits_tmp[5..4].d = dbltrg_c[] ; trgbits_tmp[9..6].d = GND; trgbts[9..0].d = sngtrg[]; trgbts[19..10].d = trgbits_tmp[].q; outpipe[9..0].shiftin = sngtrg[]; outpipe[19..10].shiftin = trgbits_tmp[].q; outpipe20.shiftin = b0_delayed; outpipe[].clock = _clk_132ns1; align_mux.data0_[] = outpipe[].q0; align_mux.data1_[] = outpipe[].q1; align_mux.data2_[] = outpipe[].q2; align_mux.data3_[] = outpipe[].q3; align_mux.data4_[] = outpipe[].q4; align_mux.data5_[] = outpipe[].q5; align_mux.data6_[] = outpipe[].q6; align_mux.data7_[] = outpipe[].q7; align_mux.sel[] = fred_delay[5..3]; select_clk.data0_0 = _clk_132ns1; select_clk.data1_0 = _clk_132ns2; select_clk.data2_0 = clk_132ns0; select_clk.data3_0 = clk_132ns1; select_clk.data4_0 = clk_132ns2; select_clk.data5_0 = _clk_132ns0; select_clk.sel[] = fred_delay[2..0]; % fine delay : selects which clock the trigger bits will be sent out to FRED on % tofred[].clk = select_clk.result0; tofred[].d = align_mux.result[]; tri_dataout[34..15].in = trgbts[].q; % these bits to go to front panel and buffers% tri_dataout[54..51].in = tofred[3..0].q; % to allign bits properly on the back plane, need to follow pfred-sumet assignements% tri_dataout[50..35].in = tofred[19..4].q; tri_dataout[55].in = tofred[20].q; tri_dataout[].oe = run; datout[] = tri_dataout[].out; dataout[34..21] = GND; dataout[55..35] = datout[55..35]; dataout[9..0] = datout[24..15]; % single trigger bits will correspond to % % first 10 bits of sumet% dataout[20..11] = datout[34..25]; % double trigger bits will correspond to % %sumex% dataout[10] = GND; sram_enable = VCC; END;