"==============================================================================================
#TITLE	 'COMMAND STRING PROCESSING for ATLAS C+C';
#ENGINEER 'Martin Postranecky / Dominic A Hayes';
#COMPANY  'University College London';
#COMMENT  'Fits to M5-256/68';
"==============================================================================================

" 9/10/98  vburst facility (for triggers only).  out_c i/p now used by burst_busy o/p.
"          NB external routing for clk_out/clk_in.
"          64bit S/R for slow commands.
" 12/10/98 en AND'ed with enc_c.
" 13/10/98 q0 added to PROC select.
" 15/10/98 modified proc calibration_burst so it should work.
" 16/10/98 increased ten_bit to sixteen bits!
"          removed proc random_trigger prbs.
" 19/10/98 removed array p o/ps.
"          added resets to slowcom s/r and bit2 counter.
" 20/10/98 made nclrc_e o/p to match mod on pld2.
" 21/10/98 swapped ldslowcom and clk_in.
" 26/10/98 added back ldslowcom input, and changed /nenc_X to enc_X (removed /nenc_X from var list)
" 27/10/98 2 FFs added to proc cal_burst to sync ldvburst.
" 28/10/98 2 sync FFs added to all ldXXXX inputs.
"          Wired input i[15] to i[15] register.
" 29/10/98 ldXXX CLOCKED_BY clk4 from /clk4.
"          en clcocked_by q_vburst*.. from vburst*... 
"          bit[2] clocked_by q_ldslowcom from ldslowcom.
"-----------------------------------------------------------------------------
PROCEDURE select
"called from Main body.

  (INPUT  out_a, out_b, out_c2, out_d, out_e, clk4, noa_rst, 
          serout_a, serout_b, serout_c, serout_d, serout_e,
          ldbcrst, ldsrst, ldtrig, ldcal1, ldcal2, ldslowcom, vburst, burst_busy, en_burst_cntr;
   OUTPUT enc_a CLOCKED_BY clk4 RESET_BY /nclrc_a;
   OUTPUT enc_b CLOCKED_BY clk4 RESET_BY /nclrc_b;
   OUTPUT enc_c CLOCKED_BY clk4 RESET_BY /nclrc_c;
   OUTPUT enc_d CLOCKED_BY clk4 RESET_BY /nclrc_d;
   OUTPUT enc_e CLOCKED_BY clk4 RESET_BY /nclrc_e;
   OUTPUT nenc_a, nenc_b, nenc_c, nenc_d, nenc_e;
   OUTPUT nclrc_a, nclrc_b, nclrc_c, nclrc_d, nclrc_e, nx, y;
   OUTPUT dataout CLOCKED_BY clk4 RESET_BY /noa_rst);
   NODE   enable, nclr, z;
   NODE   count[7] CLOCKED_BY clk4 CLOCK_ENABLED_BY /enable RESET_BY /nclr;
   NODE   ncount3, ncount7, ncount27, ncount32, ncount64 DEFAULT_TO 1;
   NODE   q1 CLOCKED_BY vburst RESET_BY (en_burst_cntr + /noa_rst);   "HIGH disables trigger

   enable = nenc_a * nenc_b * nenc_c * nenc_d * nenc_e;
   nclr   = noa_rst * /(nenc_a * nenc_b * nenc_c * nenc_d * nenc_e);

   count = count .+. 1;

   CASE count
      WHEN 3  => ncount3  = 0;
      WHEN 7  => ncount7  = 0;
      WHEN 27 => ncount27 = 0;
      WHEN 32 => ncount32 = 0;
      WHEN 64 => ncount64 = 0;
   END CASE;

   q1 = 1;

   enc_a = enc_a
         + enable * out_a;
   enc_b = enc_b
         + enable * out_b;
   enc_c = enc_c
         + enable * out_c2 * /q1 * /burst_busy;    "q1 and burst_busy disable triggers
   enc_d = enc_d
         + enable * out_d;
   enc_e = enc_e
         + enable * out_e;

   nenc_a = /enc_a; nenc_b = /enc_b; nenc_c = /enc_c; nenc_d = /enc_d; nenc_e = /enc_e;

   z       = noa_rst * /(ldbcrst + ldsrst + ldtrig + ldcal1 + ldcal2 + ldslowcom);
   nclrc_a = z * ncount7;
   nclrc_b = z * ncount7 * nenc_a;
   nclrc_c = z * ncount3 * nenc_a * nenc_b;
   nclrc_d = z * ncount27 * nenc_a * nenc_b * nenc_c;
   nclrc_e = z * ncount64 * nenc_a * nenc_b * nenc_c * nenc_d;


   nx = nclrc_c + nenc_c;
   y  = /(nclrc_d + nenc_d);

   dataout = serout_a + serout_b + serout_c + serout_d + serout_e;

