"$Id: pld9.src,v 1.26 2002/10/14 15:55:42 warren Exp $
"==============================================================================
#TITLE    'TIM PLD9: TTCrm interface';
#ENGINEER 'John Lane / Dominic A Hayes / Matthew Warren';
#COMPANY  'University College London';
#COMMENT  '';


"==============================================================================
"CVS Update Log
"==============================================================================
"$Log: pld9.src,v $
"Revision 1.26  2002/10/14 15:55:42  warren
"re-worked (AGAIN) with TTCready gating. Still not clear if it works!
"
"Revision 1.25  2002/07/31 20:14:48  warren
"fixed some strobe1 vs strobe2 confusion and improved sim for TTCrm testing
"
"Revision 1.24  2002/05/22 11:36:31  warren
"Added TTCready gating
"
"Revision 1.23  2002/03/22 17:47:47  warren
"new reg clocking
"
"Revision 1.22  2002/02/11 18:34:49  warren
"Added clock sync sparebus signals
"
"Revision 1.21  2002/01/16 16:52:30  warren
"tidied tabs
"
"Revision 1.20  2001/12/11 16:45:28  warren
"Fixed I2C writes (I think!)
"
"Revision 1.19  2001/11/20 16:54:48  warren
"removed all sgb assignments
"
"Revision 1.18  2001/11/14 20:13:01  warren
"I2C reads working, long delay reset for TTCrm
"
"Revision 1.17  2001/10/25 18:02:18  warren
"fixed TTCcmd register error
"Added sgb testpoints for TTC signal timing tests
"
"Revision 1.16  2001/08/30 12:21:10  warren
"Worrked on I2C
"Tidied, Capitalization
"
"Revision 1.15  2001/08/13 10:49:18  warren
"better code docs
"
"Revision 1.14  2001/08/10 15:35:33  warren
"All new I2C code
"
"Revision 1.13  2001/08/08 18:42:48  warren
"new I2C stuff and related simulation
"and signal names case names
"
"Revision 1.12  2001/07/23 11:18:47  warren
"renamed signals with proper polarity n prefixes and removed LOW_TRUEs
"
"Revision 1.11  2001/07/19 10:45:09  warren
"removed unused spare bus lines
"
"Revision 1.10  2001/06/22 13:09:53  warren
"Changed some signal names to upper/lowercase variations - code unchanged
"
"Revision 1.9  2001/06/15 17:02:00  warren
"Cleaned up code organisation
"
"Revision 1.8  2001/04/03 15:46:11  warren
"OA_rst stuff
"


"==============================================================================
"Mods Log
"==============================================================================
"23may00 L1Accept -> L1Ain, BCntRes -> BCRin, EvCntRes -> ECRin.
"24may00 reserved, s1_5 removed.
"05jul00 Resetb o/p added just in case.
"14sep00 rstRegTTCdata eqn added.
"26sep00 DEFAULT_TO LAST_VALUE added to some register definitions.
"03oct00 Added CLK_EN_BY to reg2c and reg28 and tidied the vme write logic MRMW
"01Nov00 Changed byte order in TTCData reg to [SubAddr,Dout] - JBL
"21Mar01 Sorted out nOA_rst polarity
"        Added OA_rst to keep things legible
"14Jun01 Re-orgaised Layout, renamed RegisterCommand to RegisterCmd
"07Aug01 Tied Resetb(TTCrm) to nOA_rst
"08Aug01 Added I2C read state_machine -- extensively simulate tested ...
"23Oct01 Fixed TTCCmdReg[7..0] reset polarity
"06Oct01 removed dboe->dboein pins -- not needed any more
"07Oct01 Added long (50us) resetb (TTCrc) reset pulse generator
"        Fixed I2C code for reads (data was reversed)
"11Nov01 Fixed I2C writes -- can write/read-back TTCrm registers now - testing?
"16May02 Changed resetb to not assert while in OA_rst
"17May02 Added TTCready reseting to all TTCrm signals via OA_rst2
"31Jul02 Fixed BrcstStr1/2 mixup, and tidied


