TITLE "Output processor"; include "lpm_add_sub.inc"; include "lpm_ram_dq.inc"; include "lpm_ff.inc"; include "lpm_mux.inc"; include "lpm_counter.inc"; SUBDESIGN outprocessor ( clock : INPUT; hit[15..0] : INPUT; stream[5..0] : INPUT; init : INPUT; fifofull[9..0] : INPUT; lostlock[3..0] : INPUT; streamdisable[9..0] : INPUT; endeventmask[43..0] : INPUT; endeventclr[43..0] : INPUT; endeventreset : INPUT; lostsyncerror[9..0] : OUTPUT; invaliddataerror[9..0] : OUTPUT; fifooverflowerror[9..0] : OUTPUT; truncateddataerror[9..0] : OUTPUT; lostlockerror[3..0] : OUTPUT; vmebarrellayerin[5..0] : INPUT; barrellayeraddress[3..0] : INPUT; barrellayerclock : INPUT; barrellayerwrite : INPUT; vmebarrellayerout[5..0] : OUTPUT; opbarrellayeraddress[3..0] : OUTPUT; ds : OUTPUT; d[20..0] : OUTPUT; -- data format: 0..14 centroid 15..17 barrel 18..20 layer ee : OUTPUT; ep : OUTPUT; validout : OUTPUT; ) VARIABLE barrellayerram: lpm_ram_dq WITH (LPM_ADDRESS_CONTROL="REGISTERED", LPM_FILE="barrellayer.mif", LPM_INDATA="REGISTERED", LPM_OUTDATA="UNREGISTERED", LPM_WIDTH=6, LPM_WIDTHAD=4); ahit,bhit,chit,ehit,fhit :lpm_ff WITH (LPM_WIDTH=16); cbarrellayer,ebarrellayer, fbarrellayer :lpm_ff WITH (LPM_WIDTH=6); bvalid,cvalid,evalid,fvalid,gvalid :lpm_ff WITH (LPM_WIDTH=1); astream :lpm_ff WITH (LPM_WIDTH=6); bstream :lpm_ff WITH (LPM_WIDTH=10); cstream : lpm_ff WITH (LPM_WIDTH=10); aastream[10..0] : NODE; bmax[13..11] : DFF; bodd : DFF; csub : lpm_add_sub WITH (LPM_WIDTH=14, LPM_REPRESENTATION="UNSIGNED", LPM_DIRECTION="SUB"); cstreamend :lpm_ff WITH (LPM_WIDTH=10); thisendevent,lastendevent :NODE; cstreamenddata[9..0] : NODE; cdupstream :lpm_ff WITH (LPM_WIDTH=10); cendevent,eendevent,fendevent,gendevent :lpm_ff WITH (LPM_WIDTH=1); cbunch :lpm_ff WITH (LPM_WIDTH=8); cbestbunch[7..0] : dff; ebestbunch[7..0] : dff; cfirststream :lpm_ff WITH (LPM_WIDTH=1); fendeventword :lpm_ff WITH (LPM_WIDTH=21); elostsync,efifooverflow,einvaliddata,etruncateddata :lpm_ff WITH (LPM_WIDTH=10); elostlock :lpm_ff WITH (LPM_WIDTH=4); eparity :lpm_ff WITH (LPM_WIDTH=1); eehitmux :lpm_mux WITH (LPM_WIDTH=21, LPM_SIZE=2, LPM_WIDTHS=1); gd :lpm_ff WITH (LPM_WIDTH=21); fspareerror,flostlockerror,ftruncateddataerror,finternaloverflowerror, finvaliddataerror,ffifooverflowerror,flostsyncerror, fparityerror,fparity :NODE; BEGIN % stage a: latch inputs % ahit.data[] = hit[]; ahit.clock = clock; ahit.aclr = init; astream.data[] = stream[]; astream.clock = clock; astream.aclr = init; % stage b: reformat stream number % CASE astream.q[] IS WHEN B"000001" => aastream[] = B"00000000001"; % stream 0 % WHEN B"000010" => aastream[] = B"00000000010"; % stream 1 % WHEN B"000100" => aastream[] = B"00000000100"; % stream 2 % WHEN B"001000" => aastream[] = B"00000001000"; % stream 3 % WHEN B"010000" => aastream[] = B"00000010000"; % stream 4 % WHEN B"100001" => aastream[] = B"00000100000"; % stream 5 % WHEN B"100010" => aastream[] = B"00001000000"; % stream 6 % WHEN B"100100" => aastream[] = B"00010000000"; % stream 7 % WHEN B"101000" => aastream[] = B"00100000000"; % stream 8 % WHEN B"110000" => aastream[] = B"01000000000"; % stream 9 % WHEN OTHERS => aastream[] = B"10000000000"; % invalid % END CASE; CASE astream.q[] IS WHEN B"000001" => opbarrellayeraddress[] = 0; WHEN B"000010" => opbarrellayeraddress[] = 1; WHEN B"000100" => opbarrellayeraddress[] = 2; WHEN B"001000" => opbarrellayeraddress[] = 3; WHEN B"010000" => opbarrellayeraddress[] = 4; WHEN B"100001" => opbarrellayeraddress[] = 5; WHEN B"100010" => opbarrellayeraddress[] = 6; WHEN B"100100" => opbarrellayeraddress[] = 7; WHEN B"101000" => opbarrellayeraddress[] = 8; WHEN B"110000" => opbarrellayeraddress[] = 9; WHEN OTHERS => opbarrellayeraddress[] = 15; END CASE; bstream.clock = clock; bstream.data[9..0] = aastream[9..0]; bvalid.clock = clock; bvalid.data[] = !aastream[10] & (aastream[9..0] & streamdisable[])==0; bvalid.aclr = init; % read barrel/layer number from barrellayer ram % barrellayerram.data[] = vmebarrellayerin[]; barrellayerram.address[] = barrellayeraddress[]; barrellayerram.inclock = barrellayerclock; barrellayerram.we = barrellayerwrite; vmebarrellayerout[] = barrellayerram.q[]; bhit.clock = clock; bhit.data[] = ahit.q[]; bhit.aclr = init; CASE astream.q[4..0] IS WHEN B"00001" => bmax[13..11].d = B"010"; WHEN B"00010" => bmax[13..11].d = B"011"; WHEN B"00100" => bmax[13..11].d = B"101"; WHEN B"01000" => bmax[13..11].d = B"110"; WHEN B"10000" => bmax[13..11].d = B"111"; WHEN OTHERS => bmax[13..11].d = B"000"; END CASE; bmax[].clk = clock; bmax[].clrn = !init; bodd.d = (aastream1 # aastream3 # aastream5 # aastream7 # aastream9 ) & !ahit.q[15]; bodd.clk = clock; bodd.clrn = !init; % stage c: latch barrel/layer result; tally done (and multi-done) streams % csub.dataa[13..11] = bmax[13..11].q; csub.dataa[10..0] = GND; csub.datab[] = bhit.q[13..0]; IF (bodd.q) THEN chit.data[13..0] = csub.result[]; ELSE chit.data[13..0] = bhit.q[13..0]; END IF; chit.data[15..14] = bhit.q[15..14]; chit.clock = clock; chit.aclr = init; cstream.clock = clock; cstream.aclr = init; cstream.data[] = bstream.q[]; cstreamend.clock = clock; cstreamend.aclr = init; cdupstream.clock = clock; cdupstream.aclr = init; IF (bhit.q[15] & bvalid.q[0] & !lastendevent) THEN % this is an end-of-stream word; last word in pipeline was not EE % cdupstream.data[] = bstream.q[9..0] & cstreamend.q[]; cstreamenddata[] = bstream.q[9..0] # cstreamend.q[] # streamdisable[9..0]; END IF; IF (bhit.q[15] & bvalid.q[0] & lastendevent) THEN % this is an EOS word; last word in pipeline was EE % cdupstream.data[] = bstream.q[9..0] & streamdisable[9..0]; cstreamenddata[] = bstream.q[9..0] # streamdisable[9..0]; END IF; IF (!(bhit.q[15] & bvalid.q[0]) & !lastendevent) THEN % this is not an EOS word; last word in pipeline was not EE % cdupstream.data[] = cdupstream.q[]; cstreamenddata[] = cstreamend.q[] # streamdisable[9..0]; END IF; IF (!(bhit.q[15] & bvalid.q[0]) & lastendevent) THEN % this is not an EOS word; last word in pipeline was EE % cdupstream.data[] = GND; cstreamenddata[] = streamdisable[9..0]; END IF; cstreamend.data[] = cstreamenddata[]; thisendevent = (cstreamenddata[]==H"3FF"); lastendevent = (cstreamend.q[9..0]==H"3FF"); cendevent.data[] = thisendevent; cendevent.clock = clock; cendevent.aclr = init; cbunch.clock = clock; IF (bhit.q[15] & bvalid.q[0]) THEN cbunch.data[] = bhit.q[7..0]; ELSE cbunch.data[] = cbunch.q[]; END IF; cbunch.aclr = init; if cendevent.q[0] then if bvalid.q[0] & bhit.q[15] & (bhit.q[7..6]!=3) then cbestbunch[].d = bhit.q[7..0]; else cbestbunch[].d = H"FF"; end if; else if bvalid.q[0] & bhit.q[15] & (bhit.q[7..6]!=3) & (cbestbunch[7..6].q==3) then cbestbunch[].d = bhit.q[7..0]; else cbestbunch[].d = cbestbunch[].q; end if; end if; cbestbunch[].prn = !init; cbestbunch[].clk = clock; cvalid.clock = clock; cvalid.data[]= bvalid.q[]; cvalid.aclr = init; cbarrellayer.clock = clock; cbarrellayer.data[] = barrellayerram.q[]; cbarrellayer.aclr = init; cfirststream.clock = clock; cfirststream.sset = cendevent.q[0]; cfirststream.aset = init; IF (chit.q[15] & cvalid.q[0]) THEN cfirststream.data[] = GND; ELSE cfirststream.data[] = cfirststream.q[]; END IF; % stage e % ebestbunch[].d = cbestbunch[].q; ebestbunch[].clk = clock; elostsync.clock = clock; elostsync.aclr = endeventreset; if eendevent.q[] then elostsync.data[] = (elostsync.q[] & !(endeventclr[9..0])) # cdupstream.q[]; else if cfirststream.q[] then elostsync.data[] = cdupstream.q[] # elostsync.q[]; else if (cbunch.q[]==cbestbunch[].q) # (cbestbunch[7..6].q==3) # (cbunch.q[7..6]==3) then elostsync.data[] = cdupstream.q[] # elostsync.q[]; else elostsync.data[] = cstream.q[] # cdupstream.q[] # elostsync.q[]; end if; end if; end if; lostsyncerror[] = elostsync.q[]; efifooverflow.clock = clock; efifooverflow.aclr = endeventreset; IF (!eendevent.q[0]) THEN efifooverflow.data[] = fifofull[] # efifooverflow.q[]; ELSE efifooverflow.data[] = fifofull[] # (efifooverflow.q[] & !(endeventclr[19..10])); END IF; fifooverflowerror[] = efifooverflow.q[]; einvaliddata.clock = clock; einvaliddata.aclr = endeventreset; IF (chit.q[15] & cvalid.q[0] & chit.q[12] & !eendevent.q[0]) THEN einvaliddata.data[] = cstream.q[] # einvaliddata.q[]; END IF; IF (chit.q[15] & cvalid.q[0] & chit.q[12] & eendevent.q[0]) THEN einvaliddata.data[] = cstream.q[] # (einvaliddata.q[] & !(endeventclr[29..20])); END IF; IF (!(chit.q[15] & cvalid.q[0] & chit.q[12]) & !eendevent.q[0]) THEN einvaliddata.data[] = einvaliddata.q[]; END IF; IF (!(chit.q[15] & cvalid.q[0] & chit.q[12]) & eendevent.q[0]) THEN einvaliddata.data[] = (einvaliddata.q[] & !(endeventclr[29..20])); END IF; invaliddataerror[] = einvaliddata.q[]; etruncateddata.clock = clock; etruncateddata.aclr = endeventreset; IF (chit.q[15] & cvalid.q[0] & chit.q[14] & !eendevent.q[0]) THEN etruncateddata.data[] = cstream.q[] # etruncateddata.q[]; END IF; IF (chit.q[15] & cvalid.q[0] & chit.q[14] & eendevent.q[0]) THEN etruncateddata.data[] = cstream.q[] # (etruncateddata.q[] & !(endeventclr[39..30])); END IF; IF (!(chit.q[15] & cvalid.q[0] & chit.q[14]) & !eendevent.q[0]) THEN etruncateddata.data[] = etruncateddata.q[]; END IF; IF (!(chit.q[15] & cvalid.q[0] & chit.q[14]) & eendevent.q[0]) THEN etruncateddata.data[] = (etruncateddata.q[] & !(endeventclr[39..30])); END IF; truncateddataerror[] = etruncateddata.q[]; elostlock.clock = clock; elostlock.aclr = endeventreset; IF (!eendevent.q[0]) THEN elostlock.data[] = lostlock[] # elostlock.q[]; ELSE elostlock.data[] = lostlock[] # (elostlock.q[] & !(endeventclr[43..40])); END IF; lostlockerror[] = elostlock.q[]; eendevent.clock = clock; eendevent.data[] = cendevent.q[]; eendevent.aclr = init; eparity.clock = clock; eparity.aclr = init; IF (!chit.q[15] & cvalid.q[0] & !eendevent.q[0]) THEN eparity.data[] = eparity.q[] $ (chit.q[0] $ chit.q[1]) $ (chit.q[2] $ chit.q[3]) $ (chit.q[4] $ chit.q[5]) $ (chit.q[6] $ chit.q[7]) $ (chit.q[8] $ chit.q[9]) $ (chit.q[10] $ chit.q[11]) $ (chit.q[12] $ chit.q[13]) $ (chit.q[14] $ cbarrellayer.q[0]) $ (cbarrellayer.q[1] $ cbarrellayer.q[2]) $ (cbarrellayer.q[3] $ cbarrellayer.q[4]) $ (cbarrellayer.q[5] $ ep); END IF; IF (!chit.q[15] & cvalid.q[0] & eendevent.q[0]) THEN eparity.data[] = (chit.q[0] $ chit.q[1]) $ (chit.q[2] $ chit.q[3]) $ (chit.q[4] $ chit.q[5]) $ (chit.q[6] $ chit.q[7]) $ (chit.q[8] $ chit.q[9]) $ (chit.q[10] $ chit.q[11]) $ (chit.q[12] $ chit.q[13]) $ (chit.q[14] $ cbarrellayer.q[0]) $ (cbarrellayer.q[1] $ cbarrellayer.q[2]) $ (cbarrellayer.q[3] $ cbarrellayer.q[4]) $ (cbarrellayer.q[5] $ ep); END IF; IF ( !(!chit.q[15] & cvalid.q[0]) & !eendevent.q[0]) THEN eparity.data[] = eparity.q[]; END IF; IF ( !(!chit.q[15] & cvalid.q[0]) & eendevent.q[0]) THEN eparity.data[] = GND; END IF; evalid.clock = clock; evalid.data[] = (!chit.q[15] & cvalid.q[0]) # cendevent.q[0]; evalid.aclr = init; ehit.data[] = chit.q[]; ehit.clock = clock; ehit.aclr = init; ebarrellayer.clock = clock; ebarrellayer.data[] = cbarrellayer.q[]; ebarrellayer.aclr = init; % stage f % fspareerror = GND; finternaloverflowerror = GND; flostlockerror = (elostlock.q[0] & !endeventmask[40]) # (elostlock.q[1] & !endeventmask[41]) # (elostlock.q[2] & !endeventmask[42]) # (elostlock.q[3] & !endeventmask[43]); ftruncateddataerror = (etruncateddata.q[0] & !endeventmask[30]) # (etruncateddata.q[1] & !endeventmask[31]) # (etruncateddata.q[2] & !endeventmask[32]) # (etruncateddata.q[3] & !endeventmask[33]) # (etruncateddata.q[4] & !endeventmask[34]) # (etruncateddata.q[5] & !endeventmask[35]) # (etruncateddata.q[6] & !endeventmask[36]) # (etruncateddata.q[7] & !endeventmask[37]) # (etruncateddata.q[8] & !endeventmask[38]) # (etruncateddata.q[9] & !endeventmask[39]); finvaliddataerror = (einvaliddata.q[0] & !endeventmask[20]) # (einvaliddata.q[1] & !endeventmask[21]) # (einvaliddata.q[2] & !endeventmask[22]) # (einvaliddata.q[3] & !endeventmask[23]) # (einvaliddata.q[4] & !endeventmask[24]) # (einvaliddata.q[5] & !endeventmask[25]) # (einvaliddata.q[6] & !endeventmask[26]) # (einvaliddata.q[7] & !endeventmask[27]) # (einvaliddata.q[8] & !endeventmask[28]) # (einvaliddata.q[9] & !endeventmask[29]); ffifooverflowerror = (efifooverflow.q[0] & !endeventmask[10]) # (efifooverflow.q[1] & !endeventmask[11]) # (efifooverflow.q[2] & !endeventmask[12]) # (efifooverflow.q[3] & !endeventmask[13]) # (efifooverflow.q[4] & !endeventmask[14]) # (efifooverflow.q[5] & !endeventmask[15]) # (efifooverflow.q[6] & !endeventmask[16]) # (efifooverflow.q[7] & !endeventmask[17]) # (efifooverflow.q[8] & !endeventmask[18]) # (efifooverflow.q[9] & !endeventmask[19]); flostsyncerror = (elostsync.q[0] & !endeventmask[0]) # (elostsync.q[1] & !endeventmask[1]) # (elostsync.q[2] & !endeventmask[2]) # (elostsync.q[3] & !endeventmask[3]) # (elostsync.q[4] & !endeventmask[4]) # (elostsync.q[5] & !endeventmask[5]) # (elostsync.q[6] & !endeventmask[6]) # (elostsync.q[7] & !endeventmask[7]) # (elostsync.q[8] & !endeventmask[8]) # (elostsync.q[9] & !endeventmask[9]); fparityerror = GND; fparity = eparity.q[0]; fendeventword.clock = clock; fendeventword.aclr = init; -- fendeventword.q[15] used to be sticky; -- unstick it for now (wja 1999-07-13) because -- I suspect a glitch on lost-lock input line IF (eendevent.q[0] & (1 # !fendeventword.q[15])) THEN fendeventword.data[20..17] = GND; fendeventword.data[16] = fspareerror; fendeventword.data[15] = flostlockerror; fendeventword.data[14] = ftruncateddataerror; fendeventword.data[13] = finternaloverflowerror; fendeventword.data[12] = finvaliddataerror; fendeventword.data[11] = ffifooverflowerror; fendeventword.data[10] = flostsyncerror; fendeventword.data[9] = fparityerror; fendeventword.data[8] = fparity; fendeventword.data[7..0] = ebestbunch[].q; ELSE fendeventword.data[] = fendeventword.q[]; END IF; fendevent.clock = clock; fendevent.data[] = eendevent.q[]; fendevent.aclr = init; fvalid.clock = clock; fvalid.data[] = evalid.q[]; fvalid.aclr = init; fhit.clock = clock; fhit.data[] = ehit.q[]; fhit.aclr = init; fbarrellayer.clock = clock; fbarrellayer.data[] = ebarrellayer.q[]; fbarrellayer.aclr = init; % stage g % gendevent.clock = clock; gendevent.data[] = fendevent.q[] # fendeventword.q[15]; gendevent.aclr = init; gvalid.clock = !clock; gvalid.data[] = fvalid.q[] # fendeventword.q[15]; gvalid.aclr = init; % multiplex end-of-event word with hits to produce final output to FRONT PANEL % eehitmux.data[0][14..0] = fhit.q[14..0]; eehitmux.data[0][20..15] = fbarrellayer.q[]; eehitmux.data[1][20..0] = fendeventword.q[]; eehitmux.sel[] = fendevent.q[] # fendeventword.q[15]; gd.clock = clock; gd.data[] = eehitmux.result[]; gd.aclr = init; % output stage % ds = clock; ee = gendevent.q[]; d[] = gd.q[]; ep = VCC; validout = gvalid.q[]; END;