TITLE "CONTROL";

% 12 09 2000 - add ID prom definitions %

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]);

FUNCTION lpm_compare (dataa[LPM_WIDTH-1..0], datab[LPM_WIDTH-1..0], clock, aclr)
   WITH (LPM_WIDTH, LPM_REPRESENTATION, LPM_PIPELINE, CHAIN_SIZE, ONE_INPUT_IS_CONSTANT)
   RETURNS (alb, aeb, agb, ageb, aneb, aleb);

FUNCTION lpm_counter (data[LPM_WIDTH-1..0], clock, clk_en, cnt_en, updown, aclr, aset, aconst, aload, sclr, sset, sconst, sload)
   WITH (LPM_WIDTH, LPM_DIRECTION, LPM_MODULUS, LPM_AVALUE, LPM_SVALUE)
   RETURNS (q[LPM_WIDTH-1..0], eq[15..0]);

FUNCTION lpm_ff (data[LPM_WIDTH-1..0], clock, enable, sclr, sset, sload, aclr, aset, aload)
   WITH (LPM_WIDTH, LPM_AVALUE, LPM_SVALUE, LPM_FFTYPE)
   RETURNS (q[LPM_WIDTH-1..0]);

FUNCTION lpm_decode (data[LPM_WIDTH-1..0], enable, clock, aclr)
   WITH (LPM_WIDTH, LPM_DECODES, LPM_PIPELINE)
   RETURNS (eq[LPM_DECODES-1..0]);

SUBDESIGN control
(
    _modsel           : INPUT;  % enables vme access to the board %
    sysclk            : INPUT;  % VME clock, 60 ns period %
    vme_tap[5..0]     : INPUT;  % vme data strobe echoed by increments of 25 ns; vme_tap0 = vme_data_str %
    vme_dat[31..24]   : BIDIR;  % port used to download the delays and control registers %
    vme_add[26..2]    : INPUT;  % VME address of word being written or read %
    vme_write         : INPUT;  % read (0) or write (1) request from VME %
    cdf_132ns[5..0]   : INPUT; % cdf_clk shifted by steps of 22 ns; cdf_132ns0 = CDF_clk % 
    src_config        : INPUT; % source of the FLEX10Ks' configuration: 0= PROMs, 1= FLEX Download Cable %
    _b0               : INPUT; % active low %
    _halt             : INPUT; % active low %
    _reset            : INPUT; % active low %
    _EF[7..0]         : INPUT; % empty FIFO error %
    _FF[7..0]         : INPUT; % full FIFO error %
    _L1A              : INPUT; % Level 1 Accept %
    _L1R              : INPUT; % Level 1 Reject %
    _L1BA[1..0]       : INPUT; % DAQ buffer write-address (sent upon a L1A signal on P2) %
	serial_number[4..0]	: INPUT; % the serial number specified in binary by DIP switches %

    L1BA[1..0]        : OUTPUT; % same as before, only made active high %
    _L1B_W            : OUTPUT; % DAQ buffer write signal (follows a L1A) %
    _L2B_R[3..0]      : OUTPUT; % DAQ buffer read signal: 0 = ID prom + BC value
                                                          1 = 4 trigger bits + missing Et
                                                          2 = sumet, sumex, sumey + error bit 
                                                          3 = sumet from previous crossing % 
    L2BA[1..0]        : OUTPUT; % DAQ buffer read-address (sent on VME_address bus subsequent to a L2A) %
    _L1FIFO_R         : OUTPUT; % L1 FIFO read signal: gets asserted upon a L1A or L1R %
    _L1FIFO_W         : OUTPUT; % gets started after delayed b0; comes 66 ns after bunch count %
    CS_132ns          : OUTPUT; % cdf_clk shifted by CS_delay %
    fred_delay[5..0]  : OUTPUT; % simply echoes the VME-loaded value of the FRED alignment delay 
                                  for use by the PreFRED "processor" %
    _ACK              : OUTPUT; % VME data transfer acknowledge signal %
    _vme_error        : OUTPUT; % VME error; on this board, set to VCC the whole time %
    _cdf_error        : OUTPUT; % board error %
    _reset_           : OUTPUT; % reset and halt %
    thres_sel[1..0]   : OUTPUT; % threshold and mask selector for VME transaction %
    src_etin          : OUTPUT; % What feeds processor: 0=backplane (normal run); 1=VME_address bus %
    lut_add_msb       : OUTPUT; % LUT extra address bit (most significant bit) used for diagnostics
                                  = 0 in run mode, vme_add14 in load mode %
    _lut_write[2..0]  : OUTPUT; % Write enable signal on the LUTs %
    vme_lut_en[2..0]  : OUTPUT; % Look Up Table selector for VME transaction;
                                  one selector enables 2 SRAMs at the same time %
    dataout_ren[1..0] : OUTPUT; % enables vme reading of dataout %
    bunch_cnt[7..0]   : OUTPUT;
    aux_spare         : OUTPUT; % goes to the AUX card %
    aux_enable        : OUTPUT; % enables the aux card %
    _BP_trigbits_en   : OUTPUT; % enables output data to FRED (backplane driver) %
    FP_str            : OUTPUT; % Strobe to send data to L2 (Front Panel driver) %
    Lights[4..0]      : OUTPUT;
    run               : OUTPUT;
    vme_fifo_wen      : OUTPUT; % enables writing of the FIFOs from VME % 
    vme_proc_clk      : OUTPUT; % clock to load thresholds into processor from VME %
    b0_delayed        : OUTPUT; % B0 signal delayed by b0_offset %
    vme_version_ren   : OUTPUT; % enables reading of Data Processor code version number %
 %  bp_spare[2..0]    : OUTPUT;  Spare bits going to P3 backplane %
)
VARIABLE
    blk_decoder    	  : lpm_decode WITH (LPM_WIDTH=4, LPM_DECODES=12);
    add_decoder       : lpm_decode WITH (LPM_WIDTH=5, LPM_DECODES=32);
    chan_decoder      : lpm_decode WITH (LPM_WIDTH=2, LPM_DECODES=3);