"==============================================================================
"CODE
"==============================================================================

         INPUT    nOA_rst;
VIRTUAL  NODE     OA_rst;
                  OA_rst = /nOA_rst;

BIPUT    db[15..0]
            ENABLED_BY dboe;

NODE     dboe;

INPUT    bWriteb,
         bReadb,
         nLEb2;

INPUT    Reg26,         "RegisterTTCdata.
         Reg28,         "RegisterTTCselect.
         Reg2E;         "RegisterCmd.

INPUT    Reg2C;         "RegisterI2C.

INPUT    RunMode;  "From pld3

INPUT    TTCready;

NODE     OA_rst2;
         OA_rst2 = OA_rst OR /TTCReady;

OUTPUT   TTC_ready_in; "to pld2 via sgbD[1]
         TTC_ready_in = TTCReady;
       
INPUT    TIM_OK_OUT; "from pld2 via sgbD[0]

"------------------------------------------------------------------------------
" TTCrm reset pulse generator (~50us)
"------------------------------------------------------------------------------

OUTPUT   Resetb;   "Reset to TTCrm  NB: Active LOW
            

NODE     en_resetb_timer;

NODE     resetb_timer[10..0]
            CLOCKED_BY  clk9
            CLOCK_ENABLED_BY en_resetb_timer
            RESET_BY OA_rst;

         resetb_timer = resetb_timer .+. 1;

         
         IF resetb_timer = 0h THEN "IF no SA-clock - allow power-on-reset
            resetb = 1;
            en_resetb_timer = 1;

         "ELSIF resetb_timer = 10h THEN   "### for sim only
         ELSIF resetb_timer = 7ffh THEN
            resetb = 1;
            en_resetb_timer = 0;

         ELSE
            resetb = 0; "Active LOW reset
            en_resetb_timer = 1;

         END IF;


"------------------------------------------------------------------------------
" CLOCKS
"------------------------------------------------------------------------------
INPUT    BCclk1b,    "buffered Clock40Des1,
         clk9,       "
         BCclk2b;    "buffered Clock40Des2;


"------------------------------------------------------------------------------
" STROBES
"------------------------------------------------------------------------------
INPUT    SinErrStr,
         DbErrStr,
         DoutStr,
         BrcstStr1,
         BrcstStr2,
         BCntStr,
         EvCntLStr,
         EvCntHStr;
         

OUTPUT   L1CntLowStrobe,            "Clocked EvCntLStr.     to pld4a
         L1CntHighStrobe,           "Clocked EvCntHStr.     to pld4a
         BCntStrobe                 "Clocked BCntStr.       to pld4b
            CLOCKED_BY clk9
            RESET_BY OA_rst2;


         L1CntHighStrobe = EvCntHStr;
         L1CntLowStrobe  = EvCntLStr;
         BCntStrobe      = BCntStr;


NODE     strobe;    "OR of the 3 xxCntStr
         strobe = (EvCntHStr OR EvCntLStr OR BCntStr);



" BUSES
"------------------------------------------------------------------------------
INPUT    BCnt[11..0],  
         Brcst[7..2],
         Dout[7..0],
         SubAddr[7..0],
         DQ[3..0];


" DECODED Brcst COMMANDS
"------------------------------------------------------------------------------
OUTPUT   CALin,
         FERin,
         Sparein
            CLOCKED_BY clk9
            RESET_BY OA_rst2;
            


         " Short Format Commands
         "=---------------------=
         
         CALin   = Brcst[6] AND BrcstStr2;
         FERin   = Brcst[2] AND BrcstStr1;
         Sparein = 0;



" COMMANDS
"------------------------------------------------------------------------------
INPUT    L1Ain,  BCRin,  ECRin;


" DECODED BCnt COMMANDS
"------------------------------------------------------------------------------
OUTPUT   BCntIn[11..0]
            CLOCKED_BY clk9
            CLOCK_ENABLED_BY strobe
            RESET_BY OA_rst2;

         BCntIn = BCnt[11..0];


