//---------------------------------------------------------
// ZBT BGA165 SSRAM pipelined: XJEase device file
// SSRAM_BGA165_pipelined.xje $Revision: 1.5 $
// (c)2001-2011 XJTAG Limited
//
// Disclaimer: XJTAG makes no guarantees whatsoever
// about this code.  You use it at your own risk ...
// This code requires XJTAG version 1.4 or later.
//
// This file tests Non-JTAG ZBTRAM using Test()(INT result)
//---------------------------------------------------------

DEVICE NAME := "ZBT SSRAM (pipelined)"

  PINS
    DATA    := M2, L2, K2, J2, M1, L1, K1, J1,
               G2, F2, E2, D2, G1, F1, E1, D1,
               G11, F11, E11, D11, G10, F10, E10, D10,
               M11, L11, K11, J11, M10, L10, K10, J10;
    ADDRESS := //R2,
               R11, R10, P10,
               B10, A10, R9, P9, B9, A9, R8, P8,
               R4, P4, R3, P3, B2, A2, P6, R6;
    nCE     := A3;
    nCE2    := A6;
    CE2     := B3;
    nOE     := B8;
    nWE     := B7;
    BWE     := B4, A4, A5, B5;
    CLK     := B6;
    Adv     := A8;
    DNU     := A1, B1;
    ZZ      := H11;
    nCKE    := A7;
  END;

  DISABLE DEVICE
    //---------------------------------------------------------------------
    // This section must be edited depending on how the chip is connected.
    // Putting pins in this section will reduce the test coverage, so only
    // set the minimum number of pins for your board.
    //---------------------------------------------------------------------

    // Disable outputting from chip: use nOE.
    nOE  := 1;

    // Disable writing to chip: Set CE lines if possible.
    nCE  := 1;
    nCE2 := 1;
    CE2  := 0;

    // If all CE and OE lines are tied, don't let the DATA bus be driven.
    //    DATA := Z;
  END;

  TEST COVERAGE
    DATA    := SHORTS OPEN HI LO;
    ADDRESS := SHORTS OPEN HI LO;
    nCE     := OPEN HI LO;
    nCE2    := OPEN HI LO;
    nOE     := OPEN HI LO;
    nWE     := OPEN HI LO;
    BWE     := SHORTS OPEN HI LO;
    CLK     := OPEN HI LO;
    Adv     := OPEN HI LO;
    ZZ      := OPEN HI LO;
    nCKE    := OPEN HI LO;
  END;

  FILES
    "memtestSSRAM.xje";
  END;

END;


//----------------------------------------------------------------------------------
// Constants and static variables
//----------------------------------------------------------------------------------

CONST INT ADDR_BUS_WIDTH := WIDTHOF(ADDRESS);
CONST INT DATA_BUS_WIDTH := WIDTHOF(DATA);
CONST INT BYTE_BUS_WIDTH := WIDTHOF(BWE);
CONST INT BYTE_WIDTH     := 8;
CONST INT DEBUG := FALSE;

INT DataPipe:=0;
INT DataPipe1 := 0;
INT AddrPipe1 := 0;
INT AddrPipe2 := 0;
INT State := 0;



