TITLE "CONTROL";


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
(
    vme_dat[31..24]   : BIDIR;  % port used to download the delays and control registers %

% INPUTS %
	serial_number[4..0]	: INPUT; % the serial number specified in binary by DIP switches %
    src_config   		: INPUT;  % source of the FLEX10Ks' configuration: 0= PROMs, 1= FLEX Download Cable %
    vme_add[26..2]    : INPUT;  % VME address of word being written or read %
% VME_Control and derived signals %
    _modsel           : INPUT;  % enables vme access to the board %
    sysclk            : INPUT;  % VME clock with 60 ns period, currently not used %  
    vme_tap[5..0]     : INPUT;  % vme data strobe echoed by increments of 22ns; vme_tap0 = vme_data_str %
    vme_write         : INPUT;  % read (0) or write (1) request from VME %
% FIFOs %
    _EF_ET_Sum[1..0]  : INPUT; % empty FIFO error %
    _EF_Trig_Sum[1..0]: INPUT; % empty FIFO error %
    _EF_ET_Raw[3..0]  : INPUT; % empty FIFO error %
    _EF_Trig_Raw[7..0]: INPUT; % empty FIFO error %
	_EF_Bunch_Ctr	  : INPUT; % empty FIFO error %
    _FF_ET_Sum[1..0]  : INPUT; % full FIFO error %
    _FF_Trig_Sum[1..0]: INPUT; % full FIFO error %
    _FF_ET_Raw[3..0]  : INPUT; % full FIFO error %
    _FF_Trig_Raw[7..0]: INPUT; % full FIFO error %
	_FF_Bunch_Ctr	  : INPUT; % full FIFO error %
% Trig_Control and derived signals %
    cdf_132ns[5..0]   : INPUT; % cdf_clk shifted by steps of 22 ns; cdf_132ns0 = CDF_clk % 
    _b0               : INPUT; % active low %
    _halt             : INPUT; % active low %
    _recover          : INPUT; % active low %
    _L1A              : INPUT; % Level 1 Accept %
    _L1R              : INPUT; % Level 1 Reject %
    _L2B[1..0]        : INPUT; % DAQ buffer write-address (sent upon a L1A signal on P2) %
% Delayed signals from itself %
	ET_clk[8..1]	  : INPUT; % The 8 P3_Latch_ET strobes echoed by increments of 22ns %
	Trig_clk[8..1]	  : INPUT; % The 8 P3_Latch_Trig strobes echoed by increments of 22ns %

% OUTPUTS %
% Back to itself %
	ET_clk0			  : OUTPUT; % P3_Latch_clk_ET strobes (even in load mode, the echoes are OK) %
	Trig_clk0		  : OUTPUT; % P3_Latch_clk_Trig strobes (even in load mode, the echoes are OK) %
% To L1FIFOs and L2 buffers %
    L2B[1..0]         : OUTPUT; % same as before, only made active high %
    _L2B_W            : OUTPUT; % DAQ buffer write signal (follows a L1A) %
    _L2BD_R[8..0]     : OUTPUT; % DAQ buffer read signal: 0 = Board ID + Bunch Counter value 
                                                          1 = ET summary
                                                          2 = Trigger bit summary 
                                                          3 = Raw DIRAC ET data for wedge 0 
                                                          4 = Raw DIRAC ET data for wedge 1
														  5 = Raw DIRAC trigger data [1..0][15..0]
														  6 = Raw DIRAC trigger data [3..2][15..0]
														  7 = Raw DIRAC trigger data [5..4][15..0]
														  8 = Raw DIRAC trigger data [7..6][15..0] %
    L2BD[1..0]        : OUTPUT; % DAQ buffer read-address (sent on VME_address bus subsequent to a L2A) %
    L1FIFO_Rclk          			: OUTPUT; % L1 FIFO read signal; gets asserted upon a L1A or L1R %
    L1FIFO_Wclk_ET_Sum   			: OUTPUT; % gets started after b0_delayed2_ET + ?? ns %
    L1FIFO_Wclk_Trig_Sum 			: OUTPUT; % gets started after b0_delayed2_Trig + ?? ns %
    L1FIFO_Wclk_ET_Raw_wedge[1..0]  : OUTPUT; % gets started after b0_delayed_ET + ?? ns %
    L1FIFO_Wclk_Trig_Raw_qtr[4..1]  : OUTPUT; % gets started after b0_delayed_Trig + ?? ns %
	L1FIFO_Wclk_Bunch_Ctr			: OUTPUT; % gets started after min(b0_ET, b0_Trig) + ?? ns %
% To P3_Latch %
	_P3_Latch_OE	  : OUTPUT; % Latch raw DIRAC data in: output enable* %
	P3_Latch_clk_ET	  : OUTPUT; % Latch raw DIRAC ET data in; 
								  in phase with ET_132ns and begins after delayed ET B0 %
	P3_Latch_clk_Trig : OUTPUT; % Latch raw DIRAC Trig data in; 
								  in phase with Trig_132ns and begins after delayed Trig B0 %
% To the processor chip %
	mask_DIRAC[7..0]  : OUTPUT; % DIRAC input masking bits (aka mask[7..0] on the processor) %
	one_or_two_bits[3..0][1..0] : OUTPUT; 
								% specifies either two 8-to-1 bit (high) or one 8*2-to-2 bit (low) summing for 
								  Trig[7..0][3..0], Trig[7..0][7..4], Trig[7..0][11..8], and Trig[7..0][15..12];
								  whether these bits are to be tied high or low will be determined after the program 
								  is completed %
    _src_data         : OUTPUT; % _src_data is the run_or_vme signal expected by the processor %
								% Input to processor: 1=backplane (normal run); 0=VME_address bus;
								  is a downloadable register. %
	proc_latch_clk_ET 	: OUTPUT; % 132 ns clock signal to latch the summed data in the processor (aka et_run_clk) %
	proc_latch_clk_Trig : OUTPUT; % 132 ns clock signal to latch the summed data in the processor (aka trig_run_clk) %
	FPmux_ET   		  : OUTPUT; % 132ns period signal controlling the multiplexed ET data (et_mux_next_cycle) %
	FPmux_Trig 		  : OUTPUT; % 132ns period signal controlling the multiplexed Trig data (trig_mux_next_cycle) %
	vme_clk_ET		  : OUTPUT; % clock to latch VME ET data into the processor (et_vme_clk) %
	vme_clk_Trig	  : OUTPUT; % clock to latch VME Trig data into the processor (trig_vme_clk) %
	store_vme_wedge_sel     : OUTPUT; % the vme ET latch wedge selector: specifies which wedge the VME data is for %
	store_vme_qtr_sel[1..0] : OUTPUT; % the vme trigger latch quarter selector (aka store_vme_qtr_select[1..0]): 
										specifies which qtr the VME data is for %
	proc_out_write	  : OUTPUT; % signal (write_to_vme) that directs the processor to return data via VME_Data;
								  when proc_out_write is high, the processor drives the vme_data bus; 
								  when proc_out_write is low, the processor output to the vme_data bus is asleep % 
	proc_out_sel[2..0]: OUTPUT; % select lines (aka sel[2..0]) which specify whether the processor returns the 
								  ET_Sum, Trig_Sum, ET_Raw, or Trig_Raw data, and which 32 bits in particular %
	proc_version_ren  : OUTPUT; % tells processor to output version number info on the vme_data bus %
% Signals on the VME_Control bus %
	_ACK			  : OUTPUT; % VME data transfer acknowlege signal %
    _vme_error        : OUTPUT; % VME error, signal on the VME_Control bus; on this board, set to VCC the whole time %
% Signals on the Trig_Control bus %
    _cdf_error        : OUTPUT; % board error, signal on the Trig_Control bus %
% Other control signals (not listed above) %
    run               : OUTPUT; % run or load mode: 0 = load; 1 = run; reflects the state of a downloadable register %
    _recover_         : OUTPUT; % _recover_ is asserted only if _recover and _halt are asserted in run mode %
    bunch_cnt[7..0]   : OUTPUT; % the bunch counter value sent to the bunch counter L1FIFO %
% Lights bus %
    Lights[6..0]      : OUTPUT;
)