% Control registers %
    ctrl_wrd[5..0][7..0]: DFFE;  % ctrl_wrd0[5..0] = b0_offset 
                                           1[2..0] = CS_delay 
                                           2[5..0] = fred_delay
                                           3[]     = board-level control bits;
                                                     strobes to write to DAQ buffers
                                           4[]     = Full FIFO Flag Masks
                                           5[]     = Aux Card control % 
    tri_ctrl_wrd[8..0][7..0]: TRI; % 6[] = Full FIFO Flags: Read only 
                                     7[] = Empty FIFO Flags: Read only
                                     8[] = Controller Program version number: Read only;
                                           version's MSB indicates whether the FLEX10Ks' configuration
                                           source is the EPC1 PROMs (0) or the FLEX download cable (1) %
    ctrl_sel          : NODE; % Enables vme transaction on control registers %
    w_ctrl            : NODE; % write enable to the control registers %
    r_ctrl            : NODE; % read    "    from "     "       "     %
% ID Prom registers %
    IDprom[31..0][7..0]: NODE;
    tri_idprom[31..0][7..0]: TRI;
    r_idprom          : NODE; % vme read enable from the ID prom words % 

    vme_data[7..0]    : TRI_STATE_NODE;    

% Bunch counter stuff %
    _halt_            : NODE; % run & _halt %
    bunch_counter     : lpm_counter WITH (LPM_WIDTH=8);
    tri_counter[7..0] : TRI;
    hold              : lpm_ff WITH (LPM_WIDTH=1);
    pipe              : lpm_shiftreg WITH (LPM_WIDTH=42);
    b0delay_mux       : lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=42, LPM_WIDTHS=6);% picks the B0 signal with desired delay %
    sclear            : NODE;
    fake_bunchcnt[7..0]: TRI;
    bunchcnt[7..0]    : TRI_STATE_NODE;