" DECODED Dout, SubAddr, DQ COMMANDS
"------------------------------------------------------------------------------
OUTPUT   TTIDin[9..0]
            CLOCKED_BY clk9
            CLOCK_ENABLED_BY enTType
            RESET_BY OA_rst2;

NODE     enTType
            DEFAULT_TO 0;

         TTIDin[7..0] = Dout[7..0];
         TTIDin[9..8] = 0;


" TT Strobe
"----------
OUTPUT   TTypeStrobe
            CLOCKED_BY clk9
            RESET_BY  OA_rst2
            DEFAULT_TO 0;
            

         " TType
         "=-----=
         
         IF (DoutStr) THEN
            IF ( (SubAddr = 0) AND (DQ = 0) ) THEN
               TTypeStrobe = 1;
               enTType = 1;
               
            END IF;
         END IF;



" Register TTCSelect
"------------------------------------------------------------------------------
NODE     RegisterTTCselect[3..0]       "Reg28
            CLOCKED_BY clk9
            CLOCK_ENABLED_BY (Reg28 AND /nLEb2)
            RESET_BY OA_rst;

         RegisterTTCselect = db[3..0];


NODE     ceRegTTCdata,
         wr26
            DEFAULT_TO 0;      "VME write to Reg26


NODE     RegisterTTCdata[15..0]  "reg26
            CLOCKED_BY clk9
            CLOCK_ENABLED_BY ceRegTTCdata
            RESET_BY wr26 OR OA_rst2;
            
         RegisterTTCdata = [ SubAddr[7..0], Dout[7..0] ];


         "Long Format Data
         "=----------------=
         IF (DoutStr) THEN
         
            IF (DQ = RegisterTTCselect) THEN
               ceRegTTCdata = 1;
            
            END IF;
               
         END IF;
         



" SHORT FORMAT COMMANDS REGISTER
"------------------------------------------------------------------------------

NODE     RegisterCmd2[15..8];       "Self-clocking register.

NODE     RegisterCmd1[7..6]
            CLOCKED_BY clk9
            CLOCK_ENABLED_BY BrcstStr2
            RESET_BY rstRegCmd;

NODE     RegisterCmd0[5..0]
            CLOCKED_BY clk9
            CLOCK_ENABLED_BY BrcstStr1
            RESET_BY rstRegCmd;

NODE     RegisterCmd[15..0]; "reg2E    "Combined Commands Register.

NODE     rstRegCmd,
         wr2E
            DEFAULT_TO 0;
            

         rstRegCmd = wr2E OR OA_rst2; "self-clocking async reset;

                 

         RegisterCmd2[15]     = 0;
         RegisterCmd2[14]     = TTCReady; "*** removed self clocking
         RegisterCmd2[13]     = /rstRegCmd AND (SinErrStr OR RegisterCmd2[13]);
         RegisterCmd2[12]     = /rstRegCmd AND (DbErrStr  OR RegisterCmd2[12]);
         RegisterCmd2[11]     = /rstRegCmd AND (DoutStr   OR RegisterCmd2[11]);
         RegisterCmd2[10]     = /rstRegCmd AND (BrcstStr2 OR RegisterCmd2[10]);
         RegisterCmd2[9]      = /rstRegCmd AND (BrcstStr1 OR RegisterCmd2[ 9]);
         RegisterCmd2[8]      = /rstRegCmd AND (L1Ain     OR RegisterCmd2[ 8]);

         RegisterCmd1[7..6]   = Brcst[7..6];

         RegisterCmd0[5..2]   = Brcst[5..2];

         RegisterCmd0[1]      = ECRin;     "Brcst[1] *** why not self clocked?
         RegisterCmd0[0]      = BCRin;     "Brcst[0] *** ditto

         RegisterCmd[15..0] = [  RegisterCmd2[15..8],
                                 RegisterCmd1[7..6],
                                 RegisterCmd0[5..0]   ];



"------------------------------------------------------------------------------
"
" I2C INTERFACE
"
"------------------------------------------------------------------------------

