"$Id: pld2.src,v 1.15 2001/02/24 14:52:27 warren Exp $
"==============================================================================================
#TITLE    'HELIX DRIVER PLD2: CONTROL LOGIC';
#ENGINEER 'Gil Nixon / John Lane / Dominic A Hayes / Matt Warren';
#COMPANY  'University College London';
#COMMENT  'Mach5 192/120-7YC';
"==============================================================================================
"$Log: pld2.src,v $
"Revision 1.15  2001/02/24 14:52:27  warren
"midway through new resets and delay unit read-back mods
"
"Revision 1.14  2001/02/23 17:08:34  warren
"Improved on_clk system
"
"Revision 1.13  2001/02/23 15:44:40  warren
"Added clk_on input
"
"Revision 1.12  2001/02/19 17:48:18  warren
"Added CVS version into  source info
"




" MODS
"------
"08sep00 channel now decoded from register_data[23..20] instead of ab[19..16].
"17oct00 delay_write replaced by write_delay_unit.
"        writeb input to replace wr.
"			Added sl_sent reg to show when loads have completed
"30nov00 changed clocking on data_reg from /db_clk to db_clk - okay? - MRMW
"        added hsd_mode to the statreg (bit3) - MRMW

"04dec00	added soft_trig input. added 'trigger' (= soft_trig OR trig) output to pld1. MRMW
"			 This makes use of 2 spare bus lines ...
"			Trig_Sent stat bit now = (trigger AND /hsd_mode AND trig_sd) MRMW
"			Added channel 15 for broadcasting to all units - JBL/MRMW
"02jan01 tp_ck is not clocked by the test - its comes from CLOCK changes needed. (JBL)
"			 test_pulse (op ff's) are clocked by a gate-delayed test signal. Its inputs are inverted mask reg.
"	 		 the ff is reset by an undelayed test - *** THIS DOES NOT WORK EITHER!!!! test is skewed on pld
"04jan01	Zero'd unused db lines for small reg reads
"			Added soft_trig ..... (see pld1 comment)
"08jan01 Changed test to use tp_ck again (hardware mod on board may work as tp_ck is on clk ip to pld)
"23feb01 Added clk_on input, also added it to stat reg (bit 4)
"			/on_clk now resets SerialLoad and Test and presets NReset.
"24feb01 TP_Mask now resets to all enabled.


"==============================================================================================






"==============================================================================================
"                                  PLD INPUT/OUTPUT DECLARATIONS
"==============================================================================================


"----------------------------------------------------------------------------------------------
" PLD-WIDE CLOCKS/RESETS etc.
"----------------------------
			INPUT	db_clk;
															
			INPUT	reset;                 "reset: (reset_cmd OR onres).    
														

		" FROM MASTER BOX
		"-----------------

         INPUT	pld_ck,
					trig,
					test;

					
	
		" VME DATABUS
		"-------------

LOW_TRUE INPUT writeb;

			BIPUT	db[23..0]            "bi-directional i/o pins.
						ENABLED_BY dboe;
			NODE  dboe;                "db output enable.


"----------------------------------------------------------------------------------------------
" SPARES
"--------
			INPUT		read_feedback;		" for VME reads of the feedback reg IF it was on this pld.
			
			
         "
         "INPUT		spare[23..0];
         INPUT		spare[21..0]; " *** used 2 spare lines:
         INPUT		soft_trig;
         			
         OUTPUT	trigger; " *** this is the new 'trig' o/p to pld1
         trigger = (soft_trig OR trig); 
         
         INPUT		clk_on;

"==============================================================================================

"  This pld:
"  - defaults to trigger pass-through mode (/hsd_mode).
"  - stores the serial data for download to each helix chip.
"  - outputs the stored data (sync'd to pld_ck) to all helix chips (in parallel).
"  - when bitstream completed (counted) a load pulse generated on relevant channel.
"  - a test pulse can also be issued to a set of (un)masked helix chips.
"  - the mask is pre-loaded from VME.
"  - a helix reset can be issued and is set during the download process.