//----------------------------------------------------------------------------------
// Memory Test. Returns 1 for a failure, 0 for a pass.
// Calls MemTest (memtestSSRAM.xje) and tests extra pins
//----------------------------------------------------------------------------------
Test()(INT result)
//----------------------------------------------------------------------------------

  IF WRITEABLE(nCE) THEN SET nCE := 0; END;
  IF WRITEABLE(CE2) THEN SET CE2 := 1; END;
  IF WRITEABLE(nCE2) THEN SET nCE2:= 0; END;
  IF WRITEABLE(nOE) THEN SET nOE := 0; END;
  IF WRITEABLE(ZZ) THEN SET ZZ  := 0; END;
  IF WRITEABLE(nCKE) THEN SET nCKE := 0; END;
  IF WRITEABLE(Adv) THEN SET Adv := 0; END;

  PRINT("\nTesting memory chip ", DEVICE_REF, "...\n");
  result := 0;

  PRINT("Calling MemTest...\n");
  MemTest()(result);

  IF (result = 1) THEN
    PRINT("Memory chip ", DEVICE_REF, " FAILED...\n\n");
    RETURN;
  END;

  WriteKnownData()();

  IF (WRITEABLE(nCE)) THEN
    PRINT("Testing nCE...\n");
    SET nCE := 1;
    TestReadWrite()(result);
    IF (result != 0) THEN
      PRINT("ERROR : nCE FAILED (setting pin high failed to disable device)\n");
      PRINT("Pin is open or shorted to ground/control line\n");
      PRINT("Memory chip ", DEVICE_REF, " FAILED...\n\n");
      RETURN;
    END;
    SET nCE := 0;
  END;

  IF (WRITEABLE(CE2)) THEN
    PRINT("Testing CE2...\n");
    SET CE2 := 0;
    TestReadWrite()(result);
    IF (result != 0) THEN
      PRINT("ERROR : CE2 FAILED (setting pin low failed to disable device)\n");
      PRINT("Pin is open or shorted to power\n");
      PRINT("Memory chip ", DEVICE_REF, " FAILED...\n\n");
      RETURN;
    END;
    SET CE2 := 1;
  END;

  IF (WRITEABLE(nCE2)) THEN
    PRINT("Testing nCE2...\n");
    SET nCE2 := 1;
    TestReadWrite()(result);
    IF (result != 0) THEN
      PRINT("ERROR : nCE2 FAILED (setting pin high failed to disable device)\n");
      PRINT("Pin is open or shorted to ground/control line\n");
      PRINT("Memory chip ", DEVICE_REF, " FAILED...\n\n");
      RETURN;
    END;
    SET nCE2 := 0;
  END;

  IF (WRITEABLE(nOE)) THEN
    PRINT("Testing OE...\n");
    TestReadWriteOE()(result);
    IF (result != 0) THEN
      PRINT("ERROR : nOE FAILED (setting pin high failed to disable readcycle)\n");
      PRINT("Pin is open or shorted to ground/control line\n");
      PRINT("Memory chip ", DEVICE_REF, " FAILED...\n\n");
      RETURN;
    END;
    SET nOE := 0;
  END;

  IF (WRITEABLE(ZZ)) THEN
    PRINT("Testing ZZ...\n");
    SET ZZ := 1;
    TestReadWrite()(result);
    IF (result != 0) THEN
      PRINT("ERROR : Sleep (ZZ) FAILED (setting pin high failed to disable device).\n");
      PRINT("Pin is open or shorted to ground/control line\n");
      PRINT("Memory chip ", DEVICE_REF, " FAILED...\n\n");
      RETURN;
    END;
    SET ZZ := 0;
  END;

  IF (WRITEABLE(nCKE)) THEN
    PRINT("Testing nCKE...\n");
    SET nCKE := 1;
    TestReadWrite()(result);
    IF (result != 0) THEN
      PRINT("ERROR : nCKE FAILED (setting pin high failed to disable device).\n");
      PRINT("Pin is open or shorted to ground/control line\n");
      PRINT("memory chip ", DEVICE_REF, " FAILED...\n\n");
      RETURN;
    END;
    SET nCKE := 0;
  END;

  IF (WRITEABLE(Adv)) THEN
    PRINT("Testing Adv...\n");
    TestBurst()(result);
    IF (result != 0) THEN
      PRINT("ERROR : Adv FAILED (burst write unsuccessful)\n");
      PRINT("Pin is open or shorted to ground/control line\n");
      PRINT("Memory chip ", DEVICE_REF, " FAILED...\n\n");
      RETURN;
    END;
  END;

  PRINT("Memory chip ", DEVICE_REF, " PASSED...\n\n");
  result := 0;

  // Disable the device before exiting...
  IF WRITEABLE(nCE) THEN SET nCE := 1; END;
  IF WRITEABLE(CE2) THEN SET CE2 := 0; END;
  IF WRITEABLE(nCE2) THEN SET nCE2:= 1; END;
  IF WRITEABLE(nOE) THEN SET nOE := 1; END;
  SAFE;