"  Background:
"  -----------
"  The I2C system works in cycles, triggered by the I2C_Go bit.
"  Each cycle uses 2 separate I2C datagrams (ie 2x start->stop)
"  The I2C spec reckons it can be done with one 'complex mode' datagram,
"  but I figure 2 is safer.
"  datagram 1 writes the i2c chip_id + TTCrm register_id
"  datagram 2 writes the i2c chip_id + R/W data to/from TTCrm reg.
"  The I2C address space is (as I understand it) defined as follows:
"  [ TTCrm I2C_ID[5:0], Data/nRegPointer, Read/nWrite ]
"  Using the TTCrm default I2C ID: 0 (anti spec. btw *) the following are useful
"  I2C ADDRESSES on the TTCrm:
"   0x02 = Write Reg_Pointer (to setup TTCrm reg access)
"   0x01 = Read Data
"   0x00 = Write Data

"  *[The I2C spec reserves certain addresses, but I don't think the TTCrm obeys this]
"
"  This actual addressing is hidden from the TIM user. who only needs to specify
"  the R/nW, the TTCrm reg_pointer and the data if writing

"  ------------------------------------------------------------
"  USAGE:
"  ------------------------------------------------------------

"  I2C Register Definition (0x2C)
"  -------------------------------
"   bit 15  =  (W)I2C_Go, (R)I2C_Busy
"   bit 14  =  I2C_Enable (I2C clock Enable)
"   bit 13  =  I2C_Read_nWrite
"   bit 12:8 = I2C_Pointer (TTCrm Register Number)
"   bit 7:0 =  I2C_Data (read from/to write to TTrx)
"
"
"  1) Enable the I2C clock (1MHz)
"     wr 0x4000

"  2) Read TTCrm I2C Status register (22d = 10110b):
"      2C wr 0xF600  [ ie. go, ena, rd,  reg_id,   data   ]
"                    [      1   1    1   10110   00000000 ] = F600
"                    NOTE: during reads the data is ignored.
"      2C rd
"      Data returned in the lower byte


"   I2C_Busy
"   --------
"   During the I2C cycle the I2C_Busy bit is set.
"   If the I2C 'hangs' I2C_Busy bit will stay set
"   The TTCrm requires 50us to reset,
"   during this time the I2C_Busy bit will stay set


"  Examples :
"  -------------------------
"  1)  Read TTCrm Status (22d)
"        2C wr 0xf600
"        2C rd

"  2)  Read TTCrm Control Reg (3d)
"        2C wr 0xE300
"        2C rd

"  3)  Write TTCrm Delay Reg (0d) with 1
"        2C wr 0xC001

"  4)  Read TTCrm Delay Reg (0d)
"        2C wr 0xE000
"        2C rd



"----------------------------------------------------------
"Generate I2C Clock (at 1MHz)
"----------------------------------------------------------

NODE     I2CClockCounter[4..0]
               CLOCKED_BY  clk9
               "CLOCK_ENABLED_BY I2C_Enable
               RESET_BY /I2C_Enable OR OA_rst2;


NODE     I2CClockCounter_max
            DEFAULT_TO 0;

                                     "### set clock freq here 20Mhz/(x-1)
         IF I2CClockCounter = 21 THEN "    use 1 for sim -- should be 21
              I2CClockCounter_max = 1;
              I2CClockCounter = 0;
              
         ELSE
            I2CClockCounter = I2CClockCounter .+. 1;

         END IF;

"###### for simulation only use below (less clocks)
"NODE    I2C_clk;
"        I2C_clk = clk9;

T_FLOP   I2C_clk
            CLOCKED_BY I2CClockCounter_max
            RESET_BY OA_rst;
         I2C_clk.T = 1;


"----------------------------------------------------------
"I2C pins and OEs
"----------------------------------------------------------


BIPUT SCL                  "Serial Clock. (i2c MASTER issues clock)
            ENABLED_BY /xSCL;

BIPUT SDA
            ENABLED_BY /xSDA; "Serial Data.
         SCL = 0;
         SDA = 0;