END select;
"-----------------------------------------------------------------------------
PROCEDURE shift_register_a
"called from main body.

  (INPUT  clk4, enc_a, nclrc_a, ldbcrst, i[6..0], noa_rst;
   OUTPUT serout_a);
   NODE   shift[6..0] CLOCKED_BY clk4;
   NODE   q1, q_ldbcrst CLOCKED_BY clk4 RESET_BY /noa_rst;
   
   q1 = ldbcrst;        "Sync
   q_ldbcrst = q1;      "FF's

   IF q_ldbcrst THEN
      shift = i;
   ELSIF enc_a THEN
"              ---->---->---->---->
      shift = [shift[0],shift[6..1]];
   ELSE
      shift = shift;
   END IF;

   serout_a =  shift[0] * nclrc_a * enc_a;

END shift_register_a;
"----------------------------------------------------------------------------------------------

"----------------------------------------------------------------------------------------------
PROCEDURE shift_register_b
"called from main body.

  (INPUT  clk4, enc_b, nclrc_b, ldsrst, i[6..0], noa_rst;
   OUTPUT serout_b);
   NODE   shift[6..0] CLOCKED_BY clk4;
   NODE   q1, q_ldsrst CLOCKED_BY clk4 RESET_BY /noa_rst;
   
   q1 = ldsrst;         "Sync 
   q_ldsrst = q1;       "FF's 1;

   IF q_ldsrst THEN
      shift = i;
   ELSIF enc_b THEN
"              ---->---->---->---->
      shift = [shift[0],shift[6..1]];
   ELSE
      shift = shift;
   END IF;

   serout_b =  shift[0] * nclrc_b * enc_b;

END shift_register_b;
"----------------------------------------------------------------------------------------------

"----------------------------------------------------------------------------------------------
PROCEDURE shift_register_c
"called from main body.

  (INPUT  clk4, enc_c, nclrc_c, ldtrig, i[2..0], noa_rst;
   OUTPUT serout_c);
   NODE   shift[2..0] CLOCKED_BY (clk4 * noa_rst);
   NODE   q1, q_ldtrig CLOCKED_BY clk4 RESET_BY /noa_rst;
   
   q1 = ldtrig;            "Sync 
   q_ldtrig = q1;          "FF's 

   IF q_ldtrig THEN
      shift = i;
   ELSIF enc_c THEN
"              ---->---->---->---->
      shift = [shift[0],shift[2..1]];
   ELSE
      shift = shift;
   END IF;

   serout_c =  shift[0] * nclrc_c * enc_c;

END shift_register_c;

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