VARIABLE
    blk_decoder    	  : lpm_decode WITH (LPM_WIDTH=4, LPM_DECODES=12);
    add_decoder       : lpm_decode WITH (LPM_WIDTH=5, LPM_DECODES=32);
    tap[5..1]         : NODE; % signals derived from vme_tap[5..0] reduced by ?? ns at the starting edge %

% Control registers and select signals %
    ctrl_wrd[13..0][7..0]: DFFE;   % ctrl_wrd0[5..0] = b0_offset_ET 
                                             1[5..0] = b0_offset_Trig
										     2[2..0] = DIRAC_ET_delay
                                             2[5..3] = DIRAC_Trig_delay
                                             3[]     = board-level control bits;
                                                       strobe to write to DAQ buffers and read out FIFOs.
                                             4[]     = DIRAC Board Masking Bits
                                             5[]     = ET_Sum, Trig_Sum, and ET_Raw Full FIFO Flag Masks 
                                             6[]     = Trig_Raw Full FIFO Flag Mask
									 		11[] 	 = _P3_Latch_OE and src_data
											12[] 	 = strobes to enable the sum chip to latch processed fake
													   ET and Trig data; strobes to latch raw and summed VME data
													   into ET and Trig L1FIFOs; strobes to latch P3; strobes to 
													   latch raw ET and Trig data in L1FIFOs
											13[]	 = parity and board error bits %
   	tri_ctrl_wrd[14..0][7..0]: TRI; % 7[] = ET_Sum, Trig_Sum, and ET_Raw Full FIFO Flags: Read only 
									  8[] = Trig_Raw Full FIFO Flags: Read only
                                      9[] = ET_Sum, Trig_Sum, and ET_Raw Empty FIFO Flags: Read only
									 10[] = Trig_Raw Empty FIFO Flags: Read only
                                     14[] = Controller Program version number: Read only;
                                            ?? still true? 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 "     "       "     %
    vme_read          : NODE; % !vme_write; this signal is used! %
    vme_sel           : NODE; % indicates that a transaction has been requested on a likely OK VME address % 
    ld_en             : NODE; % vme_sel & load %

% Control register mapping %
    b0_offset_ET[5..0]  : NODE; % time between the B0 pulse and the writing of the B0 ET data to the L1 FIFO %
    b0_offset_Trig[5..0]: NODE; % time between the B0 pulse and the writing of the B0 Trig data to the L1 FIFO %
    DIRAC_ET_delay[2..0]   : NODE; % maximum delay with which the incoming ET data arrive at the board, in units
                                   of 22 ns after the rising edge of CDF_clk %
    DIRAC_Trig_delay[2..0] : NODE; % maximum delay with which the incoming Trig data arrive at the board, in units
                                   of 22 ns after the rising edge of CDF_clk %
    run               : NODE; % ?? but this was already declared as an output?! %
    load              : NODE; % !run %
	parity			  : NODE; % specifies which wedge energy summary is sent to FP first from the processor %
    ctrl_wrd3_ld      : NODE; % load enable for control word 3 %
    ctrl_wrd12_ld     : NODE; % load enable for control word 12 %
	mask_DIRAC[7..0]  : NODE; % the masking bits for the 8 DIRAC boards responsible for providing input to CS %
    _FF_ET_Sum_[1..0]   : NODE; % masked full ET_Sum FIFO error flag (can be negated via control registers) %
    _FF_Trig_Sum_[1..0] : NODE; % masked full Trig_Sum FIFO error flag (can be negated via control registers) %
    _FF_ET_Raw_[3..0]   : NODE; % masked full ET_Raw FIFO error flag (can be negated via control registers) %
    _FF_Trig_Raw_[7..0] : NODE; % masked full Trig_Raw FIFO error flag (can be negated via control registers) %
    _FF_Bunch_Ctr_      : NODE; % masked full Bunch_Ctr FIFO error flag (can be negated via control registers) %
	proc_store_wedge[1..0] : NODE; % control register bits specifying the ET wedge that the VME data is stored for;
									 at most only one of these bits should be asserted (=1) at any time %
	proc_store_qtr[4..1]   : NODE; % control register bits specifying the Trig qtr that the VME data is stored for;
									 at most only one of these bits should be asserted (=1) at any time %
								   % also, only one of the proc_store_wedge[1..0] and proc_store_qtr[4..1] bits
									 should be asserted (=1) at any time %
	L1FIFO_Wclk_ET_Raw  : NODE; % control register bit that generates strobe signals to clock in raw ET L1FIFOs %
	L1FIFO_Wclk_Trig_Raw: NODE; % control register bit that generates strobe signals to clock in raw Trig L1FIFOs %

