TITLE "Decode SVX data stream for HITMAN processing"; include "lpm_ram_dq.inc"; include "lpm_ff.inc"; include "lpm_counter.inc"; SUBDESIGN svxdecode ( grterror : INPUT; disable : INPUT; validin : INPUT; init : INPUT; timeout : INPUT; clock : INPUT; channel[7..0] : INPUT; chipid[7..0][4..0] : INPUT; toomanyclust : INPUT; nchipexpect[3..0] : INPUT; chip[2..0] : OUTPUT; validout : OUTPUT; endeventword[14..0] : OUTPUT; endevent : OUTPUT; endeventstate : OUTPUT; idlestate : OUTPUT; headerstate : OUTPUT; runningstate : output; ) VARIABLE endeventreg :lpm_ff WITH (LPM_WIDTH=1); endeventstatereg :lpm_ff WITH (LPM_WIDTH=1); endeventwordreg :lpm_ff WITH (LPM_WIDTH=15); chipreg :lpm_ff WITH (LPM_WIDTH=4); validoutreg :lpm_ff WITH (LPM_WIDTH=1); count :lpm_ff WITH (LPM_WIDTH=5); checkchip :lpm_ff WITH (LPM_WIDTH=4); wrongchip,wrongstrip :lpm_ff WITH (LPM_WIDTH=1); previousstrip :lpm_ff WITH (LPM_WIDTH=10); notfirst : lpm_ff WITH (LPM_WIDTH=1); currentstrip[9..0] :NODE; control : MACHINE WITH STATES (wait,ready,header,rundata,enddata,disabled); BEGIN % all together now... % control.clk = clock; notfirst.clock = clock; chipreg.clock = clock; checkchip.clock = clock; wrongchip.clock = clock; previousstrip.clock = clock; wrongstrip.clock = clock; endeventwordreg.clock = clock; endeventreg.clock = !clock; endeventstatereg.clock = clock; count.clock = clock; validoutreg.clock = clock; control.reset = init; notfirst.aclr = init; chipreg.aset = init; checkchip.aset = init; wrongchip.aclr = init; previousstrip.aclr = init; wrongstrip.aclr = init; endeventwordreg.aclr = init; endeventreg.aclr = init; endeventstatereg.aclr = init; count.aclr = init; validoutreg.aclr = init; % a state machine description % CASE control IS % ready state: clear out registers and wait for data validin to come up% WHEN ready => idlestate = GND; headerstate = GND; count.data[] = GND; endeventreg.data[] = GND; endeventstatereg.data[] = GND; endeventwordreg.data[] = GND; chipreg.data[] = B"1111"; validoutreg.data[] = GND; checkchip.data[] = B"1111"; previousstrip.data[] = B"0000000000"; notfirst.data[] = GND; wrongchip.data[] = GND; IF (validin & !init & !disable) THEN control = header; END IF; IF (init & !disable) THEN control = wait; END IF; IF disable THEN control = disabled; END IF; % header state: latch in the bunch counter number from the SVX DAQ header word% WHEN header => idlestate = GND; headerstate = VCC; chipreg.data[] = B"1111"; validoutreg.data[] = GND; checkchip.data[] = B"1111"; previousstrip.data[] = B"0000000000"; notfirst.data[] = GND; wrongchip.data[] = GND; endeventreg.data[] = GND; endeventstatereg.data[] = GND; IF (validin & !init & !disable) THEN control = rundata; endeventwordreg.data[7..0] = channel[7..0]; END IF; IF (init & !disable) THEN control = wait; END IF; IF disable THEN control = disabled; END IF; % rundata state: (analyze SVX data stream.) look for chip ID words; exit when 1st z chip ID word arrives% WHEN rundata => runningstate = VCC; idlestate = GND; headerstate = GND; currentstrip[9..7] = chipreg.q[2..0]; currentstrip[6..0] = channel[6..0]; count.data[] = GND; endeventreg.data[] = GND; endeventstatereg.data[] = GND; wrongchip.data[] = wrongchip.q[] # (chipreg.q[] != checkchip.q[]); IF ((channel[] == B"100xxxxx") & validin & !grterror & !init & !disable) THEN IF (channel[4..0] == chipid[0][4..0]) THEN checkchip.data[] = 0; END IF; IF (channel[4..0] == chipid[1][4..0]) THEN checkchip.data[] = 1; END IF; IF (channel[4..0] == chipid[2][4..0]) THEN checkchip.data[] = 2; END IF; IF (channel[4..0] == chipid[3][4..0]) THEN checkchip.data[] = 3; END IF; IF (channel[4..0] == chipid[4][4..0]) THEN checkchip.data[] = 4; END IF; IF (channel[4..0] == chipid[5][4..0]) THEN checkchip.data[] = 5; END IF; IF (channel[4..0] == chipid[6][4..0]) THEN checkchip.data[] = 6; END IF; IF (channel[4..0] == chipid[7][4..0]) THEN checkchip.data[] = 7; END IF; IF (channel[4..0] != chipid[0][4..0]) & (channel[4..0] != chipid[1][4..0]) & (channel[4..0] != chipid[2][4..0]) & (channel[4..0] != chipid[3][4..0]) & (channel[4..0] != chipid[4][4..0]) & (channel[4..0] != chipid[5][4..0]) & (channel[4..0] != chipid[6][4..0]) & (channel[4..0] != chipid[7][4..0]) THEN checkchip.data[] = 15; END IF; validoutreg.data[] = GND; chipreg.data[] = chipreg.q[] + 1; endeventwordreg.data[] = endeventwordreg.q[]; previousstrip.data[] = previousstrip.q[]; notfirst.data[] = notfirst.q[]; wrongstrip.data[] = wrongstrip.q[]; END IF; IF ((channel[] == B"101xxxxx") & validin & !grterror & !init & !disable) THEN validoutreg.data[] = GND; chipreg.data[] = chipreg.q[]; checkchip.data[] = checkchip.q[]; previousstrip.data[] = previousstrip.q[]; notfirst.data[] = notfirst.q[]; wrongstrip.data[] = wrongstrip.q[]; endeventwordreg.data[] = endeventwordreg.q[]; control = enddata; END IF; IF ((channel[] == B"0xxxxxxx") & validin & !grterror & !init & !disable) THEN previousstrip.data[] = currentstrip[]; notfirst.data[] = VCC; wrongstrip.data[] = wrongstrip.q[] # ((currentstrip[] <= previousstrip.q[]) & (notfirst.q[])); validoutreg.data[] = (chipreg.q[] != 15); wrongchip.data[] = wrongchip.q[] # (chipreg.q[]==15); chipreg.data[] = chipreg.q[]; checkchip.data[] = checkchip.q[]; endeventwordreg.data[] = endeventwordreg.q[]; END IF; IF ((channel[] == B"1100xxxx") & validin & !grterror & !init & !disable) THEN -- end-of-data C-word 0xC*** checkchip.data[] = checkchip.q[]; validoutreg.data[] = GND; chipreg.data[] = chipreg.q[]; endeventwordreg.data[] = endeventwordreg.q[]; previousstrip.data[] = previousstrip.q[]; notfirst.data[] = notfirst.q[]; wrongstrip.data[] = wrongstrip.q[]; control = enddata; END IF; IF ((channel[] == B"1101xxxx") & validin & !grterror & !init & !disable) THEN -- no-op D-word 0xD*** checkchip.data[] = checkchip.q[]; validoutreg.data[] = GND; chipreg.data[] = chipreg.q[]; endeventwordreg.data[] = endeventwordreg.q[]; previousstrip.data[] = previousstrip.q[]; notfirst.data[] = notfirst.q[]; wrongstrip.data[] = wrongstrip.q[]; END IF; IF ((channel[] == B"111xxxxx") & validin & !grterror & !init & !disable) THEN -- invalid pattern 0xE*** or 0xF*** checkchip.data[] = checkchip.q[]; validoutreg.data[] = GND; chipreg.data[] = chipreg.q[]; endeventwordreg.data[] = endeventwordreg.q[] # H"1100"; previousstrip.data[] = previousstrip.q[]; notfirst.data[] = notfirst.q[]; wrongstrip.data[] = wrongstrip.q[]; control = enddata; END IF; IF (timeout & validin & !init & !disable) THEN validoutreg.data[] = GND; chipreg.data[] = chipreg.q[]; checkchip.data[] = checkchip.q[]; previousstrip.data[] = previousstrip.q[]; notfirst.data[] = notfirst.q[]; wrongstrip.data[] = wrongstrip.q[]; endeventwordreg.data[] = endeventwordreg.q[] # H"1100"; control = enddata; END IF; IF (!validin & !grterror & !init & !disable) THEN validoutreg.data[] = GND; control = enddata; endeventwordreg.data[] = endeventwordreg.q[]; END IF; IF (grterror & !init & !disable) THEN validoutreg.data[] = GND; control = enddata; endeventwordreg.data[] = endeventwordreg.q[] # H"1400"; END IF; IF (init & !disable) THEN validoutreg.data[] = GND; control = wait; END IF; IF (disable) THEN validoutreg.data[] = GND; control = disabled; END IF; % enddata state : pump the clock a fixed number of times, then insert the end of event word % WHEN enddata => idlestate = GND; headerstate = GND; validoutreg.data[] = GND; wrongchip.data[] = wrongchip.q[]; wrongstrip.data[] = wrongstrip.q[]; chipreg.data[] = chipreg.q[]; count.data[] = count.q[] + 1; endeventwordreg.data[] = endeventwordreg.q[] # (H"4000" & toomanyclust) # (H"3000" & wrongstrip.q[]) # (H"1000" & wrongchip.q[]) # (H"1800" & (chipreg.q[]!=nchipexpect[])); endeventreg.data[] = (count.q[] == 9); % flush aim pipeline with endeventstate off, then flush % % fire pipeline with endeventstate on (wja 1998-09-14); % endeventstatereg.data[] = ((count.q[] < 9) & (count.q[] > 1)); IF ((count.q[] == 9) & !init & !disable) THEN control = wait; END IF; IF (init & !disable) THEN control = wait; END IF; IF disable THEN control = disabled; END IF; % wait state: waiting for data validin to go down % WHEN wait => idlestate = VCC; headerstate = GND; validoutreg.data[] = GND; count.data[] = GND; endeventreg.data[] = GND; endeventstatereg.data[] = GND; IF (!validin & !init & !disable) THEN control = ready; END IF; IF disable THEN control = disabled; END IF; % disabled state : DAD data is ignored % WHEN disabled => idlestate = VCC; headerstate = GND; endeventreg.data[] = GND; endeventstatereg.data[] = GND; validoutreg.data[] = GND; IF !disable THEN control = wait; END IF; END CASE; % outputs % endevent = endeventreg.q[]; endeventword[] = endeventwordreg.q[]; endeventstate = endeventstatereg.q[]; chip[] = chipreg.q[2..0]; validout = validoutreg.q[]; END;