"----------------------------------------------------------------------------------------------
PROCEDURE shift_register_d
"called from main body.

  (INPUT  clk4, enc_d, nclrc_d, ldcal1, ldcal2, i[14..0], noa_rst;
   OUTPUT serout_d);
   NODE   shift[26..0]
			CLOCKED_BY (clk4 AND noa_rst); " AND (enc_d OR q_ldcal1)); " *** why AND??
			"DEFAULT_TO LAST_VALUE;
			"CLOCK_ENABLED_BY enc_d; *** doesn't fit!
   		
 "  NODE   shift2[11..0]
  " 			CLOCKED_BY (clk4 AND noa_rst); " AND (enc_d OR q_ldcal2));
	"		"DEFAULT_TO LAST_VALUE; *** this seems to create bigger equations
	"		"CLOCK_ENABLED_BY enc_d; *** doesn't fit
   
   NODE  q1, q_ldcal1,
   		q2, q_ldcal2
				CLOCKED_BY clk4
				RESET_BY /noa_rst;
  
   
   q1 = ldcal1;            "
   q_ldcal1 = q1;          "Sync
   q2 = ldcal2;            "FF's 
   q_ldcal2 = q2;          "

   IF q_ldcal1 THEN
		shift[26..15] = shift[26..15];
		shift[14..0]  = i[14..0];
	ELSIF q_ldcal2 THEN
     	shift[26..15] = i[11..0];
      shift[14..0]  = shift[14..0];	   
	ELSIF enc_d THEN
   	 "        ---->---->---->---->---->
		shift = [ shift[0],shift[26..1] ];

	END IF;

   serout_d =  shift[0] AND nclrc_d AND enc_d;

END shift_register_d;
"----------------------------------------------------------------------------------------------
"----------------------------------------------------------------------------------------------
PROCEDURE shift_register_e
"called from main body.
"This is a 4x8bit shift register preloaded in 4 stages.

  (INPUT  clk4, enc_e, nclrc_e, ldslowcom, rstslowcount, i[15..0], noa_rst;
   OUTPUT serout_e);
   NODE   ldshift1, ldshift2, ldshift3, ldshift4 DEFAULT_TO 0;
   NODE   bit2[2] CLOCKED_BY /q_ldslowcom RESET_BY bit2_rst;
   NODE   bit2_rst;
   NODE   shift1[15..0] CLOCKED_BY clk4 RESET_BY /noa_rst;
   NODE   shift2[15..0] CLOCKED_BY clk4 RESET_BY /noa_rst;
   NODE   shift3[15..0] CLOCKED_BY clk4 RESET_BY /noa_rst;
   NODE   shift4[15..0] CLOCKED_BY clk4 RESET_BY /noa_rst;
   NODE   q1, q_ldslowcom CLOCKED_BY clk4 RESET_BY /noa_rst;
   
   q1 = ldslowcom;            "Sync 
   q_ldslowcom = q1;          "FF's 

   bit2 = bit2 .+. 1;
   bit2_rst = rstslowcount + enc_e + /noa_rst;

   CASE bit2
      WHEN 0 => ldshift1 = 1;
      WHEN 1 => ldshift2 = 1;
      WHEN 2 => ldshift3 = 1;
      WHEN 3 => ldshift4 = 1;
   END CASE;

   IF (ldshift1 * q_ldslowcom) THEN
      shift1 = i;
   ELSIF enc_e THEN
"              ---->---->---->---->---->
      shift1 = [shift2[0],shift1[15..1]];
   ELSE
      shift1 = shift1;
   END IF;

   IF (ldshift2 * q_ldslowcom) THEN
      shift2 = i;
   ELSIF enc_e THEN
"              ---->---->---->---->---->
      shift2 = [shift3[0],shift2[15..1]];
   ELSE
      shift2 = shift2;
   END IF;

   IF (ldshift3 * q_ldslowcom) THEN
      shift3 = i;
   ELSIF enc_e THEN
"              ---->---->---->---->---->
      shift3 = [shift4[0],shift3[15..1]];
   ELSE
      shift3 = shift3;
   END IF;

   IF (ldshift4 * q_ldslowcom) THEN
      shift4 = i;
   ELSIF enc_e THEN
"              ---->---->---->---->---->
      shift4 = [shift1[0],shift4[15..1]];
   ELSE
      shift4 = shift4;
   END IF;

   serout_e =  shift1[0] * nclrc_e * enc_e;

END shift_register_e;
"-----------------------------------------------------------------------------