% Processor diagnostic ET and Trig data readout requests %
	proc_out			: NODE; % signals a processor diagnostic readout request %
	proc_out_Trig_Sum	: NODE;
	proc_out_ET_Sum	    : NODE;
	proc_out_Trig_qtr4	: NODE;
	proc_out_Trig_qtr3	: NODE;
	proc_out_Trig_qtr2	: NODE;
	proc_out_Trig_qtr1	: NODE;
	proc_out_ET_wedge1	: NODE;
	proc_out_ET_wedge0	: NODE;

% 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;  

% Multiplexers and signals to pick the cs_132ns 22-ns tap clock desired %
    cdfclk_ET_mux     				: lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=6, LPM_WIDTHS=3); 
	ET_132ns						: NODE;
                        			  % the 132 ns clock in phase with the incoming DIRAC ET data %
    cdfclk_Trig_mux   				: lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=6, LPM_WIDTHS=3); 
	Trig_132ns						: NODE;
                       				  % the 132 ns clock in phase with the incoming DIRAC Trig data %
    cdfclk_FPmux_ET_mux 			: lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=6, LPM_WIDTHS=3); 
                        	   		  % picks the 132 ns clock for multiplexing ET data out of the FP %
    cdfclk_FPmux_parity_mux 		: lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=2, LPM_WIDTHS=1); 
                        	   		  % specifies whether wedge 0 or wedge 1 energy summary is sent to FP first %
    cdfclk_FPmux_Trig_mux 			: lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=6, LPM_WIDTHS=3); 
                        	   		  % picks the 132 ns clock for multiplexing trigger data out of the FP %

% Bunch counter stuff % 
    _halt_            : NODE; % run & _halt %
    _recover_         : NODE; % load & _halt & _recover %
    pipe              : lpm_shiftreg WITH (LPM_WIDTH=42);
    b0delay_ET_mux    : lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=42, LPM_WIDTHS=6);
						% picks the ET B0 signal with desired delay %
    b0delay_Trig_mux  : lpm_mux WITH (LPM_WIDTH=1, LPM_SIZE=42, LPM_WIDTHS=6);
						% picks the Trig B0 signal with desired delay %
	b0_delayed_ET	  : NODE; % b0delay_ET_mux.result0 %
	b0_delayed_Trig   : NODE; % b0delay_Trig_mux.result0 %
 	diag_bunch_ctr_wen: NODE; % write enable that allows a fake bunch number to be output from TRI fake_bunchcnt %
    bunch_counter     : lpm_counter WITH (LPM_WIDTH=8);
    tri_counter[7..0] : TRI;
    fake_bunchcnt[7..0]: TRI; % ?? what's this for? %
    bunchcnt[7..0]    : TRI_STATE_NODE;

% L1FIFO write clock generation %
    hold_ET           : lpm_ff WITH (LPM_WIDTH=1);
    hold_Trig         : lpm_ff WITH (LPM_WIDTH=1);
    sclear_ET         : NODE;
    sclear_Trig		  : NODE;

% Other stuff %
    compa             : lpm_compare WITH (LPM_WIDTH=13, ONE_INPUT_IS_CONSTANT = "YES");
    compb             : lpm_compare WITH (LPM_WIDTH=3, ONE_INPUT_IS_CONSTANT = "YES");
    _cdf_error        : DFF; % ?? already declared as an output! %
	L1FIFO_Rclk		  : NODE; % This is declared because it generates a Lights signal %
	version[7..0]	  : NODE; 

BEGIN
  DEFAULTS					  % the startup state of most output signals is the unasserted state %
    _cdf_error.d = VCC;
	L1FIFO_Rclk = GND;
    L1FIFO_Wclk_ET_Sum = GND;
    L1FIFO_Wclk_Trig_Sum = GND;
    L1FIFO_Wclk_ET_Raw_wedge[] = GND;  
    L1FIFO_Wclk_Trig_Raw_qtr[] = GND;
	L1FIFO_Wclk_Bunch_Ctr = GND;    
	_L2B_W = VCC;
    _L2BD_R[] = VCC;
	_P3_Latch_OE = GND;
	P3_Latch_clk_ET = GND;
	P3_Latch_clk_Trig = GND;
	mask_DIRAC[] = GND;
  	one_or_two_bits3_[1..0] = B"00";
  	one_or_two_bits2_[1..0] = B"01";
  	one_or_two_bits1_[1..0] = B"11";
  	one_or_two_bits0_[1..0] = B"11";
	_src_data = VCC;
	proc_latch_clk_ET = GND;
	proc_latch_clk_Trig = GND;
	vme_clk_ET = GND;
	vme_clk_Trig = GND;
	store_vme_wedge_sel = GND;
	store_vme_qtr_sel[] = GND;
	proc_out_write = GND;
	proc_out_sel[] = GND; 
	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 %
    _ACK = VCC;
    _recover_ = VCC;
	run = GND;
	proc_version_ren = GND;
  END DEFAULTS;

  version7 = src_config;
  version[6..0] = 1;


%%% 0. Select the cdf_132ns[5..0] clocks in sync with the incoming ET and trigger DIRAC data;
	   these clocks will be used to latch the data in from the P3 backplane %%%
	%  Also select the cdf_132ns[5..0] clocks to be used for latching in the processed data,
	   for latching into L1 FIFOs, and for multiplexing the results out the front panel %

