TITLE "Boot Chip"; -- -- boot.tdf -- CDF SVT Hit Finder board: Boot chip -- University of Chicago 1999 -- coded by Jeff Berryhill and Bill Ashmanskas -- include "lpm_mux.inc"; include "lpm_counter.inc"; include "lpm_ff.inc"; include "lpm_compare.inc"; include "lpm_shiftreg.inc"; -- -- Prototypes for other Boot chip components -- FUNCTION bootvmedecoder( address[24..0], hfwrite, addressstrobe, bootmode, hfload, hffreeze, vmeintdswrite) RETURNS ( vmeframread, vmeframwrite, vmebookframaddressread, vmebookframaddresswrite, vmehfbusread, vmehfbuswrite, vmetestclockwrite, vmehfinitwrite, vmebrainread, vmebrainwrite, vmeidtextread, vmetimeread, vmeeventctrread, vmeeventctrreset, vmelastaddrread); FUNCTION hfcontrollogic(vmeds,vmewrite,hfload,hffreeze,hfinit, bootmode,boothfenable,bootclock,dsdelayout[9..0]) RETURNS (hfds[2..0],hfwrite,vmeack,dsdelayin); FUNCTION vme_interface( Address[31..2], _GA[4..0], _LWORD, _vme_write, AM[5..0], _AS, _IACK, _DS[1..0], _ACK, _vme_err, _delayed_modsel, _delayed_DS) RETURNS ( _DTACK, _BERR, _MODSEL, _vme_data_str, vme_write, dir_trans, vme_address[26..2], GA[4..0]); SUBDESIGN boot ( -- vme interface Address[31..2] : INPUT; -- VME address from P1/2 _GA[4..0] : INPUT; -- geographical address (slot) _LWORD : INPUT; -- _vme_write : INPUT; -- read/write* flag AM[5..0] : INPUT; -- address modifier _AS : INPUT; -- address strobe _IACK : INPUT; -- _DS[1..0] : INPUT; -- data strobes _delayed_modsel : INPUT; -- from 10 ns delay line _delayed_DS : INPUT; -- from 10 ns delay line dir_trans : OUTPUT; -- switches ABTE direction _MODSEL : OUTPUT; -- master is talking to us (to delay) _vme_data_str : OUTPUT; -- to 10 ns delay line _DTACK : BIDIR; -- O/C ack from us to master _BERR : BIDIR; -- O/C bus error (not used by HF) vmedata[31..0] : BIDIR; -- VME data from/to P1/2 -- tapped delay line interface dsdelayin : OUTPUT; -- to tapped delay line dsdelayout[9..0] : INPUT; -- 10 taps, 40 ns per tap -- SVT_INIT delay line interface INIT_DELIN : OUTPUT; -- 50 ns delay for glitch INIT_DELOUT : INPUT; -- protection on SVT_INIT_ -- hit finder board internal "VME" bus HF_VME_Addr[24..0] : OUTPUT; -- address bits 26..2 HF_VME_Data[31..0] : BIDIR; -- data HF_VME_AS : OUTPUT; -- latches in address HF_VME_DS : OUTPUT; -- clocks data HF_VME_Write : OUTPUT; -- write/read* by boot chip HF_VME_Spare : OUTPUT; -- unused -- flash RAM interface framaddress[20..0] : OUTPUT; -- address framdata[15..0] : BIDIR; -- data framoe_ : OUTPUT; -- output enable* framwe_ : OUTPUT; -- write enable* framce_ : OUTPUT; -- chip enable* framrp_ : OUTPUT; -- power-on reset* framvpen : BIDIR; -- program enable (O/C + pullup) framsts : INPUT; -- status -- FLEX configuration pins (to program MOP+10*HitMan+2*DAD) nCONFIG : OUTPUT; -- prepare* to be configured CONF_DONE : INPUT; -- OK, chips are configured nSTATUS : INPUT; -- OK, chips acknowledge* nCONFIG DATA0 : OUTPUT; -- serial data path VALID : OUTPUT; -- gates DCLK DCLK : OUTPUT; -- clocks out serial config data -- backup FLEX config pins (by-pass boot algorithm with download cable) nCONFIG_bkup : INPUT; -- gets muxed to nCONFIG CONF_DONE_bkup : OUTPUT; -- reflects CONF_DONE nSTATUS_bkup : OUTPUT; -- reflects nSTATUS DATA0_bkup : INPUT; -- gets muxed to DATA0 DCLK_bkup : INPUT; -- gets muxed to DCLK (with VALID=1) -- 30 MHz oscillator input HF_Clock : INPUT; -- 30 MHz on-board oscillator -- P2 signals SVT_INIT_ : INPUT; -- from spy control SVT_ERROR_ : OUTPUT; -- to spy control (wired OR) SVT_FREEZE_ : INPUT; -- from spy control SVT_LostLock_ : OUTPUT; -- to spy control (wired OR) SVT_SPARE_ : INPUT; -- from spy control (undefined) CDF_ERROR_ : OUTPUT; -- to tracer (wired OR) -- HF_Ctrl bus (misc signals that fan out all over the board) VTM_Reset : OUTPUT; -- supposedly resets* VTM VTM_Serial : BIDIR; -- can talk to VTM UART MOP_Spare4 : OUTPUT; -- spare line to MOP MOP_Spare3 : OUTPUT; -- spare line to MOP MOP_Spare2 : OUTPUT; -- spare line to MOP MOP_Spare1 : OUTPUT; -- spare line to MOP MOP_Spare0 : OUTPUT; -- spare line to MOP (16 Hz clock) Merger_Spare : INPUT; -- FIFOs-not-empty signal from Merger HM9_Spare : INPUT; -- spare line from HitMan #9 HM8_Spare : INPUT; -- spare line from HitMan #3 (sic) HM7_Spare : INPUT; -- spare line from HitMan #7 HM6_Spare : INPUT; -- spare line from HitMan #1 (sic) HM5_Spare : INPUT; -- spare line from HitMan #5 HM4_Spare : INPUT; -- spare line from HitMan #4 HM3_Spare : INPUT; -- spare line from HitMan #8 (sic) HM2_Spare : INPUT; -- spare line from HitMan #2 HM1_Spare : INPUT; -- spare line from HitMan #6 (sic) HM0_Spare : INPUT; -- spare line from HitMan #0 DAD1_Spare : OUTPUT; -- spare line to DAD #1 (stops clock) DAD0_Spare : OUTPUT; -- spare line to DAD #0 (stops clock) MOP_TestClock : OUTPUT; -- clocks MOP in OSPY test mode Merger_Clock : OUTPUT; -- clocks Merger (which clocks MOP) HM9_TestClock : OUTPUT; -- clocks HM9 in ISPY test mode HM8_TestClock : OUTPUT; -- clocks HM3 in ISPY test mode HM7_TestClock : OUTPUT; -- clocks HM7 in ISPY test mode HM6_TestClock : OUTPUT; -- clocks HM1 in ISPY test mode HM5_TestClock : OUTPUT; -- clocks HM5 in ISPY test mode HM4_TestClock : OUTPUT; -- clocks HM4 in ISPY test mode HM3_TestClock : OUTPUT; -- clocks HM8 in ISPY test mode HM2_TestClock : OUTPUT; -- clocks HM2 in ISPY test mode HM1_TestClock : OUTPUT; -- clocks HM6 in ISPY test mode HM0_TestClock : OUTPUT; -- clocks HM0 in ISPY test mode HF_LostLock : INPUT; -- if MOP wants us to pull P2 LLock* HF_SVTerror : INPUT; -- if MOP wants us to pull P2 SVT_Err* HF_CDFerror : INPUT; -- if MOP wants us to pull P2 CDF_Err* HF_Test2 : OUTPUT; -- Merger "deterministic" test mode HF_Test1 : OUTPUT; -- MOP OSPY-driven test mode HF_Test0 : OUTPUT; -- HitMan ISPY-driven test mode HF_Spare : OUTPUT; -- was spare; now freeze OSPY HF_Init : OUTPUT; -- active-high reset HF_Freeze : OUTPUT; -- active-high freeze (now just HM) HF_Load : OUTPUT; -- allows VME access; stops data -- Lights Test_LED : OUTPUT; -- green: test mode Load_LED : OUTPUT; -- yellow: load mode (flash=llock/bkup) Boot_LED : OUTPUT; -- red: boot mode (flash=conf not done) Error_LED : OUTPUT; -- red: CDF error asserted IntError_LED : OUTPUT; -- yellow: SVT error asserted Run_LED : OUTPUT; -- green: run mode Ack_LED : OUTPUT; -- yellow: VME DTACK* asserted ) VARIABLE node_CDFerror : NODE; -- do I pull CDF error? node_SVTerror : NODE; -- do I pull SVT error? node_LostLock : NODE; -- do I pull LostLock? force_CDFerror : DFFE; -- VME force CDF error force_SVTerror : DFFE; -- VME force SVT error force_LostLock : DFFE; -- VME force LostLock lastaddr[31..0] : DFFE; -- last VME addr strobed (not this slot) vmega[4..0] : NODE; -- from VME int subdesign vmeaddress[24..0] : NODE; -- from VME int subdesign vmeds : NODE; -- from VME int subdesign vmewrite : NODE; -- from VME int subdesign vmeack : NODE; -- returned to VME int subdesign brain[8..0] : DFFE; -- master board state register vtmresetff : DFFE; -- drives VTM reset signal freezeignore : DFFE; -- override P2 freeze? svtfreeze : NODE; -- P2 freeze after possible veto bkupconfig : NODE; -- brain bit: muxes flex chain brainfreeze : NODE; -- brain bit: vme freeze whichtestclock[1..0] : NODE; -- brain bits: 30/15/7.5/vme MHz test[2..0] : NODE; -- brain bits: test modes runmode[1..0] : NODE; -- brain bits: boot/test/run/load testclock : NODE; -- possibily divided clock bootclock : NODE; -- 1 MHz clock for boot process hfds[2..0] : NODE; -- HF AS/DS/spare for VME and boot I/O hfwrite : NODE; -- drives HF bus write-enable halfclock : DFFE; -- HF clock /2 qtrclock : DFFE; -- HF clock /4 eighthclock : DFFE; -- HF clock /8 sixteenthclock : DFFE; -- HF clock /16 thirty2ndclock : DFFE; -- HF clock /32 -- counts DAV transitions on Stream 0 eventctr : lpm_counter WITH (LPM_WIDTH=32); time[9..0] : lpm_counter WITH (LPM_WIDTH=32); -- instantiate subdesigns vmeint : vme_interface; bootvmedecode : bootvmedecoder; hfcontrol : hfcontrollogic; -- parallel to serial converter for configuration data serializer : lpm_shiftreg WITH (LPM_WIDTH=16, LPM_DIRECTION="RIGHT"); -- counter for operating serializer serialcounter : lpm_counter WITH (LPM_WIDTH=4, LPM_DIRECTION="UP"); -- multiplexes vme data with boot data for fram access framaddressmux : lpm_mux WITH (LPM_WIDTH=21, LPM_SIZE=2, LPM_WIDTHS=1); -- multiplexes vmebus with boot data for hfbus access hfbusmux : lpm_mux WITH (LPM_WIDTH=25, LPM_SIZE=2, LPM_WIDTHS=1); -- state machine for configuring and loading chips bootcontrol : MACHINE WITH STATES (standby,start,getbook,getchapter,getpage,finish); -- implements O/C output for FRAM VPEN (pulled up to 5V with resistor) framvpentri : TRI; framvpentrinode : TRI_STATE_NODE; vmevtmserialtri : TRI; brainvmetri[31..0] : TRI; framvmetri[31..0] : TRI; idtextvmetri[31..0] : TRI; vmeframtri[15..0] : TRI; vmehftri[31..0] : TRI; eventctrvmetri[31..0] : TRI; timevmetri[31..0] : TRI; hfvmetri[31..0] : TRI; boothftri[31..0] : TRI; bookframaddressvmetri[31..0] : TRI; lastaddrvmetri[31..0] : TRI; bookframaddress : lpm_ff WITH (LPM_WIDTH=12); dclken : lpm_ff WITH (LPM_WIDTH=1); vtmserialtri : TRI_STATE_NODE; framdatatri[15..0] : TRI_STATE_NODE; vmedatatri[31..0] : TRI_STATE_NODE; hfdatatri[31..0] : TRI_STATE_NODE; vmeframread : NODE; vmeframwrite : NODE; vmebookframaddressread : NODE; vmebookframaddresswrite : NODE; vmehfbusread : NODE; vmehfbuswrite : NODE; vmebrainread : NODE; vmebrainwrite : NODE; vmetestclockwrite : NODE; vmehfinitwrite : NODE; vmeidtextread : NODE; vmetimeread : NODE; vmeeventctrread : NODE; vmeeventctrreset : NODE; vmelastaddrread : NODE; bootmode : NODE; boothfenable : NODE; bootreset : NODE; boothfaddress[24..0] : NODE; bootframaddress[20..0] : NODE; getbookcounter : lpm_counter WITH (LPM_WIDTH=1); tocframaddress : lpm_ff WITH (LPM_WIDTH=16); getchaptercounter :lpm_counter WITH (LPM_WIDTH=3); afirstpageframaddress :lpm_ff WITH (LPM_WIDTH=16); bfirstpageframaddress :lpm_ff WITH (LPM_WIDTH=5); firstpageframaddress[20..0] :NODE; alastpageframaddress :lpm_ff WITH (LPM_WIDTH=16); blastpageframaddress :lpm_ff WITH (LPM_WIDTH=5); lastpageframaddress[20..0] :NODE; afirstpagehfaddress :lpm_ff WITH (LPM_WIDTH=16); bfirstpagehfaddress :lpm_ff WITH (LPM_WIDTH=9); firstpagehfaddress[24..0] :NODE; bootinstructions :lpm_ff WITH (LPM_WIDTH=16); % bits of bootinstructions 0 last chapter in a book 1 hfdata bus is enabled for this chapter 2 DATA0 and DCLK enabled for this chapter; 16 to 1 parallel to serial conversion 3 drive nCONFIG low for this chapter (initiates configuration) 4 suppress DCLK for last 8 bits of chapter (allows odd # bytes) 15 terminate boot (protects against unprogrammed fram) % pageframaddresscounter :lpm_counter WITH (LPM_WIDTH=21); tocframaddresscounter :lpm_counter WITH (LPM_WIDTH=16); pagehfaddresscounter :lpm_counter WITH (LPM_WIDTH=25); boothfdata :lpm_ff WITH (LPM_WIDTH=16); % for one-time power-up actions % powerup,powerup1 : DFFE; poweron,poweron1 : NODE; % for very slow oscillators % slowcounter :lpm_counter WITH (LPM_WIDTH=21, LPM_DIRECTION="DOWN"); oscsec, oschalfsec, oscqtrsec : NODE; davledcnt :lpm_counter WITH (LPM_WIDTH=2); BEGIN -- error signals (for Franco Spinella) force_CDFerror.d = vmedata[20]; force_CDFerror.clk = vmebrainwrite & HF_VME_DS; node_CDFerror = HF_CDFerror # force_CDFerror.q; force_SVTerror.d = vmedata[21]; force_SVTerror.clk = vmebrainwrite & HF_VME_DS; node_SVTerror = HF_SVTerror # force_SVTerror.q; force_LostLock.d = vmedata[22]; force_LostLock.clk = vmebrainwrite & HF_VME_DS; node_LostLock = HF_LostLock # force_LostLock.q; -- last VME address strobed (but not to -- this slot), for Franco Spinella's tests lastaddr[].clk = !_AS; lastaddr[].ena = (Address[31..27] != (!_GA[4..0])); lastaddr[31..2].d = Address[]; lastaddr[1].d = GND; lastaddr[0].d = !_vme_write; lastaddrvmetri[].in = lastaddr[].q; lastaddrvmetri[].oe = vmelastaddrread; vmedatatri[] = lastaddrvmetri[].out; % vme interface % vmeint.Address[31..2] = Address[31..2]; vmeint._GA[4..0] = _GA[4..0]; vmeint._LWORD = _LWORD; vmeint._vme_write = _vme_write; vmeint.AM[5..0] = AM[5..0]; vmeint._AS = _AS; vmeint._IACK = _IACK; vmeint._DS[1..0] = _DS[1..0]; vmeint._ACK = !vmeack; % internal node % vmeint._vme_err = VCC; % internal node % vmeint._delayed_modsel = _delayed_modsel; vmeint._delayed_DS = _delayed_DS; _DTACK = vmeint._DTACK; _BERR = vmeint._BERR; _MODSEL = vmeint._MODSEL; _vme_data_str = vmeint._vme_data_str; vmeds = !_vme_data_str; % internal node % vmewrite = vmeint.vme_write; % internal node % dir_trans = vmeint.dir_trans; vmeaddress[24..0] = vmeint.vme_address[26..2]; % internal node % vmega[4..0] = vmeint.GA[4..0]; % internal node % -- Event counter eventctr.clock = hm0_spare; eventctr.aclr = hf_init # vmeeventctrreset; eventctrvmetri[].in = eventctr.q[]; eventctrvmetri[].oe = vmeeventctrread; vmedatatri[] = eventctrvmetri[].out; time0.cnt_en = hm0_spare; time1.cnt_en = hm1_spare; time2.cnt_en = hm2_spare; time3.cnt_en = hm3_spare; time4.cnt_en = hm4_spare; time5.cnt_en = hm5_spare; time6.cnt_en = hm6_spare; time7.cnt_en = hm7_spare; time8.cnt_en = hm8_spare; time9.cnt_en = hm9_spare; time[].clock = bootclock; time[].aclr = hf_init # vmeeventctrreset; case vmeaddress[3..0] is when 0 => timevmetri[].in = time[0].q[]; when 1 => timevmetri[].in = time[1].q[]; when 2 => timevmetri[].in = time[2].q[]; when 3 => timevmetri[].in = time[3].q[]; when 4 => timevmetri[].in = time[4].q[]; when 5 => timevmetri[].in = time[5].q[]; when 6 => timevmetri[].in = time[6].q[]; when 7 => timevmetri[].in = time[7].q[]; when 8 => timevmetri[].in = time[8].q[]; when 9 => timevmetri[].in = time[9].q[]; end case; timevmetri[].oe = vmetimeread; vmedatatri[] = timevmetri[].out; % Lights % -- in run mode, test LED shows stream 0 DAV davledcnt.clock = slowcounter.q[8]; davledcnt.cnt_en = !hm0_spare & !(davledcnt.eq[3]); davledcnt.aclr = hm0_spare; Test_LED = !((runmode[]==2) # ((runmode[]==1) & !davledcnt.eq[3])); Load_LED = !(runmode[]==0); Boot_LED = !bootmode; IF (!conf_done) THEN Error_LED = oschalfsec; ELSE Error_LED = !node_CDFerror; END IF; IF (bkupconfig) THEN IntError_LED = oschalfsec; ELSIF (node_LostLock) THEN IntError_LED = oscsec; ELSE IntError_LED = !node_SVTerror; END IF; Run_LED = !(runmode[]==1); Ack_LED = !vmeack; % P2 outputs % CDF_ERROR_ = !node_CDFerror; SVT_ERROR_ = !node_SVTerror; SVT_LostLock_ = !node_LostLock; % VTM serial port (not fully implemented yet) % vtmserialtri = vmevtmserialtri; vmevtmserialtri.in = GND; vmevtmserialtri.oe = GND; -- register to hold VTM_Reset state vtmresetff.d = vmedata[18]; vtmresetff.clk = vmebrainwrite & HF_VME_DS; -- register for overriding backplane freeze signal freezeignore.d = vmedata[19]; freezeignore.clk = vmebrainwrite & HF_VME_DS; % HF_Ctrl bus outputs % VTM_Reset = !vtmresetff.q; VTM_Serial = vtmserialtri; MOP_TestClock = testclock; IF (runmode[]==1) THEN Merger_Clock = HF_Clock; ELSE Merger_Clock = testclock; END IF; HM9_TestClock = testclock; HM8_TestClock = testclock; HM7_TestClock = testclock; HM6_TestClock = testclock; HM5_TestClock = testclock; HM4_TestClock = testclock; HM3_TestClock = testclock; HM2_TestClock = testclock; HM1_TestClock = testclock; HM0_TestClock = testclock; HF_Test2 = test[2] & (runmode[]==2); HF_Test1 = test[1] & (runmode[]==2); HF_Test0 = test[0] & (runmode[]==2); HF_Init = (INIT_DELIN & INIT_DELOUT) # vmehfinitwrite; HF_Load = ((runmode[]==0) # boothfenable); -- allow SVT_FREEZE_ to be overridden svtfreeze = !SVT_FREEZE_ & !freezeignore.q; -- This freeze line now controls only the ISPY and -- is suppressed when ISPY is the data source HF_Freeze = ((svtfreeze # brainfreeze) & !HF_Test0) # (Merger_Spare & HF_Test0); -- This spare line is now the OSPY freeze and -- is suppressed when OSPY is the data source HF_Spare = (svtfreeze # brainfreeze) & !HF_Test1; % SVT_INIT glitch suppression % INIT_DELIN = !SVT_INIT_; % Clock generation % % 15 MHz % halfclock.d = !halfclock.q; halfclock.clk = HF_Clock; halfclock.ena = VCC; halfclock.clrn = !(vmetestclockwrite & HF_VME_DS); % 7.5 MHz % qtrclock.d = !qtrclock.q; qtrclock.clk = halfclock.q; qtrclock.ena = VCC; qtrclock.clrn = !(vmetestclockwrite & HF_VME_DS); % 3.75 MHz % eighthclock.d = !eighthclock.q; eighthclock.clk = qtrclock.q; eighthclock.ena = VCC; eighthclock.clrn = !(vmetestclockwrite & HF_VME_DS); % 1.875 MHz % sixteenthclock.d = !sixteenthclock.q; sixteenthclock.clk = eighthclock.q; sixteenthclock.ena = VCC; sixteenthclock.clrn = !(vmetestclockwrite & HF_VME_DS); % 0.9375 MHz % thirty2ndclock.d = !thirty2ndclock.q; thirty2ndclock.clk = sixteenthclock.q; thirty2ndclock.ena = VCC; thirty2ndclock.clrn = !(vmetestclockwrite & HF_VME_DS); % Select test clock (30, 15, 7.5, VME) % if ( whichtestclock[] == 0 ) then testclock = vmetestclockwrite & HF_VME_DS; end if; if ( whichtestclock[] == 1 ) then testclock = qtrclock.q; % testclock = sixteenthclock.q; % % temporary patch % end if; if ( whichtestclock[] == 2 ) then testclock = halfclock.q; end if; if ( whichtestclock[] == 3) then testclock = HF_Clock; end if; % Boot clock is HF_Clock at 1/32 freq % bootclock = thirty2ndclock.q; poweron = powerup.q; poweron1 = powerup1.q; % Read/write brain state over VME % if (poweron1) then brain[].d = vmedata[8..0]; else brain[].d = 3; end if; brain[].ena = (vmebrainwrite & HF_VME_DS) # !poweron; brain[].clk = HF_Clock; brain[1..0].clrn = (bootcontrol!=finish); brainvmetri[31].in = MOP_Spare0; brainvmetri[30].in = framsts; brainvmetri[29].in = HM9_Spare; brainvmetri[28].in = HM8_Spare; brainvmetri[27].in = HM7_Spare; brainvmetri[26].in = HM6_Spare; brainvmetri[25].in = HM5_Spare; brainvmetri[24].in = !SVT_FREEZE_; brainvmetri[23].in = !SVT_INIT_; brainvmetri[22].in = force_LostLock.q; brainvmetri[21].in = force_SVTerror.q; brainvmetri[20].in = force_CDFerror.q; brainvmetri[19].in = freezeignore.q; brainvmetri[18].in = vtmresetff.q; brainvmetri[17].in = !SVT_SPARE_; brainvmetri[16].in = node_CDFerror; brainvmetri[15].in = node_SVTerror; brainvmetri[14].in = node_LostLock; brainvmetri[13].in = HF_Spare; brainvmetri[12].in = HF_Init; brainvmetri[11].in = HF_Freeze; brainvmetri[10].in = !CONF_DONE; brainvmetri[9].in = !nSTATUS; brainvmetri[8..0].in = brain[].q; brainvmetri[].oe = vmebrainread; vmedatatri[] = brainvmetri[].out; % Dissect the brain % bkupconfig = brain[8].q; brainfreeze = brain[7].q; whichtestclock[] = brain[6..5].q; test[] = brain[4..2].q; runmode[] = brain[1..0].q; % HF_VME_Ctrl bus % HF_VME_Spare = hfds[2]; HF_VME_DS = hfds[1]; % HF_VME_AS = hfds[0] & (hf_load # hf_freeze # boothfenable); % HF_VME_AS = hfds[0] & (vmehfbusread # vmehfbuswrite # boothfenable); HF_VME_Write = hfwrite; % DAD spare lines % DAD0_Spare = HF_Load; DAD1_Spare = HF_Load; % read ID PROM text over VME % idtextvmetri[31..24] = framdata[7..0]; idtextvmetri[23..0] = GND; idtextvmetri[].oe = vmeidtextread; vmedatatri[] = idtextvmetri[]; % tri state buses % vmedata[] = vmedatatri[]; framdata[] = framdatatri[]; HF_VME_Data[] = hfdatatri[]; % control logic for vme transactions % hfcontrol.vmeds = vmeds; hfcontrol.vmewrite = vmewrite; hfcontrol.hfload = HF_Load; hfcontrol.hfinit = HF_Init; hfcontrol.hffreeze = HF_Freeze; hfcontrol.bootclock = bootclock; hfcontrol.bootmode = bootmode; hfcontrol.boothfenable = boothfenable; hfcontrol.dsdelayout[] = dsdelayout[]; vmeack = hfcontrol.vmeack; dsdelayin = hfcontrol.dsdelayin; hfds[] = hfcontrol.hfds[]; hfwrite = hfcontrol.hfwrite; % FRAM interface with vme and boot % framwe_ = !(HF_VME_DS & vmeframwrite); framoe_ = !((HF_VME_DS & (vmeframread # vmeidtextread)) # bootmode); framce_ = GND; framrp_ = !(vmebrainwrite & hf_vme_ds & (vmedata[1..0]==3)); framvpentri.in = GND; framvpentri.oe = GND; framvpentrinode = framvpentri.out; framvpen = framvpentrinode; % multiplex addresses from vme and boot % framaddressmux.data[0][20..0] = bootframaddress[]; framaddressmux.data[1][7..0] = vmeaddress[7..0]; IF (vmeidtextread) THEN framaddressmux.data[1][20..8] = GND; ELSE framaddressmux.data[1][20..8] = vmeaddress[20..8]; END IF; framaddressmux.sel[] = vmeframread # vmeframwrite # vmeidtextread; framaddress[] = framaddressmux.result[20..0]; % enable fram data onto vmebus during vme read % framvmetri[15..0].in = framdata[]; framvmetri[31..16].in = GND; framvmetri[].oe = vmeframread; vmedatatri[31..0] = framvmetri[].out; % enable hf data onto vmebus during vme read % hfvmetri[].in = HF_VME_Data[]; hfvmetri[].oe = !bootmode & vmehfbusread; vmedatatri[] = hfvmetri[].out; % enable vme data onto fram during vmewrite % vmeframtri[].in = vmedata[15..0]; vmeframtri[].oe = vmeframwrite; framdatatri[] = vmeframtri[].out; % multiplex boot and vme address during boot/vme read/write % hfbusmux.data[0][24..0] = vmeaddress[]; hfbusmux.data[1][24..0] = boothfaddress[]; hfbusmux.sel[] = boothfenable; HF_VME_Addr[] = hfbusmux.result[24..0]; % enable boot data onto hfbus during boot write % boothftri[15..0].in = boothfdata.q[]; boothftri[31..16].in = GND; boothftri[].oe = boothfenable; hfdatatri[] = boothftri[].out; % enable vme data onto hfbus during vmewrite % vmehftri[].in = vmedata[]; vmehftri[].oe = vmehfbuswrite; hfdatatri[] = vmehftri[].out; % vme decoder % bootvmedecode.address[] = HF_VME_Addr[]; bootvmedecode.hfwrite = hfwrite; bootvmedecode.addressstrobe = hfds[0]; bootvmedecode.bootmode = bootmode; bootvmedecode.hfload = HF_Load; bootvmedecode.hffreeze = HF_Freeze; bootvmedecode.vmeintdswrite = (!_delayed_DS & !_vme_write); vmeframread = bootvmedecode.vmeframread; vmeframwrite = bootvmedecode.vmeframwrite; vmebookframaddressread = bootvmedecode.vmebookframaddressread; vmebookframaddresswrite = bootvmedecode.vmebookframaddresswrite; vmehfbusread = bootvmedecode.vmehfbusread; vmehfbuswrite = bootvmedecode.vmehfbuswrite; vmebrainread = bootvmedecode.vmebrainread; vmebrainwrite = bootvmedecode.vmebrainwrite; vmetestclockwrite = bootvmedecode.vmetestclockwrite; vmehfinitwrite = bootvmedecode.vmehfinitwrite; vmeidtextread = bootvmedecode.vmeidtextread; vmetimeread = bootvmedecode.vmetimeread; vmeeventctrread = bootvmedecode.vmeeventctrread; vmeeventctrreset = bootvmedecode.vmeeventctrreset; vmelastaddrread = bootvmedecode.vmelastaddrread; % getbook registers % getbookcounter.clock = bootclock; % write to bookframaddress over VME % bookframaddress.clock = HF_VME_DS; bookframaddress.enable = vmebookframaddresswrite; bookframaddress.data[] = vmedata[11..0]; % read bookframaddress over VME % bookframaddressvmetri[11..0].in = bookframaddress.q[]; bookframaddressvmetri[31..12].in = GND; bookframaddressvmetri[].oe = vmebookframaddressread; vmedatatri[] = bookframaddressvmetri[].out; tocframaddress.clock = !bootclock; tocframaddress.data[] = framdata[15..0]; tocframaddress.enable = getbookcounter.eq[0] & (bootcontrol == getbook); % getchapter registers % getchaptercounter.clock = bootclock; tocframaddresscounter.clock = bootclock; tocframaddresscounter.cnt_en = (bootcontrol == getchapter); tocframaddresscounter.sload = getbookcounter.eq[1] & (bootcontrol == getbook); tocframaddresscounter.data[] = tocframaddress.q[]; afirstpageframaddress.clock = !bootclock; afirstpageframaddress.data[] = framdata[]; afirstpageframaddress.enable = getchaptercounter.eq[0] & (bootcontrol == getchapter); bfirstpageframaddress.clock = !bootclock; bfirstpageframaddress.data[] = framdata[4..0]; bfirstpageframaddress.enable = getchaptercounter.eq[1] & (bootcontrol == getchapter); firstpageframaddress[15..0] = afirstpageframaddress.q[]; firstpageframaddress[20..16] = bfirstpageframaddress.q[]; alastpageframaddress.clock = !bootclock; alastpageframaddress.data[] = framdata[]; alastpageframaddress.enable = getchaptercounter.eq[2] & (bootcontrol == getchapter); blastpageframaddress.clock = !bootclock; blastpageframaddress.data[] = framdata[4..0]; blastpageframaddress.enable = getchaptercounter.eq[3] & (bootcontrol == getchapter); lastpageframaddress[15..0] = alastpageframaddress.q[]; lastpageframaddress[20..16] = blastpageframaddress.q[]; afirstpagehfaddress.clock = !bootclock; afirstpagehfaddress.data[] = framdata[]; afirstpagehfaddress.enable = getchaptercounter.eq[4] & (bootcontrol == getchapter); bfirstpagehfaddress.clock = !bootclock; bfirstpagehfaddress.data[] = framdata[8..0]; bfirstpagehfaddress.enable = getchaptercounter.eq[5] & (bootcontrol == getchapter); firstpagehfaddress[15..0] = afirstpagehfaddress.q[]; firstpagehfaddress[24..16] = bfirstpagehfaddress.q[]; bootinstructions.clock = !bootclock; bootinstructions.data[] = framdata[]; bootinstructions.enable = getchaptercounter.eq[6] & (bootcontrol == getchapter); % getpage registers % boothfdata.clock = !bootclock; boothfdata.data[] = framdata[]; boothfdata.enable = (bootcontrol == getpage); boothfenable = (bootcontrol == getpage) & bootinstructions.q[1]; pageframaddresscounter.clock = bootclock; pageframaddresscounter.cnt_en = ((bootcontrol == getpage) & !bootinstructions.q[2]) # ((bootcontrol == getpage) & serialcounter.eq[15]); pageframaddresscounter.data[] = firstpageframaddress[]; pageframaddresscounter.sload = getchaptercounter.eq[7] & (bootcontrol == getchapter); pagehfaddresscounter.clock = bootclock; pagehfaddresscounter.cnt_en = (bootcontrol == getpage); pagehfaddresscounter.data[] = firstpagehfaddress[]; pagehfaddresscounter.sload = getchaptercounter.eq[7] & (bootcontrol == getchapter); bootcontrol.clk = bootclock; bootmode = ((bootcontrol != standby) & (bootcontrol != start)); bootreset = (runmode[]!=3); CASE bootcontrol IS WHEN standby => bootframaddress[] = GND; boothfaddress[] = GND; getbookcounter.cnt_en = GND; getbookcounter.sclr = VCC; IF (!bootreset) THEN bootcontrol = start; END IF; WHEN start => bootframaddress[] = GND; boothfaddress[] = GND; getbookcounter.cnt_en = GND; getbookcounter.sclr = VCC; IF (bootreset) THEN bootcontrol = finish; ELSE bootcontrol = getbook; END IF; WHEN getbook => getbookcounter.sclr = GND; getbookcounter.cnt_en = VCC; bootframaddress[11..0] = bookframaddress.q[]; bootframaddress[20..12] = GND; IF (getbookcounter.eq[1] & !bootreset) THEN bootcontrol = getchapter; END IF; IF (bootreset) THEN bootcontrol = finish; END IF; WHEN getchapter => getchaptercounter.sclr = GND; getchaptercounter.cnt_en = VCC; bootframaddress[20..16] = GND; bootframaddress[15..0] = tocframaddresscounter.q[]; IF (getchaptercounter.eq[7] & !bootreset) THEN bootcontrol = getpage; END IF; IF (bootreset) THEN bootcontrol = finish; END IF; WHEN getpage => bootframaddress[] = pageframaddresscounter.q[]; boothfaddress[] = pagehfaddresscounter.q[]; IF ((!bootinstructions.q[2] # serialcounter.eq[15]) & % last bit of a DATA0 page % (pageframaddresscounter.q[] == lastpageframaddress[]) & % last page % !bootinstructions.q[0] & % not last chapter % !bootreset) THEN bootcontrol = getchapter; END IF; IF ((!bootinstructions.q[2] # serialcounter.eq[15]) & % last bit of a DATA0 page % (pageframaddresscounter.q[] == lastpageframaddress[]) & % last page % bootinstructions.q[0] & % last chapter % !bootreset) THEN bootcontrol = finish; END IF; IF (bootreset # bootinstructions.q[15]) THEN bootcontrol = finish; END IF; WHEN finish => bootframaddress[] = GND; boothfaddress[] = GND; getbookcounter.cnt_en = GND; getbookcounter.sclr = VCC; bootcontrol = standby; END CASE; serialcounter.clock = bootclock; serialcounter.cnt_en = (bootcontrol == getpage) & bootinstructions.q[2]; serialcounter.sclr = (bootcontrol != getpage); serializer.load = serialcounter.eq[0] & bootinstructions.q[2]; serializer.data[] = boothfdata.q[]; serializer.enable = (bootcontrol == getpage) & bootinstructions.q[2]; serializer.clock = bootclock; dclken.clock = bootclock; % Enable clock when sending a page containing configuration data. If bootinstructions bit 4 is set, then suppress the clock for the last 8 bits of data for this chapter. % dclken.data[] = (bootcontrol == getpage) & bootinstructions.q[2] & !(bootinstructions.q[4] & serialcounter.q[3] & (pageframaddresscounter.q[] == lastpageframaddress[])); IF (!bkupconfig) THEN VALID = dclken.q[]; DATA0 = serializer.shiftout; DCLK = !bootclock; nCONFIG = !bootinstructions.q[3]; END IF; % to configure using the backup port % IF (bkupconfig) THEN nCONFIG = nCONFIG_bkup; DATA0 = DATA0_bkup; DCLK = DCLK_bkup; VALID = VCC; END IF; CONF_DONE_bkup = CONF_DONE; nSTATUS_bkup = nSTATUS; % power-up stuff % powerup.clk = HF_Clock; powerup.d = VCC; powerup1.clk = HF_Clock; powerup1.d = powerup.q; % very slow oscillator % slowcounter.clock = bootclock; slowcounter.cnt_en = VCC; oscsec = (slowcounter.q[19]); oschalfsec = (slowcounter.q[18]); oscqtrsec = (slowcounter.q[17]); mop_spare0 = slowcounter.q[15]; mop_spare1 = GND; mop_spare2 = GND; mop_spare3 = GND; mop_spare4 = GND; END;