"-----------------------------------------------------------------------------
PROCEDURE calibration_burst
"called from main body.
"NB clk_out and clk_in are SAME signal linked externally.  (Requirement for fitting.)

  (INPUT  clk4, noa_rst, ten_bit_clk_in, enc_c, ldvburst, vburst, i[15..0];
   OUTPUT burst_busy, ten_bit_clk_out, en_burst_cntr);
   NODE   en CLOCKED_BY (q_ldvburst * clk4) RESET_BY en_rst;
   NODE   ten_bit[15..0] CLOCKED_BY ten_bit_clk_in CLOCK_ENABLED_BY en PRESET_BY /noa_rst;
   NODE   at_zero, en_rst;
   NODE   q1, q_ldvburst CLOCKED_BY /clk4 RESET_BY /noa_rst;
   
   q1 = ldvburst;             "Sync 
   q_ldvburst = q1;           "FF's 

   en_rst = /noa_rst 
          + /q_ldvburst * at_zero;
   
   en  = vburst;

   ten_bit_clk_out = enc_c * en           "en gates out enc_c when vburst not enabled.
                   + clk4 * q_ldvburst;   "clk4 clocks ten_bit when ldvburst high.
   
   IF q_ldvburst THEN
      ten_bit = i;                  "synchronous preload from VME data bus
   ELSE                             "  (sync'ous because ten_bit is clocked)
      ten_bit = ten_bit .-. 1;      "count down
   END IF;

   CASE ten_bit 
      WHEN 0 => at_zero = 1;        "count finished
      ELSE      at_zero = 0;
   END CASE;
		
   burst_busy = at_zero * vburst; "
   en_burst_cntr = en;              " !!encal_burst on PLD2

END calibration_burst;
"-----------------------------------------------------------------------------

"=============================================================================
"-----------------------------------------------------------
"        SIGNAL DECLARATIONS for MAIN BODY
"  (INPUT/OUTPUT are chip I/O, NODES are internal signals)
"-----------------------------------------------------------
INPUT    noa_rst, clk4, out_a, out_b, out_c2, out_d, out_e, vburst, clk_in,
         ldbcrst, ldsrst, ldtrig, ldcal1, ldcal2, ldslowcom, ldvburst, rstslowcount, i[15..0];

NODE     serout_a, serout_b, serout_c, serout_d, serout_e,
         enc_a, enc_b, enc_c, enc_d, enc_e, nenc_a, nenc_b, nenc_c, nenc_d, nenc_e,
         nclrc_a,  nclrc_b,  nclrc_c,  nclrc_d;

OUTPUT   nx, y, dataout, burst_busy, clk_out, nclrc_e,
         en_burst_cntr;                                  " !!encal_burst on PLD2

"-----------------------------------------------------------
"        CODE for MAIN BODY
"-----------------------------------------------------------

select
  (out_a, out_b, out_c2, out_d, out_e, clk4, noa_rst, 
      serout_a, serout_b, serout_c, serout_d, serout_e,
      ldbcrst, ldsrst, ldtrig, ldcal1, ldcal2, ldslowcom, vburst, burst_busy, en_burst_cntr,
   enc_a, enc_b, enc_c, enc_d, enc_e, nenc_a, nenc_b, nenc_c, nenc_d, nenc_e,
      nclrc_a, nclrc_b, nclrc_c, nclrc_d, nclrc_e, nx, y, dataout);

shift_register_a
  (clk4, enc_a, nclrc_a, ldbcrst, i[6..0], noa_rst,
   serout_a);

shift_register_b
  (clk4, enc_b, nclrc_b, ldsrst, i[6..0], noa_rst,
   serout_b);

shift_register_c
  (clk4, enc_c, nclrc_c, ldtrig, i[2..0], noa_rst,
   serout_c);

shift_register_d
  (clk4, enc_d, nclrc_d, ldcal1, ldcal2, i[14..0], noa_rst,
   serout_d);

shift_register_e
  (clk4, enc_e, nclrc_e, ldslowcom, rstslowcount, i[15..0], noa_rst,
   serout_e);

calibration_burst
   (clk4, noa_rst, clk_in, enc_c, ldvburst, vburst, i[15..0],
   burst_busy, clk_out, en_burst_cntr);

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