% Other stuff %
    cdfclk_mux        : lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=6, LPM_WIDTHS=3); 
                        % picks the 132 ns clock in phase with the incoming data from the Cratesums %
    _FF_[7..0]         : NODE; % masked full FIFO error flag (can be always negated via control registers) %
    CS_delay[2..0]    : NODE; % max. delay with which the incoming data arrive at the board, in units
                                of 22 ns after the rising edge of CDF_clk %
    b0_offset[5..0]   : NODE; % time between the B0 pulse and the writing of the B0 data to the L1 FIFO %
    run               : NODE;
    load              : NODE; % !run %
    vme_read          : NODE;
    ld_en             : NODE; 
    vme_fifo_wen      : NODE; % allows vme-writing to L1_FIFO %
    tap[5..1]         : NODE;
    ctrl_wrd3_ld      : NODE;
    proc_counter      : lpm_counter WITH (LPM_WIDTH=3,LPM_MODULUS=8);
    version[7..0]     : NODE;
    _cdf_error        : DFF;
    compa             : lpm_compare WITH (LPM_WIDTH=10, ONE_INPUT_IS_CONSTANT = "YES");
    compb             : lpm_compare WITH (LPM_WIDTH=6, ONE_INPUT_IS_CONSTANT = "YES");
    vme_sel           : NODE; 
BEGIN
  DEFAULTS
    _cdf_error.d = VCC;
    _L1FIFO_W = VCC;
    _L1FIFO_R = VCC;
    _L1B_W = VCC;
	IDprom2_[] = H"30"; 		% Hex ASCII code for 0 % % If these 2 bits are returned as 0, something is wrong, %
	IDprom3_[] = H"30"; 		% Hex ASCII code for 0 % % since no serial number is 0 %
    %IDprom[][] = VCC; %
    _ACK = VCC;
    _reset_ = VCC;
    _BP_trigbits_en = VCC;
    _L2B_R[] = VCC;
  END DEFAULTS;
 
  version7 = src_config;
  version[6..0] = 1;

%%% 0. Clk selector to be in sync with the incoming Cratesum data %%%

  cdfclk_mux.data[][] = cdf_132ns[];
  cdfclk_mux.sel[] = CS_delay[];
  CS_132ns = cdfclk_mux.result0;
  
%%% I. VME transactions %%%