NODE     xSCL,          "NOTE: these required so we never actually
         xSDA           "      drive the bus
            DEFAULT_TO 1;



"----------------------------------------------------------
"I2C Register Definition (Reg2C)
"----------------------------------------------------------

NODE     I2C_OA_rst;

NODE     I2C_Busy;

NODE     I2C_Go
            CLOCKED_BY clk9
            CLOCK_ENABLED_BY (Reg2C AND /nLEb2)
            RESET_BY i2c_reset OR I2C_OA_rst;

NODE     I2C_Enable,
         I2C_Read_nWrite,
         I2C_Pointer[4..0]
            CLOCKED_BY clk9
            CLOCK_ENABLED_BY (Reg2C AND /nLEb2)
            RESET_BY OA_rst;

         I2C_Go            = db[15];
         I2C_Enable        = db[14];
         I2C_Read_nWrite   = db[13];
         I2C_Pointer[4..0] = db[12..8];


NODE     I2C_Data[7..0]    "*** I would like to improve this clocking scheme ...
            CLOCKED_BY i2c_data_clk
            RESET_BY OA_rst;


NODE     RegisterI2C[15..0];  "Reg2C
         RegisterI2C[15..0] = [
                                 I2C_Busy,
                                 I2C_Enable,
                                 I2C_Read_nWrite,
                                 I2C_Pointer[4..0],
                                 I2C_Data[7..0]
                              ];

         I2C_OA_rst = /I2C_Enable OR OA_rst2;
         I2C_Busy   = I2C_Go OR /resetb;



"------------------------------------------------------------------------------
"THE I2C MACHINE
"------------------------------------------------------------------------------

NODE     i2c_reset,
         i2c_data_clk,
         i2c_data_shift_clk
            DEFAULT_TO 0;

         IF (I2C_Busy AND i2c_Read_nWrite) THEN
            I2C_Data[7..0] = [I2C_Data[6..0], SDA];
            i2c_data_clk = i2c_data_shift_clk;

         ELSIF (bWriteb AND Reg2C) THEN
            I2C_Data = db[7..0];
            i2c_data_clk = nLEb2;

         ELSE
            I2C_Data = I2C_Data;

         END IF;


NODE     i2c_data_mode_set,
         i2c_data_npointer_reset
            DEFAULT_TO 0;

NODE     i2c_data_npointer
            CLOCKED_BY  i2c_data_mode_set
            RESET_BY i2c_data_npointer_reset OR OA_rst2;
         i2c_data_npointer = 1;

NODE     i2c_write_data[7..0];

         IF (i2c_data_npointer) THEN
            i2c_write_data = I2C_Data;

         ELSE
            i2c_write_data = [0,0,0, I2C_Pointer];

         END IF;


NODE     i2c_id[7..0];
         i2c_id[7..2] = 0; "### this is a preset for now -- TTCrm should not change

         i2c_id[1] = i2c_Data_nPointer;
         i2c_id[0] = i2c_Read_nWrite AND i2c_Data_nPointer;