% 0.1 Incoming ET data %
  cdfclk_ET_mux.data[][] = cdf_132ns[]; % data inputs to the multiplexer are the cdf_clk 22 ns delayed signals %
  cdfclk_ET_mux.sel[] = DIRAC_ET_delay[]; % selection of the cdf_clk line to use is done 
											by this downloadable register %
  ET_132ns = cdfclk_ET_mux.result0; % the selected clf_clk line is named ET_132 ns %
  
% 0.2 Incoming Trig data %
  cdfclk_Trig_mux.data[][] = cdf_132ns[]; % data inputs to the multiplexer are the cdf_clk 22 ns delayed signals %
  cdfclk_Trig_mux.sel[] = DIRAC_Trig_delay[]; % selection of the cdf_clk line to use is done
											    by this downloadable register %
  Trig_132ns = cdfclk_Trig_mux.result0; % the selected clf_clk line is named Trig_132 ns %

% 0.9 ET_Sum FP multiplexing %
  cdfclk_FPmux_ET_mux.data0_[] = cdf_132ns1; % the cdf_132ns line to pick can be determined by simulation %
  cdfclk_FPmux_ET_mux.data1_[] = cdf_132ns2; % the numbers are modulo 6 %
  cdfclk_FPmux_ET_mux.data2_[] = cdf_132ns3; % currently, the multiplexing clock is the inverse of the *continuous* %
  cdfclk_FPmux_ET_mux.data3_[] = cdf_132ns4; % processed summary latch clock (so wedge 0 is default output first); %
  cdfclk_FPmux_ET_mux.data4_[] = cdf_132ns5; % note that this signal does not wait for the delayed b0 signal %
  cdfclk_FPmux_ET_mux.data5_[] = cdf_132ns0; % THE TIMING HERE IS BASED ON THE PROC_LATCH_CLK_ET SIGNAL %
  cdfclk_FPmux_ET_mux.sel[] = DIRAC_ET_delay[];
  
  cdfclk_FPmux_parity_mux.data0_[] = cdfclk_FPmux_ET_mux.result0;
  cdfclk_FPmux_parity_mux.data1_[] = !cdfclk_FPmux_ET_mux.result0;
  cdfclk_FPmux_parity_mux.sel[] = parity;
  FPmux_ET = cdfclk_FPmux_parity_mux.result0;

% 0.10 Trig_Sum FP multiplexing %
  cdfclk_FPmux_Trig_mux.data0_[] = cdf_132ns1; % the cdf_132ns line to pick can be determined by simulation %
  cdfclk_FPmux_Trig_mux.data1_[] = cdf_132ns2; % the numbers are modulo 6 %
  cdfclk_FPmux_Trig_mux.data2_[] = cdf_132ns3; % currently, the multiplexing clock is the inverse of the *continuous* %
  cdfclk_FPmux_Trig_mux.data3_[] = cdf_132ns4; % processed summary latch clock; %
  cdfclk_FPmux_Trig_mux.data4_[] = cdf_132ns5; % note that this signal does not wait for the delayed b0 signal %
  cdfclk_FPmux_Trig_mux.data5_[] = cdf_132ns0; % THE TIMING HERE IS BASED ON THE PROC_LATCH_CLK_TRIG SIGNAL %
  cdfclk_FPmux_Trig_mux.sel[] = DIRAC_Trig_delay[];
  FPmux_Trig = cdfclk_FPmux_Trig_mux.result0;

%%% I. VME transactions %%%

% I.0/ Basic signal generation and preliminary address decoding %
  
  vme_read = !vme_write;
  tap1 = vme_tap0 & vme_tap1; % vme_tap[5..0] are generated from the vme_data_str signal, 
								inverted from VME_Control bus %
  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;
  _ACK = !(vme_tap0 & tap5); % ?? isn't this redundant, since tap5 already involves "and"ing vme_tap0?
								  should this be changed to just tap5? %
  _vme_error = VCC;
  blk_decoder.data[] = vme_add[23..20]; % the block decoder tells what block the VME is trying to access %
  add_decoder.data[] = vme_add[6..2]; % the address decoder specifies which 32-bit word is being accessed; %
									  % that is why bits vme_add[1..0] are ignored %
									  % note that add_decoder returns ?? bits and add_decoder.eqYY returns
										the bit in the YYth place % 

% 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,
  Generate signals vme_sel & ld_en for that purpose  %
 
  compa.dataa[]  = vme_add[19..7]; % these bits should all be 0 when an appropriate 
									 VME address is being accessed %
  compa.datab[] = GND;
  compb.dataa[] = vme_add[26..24]; % these bits should always be set to 0;
									 they are the last 3 bits of the 5-bit GA word %
  compb.datab[] = GND;
  vme_sel = tap1 & !_modsel & compa.aeb & compb.aeb; % indicates that a transaction has been requested
													   on a likely OK VME address %
  ld_en = load & tap1 & !_modsel & compa.aeb & compb.aeb; % vme_sel & load; the reason it is not defined this way 
											 	 		    is because of signal time delay considerations %
   

