//---------------------------------------------------------
// ZBT TQFP100 SSRAM flowthrough: XJEase device file
// SSRAM_TQFP100_flowthrough.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 TQFP100 SSRAM (flowthrough)"

  PINS
    ADDRESS := 84, 100, 99, 83,
               82, 81, 44, 45, 46, 47, 48,
               49, 50, 32, 33, 34, 35, 36, 37;
    DATA    := 30,  1, 80, 51,
               29, 28, 25, 24, 23, 22, 19, 18, // DQd
               13, 12,  9,  8,  7,  6,  3,  2, // DQc
               79, 78, 75, 74, 73, 72, 69, 68, // DQb
               63, 62, 59, 58, 57, 56, 53, 52; // DQa
    nCE     := 98;
    nCE2    := 92;
    CE2     := 97;
    nOE     := 86;
    nWE     := 88;
    BWE     := 96, 95, 94, 93;
    CLK     := 89;
    Adv     := 85;
    DNU     := 43, 42;
    ZZ      := 64;
    nCKE    := 87;
  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 WIDTH DATA_BUS_WIDTH;
INT AddrPipe WIDTH ADDR_BUS_WIDTH;
INT State WIDTH 1;


//----------------------------------------------------------------------------------
// 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, nWE := 0, DATA := data1, BWE := 0, Adv := 0;
  SET CLK := 1;
  SET CLK := 0, Adv := 1;
  SET CLK := 1;
  SET CLK := 0, nWE := 1, Adv := 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)(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);

END;

//----------------------------------------------------------------------------------
// Function to apply a simple write / read cycle testing the CE, OE, WE, CLK, pins
// Fails if write and read works, since setting the control line should have stopped
// it working.
//----------------------------------------------------------------------------------
TestReadWrite()(INT result)
//----------------------------------------------------------------------------------
  INT bigWord WIDTH DATA_BUS_WIDTH;
  result := 0;

  ReadCyclePipe(0)(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 DATA_BUS_WIDTH;
  result := 0;

  SET CLK := 0, ADDRESS := 0, nWE:=1, DATA:=I, nOE := 1;
  SET CLK := 1, DATA:=I;
  SET CLK := 0, ADDRESS := 1;
  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, ADDRESS := 1;
  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.
//----------------------------------------------------------------------------------


//----------------------------------------------------------------------------------
// Function to perform a write cycle, write code to specified address
// IMPORTANT : write will not occur until next clock cycle.
// 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 read at address 2 (address3 is a dummy variable).
//----------------------------------------------------------------------------------
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)();
    ReadCyclePipe(addr2)(result);
    State := 1;
  ELSE
    IF addr1 = AddrPipe THEN
      ReadCyclePipe(addr2)(result);
    ELSE
      ReadCyclePipe(addr1)(result);
      ReadCyclePipe(addr2)(result);
    END;
  END;
  AddrPipe := addr2;

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

END;




//----------------------------------------------------------------------------------
WriteCyclePipe(INT addr WIDTH ADDR_BUS_WIDTH, INT code WIDTH DATA_BUS_WIDTH, INT byte)()
//----------------------------------------------------------------------------------

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

END;

//----------------------------------------------------------------------------------
WriteCyclePipeEnd(INT addr WIDTH ADDR_BUS_WIDTH)()
//----------------------------------------------------------------------------------

  SET CLK := 0, ADDRESS := addr, nWE:=1, DATA:=DataPipe;
  SET CLK := 1;

END;

//----------------------------------------------------------------------------------
ReadCyclePipe(INT addr WIDTH ADDR_BUS_WIDTH)(INT result WIDTH DATA_BUS_WIDTH)
//----------------------------------------------------------------------------------

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

END;