-- -- gb.tdf -- data processor chip for SVT GhostBuster card -- begun April 2001 by Bill Ashmanskas, U. Chicago / CDF -- title "delete duplicate tracks; perform various utility functions"; include "lpm_counter.inc"; include "altclklock.inc"; include "lpm_ram_dp.inc"; include "lpm_fifo_dc.inc"; include "lpm_add_sub.inc"; -- -- Upon L1A with corresponding buffer number, records data -- for later VME readout -- function buffer ( indata[23..0], clock, trigger, reset, raddr[8..0], rclk) returns (idle, data[23..0]); subdesign gb ( -- input data from FIFO; associated control signals din[22..0] : input; -- FIFO data _fifoef[1..0] : input; -- empty* flags (2 FIFOs) _fifofull : input; -- full* flag (1st FIFO) _fifoaf : input; -- almost-full* flag (1st FIFO) fiforclk : output; -- read clock (2 FIFOs) _fiforena : output; -- read enable* (2 FIFOs) _fiforeset : output; -- reset* (2 FIFOs) inphold : output; -- flow control to upstream board _inpds : input; -- upstream data strobe* (useful?) -- output data to downstream board; control signals dout[22..0] : output; -- cable data _dsout : output; -- data strobe* outphold : input; -- flow control from downstream board -- flash RAM, perhaps to store lookup tables framaddr[20..0] : output; -- address bus framdata[15..0] : bidir; -- data bus _framoe : output; -- output enable* _framwe : output; -- write ena* (rising edge latches A/D) _framrp : output; -- reset* _framwp : output; -- write prot* (pulldown for safety?) framsts : input; -- status (ready/busy*) (needs pullup) -- VME I/O addr[23..2] : input; -- address (minus GA, unused 26-24,1-0) data[31..0] : bidir; -- data lines vmewrite : input; -- qualifies address value (r vs w) vmeas : input; -- derived signal for latching address vmeds : input; -- derived signal for latching data -- CDF J2 custom backplane signals: see CDF 2388 for specification cdfclk : input; -- 132 ns clock _cdfbc : input; -- bunch crossing _cdfb0 : input; -- bunch zero marker _cdfl1a : input; -- level 1 accept _cdfl1r : input; -- level 1 reject _cdfl2b0 : input; -- level 2 buffer number (bit 0) _cdfl2b1 : input; -- level 2 buffer number (bit 1) _cdfhalt : input; -- _cdfrecover : input; -- _cdfl2a : input; -- level 2 accept -- SVT-specific J2 control signals _svtinit : input; -- clear FIFOs, etc. _svtfreeze : input; -- freeze spy buffers (N/A?) _svtspare : input; -- reserved input -- these should be O/C outputs, so that any chip can drive them _svterror : output; -- assert the SVT_ERROR* signal _cdferror : output; -- assert the CDF_ERROR* signal -- VME access to *next* chip's JTAG connector vmejtagtck : input; -- TCK (should be tri-stated) vmejtagtdo : input; -- TDO vmejtagtms : input; -- TMS (should be tri-stated) vmejtagtdi : input; -- TDI (should be tri-stated) -- various and sundry I/O clock : input; -- on-board 30 MHz oscillator id[1..0] : input; -- which channel am I (of 3 on board)? dip[2..0] : input; -- board ID DIP switch debug[15..0] : output; -- to logic analyzer debugclk : output; -- clock to logic analyzer sysclk : input; -- VME system clock (possibly useful) spare[29..0] : input; -- bussed spare lines ctrlspare[2..0] : input; -- spare global control lines (??) l2data[33..0] : input; -- LEDs dsinled : output; -- input data strobe holdinled : output; -- input hold dsoutled : output; -- output data strobe holdoutled : output; -- output hold runled : output; -- run-mode LED errorled : output; -- error LED (O/C output?) ) variable ffin[22..0] : dff; -- latch inputs dvin : dff; -- input valid flag dvxmag[9..0] : node; acceptall : node; rejectall : node; acceptothers : node; unique : node; dvxcut[8..0] : node; dobigdvxcut : node; bigdvxcut[8..0] : node; dobigcrvcut : node; dofilter : node; docrvcut : node; crvcut[7..0] : node; csqcut[10..0] : node; ntkcut[9..0] : node; goodtrack : node; beamfix : lpm_ram_dp with ( LPM_WIDTH=10, LPM_WIDTHAD=13, lpm_file="db.mif", lpm_outdata="unregistered", lpm_rdaddress_control="unregistered", lpm_wraddress_control="registered", lpm_indata="registered"); dda[22..0] : dffe; -- extra stage dva : dffe; -- extra stage valid flag wca : lpm_counter with (lpm_width=4); ddb[22..0] : dffe; -- extra stage dvb : dffe; -- extra stage valid flag wcb[3..0] : dffe; ddc[22..0] : dffe; -- extra stage bfc[9..0] : dffe; d2cc[9..0] : dffe; wcc[3..0] : dffe; dvc : dffe; -- extra stage valid flag ddd[22..0] : dffe; -- extra stage adder : lpm_add_sub with (LPM_WIDTH=10); negdiff[9..0] : node; diffd[9..0] : dffe; wcd[3..0] : dffe; bfd[9..0] : dffe; dvd : dffe; -- extra stage valid flag dde[22..0] : dffe; -- extra stage ntrackse : lpm_counter with (lpm_width=10); dve : dffe; -- extra stage valid flag lastxft[8..0] : dffe; ddf[22..0] : dffe; -- extra stage ntracksf[9..0] : dffe; dvf : dffe; -- extra stage valid flag ddg[22..0] : dffe; -- extra stage dvg : dffe; -- extra stage valid flag ddh[22..0] : dffe; -- extra stage dvh : dffe; -- extra stage valid flag ddi[22..0] : dffe; -- extra stage dvi : dffe; -- extra stage valid flag ffout[22..0] : dff; -- latch outputs dvout : dff; -- output valid flag _dataready : dff; -- data are available to read skipff : dff; skipff0 : dff; ctrlreg[31..0] : dff; -- misc control registers ctrl1reg[31..0] : dff; addrchk[31..0] : dff; -- test VME address bus ctrl[31..0] : node; -- alias for ctrlreg.q cdfl1a : dff; -- latch/invert backplane sigs cdfl2b0 : dff; cdfl2b1 : dff; cdfb0 : dff; cdfrec : dff; cdfcc : lpm_counter -- count CDF_CLKs between B0 with (LPM_WIDTH=8); cdfcc1 : lpm_counter -- count CDF_CLKs since marker with (LPM_WIDTH=8, LPM_MODULUS=159); l1afifo : lpm_fifo_dc -- with (LPM_WIDTH=10,LPM_NUMWORDS=7,LPM_WIDTHU=3); eplastvalid : dffe; enable : dff; prescale : lpm_counter with (lpm_width=16); buf0time : lpm_counter with (lpm_width=20); l1a0sync0 : dff; l1a0sync : dff; whichblock[5..0] : dff; -- synchronize, invert hold signal from downstream board _outputhold0 : dff; _outputhold : dff; -- tri-state buffers for VME and FRAM data lines datatri[31..0] : tri_state_node; dataout[31..0] : tri; -- vme readout gets muxed here fdtri[15..0] : tri_state_node; fdout[15..0] : tri; -- -- nodes holding results of VME address decoding vme_clr_ctrs : node; -- reset counters vme_ctrlwrite : node; -- write control registers vme_ctrl1write : node; vme_beamwrite : node; vme_framwrite : node; vme_framread : node; vme_whichblockwrite : node; vme_whichblockread : node; renanode : node; -- lcell for fiforena begin -- handle control register ctrlreg[].d = data[]; ctrlreg[].clk = vme_ctrlwrite; ctrl[] = ctrlreg[].q; ctrl1reg[].d = data[]; ctrl1reg[].clk = vme_ctrl1write; whichblock[].d = data[5..0]; whichblock[].clk = vme_whichblockwrite; -- register to check VME address bus addrchk[31..24].d = GND; addrchk[23..2].d = addr[23..2]; addrchk[1..0].d = GND; addrchk[].clk = vmeas & vmewrite; -- latch backplane trigger signals; write L1A into FIFO cdfl1a.d = !_cdfl1a; -- get active-high L1A cdfl1a.clk = cdfclk; -- and latch to clock cdfrec.d = !_cdfrecover; -- CDF_RECOVER cdfrec.clk = cdfclk; cdfl2b0.d = !_cdfl2b0; -- L2B0 cdfl2b0.clk = cdfclk; -- cdfl2b1.d = !_cdfl2b1; -- L2B1 cdfl2b1.clk = cdfclk; -- cdfb0.d = !_cdfb0; -- B0 marker cdfb0.clk = cdfclk; -- cdfcc.clock = cdfclk; -- clocks-since-B0 counter cdfcc.sclr = cdfb0.q; -- cdfcc1.clock = cdfclk; -- clocks-since-Bn (set n via VME) cdfcc1.sclr = (cdfcc.q[]==ctrl[31..24]); l1afifo.data[7..0] = cdfcc1.q[]; -- bunch counter number l1afifo.data[8] = cdfl2b0.q; -- L2 buffer number l1afifo.data[9] = cdfl2b1.q; -- l1afifo.wrreq = cdfl1a.q; -- write every L1A l1afifo.wrclock = cdfclk; -- l1afifo.aclr = !_svtinit; l1afifo.rdreq = GND; l1afifo.rdclock = clock; -- l1a0sync0.d = cdfl1a.q & !cdfl2b0.q & !cdfl2b1.q; l1a0sync0.clk = clock; l1a0sync.d = l1a0sync0.q; l1a0sync.clk = clock; buf0time.aclr = !_svtinit; buf0time.sclr = l1a0sync.q; buf0time.clock = clock; -- drive VME data lines from tri-state buffers data[] = datatri[]; datatri[] = dataout[].out; -- some vme decoding vme_ctrlwrite = vmeas & vmewrite & addr[12..11]==id[] & (addr[23..14]==H"0") & (addr[10..2]==H"1"); vme_clr_ctrs = vmeas & vmewrite & addr[12..11]==id[] & (addr[23..14]==H"0") & (addr[10..2]==H"2"); vme_beamwrite = vmeas & vmewrite & addr[19..18]==id[] & (addr[23..20]==H"2"); vme_framwrite = vmeas & vmewrite & addr[19..18]==id[] & (addr[23..20]==H"3"); vme_framread = vmeas & !vmewrite & addr[19..18]==id[] & (addr[23..20]==H"3"); vme_ctrl1write = vmeas & vmewrite & addr[12..11]==id[] & (addr[23..14]==H"0") & (addr[10..2]==H"3"); vme_whichblockwrite = vmeas & vmewrite & addr[12..11]==id[] & (addr[23..14]==H"0") & (addr[10..2]==H"5"); vme_whichblockread = vmeas & !vmewrite & addr[12..11]==id[] & (addr[23..14]==H"0") & (addr[10..2]==H"5"); -- read data via vme if (vme_framread) then dataout[31..16] = GND; dataout[15..0].in = framdata[]; end if; if (vme_whichblockread) then dataout[31..7] = GND; dataout[6] = framsts; dataout[5..0] = whichblock[].q; end if; if ((addr[23..14]==H"0") & (addr[10..2]==H"0")) then dataout[].in = H"deadbeef"; end if; if ((addr[23..14]==H"0") & (addr[10..2]==H"1")) then dataout[].in = ctrlreg[].q; end if; if ((addr[23..14]==H"0") & (addr[10..2]==H"2")) then dataout[31..0].in = H"fab40000"; end if; if ((addr[23..14]==H"0") & (addr[10..2]==H"3")) then dataout[31..0].in = ctrl1reg[].q; end if; if ((addr[23..14]==H"0") & (addr[10..2]==H"4")) then dataout[].in = addrchk[].q; end if; -- ID prom if (addr[23..2]==H"40000") then dataout[].in = H"30000000"; end if; if (addr[23..2]==H"40001") then dataout[].in = H"30000000"; end if; if (addr[23..2]==H"40002") then dataout[].in = H"30000000"; end if; if (addr[23..2]==H"40003") then dataout[31..28].in = H"3"; dataout[27].in = GND; dataout[26..24].in = !dip[2..0]; dataout[23..0].in = GND; end if; if (addr[23..2]==H"40004") then dataout[].in = H"20000000"; end if; if (addr[23..2]==H"40005") then dataout[].in = H"30000000"; end if; if (addr[23..2]==H"40006") then dataout[].in = H"37000000"; end if; if (addr[23..2]==H"40007") then dataout[].in = H"33000000"; end if; if (addr[23..2]==H"40008") then dataout[].in = H"20000000"; end if; if (addr[23..2]==H"40009") then dataout[].in = H"43000000"; end if; if (addr[23..2]==H"4000a") then dataout[].in = H"44000000"; end if; if (addr[23..2]==H"4000b") then dataout[].in = H"46000000"; end if; if (addr[23..2]==H"4000c") then dataout[].in = H"20000000"; end if; if (addr[23..2]==H"4000d") then dataout[].in = H"53000000"; end if; if (addr[23..2]==H"4000e") then dataout[].in = H"56000000"; end if; if (addr[23..2]==H"4000f") then dataout[].in = H"54000000"; end if; if (addr[23..2]==H"40010") then dataout[].in = H"20000000"; end if; if (addr[23..2]==H"40011") then dataout[].in = H"47000000"; end if; if (addr[23..2]==H"40012") then dataout[].in = H"68000000"; end if; if (addr[23..2]==H"40013") then dataout[].in = H"6f000000"; end if; if (addr[23..2]==H"40014") then dataout[].in = H"73000000"; end if; if (addr[23..2]==H"40015") then dataout[].in = H"74000000"; end if; if (addr[23..2]==H"40016") then dataout[].in = H"42000000"; end if; if (addr[23..2]==H"40017") then dataout[].in = H"75000000"; end if; if (addr[23..2]==H"40018") then dataout[].in = H"73000000"; end if; if (addr[23..2]==H"40019") then dataout[].in = H"74000000"; end if; if (addr[23..2]==H"4001a") then dataout[].in = H"65000000"; end if; if (addr[23..2]==H"4001b") then dataout[].in = H"72000000"; end if; if (addr[23..2]==H"4001c") then dataout[].in = H"20000000"; end if; if (addr[23..2]==H"4001d") then dataout[].in = H"76000000"; end if; if (addr[23..2]==H"4001e") then dataout[].in = H"30000000"; end if; if (addr[23..2]==H"4001f") then dataout[].in = H"30000000"; end if; dataout[].oe = vmeas & !vmewrite & (((addr[23..20]==0) & (addr[12..11]==id[])) # (vme_framread)); -- beam correction beamfix.data[] = data[9..0]; beamfix.wrclock = vmeds; beamfix.wren = vme_beamwrite; beamfix.wraddress[] = addr[14..2]; -- beamfix.rdclock = clock; beamfix.rdaddress[] = ddc[15..3].q; -- hold logic and I/O LEDs _outputhold0.d = !outphold; _outputhold0.clk = clock; _outputhold.d = _outputhold0.q; _outputhold.clk = clock; inphold = !_fifoaf; holdinled = !_fifoaf; holdoutled = !_outputhold.q; dsoutled = dvi.q; dsinled = cdfl1a.q; -- input FIFO skipff0.d = VCC; skipff0.clk = clock; skipff0.clrn = _svtinit; skipff.d = skipff0.q; skipff.clk = !clock; fiforclk = clock; renanode = lcell(!(_fifoef1 & _fifoef0 & skipff.q)); _dataready.d = renanode; _dataready.clk = clock; _fiforena = renanode; _fiforeset = _svtinit; ffin[].d = din[]; ffin[].clk = clock; dvin.d = !_dataready.q; dvin.clk = clock; eplastvalid.d = ffin[21].q; eplastvalid.ena = dvin.q; eplastvalid.clrn = _svtinit; eplastvalid.clk = clock; -- enable the pipeline if we read a valid word -- or clock it anyway if the last valid word was -- an end-of-packet word enable.d = dvin.q # eplastvalid.q; enable.clk = clock; debug[] = GND; -- output data dda[].d = ffin[].q; dda[].ena = VCC; dda[].clk = clock; dda[].clrn = _svtinit; dva.d = dvin.q & (ffin[].q!=H"3fffff"); dva.clrn = _svtinit; dva.ena = VCC; dva.clk = clock; wca.aclr = !_svtinit; wca.sclr = (!dva.q # dda[21].q) & enable.q; wca.cnt_en = enable.q; wca.clock = clock; ddb[22..21].d = dda[22..21].q; ddb[19..0].d = dda[19..0].q; dvxcut[8..5] = GND; dvxcut[4..0] = ctrl[4..0]; csqcut[10..8] = GND; csqcut[7..0] = ctrl[15..8]; ntkcut[9..3] = GND; ntkcut[2..0] = ctrl[7..5]; dobigdvxcut = ctrl[17]; bigdvxcut[] = ctrl1reg[16..8].q; docrvcut = ctrl[18]; crvcut[] = ctrl1reg[7..0].q; dofilter = ctrl[19]; acceptothers = ctrl[29]; rejectall = ctrl[28]; acceptall = ctrl[27]; unique = ctrl[26]; if (wca.eq[4]) then ddb[20].d = ((dvxcut[]==0) # (diffd[8..0].q>=dvxcut[])) & ((!dobigdvxcut) # (diffd[8..0].q<=bigdvxcut[])) & ((!docrvcut) # (ddd[17..10].q<=crvcut[])); else ddb[20].d = dda[20].q; end if; ddb[].ena = enable.q; ddb[].clk = clock; dvb.d = dva.q; dvb.clrn = _svtinit; dvb.ena = enable.q; dvb.clk = clock; wcb[].d = wca.q[]; wcb[].ena = enable.q; wcb[].clk = clock; ddc[22..21].d = ddb[22..21].q; ddc[19..0].d = ddb[19..0].q; if (wca.eq[5]) then ddc[20].d = ddb[20].q & ((csqcut[]==0) # (dda[20..10].q<=csqcut[])); else ddc[20].d = ddb[20].q; end if; ddc[].ena = enable.q; ddc[].clk = clock; dvc.d = dvb.q; dvc.clrn = _svtinit; dvc.ena = enable.q; dvc.clk = clock; bfc[].d = -beamfix.q[]; bfc[].ena = enable.q; bfc[].clk = clock; dvxmag[9] = GND; dvxmag[8..0] = ddb[8..0].q; if (ddb[9].q) then d2cc[].d = -dvxmag[]; else d2cc[].d = dvxmag[]; end if; d2cc[].ena = enable.q; d2cc[].clk = clock; wcc[].d = wcb[].q; wcc[].ena = enable.q; wcc[].clk = clock; if (ddc[22].q) then lastxft[].d = H"1FF"; elsif (ddc[21].q) then lastxft[].d = ddc[8..0].q; else lastxft[].d = lastxft[].q; end if; lastxft[].ena = enable.q; lastxft[].clk = clock; lastxft[].prn = _svtinit; ddd[22..21].d = ddc[22..21].q; ddd[19..0].d = ddc[19..0].q; if (wca.eq[6]) then ddd[20].d = ddc[20].q & !(unique & (dda[8..0].q==lastxft[].q)); else ddd[20].d = ddc[20].q; end if; ddd[].ena = enable.q; ddd[].clk = clock; dvd.d = dvc.q; dvd.clrn = _svtinit; dvd.ena = enable.q; dvd.clk = clock; bfd[].d = bfc[].q; bfd[].ena = enable.q; bfd[].clk = clock; adder.dataa[] = d2cc[].q; adder.datab[] = bfc[].q; negdiff[] = -adder.result[]; if ((adder.result[9]) & (adder.result[8..0]!=0)) then diffd[9].d = VCC; diffd[8..0].d = negdiff[8..0]; else diffd[9].d = GND; diffd[8..0].d = adder.result[8..0]; end if; diffd[].ena = enable.q; diffd[].clk = clock; wcd[].d = wcc[].q; wcd[].ena = enable.q; wcd[].clk = clock; goodtrack = ddd[21].q & (wcd[].q==6) & ddf[20].q; ntrackse.cnt_en = goodtrack & enable.q; ntrackse.sclr = dde[22].q & enable.q; ntrackse.aclr = !_svtinit; ntrackse.clock = clock; if (wcd[].q==1) then dde[22..10].d = ddd[22..10].q; dde[9..0].d = diffd[].q; else dde[].d = ddd[].q; end if; dde[].ena = enable.q; dde[].clk = clock; dve.d = dvd.q; dve.clrn = _svtinit; dve.ena = enable.q; dve.clk = clock; ntracksf[].d = ntrackse.q[]; ntracksf[].ena = enable.q; ntracksf[].clk = clock; ntracksf[].clrn = _svtinit; ddf[].d = dde[].q; ddf[].ena = enable.q; ddf[].clk = clock; dvf.d = dve.q; dvf.clrn = _svtinit; dvf.ena = enable.q; dvf.clk = clock; ddg[22..19].d = ddf[22..19].q; ddg[17..0].d = ddf[17..0].q; if (rejectall) then ddg[18].d = GND; elsif (acceptall) then ddg[18].d = VCC; elsif (ctrl[25]) then ddg[18].d = prescale.eq[0]; elsif (ddf[22].q) then if (ddf[18].q) then ddg[18].d = (ntracksf[].q>=ntkcut[]); else ddg[18].d = acceptothers; end if; else ddg[18].d = ddf[18].q; end if; ddg[].ena = enable.q; ddg[].clk = clock; dvg.d = dvf.q; dvg.clrn = _svtinit; dvg.ena = enable.q; dvg.clk = clock; prescale.clock = clock; prescale.cnt_en = enable.q & ddg[22].q & dvg.q; prescale.aclr = !_svtinit; prescale.sclr = (prescale.q[]==ctrl[15..0]) & ctrl[16] & dvg.q; if (ctrl[30]) then ddh[22..20].d = ddg[22..20].q; ddh[19..0].d = buf0time.q[]; dvh.d = dvg.q & ddg[22].q & !ddg[20].q & !ddg[19].q; else ddh[].d = ddg[].q; dvh.d = dvg.q; end if; ddh[].ena = enable.q; ddh[].clk = clock; dvh.clrn = _svtinit; dvh.ena = enable.q; dvh.clk = clock; ddi[].d = ddh[].q; ddi[].ena = enable.q; ddi[].clk = clock; dvi.d = dvh.q & enable.q; dvi.clrn = _svtinit; dvi.ena = VCC; dvi.clk = clock; ffout[].d = ddi[].q; ffout[].clk = clock; dout[] = ffout[].q; dvout.d = dvi.q; -- & enable.q; dvout.clk = !clock; _dsout = !lcell(dvout.q & clock); framaddr[20..15] = whichblock[].q; framaddr[14..0] = addr[16..2]; framdata[] = fdtri[]; fdtri[] = fdout[].out; fdout[].in = data[15..0]; fdout[].oe = vme_framwrite; _framoe = !vme_framread; _framwe = !vme_framwrite; _framrp = VCC; _framwp = VCC; -- drive unimplemented outputs debugclk = clock; _svterror = VCC; _cdferror = VCC; runled = GND; errorled = GND; end;