END;



//----------------------------------------------------------------------------------
// Test that burst mode works by writing two values rather than one
//----------------------------------------------------------------------------------
TestBurst()(INT result)
//----------------------------------------------------------------------------------
  INT value1 WIDTH DATA_BUS_WIDTH, value2 WIDTH DATA_BUS_WIDTH;
  INT data1 := 0xaa55ff00[(DATA_BUS_WIDTH-1)..0];
  INT data2 := 0xdeaddead[(DATA_BUS_WIDTH-1)..0];

  result := 1;


  SET CLK := 0, ADDRESS := 0, DATA := data1, nWE := 0, BWE := 0, Adv := 0;
  SET CLK := 1;
  SET CLK := 0, Adv := 1;
  SET CLK := 1;
  SET CLK := 0, Adv := 0, nWE :=1;
  SET CLK := 1;
  SET CLK := 0, DATA := data2;
  SET CLK := 1;

  IF DEBUG THEN
    PRINT("Writing OxAA55ff00 to 0x0 and 0xDEADDEAD to 0x1 in burst mode\n");
  END;

  ReadCyclePipe(0)(value1);
  ReadCyclePipe(1)(value1);
  ReadCyclePipe(1)(value1);
  ReadCyclePipe(1)(value2);

  IF (DEBUG) THEN
    PRINT("Read 0x",HEX(value1)," and 0x",HEX(value2)," from 0x0 and 0x1 respectively\n");
  END;


  IF (value1 != data1 || value2 != data2) THEN
    RETURN;
  END;

  result := 0;
END;


//----------------------------------------------------------------------------------
WriteKnownData()()
//----------------------------------------------------------------------------------

  WriteCyclePipe(0, 0xAB, 0);
  WriteCyclePipe(1, 0xCD, 0);
  WriteCyclePipeEnd(0,1);

END;

//----------------------------------------------------------------------------------
// Function to apply a simple write / read cycle testing the CE, OE, WE, CLK, pins
//----------------------------------------------------------------------------------
TestReadWrite()(INT result)
//----------------------------------------------------------------------------------
  INT bigWord;
  result := 0;

  ReadCyclePipe(0)(bigWord);
  ReadCyclePipe(1)(bigWord);
  ReadCyclePipe(1)(bigWord);

  IF (bigWord != 0xAB) THEN
    IF (DEBUG) THEN
      PRINT("Wrote 1 received 0x", HEX(bigWord), "\n");
    END;
    RETURN;
  END;

  ReadCyclePipe(1)(bigWord);

  IF (bigWord != 0xCD) THEN
    IF (DEBUG) THEN
      PRINT("Wrote 0 received 0x", HEX(bigWord), "\n");
    END;
    RETURN;
  END;

  result := 1;

END;



//----------------------------------------------------------------------------------
// Function to apply a simple write / read cycle but holding the OE pin high,
// Meaning that the value should not be read.
//----------------------------------------------------------------------------------
TestReadWriteOE()(INT result)
//----------------------------------------------------------------------------------

  INT bigWord WIDTH 36;
  result := 0;

  SET CLK := 0, ADDRESS := 0, nWE:=1, DATA:=I, nOE := 1;
  SET CLK := 1;
  SET CLK := 0, ADDRESS := 1;
  SET CLK := 1;
  SET CLK := 0, DATA := I;
  SET CLK := 1, bigWord := DATA;

  IF (bigWord != 0xAB) THEN
    IF (DEBUG) THEN
      PRINT("Wrote 1 received 0x", HEX(bigWord), "\n");
    END;
    RETURN;
  END;

  SET CLK := 0, DATA := I;
  SET CLK := 1, bigWord := DATA;

  IF (bigWord != 0xCD) THEN
    IF (DEBUG) THEN
      PRINT("Wrote 0, received 0x", HEX(bigWord), "\n");
    END;
    RETURN;
  END;

  result := 1;

END;




//----------------------------------------------------------------------------------
// Functions required for use of device file with memtestSSRAM.xje
//----------------------------------------------------------------------------------