"--------------------------------------------------------------------
"The actual machine
"--------------------------------------------------------------------


         STATE_MACHINE  i2c_machine
            CLOCKED_BY  i2c_clk
            RESET_BY    I2C_OA_rst;


            STATE reset_state:      "This state sets the defaults
               xSCL = 1;            "for all state variables
               xSDA = 1;

               i2c_data_npointer_reset = 1;

               IF (I2C_Go) THEN
                  GOTO  start0;

               ELSE
                  GOTO reset_state;

               END IF;


         "---------------------------------------------------------
         "SEND START CONDITION
         "---------------------------------------------------------
            STATE start0:        "idle time to gather wits
               xSCL = 1;
               xSDA = 1;
               GOTO  start1;


            STATE start1:
               xSCL = 1;
               xSDA = 0;            "data low first
               GOTO  start2;

            STATE start2:
               xSCL = 0;            " then clock low
               xSDA = 0;

               GOTO  send_id7;


         "---------------------------------------------------------
         "SEND I2C CHIP ID
         "---------------------------------------------------------
            "ID7 --------
            STATE send_id7:
               xSCL = 0;
               xSDA = i2c_id[7];
               GOTO  send_id7c;

            STATE send_id7c:
               xSCL = 1;
               xSDA = i2c_id[7];
               GOTO  send_id6;

            "ID6 ---------
            STATE send_id6:
               xSCL = 0;
               xSDA = i2c_id[6];
               GOTO  send_id6c;

            STATE send_id6c:
               xSCL = 1;
               xSDA = i2c_id[6];
               GOTO  send_id5;

            "ID5 --------
            STATE send_id5:
               xSCL = 0;
               xSDA = i2c_id[5];
               GOTO  send_id5c;

            STATE send_id5c:
               xSCL = 1;
               xSDA = i2c_id[5];
               GOTO  send_id4;

            "ID4 --------
            STATE send_id4:
               xSCL = 0;
               xSDA = i2c_id[4];
               GOTO  send_id4c;

            STATE send_id4c:
               xSCL = 1;
               xSDA = i2c_id[4];
               GOTO  send_id3;

            "ID3 --------
            STATE send_id3:
               xSCL = 0;
               xSDA = i2c_id[3];
               GOTO  send_id3c;

            STATE send_id3c:
               xSCL = 1;
               xSDA = i2c_id[3];
               GOTO  send_id2;

            "ID2 --------
            STATE send_id2:
               xSCL = 0;
               xSDA = i2c_id[2];
               GOTO  send_id2c;

            STATE send_id2c:
               xSCL = 1;
               xSDA = i2c_id[2];

               GOTO  send_id1;

            "ID1 --------
            STATE send_id1:
               xSCL = 0;
               xSDA = i2c_id[1];

               GOTO  send_id1c;

            STATE send_id1c:
               xSCL = 1;
               xSDA = i2c_id[1];

               GOTO  send_id0;

            "ID0 --------
            STATE send_id0:
               xSCL = 0;
               xSDA = i2c_id[0];

               GOTO  send_id0c;

            STATE send_id0c:
               xSCL = 1;
               xSDA = i2c_id[0];

               GOTO  send_id_done;

            "ID tidy finish -----
            STATE send_id_done:
               xSCL = 0;
               xSDA = 0;

               GOTO  id_release_bus;

            "-----------------------
            "ID: WAIT FOR SLAVE ACK
            "-----------------------
            STATE id_release_bus:
               xSCL = 0;
               xSDA = 1;         "release sdl

               GOTO  id_wait_ack;

            "--------
            STATE id_wait_ack:
               xSDA = 1;
               xSCL = 1;

               IF SDA = 0 THEN   "read data
                  GOTO id_action_ack;

               ELSE
                  GOTO id_wait_ack;

               END IF;                 "NOTE: should be timeout here
                                       "      but it works as is and timeout=FFs

            STATE id_action_ack:
               xSCL = 0;
               xSDA = 1;

               IF (/i2c_data_npointer) THEN
                  GOTO write_byte7;    " --- WRITE POINTER

               ELSIF (i2c_Read_nWrite) THEN
                  GOTO  read_byte7;    "--- I2C READ MODE ---

               ELSE
                  GOTO  write_byte7;   "--- I2C WRITE MODE --

               END IF;



         "---------------------------------------------------------
         "READ BYTE
         "---------------------------------------------------------
            "read_byte7 --------
            STATE read_byte7:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  read_byte7c;


            STATE read_byte7c:
               xSCL = 1;
               xSDA = 1;
               i2c_data_shift_clk = 1;
               GOTO  read_byte6;


            "read_byte6 ---------
            STATE read_byte6:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  read_byte6c;

            STATE read_byte6c:
               xSCL = 1;
               xSDA = 1;
               i2c_data_shift_clk = 1;
               GOTO  read_byte5;

            "read_byte5 --------
            STATE read_byte5:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  read_byte5c;

            STATE read_byte5c:
               xSCL = 1;
               xSDA = 1;
               i2c_data_shift_clk = 1;
               GOTO  read_byte4;

            "read_byte4 --------
            STATE read_byte4:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  read_byte4c;

            STATE read_byte4c:
               xSCL = 1;
               xSDA = 1;
               i2c_data_shift_clk = 1;
               GOTO  read_byte3;

            "read_byte3 --------
            STATE read_byte3:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  read_byte3c;

            STATE read_byte3c:
               xSCL = 1;
               xSDA = 1;
               i2c_data_shift_clk = 1;
               GOTO  read_byte2;

            "read_byte2 --------
            STATE read_byte2:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  read_byte2c;

            STATE read_byte2c:
               xSCL = 1;
               xSDA = 1;
               i2c_data_shift_clk = 1;
               GOTO  read_byte1;

            "read_byte1 --------
            STATE read_byte1:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  read_byte1c;

            STATE read_byte1c:
               xSCL = 1;
               xSDA = 1;
               i2c_data_shift_clk = 1;
               GOTO  read_byte0;

            "read_byte0 --------
            STATE read_byte0:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  read_byte0c;

            STATE read_byte0c:
               xSCL = 1;
               xSDA = 1;
               i2c_data_shift_clk = 1;
               GOTO  read_byte_done;


            "---------------------
            "READ SEND ACK
            "---------------------
            STATE read_byte_done:
               xSCL = 0;
               xSDA = 1;
               i2c_data_shift_clk = 0;
               GOTO  give_ack0;

            STATE give_ack0:
               xSCL = 0;
               xSDA = 0;
               GOTO  give_ack1;

            STATE give_ack1:
               xSCL = 1;
               xSDA = 0;
               GOTO  send_stop;


         "---------------------------------------------------------
         "WRITE BYTE
         "---------------------------------------------------------
            "write_byte7 --------
            STATE write_byte7:
               xSCL = 0;
               xSDA = i2c_write_data[7];
               GOTO  write_byte7c;


            STATE write_byte7c:
               xSCL = 1;
               xSDA = i2c_write_data[7];
               GOTO  write_byte6;


            "write_byte6 ---------
            STATE write_byte6:
               xSCL = 0;
               xSDA = i2c_write_data[6];
               GOTO  write_byte6c;

            STATE write_byte6c:
               xSCL = 1;
               xSDA = i2c_write_data[6];
               GOTO  write_byte5;

            "write_byte5 --------
            STATE write_byte5:
               xSCL = 0;
               xSDA = i2c_write_data[5];
               GOTO  write_byte5c;

            STATE write_byte5c:
               xSCL = 1;
               xSDA = i2c_write_data[5];
               GOTO  write_byte4;

            "write_byte4 --------
            STATE write_byte4:
               xSCL = 0;
               xSDA = i2c_write_data[4];
               GOTO  write_byte4c;

            STATE write_byte4c:
               xSCL = 1;
               xSDA = i2c_write_data[4];
               GOTO  write_byte3;

            "write_byte3 --------
            STATE write_byte3:
               xSCL = 0;
               xSDA = i2c_write_data[3];
               GOTO  write_byte3c;

            STATE write_byte3c:
               xSCL = 1;
               xSDA = i2c_write_data[3];
               GOTO  write_byte2;

            "write_byte2 --------
            STATE write_byte2:
               xSCL = 0;
               xSDA = i2c_write_data[2];
               GOTO  write_byte2c;

            STATE write_byte2c:
               xSCL = 1;
               xSDA = i2c_write_data[2];
               GOTO  write_byte1;

            "write_byte1 --------
            STATE write_byte1:
               xSCL = 0;
               xSDA = i2c_write_data[1];
               GOTO  write_byte1c;

            STATE write_byte1c:
               xSCL = 1;
               xSDA = i2c_write_data[1];
               GOTO  write_byte0;

            "write_byte0 --------
            STATE write_byte0:
               xSCL = 0;
               xSDA = i2c_write_data[0];
               GOTO  write_byte0c;

            STATE write_byte0c:
               xSCL = 1;
               xSDA = i2c_write_data[0];
               GOTO  wr_release_bus;


            "---------------------------
            "WRITE: WAIT FOR SLAVE ACK
            "---------------------------
            STATE wr_release_bus: "This delay helps show ACKS on scope/sim etc
               xSCL = 0;
               xSDA = 1;
               GOTO  wr_release_bus1;

            STATE wr_release_bus1:
               xSCL = 1;
               xSDA = 1;
               GOTO  wr_wait_ack;

            "--------
            STATE wr_wait_ack:
               xSCL = 1;
               xSDA = 1;

               IF SDA = 0 THEN
                  GOTO  wr_action_ack;    "everything is fine, continue

               ELSE        "NOTE: see timeout not above..
                  GOTO   wr_wait_ack;

               END IF;


            STATE wr_action_ack:
               xSCL = 0;
               xSDA = 1;
               GOTO  send_stop;




         "---------------------------------------------------------
         "SEND STOP
         "---------------------------------------------------------
            STATE send_stop:
               xSCL = 0;
               xSDA = 0;
               GOTO  send_stop1;

            STATE send_stop1:
               xSCL = 1;
               xSDA = 0;
               GOTO  send_stop2;

            STATE send_stop2:
               xSCL = 1;
               xSDA = 1;
               GOTO  finished;

            STATE finished:
               xSCL = 1;
               xSDA = 1;

               IF (/i2c_data_npointer) THEN
                  GOTO repeat_for_data;

               ELSE
                  i2c_reset = 1;
                  GOTO reset_state;

               END IF;


            "--------------------------
            STATE repeat_for_data:
               i2c_data_mode_set = 1;
               GOTO  start0;


         "---------------------------------------------------------
         END i2c_machine;