% I.0/ Basic signal generation and preliminary address decoding %
  
  vme_read = !vme_write;
  tap1 = vme_tap0 & vme_tap1;
  tap2 = vme_tap0 & vme_tap1 & vme_tap2;
  tap3 = vme_tap0 & vme_tap1 & vme_tap2 & vme_tap3;
  tap4 = vme_tap0 & vme_tap1 & vme_tap2 & vme_tap3 & vme_tap4;
  tap5 = vme_tap0 & vme_tap1 & vme_tap2 & vme_tap3 & vme_tap4 & vme_tap5;
  proc_counter.clock = CS_132ns;
  proc_counter.aclr = src_etin & !tap2;
  _ACK = !(vme_tap0 & tap5 & (!blk_decoder.eq6 # (blk_decoder.eq6 & proc_counter.eq6)));
  _vme_error = VCC;
  blk_decoder.data[] = vme_add[23..20];
  chan_decoder.data[] = vme_add[16..15];
  add_decoder.data[] = vme_add[6..2];

% While in run mode, forbid any VME transaction other than:
         1/ DAQ buffer reading,
         2/ reading of control and IDprom words,
         3/ run control word w/r,
         4/ trigger threshold reading. 
  Generate signals vme_sel & ld_en for that purpose  %
 
  compa.dataa[]  = vme_add[16..7];
  compa.datab[] = GND;
  compb.dataa[5..3] = vme_add[26..24];
  compb.dataa[2..0] = vme_add[19..17];
  compb.datab[] = GND;
  vme_sel = tap1 & compa.aeb & compb.aeb;
  ld_en = load & tap1 & compb.aeb;
   
% I.1/ VME read/write operations on control registers %

  ctrl_sel = vme_sel & blk_decoder.eq0;
  w_ctrl = vme_write & ctrl_sel & load;
  r_ctrl = vme_read & ctrl_sel;
  ctrl_wrd[][].clk = tap2; % write strobe for control registers %
  ctrl_wrd0_[].ena = w_ctrl & add_decoder.eq0;
  ctrl_wrd1_[].ena = w_ctrl & add_decoder.eq1;
  ctrl_wrd2_[].ena = w_ctrl & add_decoder.eq2;
  ctrl_wrd3_0.ena = vme_write & ctrl_sel & add_decoder.eq3; % authorizes overwriting of run ctrl word when in run mode %
  ctrl_wrd3_[7..1].ena = w_ctrl & add_decoder.eq3;
  ctrl_wrd4_[].ena = w_ctrl & add_decoder.eq4;
  ctrl_wrd5_[].ena = w_ctrl & add_decoder.eq5;
  ctrl_wrd[][].d = vme_dat[];
  tri_ctrl_wrd[5..0][].in = ctrl_wrd[][].q;
  tri_ctrl_wrd6_[].in = !_FF[];
  tri_ctrl_wrd7_[].in = !_EF[];
  tri_ctrl_wrd8_[].in = version[];
  tri_ctrl_wrd0_[].oe = r_ctrl & add_decoder.eq0;
  tri_ctrl_wrd1_[].oe = r_ctrl & add_decoder.eq1;
  tri_ctrl_wrd2_[].oe = r_ctrl & add_decoder.eq2;
  tri_ctrl_wrd3_[].oe = r_ctrl & add_decoder.eq3;
  tri_ctrl_wrd4_[].oe = r_ctrl & add_decoder.eq4;
  tri_ctrl_wrd5_[].oe = r_ctrl & add_decoder.eq5;
  tri_ctrl_wrd6_[].oe = r_ctrl & add_decoder.eq6;
  tri_ctrl_wrd7_[].oe = r_ctrl & add_decoder.eq7;
  tri_ctrl_wrd8_[].oe = r_ctrl & add_decoder.eq8;
  vme_version_ren = r_ctrl & add_decoder.eq9;
  vme_data[] = tri_ctrl_wrd0_[].out;
  vme_data[] = tri_ctrl_wrd1_[].out;
  vme_data[] = tri_ctrl_wrd2_[].out;
  vme_data[] = tri_ctrl_wrd3_[].out;
  vme_data[] = tri_ctrl_wrd4_[].out;
  vme_data[] = tri_ctrl_wrd5_[].out;
  vme_data[] = tri_ctrl_wrd6_[].out;
  vme_data[] = tri_ctrl_wrd7_[].out;
  vme_data[] = tri_ctrl_wrd8_[].out;
  
% Control register mapping %
  b0_offset[] = ctrl_wrd0_[5..0].q; 
  CS_delay[] = ctrl_wrd1_[2..0].q;
  fred_delay[] = ctrl_wrd2_[5..0].q;
  run = ctrl_wrd3_0.q; % Run or load mode : 0 = load; 1 = run %
  load = !run;
  _BP_trigbits_en = !(load & ctrl_wrd3_2.q);
  FP_str = load & ctrl_wrd3_3.q; % just to check associated LED %
  ctrl_wrd3_ld = tap3 & !_modsel & blk_decoder.eq0 & vme_write & load & add_decoder.eq3;
  _reset_ = !(ctrl_wrd3_1.q & ctrl_wrd3_ld);
  _L1FIFO_R = !(ctrl_wrd3_4.q & ctrl_wrd3_ld);
  _L1B_W = !(ctrl_wrd3_5.q & ctrl_wrd3_ld & !tap5);
  L1BA[] = load & ctrl_wrd3_[7..6].q;
  _FF_[] = _FF[] # ctrl_wrd4_[].q; % mask FF flag in order to be able to still run with bad FIFO %
  aux_enable = load & ctrl_wrd5_0.q;
  aux_spare = load & ctrl_wrd5_1.q;

% I.2/ VME read operations on IDprom %


% I.2a/ IDprom character assignments %

	IDprom0_[] = H"30"; 		% Hex ASCII code for 0 %
	IDprom1_[] = H"30"; 		% Hex ASCII code for 0 %
  CASE serial_number[] IS
	WHEN 1 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"31"; 		% Hex ASCII code for 1 %
	WHEN 2 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"32"; 		% Hex ASCII code for 2 %
	WHEN 3 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"33"; 		% Hex ASCII code for 3 %
	WHEN 4 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"34"; 		% Hex ASCII code for 4 %
	WHEN 5 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"35"; 		% Hex ASCII code for 5 %
	WHEN 6 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"36"; 		% Hex ASCII code for 6 %
	WHEN 7 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"37"; 		% Hex ASCII code for 7 %
	WHEN 8 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"38"; 		% Hex ASCII code for 8 %
	WHEN 9 =>
	  IDprom2_[] = H"30"; 		% Hex ASCII code for 0 %
	  IDprom3_[] = H"39"; 		% Hex ASCII code for 9 %
	WHEN 10 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"30"; 		% Hex ASCII code for 0 %
	WHEN 11 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"31"; 		% Hex ASCII code for 1 %
	WHEN 12 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"32"; 		% Hex ASCII code for 2 %
	WHEN 13 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"33"; 		% Hex ASCII code for 3 %
	WHEN 14 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"34"; 		% Hex ASCII code for 4 %
	WHEN 15 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"35"; 		% Hex ASCII code for 5 %
	WHEN 16 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"36"; 		% Hex ASCII code for 6 %
	WHEN 17 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"37"; 		% Hex ASCII code for 7 %
	WHEN 18 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"38"; 		% Hex ASCII code for 8 %
	WHEN 19 =>
	  IDprom2_[] = H"31"; 		% Hex ASCII code for 1 %
	  IDprom3_[] = H"39"; 		% Hex ASCII code for 9 %
	WHEN 20 =>
	  IDprom2_[] = H"32"; 		% Hex ASCII code for 2 %
	  IDprom3_[] = H"30"; 		% Hex ASCII code for 0 %
  END CASE;
	IDprom4_[] = H"20";			% Hex ASCII code for blank space %
	IDprom5_[] = H"30"; 		% Hex ASCII code for 0 %
	IDprom6_[] = H"31"; 		% Hex ASCII code for 1 %
	IDprom7_[] = H"34"; 		% Hex ASCII code for 4 %
	IDprom8_[] = H"20";			% Hex ASCII code for blank space %
	IDprom9_[] = H"50"; 		% Hex ASCII code for P %
	IDprom10_[] = H"52"; 		% Hex ASCII code for R %
	IDprom11_[] = H"45"; 		% Hex ASCII code for E %
	IDprom12_[] = H"46"; 		% Hex ASCII code for F %
	IDprom13_[] = H"52"; 		% Hex ASCII code for R %
	IDprom14_[] = H"45"; 		% Hex ASCII code for E %
	IDprom15_[] = H"44"; 		% Hex ASCII code for D %
	IDprom[31..16][] = H"00"; 	% Hex ASCII code for null %


  r_idprom = vme_sel & blk_decoder.eq1 & vme_read;
  tri_idprom[][].in = IDprom[][];
  tri_idprom[]_0.oe = r_idprom & add_decoder.eq[];
  tri_idprom[]_1.oe = r_idprom & add_decoder.eq[];
  tri_idprom[]_2.oe = r_idprom & add_decoder.eq[];
  tri_idprom[]_3.oe = r_idprom & add_decoder.eq[];
  tri_idprom[]_4.oe = r_idprom & add_decoder.eq[];
  tri_idprom[]_5.oe = r_idprom & add_decoder.eq[];
  tri_idprom[]_6.oe = r_idprom & add_decoder.eq[];
  tri_idprom[]_7.oe = r_idprom & add_decoder.eq[];
  vme_data[] = tri_idprom0_[].out;
  vme_data[] = tri_idprom1_[].out;
  vme_data[] = tri_idprom2_[].out;
  vme_data[] = tri_idprom3_[].out;
  vme_data[] = tri_idprom4_[].out;
  vme_data[] = tri_idprom5_[].out;
  vme_data[] = tri_idprom6_[].out;
  vme_data[] = tri_idprom7_[].out;
  vme_data[] = tri_idprom8_[].out;
  vme_data[] = tri_idprom9_[].out;
  vme_data[] = tri_idprom10_[].out;
  vme_data[] = tri_idprom11_[].out;
  vme_data[] = tri_idprom12_[].out;
  vme_data[] = tri_idprom13_[].out;
  vme_data[] = tri_idprom14_[].out;
  vme_data[] = tri_idprom15_[].out;
  vme_data[] = tri_idprom16_[].out;
  vme_data[] = tri_idprom17_[].out;
  vme_data[] = tri_idprom18_[].out;
  vme_data[] = tri_idprom19_[].out;
  vme_data[] = tri_idprom20_[].out;
  vme_data[] = tri_idprom21_[].out;
  vme_data[] = tri_idprom22_[].out;
  vme_data[] = tri_idprom23_[].out;
  vme_data[] = tri_idprom24_[].out;
  vme_data[] = tri_idprom25_[].out;
  vme_data[] = tri_idprom26_[].out;
  vme_data[] = tri_idprom27_[].out;
  vme_data[] = tri_idprom28_[].out;
  vme_data[] = tri_idprom29_[].out;
  vme_data[] = tri_idprom30_[].out;
  vme_data[] = tri_idprom31_[].out;
  vme_dat[] = vme_data[];





  
% I.3/ Generation of signals to handle VME transactions on to other chips on the board %

%  a/ read/write to LUTs %

    vme_lut_en[] = ld_en & blk_decoder.eq4 & chan_decoder.eq[];
    _lut_write[] = !(vme_lut_en[] & vme_write) # tap4; % must leave time for clk_66ns rise %
    lut_add_msb = load & vme_add14;    % 0 when in run mode, vme_add14 when in load mode %
    
%  b/ read/write trigger thresholds from/to data_processor % 

   thres_sel[] = vme_sel & blk_decoder.eq5 & (add_decoder.eq[1..0] # add_decoder.eq2);
 
    vme_proc_clk = tap4;
    
%  c/ read from data_processor %

    src_etin = ld_en & blk_decoder.eq6 & vme_read;
    dataout_ren[] = src_etin & chan_decoder.eq[1..0];

%  d/ write to L1 FIFOs %

    vme_fifo_wen = ld_en & blk_decoder.eq7 & vme_write; 
    fake_bunchcnt[].in = vme_dat[];
    fake_bunchcnt[].oe = vme_fifo_wen;
    bunchcnt[] = fake_bunchcnt[].out;
    _L1FIFO_W = !(vme_fifo_wen & tap2) # tap4;  % used to be tap1) # tap3, 10/21/97 %
    
%  e/ read from DAQ buffers %

    _L2B_R[] = !(vme_sel & (blk_decoder.eq8 # blk_decoder.eq9 # blk_decoder.eq10 # blk_decoder.eq11)
                 & vme_read & add_decoder.eq[3..0]);  
    L2BA[] = vme_add[21..20];

%%% II. RUN mode: Handling of halt/reset start-up sequence and DAQ buffer management %%%

    _halt_ = _halt & run;  % _halt_ is always asserted in load mode %
    _reset_ = load # _halt # _reset; % _reset_ is only asserted if _halt is asserted when in run mode %
    
% II.1/ Bunch Counter - Note: no need to reset/hold its value before b0 on startup sequence %

    pipe.enable = _halt_; 
    pipe.aclr = !_reset_;
    pipe.clock = CS_132ns;
    pipe.shiftin = !_b0;
    b0delay_mux.data[][] = pipe.q[];
    b0delay_mux.sel[] = b0_offset[] - 1;
    b0_delayed = b0delay_mux.result0;
    bunch_counter.sclr = b0delay_mux.result0; 
    bunch_counter.cnt_en = _halt_;
    bunch_counter.clock = CS_132ns;
    tri_counter[].in = bunch_counter.q[];
    tri_counter[].oe = run; 
    bunchcnt[] = tri_counter[].out;
    bunch_cnt[] = bunchcnt[];
     
% II.2/ Write to L1 FIFOs - asserted by delayed B0 signal after a halt %
    
    hold.clock = CS_132ns;
    sclear = _halt_ & b0delay_mux.result0;
    hold.enable = sclear;  
    hold.aset = !_halt_;
    hold.sclr = sclear;
    _L1FIFO_W = hold.q0 # !CS_132ns;

% II.3/ Read out of L1 FIFOs / write to DAQ buffers % 
    
    _L1FIFO_R = !_halt_ # (_L1A & _L1R) # (cdf_132ns4 & cdf_132ns5); 
    _L1B_W = !_halt_ # _L1A # cdf_132ns4 # cdf_132ns5; 
    L1BA[] = run & !_L1BA[];

%%% III. Error handling %%%

    _cdf_error.clk = cdf_132ns0;
    _cdf_error.d = _FF_0 & _FF_1 & _FF_2 & _FF_3 & _FF_4 & _FF_5 & _FF_6 & _FF_7;
    _cdf_error.prn  = _reset_;

%%% IV. Backplane and Front panel control %%%

    _BP_trigbits_en = load;
    aux_enable = run;
    aux_spare = GND;
	FP_str = !_L1B_W;
    Lights0 = load; % Note: Lights(1..0) is active low, so Lights0 actually qualifies the running mode %
    Lights1 = run;
    Lights2 = _cdf_error;
    Lights3 = CS_132ns;
    Lights4 = FP_str;

END;