% I.1/ VME read/write operations on *CONTROL* registers %

  ctrl_sel = vme_sel & blk_decoder.eq0; % ctrl_sel specifies whther a transaction (read or write operation) 
										  has been requested on the ctrl registers; 
										  blk_decoder.eq0 is 1 if the VME is addressing the control registers: 
										  0x000030 to 0x000000 in VME address space; 
										  it is not necessary to be in the load mode for ctrl_sel to be asserted %
  w_ctrl = vme_write & ctrl_sel & load; % only allow writing to the control registers in the load mode %
										% Note: it takes one VME write cycle to set the run control bit;
										  		setting other registers in the same word doesn't produce the
												desired result %
  r_ctrl = vme_read & ctrl_sel; % reading the control registers via VME can be done in the run mode also %
  ctrl_wrd[][].clk = tap2; % write strobe for control registers; 
							  ?? tap2 used because tap1 is the signal that enables ld_en? %
  ctrl_wrd0_[].ena = w_ctrl & add_decoder.eq0; % only allows writing in the load mode %
  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 the "run" ctrl bit when in run mode %
  ctrl_wrd3_[7..1].ena = w_ctrl & add_decoder.eq3; % back to allowing only writing in the load mode %
  ctrl_wrd4_[].ena = w_ctrl & add_decoder.eq4;
  ctrl_wrd5_[].ena = w_ctrl & add_decoder.eq5;
  ctrl_wrd6_[].ena = w_ctrl & add_decoder.eq6;
  ctrl_wrd11_[].ena = w_ctrl & add_decoder.eq11;
  ctrl_wrd12_[].ena = w_ctrl & add_decoder.eq12;
  ctrl_wrd13_[].ena = w_ctrl & add_decoder.eq13;
  ctrl_wrd[][].d = vme_dat[];
  tri_ctrl_wrd[6..0][].in = ctrl_wrd[6..0][].q;
  tri_ctrl_wrd7_[1..0].in = !_FF_ET_Sum[1..0]; % just FF_ET_Sum[1..0], asserted high %
  tri_ctrl_wrd7_[3..2].in = !_FF_Trig_Sum[1..0];
  tri_ctrl_wrd7_[7..4].in = !_FF_ET_Raw[3..0];
  tri_ctrl_wrd8_[].in = !_FF_Trig_Raw[7..0];
  tri_ctrl_wrd9_[1..0].in = !_EF_ET_Sum[1..0];
  tri_ctrl_wrd9_[3..2].in = !_EF_Trig_Sum[1..0];
  tri_ctrl_wrd9_[7..4].in = !_EF_ET_Raw[3..0];
  tri_ctrl_wrd10_[].in = !_EF_Trig_Raw[7..0];
  tri_ctrl_wrd11_[].in = ctrl_wrd11_[].q;
  tri_ctrl_wrd12_[].in = ctrl_wrd12_[].q;
  tri_ctrl_wrd13_0.in = ctrl_wrd13_0.q;
  tri_ctrl_wrd13_1.in = !_cdf_error; % the board error bit; read only %
  tri_ctrl_wrd13_2.in = !_FF_Bunch_Ctr;
  tri_ctrl_wrd13_3.in = !_EF_Bunch_Ctr;
  tri_ctrl_wrd13_[7..4].in = ctrl_wrd13_[7..4].q; % spare bits %
  tri_ctrl_wrd14_[].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;
  tri_ctrl_wrd9_[].oe = r_ctrl & add_decoder.eq9;
  tri_ctrl_wrd10_[].oe = r_ctrl & add_decoder.eq10;
  tri_ctrl_wrd11_[].oe = r_ctrl & add_decoder.eq11;
  tri_ctrl_wrd12_[].oe = r_ctrl & add_decoder.eq12;
  tri_ctrl_wrd13_[].oe = r_ctrl & add_decoder.eq13;
  tri_ctrl_wrd14_[].oe = r_ctrl & add_decoder.eq14;
  proc_version_ren = tap1 & r_ctrl & add_decoder.eq15;
  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;
  vme_data[] = tri_ctrl_wrd9_[].out;
  vme_data[] = tri_ctrl_wrd10_[].out;
  vme_data[] = tri_ctrl_wrd11_[].out;
  vme_data[] = tri_ctrl_wrd12_[].out;
  vme_data[] = tri_ctrl_wrd13_[].out;
  vme_data[] = tri_ctrl_wrd14_[].out;
  