"------------------------------------------------------------------------------
" VME ACCESS
"------------------------------------------------------------------------------


         IF (bWriteb AND Reg26) THEN
            wr26 = 1;                     "resets TTCdata register.
            wr2E = 0;
            
         ELSIF (bWriteb AND Reg2E) THEN
            wr26 = 0;
            wr2E = 1;                     "resets Commands register.
            
         ELSE
            wr26 = 0;
            wr2E = 0;

                   
         END IF;

 
         IF (Reg26) THEN
            db = RegisterTTCdata;

         ELSIF (Reg28) THEN
            db[3..0] = RegisterTTCselect;
            db[15..4] = 0;

         ELSIF (Reg2C) THEN
            db = RegisterI2C;

         ELSIF (Reg2E) THEN
            db = RegisterCmd;

         END IF;


         dboe = bReadb AND (Reg26 OR Reg28 OR Reg2C OR Reg2E);    "OE




"==============================================================================
" SPARE I/O
"==============================================================================

"I2C Test
"OUTPUT   sgbC[7..0];             "TIM1

"         sgbC[0] = SCL;                "pl163
"         sgbC[1] = SDA;                "pl164
"         sgbC[2] = xSCL;               "pl165
"         sgbC[3] = xSDA;               "pl166

"         sgbC[4] = I2C_enable;         "pl167
"         sgbC[5] = I2C_busy;           "pl168
"         sgbC[6] = i2c_Data_nPointer;  "pl169
"         sgbC[7] = i2c_Read_nWrite;    "pl170


"OUTPUT  sgbC[7..0];

"        sgbC[5] = BCntStr;
"        sgbC[4] = EvCntHStr;
"        sgbC[3] = EvCntLStr;
"        sgbC[2] = L1CntHighStrobe;
"        sgbC[1] = L1CntLowStrobe;
"        sgbC[0] = BCntStrobe;



INPUT    sgbA[7..0];     "Spare global bus A
INPUT    sgbB[7..0];     "Spare global bus B
INPUT    sgbC[7..0];     "Spare global bus C
INPUT    sgbD[4..2];     "Spare global bus D
INPUT    enExtRodBusy;    "was sgbD[5]
        "sgbD[0] now = TIM_OK_OUT defined above
        "sgbD[1] now = TTC_ready_in defined above

INPUT    s3_9[7..0];     "Spare local bus
INPUT    s8_9[7..0];     "Spare local bus








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