"----------------------------------------------------------------------------------------------

	   
	"---------------------------------------------------------------------------
	" STARTING THE OUTPUT SEQUENCE - OUTPUT_DATA
	"------------------------------------------------------
	
	"gets output_data_set from pld1, and
	" syncs it with the pld clk issuing output_data
	
		INPUT		output_data_set;   "*** added _set   "Set board to Output Data to the Helix.  (pld_ck sync'd signal)
		OUTPUT	output_busy			 " high when busy sending
						DEFAULT_TO 0;
		
		NODE		seq_count_max, 		"seq_counter o/ps, reset seq_counter and issue load signal.
					seq_count_reset  
						DEFAULT_TO 0;

	
	
	   NODE   qstore                       "Stored output_data_set.
	            CLOCKED_BY output_data_set  
	            RESET_BY (seq_count_max OR reset);
	            
	   NODE   qsync                        "sync to pld_ck FF.
	            CLOCKED_BY /pld_ck			"
	            RESET_BY (seq_count_max OR reset);
	            
	   NODE   output_data                  "sync'd output_data signal.
	            CLOCKED_BY pld_ck
	            RESET_BY (seq_count_reset OR reset);

		qstore.D      = 1;            "store    
		qsync.D       = qstore;       "i/p to first sync FF    
		output_data.D = qsync;        "i/p to final sync FF.    
	
  		output_busy	  = qstore OR output_data; " the 'OR output_data' lengthens busy_time one clk
		

	
		"--------------------
		" seq_counter
		"-------------
		

		
		NODE	seq_count[5]              "sequence length ring counter.
					CLOCKED_BY pld_ck
					CLOCK_ENABLED_BY output_data
					RESET_BY (seq_count_reset OR reset);
					
	
	   NODE   load                      "load signal, generated at completion of
	            DEFAULT_TO 0;           "  data sequence output.
	
		
		seq_count.D = seq_count .+. 1;       "defines inputs to seq_count FF's => seq_counter.
		
		CASE seq_count
      	WHEN 21 => seq_count_max   = 1;    "resets en_feedback, and q1/2 voutput_data sync FFs.
      	WHEN 22 => seq_count_reset = 1;    "resets output_data FF.
	   END CASE;
	   
	   load = seq_count_max;
      
	 	   
	"-------------------------------------------------------------------------------------------
	" Trigger/Serial Data Multiplexer (requires reset to reset FF)
	"-------------------------------------------------------------
	

		INPUT	 hsd_mode;						"for setting mode to Serial Download

		OUTPUT trig_sd
					CLOCKED_BY /pld_ck
					RESET_BY reset;

		NODE   data_out                  "the data stream from sequence register (before o/p MUX)
	            DEFAULT_TO 0;
		
		
		IF (hsd_mode) THEN					"board in "helix serial data" mode.
			trig_sd = data_out;
		ELSE										"default normal running, trigger pass-through.
			trig_sd = trigger;
		END IF;

			
	"-------------------------------------------------------------------------------------------
	" DATA Register
	"--------------------
	
		INPUT	access_data;						"VME access to the sequence Data Register
 	
	   NODE   register_data[23..0]			"the sequence register  VME R/W.
	            CLOCKED_BY db_clk	
	            CLOCK_ENABLED_BY	(writeb AND access_data)
	            RESET_BY reset;
	            
	   register_data[23..0] = db[23..0];						"for VME write to register
	

		
		" 4 TO 16 DECODE VME ADDRESS
		"----------------------------
	
	   NODE   channel[14..0]
	            DEFAULT_TO 0;
	
	
	   CASE (register_data[23..20])                 "upper 4bits of register_data.
	      WHEN 0  => channel[ 0] = 1;					" select the channel
	      WHEN 1  => channel[ 1] = 1;
	      WHEN 2  => channel[ 2] = 1;
	      WHEN 3  => channel[ 3] = 1;
	      WHEN 4  => channel[ 4] = 1;
	      WHEN 5  => channel[ 5] = 1;
	      WHEN 6  => channel[ 6] = 1;
	      WHEN 7  => channel[ 7] = 1;
	      WHEN 8  => channel[ 8] = 1;
	      WHEN 9  => channel[ 9] = 1;
	      WHEN 10 => channel[10] = 1;
	      WHEN 11 => channel[11] = 1;
	      WHEN 12 => channel[12] = 1;
	      WHEN 13 => channel[13] = 1;
	      WHEN 14 => channel[14] = 1;
	      WHEN 15 => channel[14..0] = 7FFFh; " broadcast to all units
	   END CASE;

	   
		CASE (seq_count)
			WHEN  1 => data_out = register_data[19];
			WHEN  2 => data_out = register_data[18];
			WHEN  3 => data_out = register_data[17];
			WHEN  4 => data_out = register_data[16];
			WHEN  5 => data_out = register_data[15];
			WHEN  6 => data_out = register_data[14];
			WHEN  7 => data_out = register_data[13];
			WHEN  8 => data_out = register_data[12];
			WHEN  9 => data_out = register_data[11];
			WHEN 10 => data_out = register_data[10];
			WHEN 11 => data_out = register_data[ 9];   
			WHEN 12 => data_out = register_data[ 8]; 
			WHEN 13 => data_out = register_data[ 7]; 
			WHEN 14 => data_out = register_data[ 6]; 
			WHEN 15 => data_out = register_data[ 5]; 
			WHEN 16 => data_out = register_data[ 4]; 
			WHEN 17 => data_out = register_data[ 3]; 
			WHEN 18 => data_out = register_data[ 2]; 
			WHEN 19 => data_out = register_data[ 1]; 
			WHEN 20 => data_out = register_data[ 0]; 
		END CASE;



	"-------------------------------------------------------------------------------------------
	" SER_LOAD register - 
	"-----------------------

	   OUTPUT   ser_load[14..0]
	         	   CLOCKED_BY /pld_ck
	            	RESET_BY (reset OR /clk_on)
		            DEFAULT_TO 0;

		" load pulse generation
		ser_load[14].D	= channel[14] AND load;
		ser_load[13].D = channel[13] AND load;
		ser_load[12].D = channel[12] AND load;
		ser_load[11].D = channel[11] AND load;
		ser_load[10].D = channel[10] AND load;
		ser_load[ 9].D = channel[ 9] AND load;
		ser_load[ 8].D = channel[ 8] AND load;
		ser_load[ 7].D = channel[ 7] AND load;
		ser_load[ 6].D = channel[ 6] AND load;
		ser_load[ 5].D = channel[ 5] AND load;
		ser_load[ 4].D = channel[ 4] AND load;
		ser_load[ 3].D = channel[ 3] AND load;
		ser_load[ 2].D = channel[ 2] AND load;
		ser_load[ 1].D = channel[ 1] AND load;
		ser_load[ 0].D = channel[ 0] AND load;
		          

	"-------------------------------------------------------------------------------------------
	" SL_SENT REGISTER 
	"---------------------------
		" reg 'remembers' ser_loads as they are sent
		
		INPUT	access_sl_sent;
		
		NODE register_sl_sent[14..0];


		NODE sls_rst; " for legibility only:
		sls_rst = (access_sl_sent AND writeb) OR reset;

		" self clocking registers
		register_sl_sent[ 0] = /sls_rst AND (register_sl_sent[ 0] OR ser_load[ 0]);
		register_sl_sent[ 1] = /sls_rst AND (register_sl_sent[ 1] OR ser_load[ 1]);
		register_sl_sent[ 2] = /sls_rst AND (register_sl_sent[ 2] OR ser_load[ 2]);
		register_sl_sent[ 3] = /sls_rst AND (register_sl_sent[ 3] OR ser_load[ 3]);
		register_sl_sent[ 4] = /sls_rst AND (register_sl_sent[ 4] OR ser_load[ 4]);
		register_sl_sent[ 5] = /sls_rst AND (register_sl_sent[ 5] OR ser_load[ 5]);
		register_sl_sent[ 6] = /sls_rst AND (register_sl_sent[ 6] OR ser_load[ 6]);
		register_sl_sent[ 7] = /sls_rst AND (register_sl_sent[ 7] OR ser_load[ 7]);
		register_sl_sent[ 8] = /sls_rst AND (register_sl_sent[ 8] OR ser_load[ 8]);
		register_sl_sent[ 9] = /sls_rst AND (register_sl_sent[ 9] OR ser_load[ 9]);
		register_sl_sent[10] = /sls_rst AND (register_sl_sent[10] OR ser_load[10]);
		register_sl_sent[11] = /sls_rst AND (register_sl_sent[11] OR ser_load[11]);
		register_sl_sent[12] = /sls_rst AND (register_sl_sent[12] OR ser_load[12]);
		register_sl_sent[13] = /sls_rst AND (register_sl_sent[13] OR ser_load[13]);
		register_sl_sent[14] = /sls_rst AND (register_sl_sent[14] OR ser_load[14]);

		
	
	
	"-------------------------------------------------------------------------------------------
	" RESET pulse generation
	"------------------------
	
		LOW_TRUE INPUT	nres;

		OUTPUT   nreset
						CLOCKED_BY /pld_ck
						PRESET_BY (reset OR /clk_on);
				
	   nreset = /(output_busy OR nres);    " CHECK THIS helix (frontend) CHIP reset.
	



	"-------------------------------------------------------------------------------------------
	" TEST_PULSE register/output, masked by TP_MASK register 
	"-------------------------------------------------------


		INPUT		access_tp_mask;				"VME access to the Test Pulse Mask Register

	   INPUT		tp_ck;				" From TEST pulse delay unit
													"  for clocking the test pulse ff

					
	   NODE	   register_tp_mask[14..0]    "VME R/W
						CLOCKED_BY db_clk
						CLOCK_ENABLED_BY (writeb AND access_tp_mask)
						PRESET_BY (reset OR /clk_on); "
						
	            
      register_tp_mask[14..0] = db[14..0];
      
      
      NODE     tp_reset;
      
      OUTPUT 	test_pulse[14..0];

 
               test_pulse[14] = tp_ck AND register_tp_mask[14];
               test_pulse[13] = tp_ck AND register_tp_mask[13];
               test_pulse[12] = tp_ck AND register_tp_mask[12];
               test_pulse[11] = tp_ck AND register_tp_mask[11];
               test_pulse[10] = tp_ck AND register_tp_mask[10];
               test_pulse[09] = tp_ck AND register_tp_mask[09];
               test_pulse[08] = tp_ck AND register_tp_mask[08];
               test_pulse[07] = tp_ck AND register_tp_mask[07];
               test_pulse[06] = tp_ck AND register_tp_mask[06];
               test_pulse[05] = tp_ck AND register_tp_mask[05];
               test_pulse[04] = tp_ck AND register_tp_mask[04];
               test_pulse[03] = tp_ck AND register_tp_mask[03];
               test_pulse[02] = tp_ck AND register_tp_mask[02];
               test_pulse[01] = tp_ck AND register_tp_mask[01];
               test_pulse[00] = tp_ck AND register_tp_mask[00];


	

	"-------------------------------------------------------------------------------------------
	" STATUS REGISTER
	"-----------------------

		INPUT		access_status;             "VME access to the Status Register

	   NODE		register_status[4..0];		"VME R (write causes a reset except bit 0)
	   
	   NODE		write_status;					"this extraneous logic is needed
	   											"  to fit 2 pterm reset logic
		

		write_status = (access_status AND writeb);
		
	   
	   "NODE	download                                   "STATUS REGISTER bit 0
	   "			CLOCKED_BY output_data                       "  HIGH during sequence download. 
	   "			RESET_BY (seq_count_reset OR reset);             "  end of sequence download.
	
	   NODE	test_pulse_sent                            "STATUS REGISTER bit 1              
					CLOCKED_BY test                              "  HIGH once test pulse sent.
					RESET_BY (write_status OR reset);   "  reset by write to register.
	
	   NODE	trig_sent                        "STATUS REGISTER bit 2 - HIGH once trig sent. 
					CLOCKED_BY (trigger AND /hsd_mode AND trig_sd)
					RESET_BY (write_status OR reset);   "  reset by write to register.     
	

					
	
	   "download.D             = 1;
	   test_pulse_sent.D      = 1;
	   trig_sent.D            = 1;
	   	   
	
	   "register_status[23..3] = 0;
	   register_status[ 4..0] = [	clk_on,
	   									hsd_mode,
                                 trig_sent, 
	   									test_pulse_sent, 
	   									output_busy ]; " *** was download, .._busy seems the same ...
	   									
   	
   									
		

"----------------------------------------------------------------------------------------------



	" VME READS FROM REGISTERS
	"-------------------------

	NODE readb;   		" for clarity - not ness.
	readb = /writeb;

	
	IF (readb) THEN
		IF (access_data) THEN							"VME reads sequence data register.
			db[23..0] = register_data[23..0];
			
		ELSIF (access_status) THEN						"VME reads status register.
			db[4..0] = register_status[4..0];		" *** IS THIS THE RIGHT SIZE?
			db[23..5] = 0;
			
		ELSIF (access_tp_mask) THEN					"VME reads test pulse mask register.
			db[14..0] = register_tp_mask[14..0];
			db[23..15] = 0;
			
		ELSIF (access_sl_sent) THEN					"VME reads sl_sent register.
			db[14..0] = register_sl_sent[14..0];	"
			db[23..15] = 0;
				
		"ELSIF (read_feedback) THEN					   "VME reads feedback register.
		"	db[19..0] = register_feedback[19..0];	" *** may be needed still
		
			
		END IF;
	END IF;
	

	dboe = readb AND (	access_data OR					"databus output enable.
								access_status OR 
								access_sl_sent OR    
								access_tp_mask); " OR	
								"read_feedback		); " ***
								
"==============================================================================================