% Control register mapping (and associated generation of strobes for diagnostics) %
  b0_offset_ET[] = ctrl_wrd0_[5..0].q; 
  b0_offset_Trig[] = ctrl_wrd1_[5..0].q;
  DIRAC_ET_delay[] = ctrl_wrd2_[2..0].q;
  DIRAC_Trig_delay[] = ctrl_wrd2_[5..3].q;
  run = ctrl_wrd3_0.q; % Run or load mode : 0 = load; 1 = run %
  load = !run;
  parity = ctrl_wrd13_0.q; % specifies whether CS returns the wedge 0 or wedge 1 summary first %
  ctrl_wrd3_ld = tap3 & !_modsel & blk_decoder.eq0 & vme_write & load & add_decoder.eq3;
  ctrl_wrd12_ld = tap3 & !_modsel & blk_decoder.eq0 & vme_write & load & add_decoder.eq12;
  _recover_ = !(ctrl_wrd3_1.q & ctrl_wrd3_ld); 
					% when control register recover = 1 in load mode, resets the L1 FIFOs and the board error bit %
  L1FIFO_Rclk = ctrl_wrd3_2.q & ctrl_wrd3_ld;
					% when control register FIFO_R = 1 in load mode, generates a strobe that reads out the L1 FIFOs %
  _L2B_W = !(ctrl_wrd3_3.q & ctrl_wrd3_ld & !tap5);
					% when control register L2B_W = 1 in load mode, generates a strobe that writes to a L2 buffer %
					% the strobe comes from the !tap5 part; ?? why is !tap5 used? %	  
  L2B[] = load & ctrl_wrd3_[5..4].q;
					% in load mode, specifies the L2 buffer address to write to when L2B_W is asserted %
  mask_DIRAC[] = ctrl_wrd4_[].q;
  _FF_ET_Sum_[] = _FF_ET_Sum[] # ctrl_wrd5_[1..0].q; 
					% mask FF_ET_Sum flag in order to be able to still run with bad FIFO %
  _FF_Trig_Sum_[] = _FF_Trig_Sum[] # ctrl_wrd5_[3..2].q; 
					% mask FF_Trig_Sum flag in order to be able to still run with bad FIFO %
  _FF_ET_Raw_[] = _FF_ET_Raw[] # ctrl_wrd5_[7..4].q; 
					% mask FF_ET_Raw flag in order to be able to still run with bad FIFO %
  _FF_Trig_Raw_[] = _FF_Trig_Raw[] # ctrl_wrd6_[].q; 
					% mask FF_Trig_Raw flag in order to be able to still run with bad FIFO %
  _FF_Bunch_Ctr_ = _FF_Bunch_Ctr # ctrl_wrd11_2.q; 
					% mask FF_Bunch_Ctr flag in order to be able to still run with bad FIFO %
  _P3_Latch_OE = ctrl_wrd11_0.q; % 0 if P3 Latch is enabled; 1 if latch doesn't drive input data bus %
  _src_data = !ctrl_wrd11_0.q; % 0 when input data comes from VME data bus; 
								 note that a one-bit control register controls both _P3_Latch_OE and _src_data %
  proc_store_wedge0 = ld_en & vme_write & blk_decoder.eq2 & add_decoder.eq0;
					% when the proper write address is issued in load mode, 
					  strobe signals are generated to enable the processor to latch data
					  on the VME_Data bus as ET wedge 1 inputs, and also to latch data into Wedge0 ET Raw L1FIFOs %
  proc_store_wedge1 = ld_en & vme_write & blk_decoder.eq2 & add_decoder.eq1;
					% when the proper write address is issued in load mode, 
					  strobe signals are generated to enable the processor to latch data
					  on the VME_Data bus as ET wedge 1 inputs, and also to latch data into Wedge1 ET Raw L1FIFOs %
  proc_latch_clk_ET = ctrl_wrd12_0.q & ctrl_wrd12_ld;
					% when =1 in load mode, a strobe signal is generated to enable the processor to latch 
					  processed data before outputting %
  L1FIFO_Wclk_ET_Sum = ctrl_wrd12_1.q & ctrl_wrd12_ld;
					% when =1 in load mode, a strobe signal is generated to enable the processor to latch data
					  into the summed ET L1FIFOs %
  proc_store_qtr1 = ld_en & vme_write & blk_decoder.eq3 & add_decoder.eq0;
					% when the proper write address is issued in load mode, 
					  strobe signals are generated to enable the processor to latch data
					  on the VME_Data bus as Trig qtr 1 inputs, and also to latch data into qtr1 Trig Raw L1FIFOs %
  proc_store_qtr2 = ld_en & vme_write & blk_decoder.eq3 & add_decoder.eq1;
					% when the proper write address is issued in load mode, 
					  strobe signals are generated to enable the processor to latch data
					  on the VME_Data bus as Trig qtr 1 inputs, and also to latch data into qtr1 Trig Raw L1FIFOs %
  proc_store_qtr3 = ld_en & vme_write & blk_decoder.eq3 & add_decoder.eq2;
					% when the proper write address is issued in load mode, 
					  strobe signals are generated to enable the processor to latch data
					  on the VME_Data bus as Trig qtr 1 inputs, and also to latch data into qtr1 Trig Raw L1FIFOs %
  proc_store_qtr4 = ld_en & vme_write & blk_decoder.eq3 & add_decoder.eq3;
					% when the proper write address is issued in load mode, 
					  strobe signals are generated to enable the processor to latch data
					  on the VME_Data bus as Trig qtr 1 inputs, and also to latch data into qtr1 Trig Raw L1FIFOs %
  proc_latch_clk_Trig = ctrl_wrd12_2.q & ctrl_wrd12_ld;
					% when =1 in load mode, a strobe signal is generated to enable the processor to latch 
					  processed data before outputting %
  L1FIFO_Wclk_Trig_Sum = ctrl_wrd12_3.q & ctrl_wrd12_ld;
					% when =1 in load mode, a strobe signal is generated to enable the processor to latch data
					  into the summed Trig L1FIFOs %
  P3_Latch_clk_ET = ctrl_wrd12_4.q & ctrl_wrd12_ld;
					% when =1 in load mode, a strobe signal is generated to enable latching of data on P3 %
  P3_Latch_clk_Trig = ctrl_wrd12_5.q & ctrl_wrd12_ld;
					% when =1 in load mode, a strobe signal is generated to enable latching of data on P3 %
  L1FIFO_Wclk_ET_Raw = ctrl_wrd12_6.q & ctrl_wrd12_ld;
					% when =1 in load mode, a strobe signal is generated to enable latching of raw data into L1FIFOs %
  L1FIFO_Wclk_Trig_Raw = ctrl_wrd12_7.q & ctrl_wrd12_ld;
					% when =1 in load mode, a strobe signal is generated to enable latching of raw data into L1FIFOs %
  L1FIFO_Wclk_ET_Raw_wedge0 = L1FIFO_Wclk_ET_Raw; 
  L1FIFO_Wclk_ET_Raw_wedge1 = L1FIFO_Wclk_ET_Raw; 
  L1FIFO_Wclk_Trig_Raw_qtr1 = L1FIFO_Wclk_Trig_Raw; 
  L1FIFO_Wclk_Trig_Raw_qtr2 = L1FIFO_Wclk_Trig_Raw; 
  L1FIFO_Wclk_Trig_Raw_qtr3 = L1FIFO_Wclk_Trig_Raw; 
  L1FIFO_Wclk_Trig_Raw_qtr4 = L1FIFO_Wclk_Trig_Raw; 


% I.2/ Generation of signals to handle VME transactions with other chips on the board, including:
	   - diagnostic strobes issued in the load mode
	   - VME readout of buffers during run-time		 %
   