PrintByte(INT i)()
  PRINT(PINNUM(BWE[i]));
END;

PrintAddr(INT i)()
  PRINT(PINNUM(ADDRESS[i]));
END;

PrintData(INT i)()
  PRINT(PINNUM(DATA[i]));
END;

IsByteWriteAble()(INT result)
  IF (WRITEABLE(BWE)) THEN
    result := 1;
  ELSE
    result := 0;
  END;
END;


//----------------------------------------------------------------------------------
// Read and write cycles.
// "WriteCycle" and "ReadCycle" use the pipelined cycles below to optimise performance.
// Note the optimised cycles are NOT used in the control line tests found in the device
// file. This ensures each test case is seperate from one another.
//----------------------------------------------------------------------------------



//----------------------------------------------------------------------------------
// Function to perform a write cycle, write code to specified address
// byte specifies which byte will be written to:
// byte = 0 - All bytes
// byte = 0x1110 - DQa
// byte = 0x1101 - DQb
// byte = 0x1011 - DQc
// byte = 0x0111 - DQd
//----------------------------------------------------------------------------------
WriteCycle( INT addr WIDTH ADDR_BUS_WIDTH, INT data WIDTH DATA_BUS_WIDTH, INT byte WIDTH BYTE_BUS_WIDTH)()
//----------------------------------------------------------------------------------

  WriteCyclePipe(addr,data,byte);
  State := 0;
  IF DEBUG THEN PRINT("\tWriting 0x", HEX(data)," to address 0x", HEX(addr), " (with BWE set to 0x",HEX(byte),")\n"); END;

END;

//----------------------------------------------------------------------------------
// Function to perform a read cycle, which reads from address1, with result the outputted data
// Function sets up address for next 2 reads at address2 and address3 respectively.
//----------------------------------------------------------------------------------
ReadCycle( INT addr1 WIDTH ADDR_BUS_WIDTH, INT addr2 WIDTH ADDR_BUS_WIDTH, INT addr3 WIDTH ADDR_BUS_WIDTH ) ( INT result )
//----------------------------------------------------------------------------------

  IF (State = 0) THEN
    WriteCyclePipeEnd(addr1,addr2);
    ReadCyclePipe(addr3)(result);
  ELSE


    IF ( (addr1 = AddrPipe1)&&(addr2 = AddrPipe2) ) THEN
      ReadCyclePipe(addr3)(result);
    ELSE
      ReadCyclePipe(addr1)(result);
      ReadCyclePipe(addr2)(result);
      ReadCyclePipe(addr3)(result);
    END;

    AddrPipe1 := AddrPipe2;
    AddrPipe2 := addr3;

  END;

  State := 1;
  IF DEBUG THEN PRINT("\tRead 0x", HEX(result)," from address 0x", HEX(addr1),"\n"); END;

END;

//----------------------------------------------------------------------------------
WriteCyclePipe(INT address WIDTH ADDR_BUS_WIDTH, INT code, INT byte)()
//----------------------------------------------------------------------------------

  SET CLK := 0, ADDRESS := address, nWE:=0, DATA:=DataPipe1, BWE := byte[3..0];
  SET CLK := 1;
  DataPipe1 := DataPipe;
  DataPipe := code;

END;

//----------------------------------------------------------------------------------
WriteCyclePipeEnd(INT address1 WIDTH ADDR_BUS_WIDTH, INT address2 WIDTH ADDR_BUS_WIDTH)()
//----------------------------------------------------------------------------------

  SET CLK := 0, ADDRESS := address1, nWE:=1, DATA:=DataPipe1;
  SET CLK := 1;
  AddrPipe1 := address1;
  SET CLK := 0, ADDRESS := address2, nWE:=1, DATA:=DataPipe;
  SET CLK := 1;
  AddrPipe2 := address2;

END;

//----------------------------------------------------------------------------------
ReadCyclePipe(INT address WIDTH ADDR_BUS_WIDTH)(INT result )
//----------------------------------------------------------------------------------

  SET CLK := 0, ADDRESS := address, nWE:=1, DATA:= I;
  SET CLK := 1, result := DATA;

END;