%  a.1/ ET diagnostic VME data input strobes:
	    generate strobe signals to enable processor to latch in VME_Data as ET inputs for wedge 0 or 1;
	    generate a strobe to enable the wedge 0 or 1 ET Raw L1FIFOs to latch in input data driven by processor %
	
	store_vme_wedge_sel = proc_store_wedge1;
					% the default value of store_vme_wedge_sel is 0 (wedge 0), unless wedge 1 is specified %
	vme_clk_ET = (proc_store_wedge0 # proc_store_wedge1) & vme_tap2 & !vme_tap5;
					% & !tap5 is needed to insure that vme_clk_ET goes low BEFORE store_vme_wedge_sel goes low %
	L1FIFO_Wclk_ET_Raw_wedge0 = proc_store_wedge0 & tap4;
	L1FIFO_Wclk_ET_Raw_wedge1 = proc_store_wedge1 & tap4;

%  a.2/ Trig diagnostic VME data input strobes:
	    generate strobe signals to enable processor to latch in VME_Data as Trig inputs for quarter 1, 2, 3, or 4;
	    generate a strobe to enable qtr 1, 2, 3, or 4 Trig Raw L1FIFOs to latch in input data driven by processor %
	
	store_vme_qtr_sel1 = proc_store_qtr3 # proc_store_qtr4;
	store_vme_qtr_sel0 = proc_store_qtr2 # proc_store_qtr4;
					% the default value of store_vme_qtr_sel[1..0] is 0 (qtr 1), unless another qtr is specified %
	vme_clk_Trig = (proc_store_qtr1 # proc_store_qtr2 # proc_store_qtr3 # proc_store_qtr4) & tap3;
	L1FIFO_Wclk_Trig_Raw_qtr1 = proc_store_qtr1 & tap5;
	L1FIFO_Wclk_Trig_Raw_qtr2 = proc_store_qtr2 & tap5;
	L1FIFO_Wclk_Trig_Raw_qtr3 = proc_store_qtr3 & tap5;
	L1FIFO_Wclk_Trig_Raw_qtr4 = proc_store_qtr4 & tap5;

%  b/ Reading out raw and processed ET and Trig data from the processor directly %
	
%  b.1/ Decoding the address to determine what data is requested for readout %

	proc_out = ld_en & blk_decoder.eq4 & vme_read;
					% analogous to the r_ctrl node for the control registers section %
	proc_out_Trig_Sum = proc_out & add_decoder.eq7;
	proc_out_ET_Sum = proc_out & add_decoder.eq6;
	proc_out_Trig_qtr4 = proc_out & add_decoder.eq5;
	proc_out_Trig_qtr3 = proc_out & add_decoder.eq4;
	proc_out_Trig_qtr2 = proc_out & add_decoder.eq3;
	proc_out_Trig_qtr1 = proc_out & add_decoder.eq2;
	proc_out_ET_wedge1 = proc_out & add_decoder.eq1;
	proc_out_ET_wedge0 = proc_out & add_decoder.eq0;

%  b.2/ Generating the strobes %

	proc_out_write = (proc_out_Trig_Sum # proc_out_ET_Sum
					  # proc_out_Trig_qtr4 # proc_out_Trig_qtr3 # proc_out_Trig_qtr2 # proc_out_Trig_qtr1
					  # proc_out_ET_wedge1 # proc_out_ET_wedge0) & tap4;
	proc_out_sel2 = (proc_out_Trig_Sum # proc_out_ET_Sum # proc_out_Trig_qtr4 # proc_out_Trig_qtr3) & tap2;
	proc_out_sel1 = (proc_out_Trig_Sum # proc_out_ET_Sum # proc_out_Trig_qtr2 # proc_out_Trig_qtr1) & tap2;
	proc_out_sel0 = (proc_out_Trig_Sum # proc_out_Trig_qtr4 # proc_out_Trig_qtr2 # proc_out_ET_wedge1) & tap2;

%  c/ Writing to the bunch counter L1FIFO %

    diag_bunch_ctr_wen = ld_en & vme_write & blk_decoder.eq5 & add_decoder.eq0;
					% output enable for the fake_bunchcnt TRI node %
    fake_bunchcnt[].in = vme_dat[];
    fake_bunchcnt[].oe = diag_bunch_ctr_wen;
    bunchcnt[] = fake_bunchcnt[].out;
    L1FIFO_Wclk_Bunch_Ctr = diag_bunch_ctr_wen & tap3; % the tap signal used may change %

%  d/ Read from DAQ buffers %

    _L2BD_R[] = !(vme_sel & (blk_decoder.eq8 # blk_decoder.eq9 # blk_decoder.eq10 # blk_decoder.eq11)
                 & vme_read & add_decoder.eq[8..0]); 
							% blk_decoder.eq8 = DAQ Buffer 1
							  blk_decoder.eq9 = DAQ Buffer 2
							  blk_decoder.eq10 = DAQ Buffer 3
							  blk_decoder.eq11 = DAQ Buffer 4 %
    L2BD[] = vme_add[21..20];

% I.3 / IDprom word %

% I.3a/ 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"30"; 		% Hex ASCII code for 0 %
	IDprom8_[] = H"20";			% Hex ASCII code for blank space %
	IDprom9_[] = H"43"; 		% Hex ASCII code for C %
	IDprom10_[] = H"52"; 		% Hex ASCII code for R %
	IDprom11_[] = H"41"; 		% Hex ASCII code for A %
	IDprom12_[] = H"54"; 		% Hex ASCII code for T %
	IDprom13_[] = H"45"; 		% Hex ASCII code for E %
	IDprom14_[] = H"53"; 		% Hex ASCII code for S %
	IDprom15_[] = H"55"; 		% Hex ASCII code for U %
	IDprom16_[] = H"4D"; 		% Hex ASCII code for M %
	IDprom[31..17][] = H"00"; 	% Hex ASCII code for null %

% I.3a/ VME read operations on IDprom %

  r_idprom = vme_sel & blk_decoder.eq1 & vme_read;
  tri_idprom[][].in = IDprom[][];
  tri_idprom[]_0.oe = r_idprom & add_decoder.eq[]; % this block of code enables all the bits %
  tri_idprom[]_1.oe = r_idprom & add_decoder.eq[]; % of one ASCII character to be returned %
  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; % this block of code puts only one ASCII character (8 bits) %
  vme_data[] = tri_idprom1_[].out; % in the 8-bit bus vme_data, which is then mapped to vme_dat[31..24] %
  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[]; % connects vme_data[7..0] to vme_dat[31..24] %
  

    
%%% II. RUN mode: Handling of halt/reset start-up sequence and DAQ buffer management %%%

    _halt_ = _halt & run;  % _halt_ is always asserted in load mode %
    _recover_ = load # _halt # _recover; % _recover_ is asserted only if _halt and _recover 
										   are asserted when in run mode %
    
% II.1/ Bunch Counter - Note: no need to reset/hold its value before b0 on startup sequence %

		
% Generating the b0_delayed signals, one for P3_Latch_clk, proc_latch_clk, and raw data latching,
  and the other for summed data latching %

    pipe.enable = _halt_; 
    pipe.aclr = !_recover_; % the pipe is cleared (all 42 bits set to 0) when _recover_ is asserted (=0) %
    pipe.clock = cdf_132ns3; % choosing this cdf_clk tap signal allows the data input (!_b0) to be valid before clk %
    pipe.shiftin = !_b0; % the bit shifted in is 1 if the bunch is b0 %

% Generate b0delayed %

    b0delay_ET_mux.data[][] = pipe.q[]; % the input is 42 bits %
    b0delay_ET_mux.sel[] = b0_offset_ET[] - 1; % this downloadable offset register specifies by how
												 much the b0delay_ET signal should be delayed after b0 %
											   % ?? keep the "-1" part? %
    b0_delayed_ET = b0delay_ET_mux.result0; % ?? should this new variable be kept? %
 
    b0delay_Trig_mux.data[][] = pipe.q[]; % the input is 42 bits %
    b0delay_Trig_mux.sel[] = b0_offset_Trig[] - 1; % this downloadable offset register specifies by how
												     much the b0delay_ET signal should be delayed after b0 %
												   % ?? keep the "-1" part? %
    b0_delayed_Trig = b0delay_Trig_mux.result0; % ?? should this new variable be kept? %

% Bunch counter and bunch counter L1FIFO clock %

    bunch_counter.sclr = b0_delayed_ET; % choose ET to base bunch counter timing on %
    bunch_counter.cnt_en = _halt_;
    bunch_counter.clock = ET_132ns;
    tri_counter[].in = bunch_counter.q[];
    tri_counter[].oe = run; 
    bunchcnt[] = tri_counter[].out;
    bunch_cnt[] = bunchcnt[];

	L1FIFO_Wclk_Bunch_Ctr = !hold_ET.q0 & ET_clk2 & run;
							% L1FIFO write clock for the bunch counter is based on ET timing%
     
% II.2a/ ET clocks; L1 FIFO write clocks are asserted by the ET delayed B0 signal after a halt %
    
    hold_ET.clock = ET_132ns; % ?? is this the correct clk signal to use? %
    sclear_ET = _halt_ & b0_delayed_ET; 
						% sclear = 0 if either _halt is asserted (=0) or b0_delayed_ET = 0;
						  sclear = 1 if both NOT halted and b0_delayed_ET = 1
						  (this corresponds to waiting for the correct number of bunch time cycles) %
    hold_ET.enable = sclear_ET;  
    hold_ET.aset = !_halt_; % when _halt is asserted (=0), hold.q is set to 1 %
    hold_ET.sclr = sclear_ET; % when sclear = 1, hold.q is set to 0 %
	P3_Latch_clk_ET = !hold_ET.q0 & ET_132ns; % When operating normally, hold.q = 0 %
	ET_clk0 = P3_Latch_clk_ET;
    L1FIFO_Wclk_ET_Raw_wedge[1..0] = !hold_ET.q0 & ET_clk1;
	proc_latch_clk_ET = !hold_ET.q0 & ET_clk3;
	L1FIFO_Wclk_ET_Sum = !hold_ET.q0 & ET_clk4;

% II.2b/ Trig clocks; L1 FIFO write clocks are asserted by the Trig delayed B0 signal after a halt %
    
    hold_Trig.clock = Trig_132ns; % ?? is this the correct clk signal to use? %
    sclear_Trig = _halt_ & b0_delayed_Trig; 
						% sclear = 0 if either _halt is asserted (=0) or b0_delayed_Trig = 0;
						  sclear = 1 if both NOT halted and b0_delayed_Trig = 1
						  (this corresponds to waiting for the correct number of bunch time cycles) %
    hold_Trig.enable = sclear_Trig;  
    hold_Trig.aset = !_halt_; % when _halt is asserted (=0), hold.q is set to 1 %
    hold_Trig.sclr = sclear_Trig; % when sclear = 1, hold.q is set to 0 %
	P3_Latch_clk_Trig = !hold_Trig.q0 & Trig_132ns; % When operating normally, hold.q = 0 %
	Trig_clk0 = P3_Latch_clk_Trig;
    L1FIFO_Wclk_Trig_Raw_qtr[4..1] = !hold_Trig.q0 & Trig_clk1; 
	proc_latch_clk_Trig = !hold_Trig.q0 & Trig_clk3;
	L1FIFO_Wclk_Trig_Sum = !hold_Trig.q0 & Trig_clk4;

% II.3/ Read out of L1 FIFOs / write to DAQ buffers % 
					% since these are L1 decision FIFO reads and buffer writes, does it matter what signals to use? %
    
    L1FIFO_Rclk = _halt_ & !(_L1A & _L1R) & cdf_132ns3 & cdf_132ns4;
						% you don't have to wait for the delayed B0 signal because operation is based on
						  receipt of the L1A or L1R signal % 
						% you DO have to base the control of this signal on the cdf_132ns clocks, because the L1A
						  L1R are based on the cdf_132ns0 clock! %
						% The gating for this strobe has been selected for the 74ACT7806 FIFO chip. % 
    _L2B_W = !_halt_ # _L1A # cdf_132ns4 # cdf_132ns5; 
						% The gating for this strobe has been selected for the 74ACT7806 FIFO chip. % 
    L2B[] = run & !_L2B[];

%%% III. Error handling %%%

    _cdf_error.clk = cdf_132ns0;
    _cdf_error.d = _FF_ET_Sum_0 & _FF_ET_Sum_1 & _FF_Trig_Sum_0 & _FF_Trig_Sum_1 
				 & _FF_ET_Raw_0 & _FF_ET_Raw_1 & _FF_ET_Raw_2 & _FF_ET_Raw_3 
				 & _FF_Trig_Raw_0 & _FF_Trig_Raw_1 & _FF_Trig_Raw_2 & _FF_Trig_Raw_3
				 & _FF_Trig_Raw_4 & _FF_Trig_Raw_5 & _FF_Trig_Raw_6 & _FF_Trig_Raw_7
				 & _FF_Bunch_Ctr_;
    _cdf_error.prn  = _recover_;

%%% IV. Backplane and Front panel control %%%
	% Note: there is a LED for power, which does not require a Lights signal %

    Lights0 = run; 
    Lights1 = load;
	Lights2 = vme_sel;
    Lights3 = cdf_132ns0; 
	Lights4 = L1FIFO_Rclk;
	Lights5 = parity;
    Lights6 = _cdf_error;

END;
