CONST INT MEMTEST_DEBUG_ALL := 0;
CONST INT MEMTEST_DEBUG_SOME := 1;
CONST INT MEMTEST_DEBUG_NONE := 2;
CONST INT MEMTEST_DEBUG_LEVEL := MEMTEST_DEBUG_SOME;
CONST INT TOPADDR := ~0[ADDR_WIDTH-1..0];
CONST INT TOPDATA := ~0[(DATA_BUS_WIDTH-1)..0];
CONST INT DATABUSTESTNUM := LOG(DATA_BUS_WIDTH) + 1 + (1 << (LOG(DATA_BUS_WIDTH)) < DATA_BUS_WIDTH);
MemTest()(INT testFail)
INT failTestA;
INT tempResult;
testFail := 0;
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN
PRINT("Starting Optimised Address Bus & Data Bus Test..\n");
END;
OptimisedTestAddrData()(failTestA,tempResult);
IF tempResult THEN
testFail := 1;
IF (MEMTEST_DEBUG_LEVEL <=1) THEN PRINT("Optimised Address & Data Bus Test FAILED... Moving on to Detailed test...\n"); END;
TestDetail(failTestA)();
ELSE
IF (MEMTEST_DEBUG_LEVEL <=1) THEN PRINT("Optimised Addr & Data test Passed\nMoving on to DQM test...\n"); END;
DQMTest()(tempResult);
IF (tempResult) THEN
testFail := 1;
END;
END;
END;
OptimisedTestAddrData()(INT failTestA, INT OpTestFail)
INT result;
INT address WIDTH ROW_WIDTH;
INT data WIDTH DATA_BUS_WIDTH;
INT correctData WIDTH DATA_BUS_WIDTH;
INT i;
INT dummyvar;
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test A : Primarily testing Address Bus\n"); END;
WriteCycle(0,0,0);
address := 1<< COL_WIDTH;
FOR i:=0 FOR (ROW_WIDTH+BANK_BUS_WIDTH)
Databustestvalue(i)(data);
WriteCycle(address, data,0);
address := address << 1;
END;
CheckMemValue(0,0)(result,dummyvar);
IF result THEN failTestA := TRUE; END;
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test B : Primarily testing Data Bus\n"); END;
address := 1<<COL_WIDTH;
FOR i := 0 FOR DATABUSTESTNUM
Databustestvalue(i)(correctData);
CheckMemValue(address,correctData)(result,dummyvar);
address := address << 1;
END;
IF !result THEN
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test C : Testing for shorts between address lines, and shorts betweeen address and data lines\n"); END;
InvertedAddressTest()(result);
END;
OpTestFail := result;
END;
TestDetail(INT failTestA)()
INT dataFailures WIDTH DATA_BUS_WIDTH;
INT addFailures WIDTH ROW_WIDTH;
INT bankFailures WIDTH BANK_BUS_WIDTH;
INT addrdataFailures WIDTH ROW_WIDTH;
INT result;
INT failByteEnable;
INT controlFailure;
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test 1 : Checks potential data bus errors\n"); END;
DataBusTest()(dataFailures);
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("End of databus test. Concrete diagnosis not possible until further testing done\n"); END;
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test 2 : Analysis of Test 1 results\n"); END;
ControlCheck(dataFailures)(failByteEnable, controlFailure);
IF failByteEnable THEN
IF CLK_BUS_WIDTH > 1 THEN
PRINT("NOTE: With multiple clock signals, errors that appear to be due to DQM/DQS failures may actually be due to CLK errors\n");
END;
RETURN;
END;
IF controlFailure THEN
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN
PRINT("Large failures found. Check Command lines (CS/RAS/CAS/WE)");
IF (DQM_BUS_WIDTH = 1) THEN PRINT(", DQM");
IF (DQS_BUS_WIDTH) THEN PRINT("/DQS"); END;
END;
PRINT(" pin, address/bank/clock-enable pins...\n");
END;
RETURN;
END;
IF (dataFailures != 0) THEN
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test 3 : Checking for shorts between the address and data bus\n"); END;
AddrDataShortTestDetail()(result);
IF result THEN RETURN; END;
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test 4 : Checking for shorted data lines\n"); END;
DataBusShortTest(dataFailures)();
ELSE
IF !failTestA THEN
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test 5 : Checking for shorted address lines\n"); END;
AddShortHighTest()();
ELSE
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test 6 : Checking for address line failures\n"); END;
AddressTest()(addFailures,bankFailures);
IF ((addFailures!=0)||(bankFailures!=0)) THEN
IF (MEMTEST_DEBUG_LEVEL = 0) THEN PRINT("Starting Test 7 : Checking for shorted address lines\n"); END;
AddShortLowTest(addFailures)();
END;
END;
END;
END;
DQMLinePrint(INT bool, INT byteFailures)()
INT i;
FOR i:=0 FOR DQM_BUS_WIDTH
IF byteFailures[i] = 1 THEN
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN
PRINT("DQM failure, line ",i," pin number: "); PrintDQM(i);
IF (bool && DQS_BUS_WIDTH) THEN PRINT(" OR DQS failure, line ",i," pin number: "); PrintDQS(i); END;
PRINT("\n");
END;
END;
END;
END;
DQMTest()(INT dqmTestFail)
INT i,j;
INT data WIDTH DATA_BUS_WIDTH;
INT dqmFailures WIDTH DQM_BUS_WIDTH;
INT count;
INT correctData := 0;
IF (DQM_BUS_WIDTH = 1) THEN
WriteCycle(0,0xAA,1);
ReadCycle(0)(data);
IF (data = 0xAA) THEN
dqmTestFail := 1;
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN PRINT("Error: DQM appears to be stuck low.\n"); END;
END;
ELSE
FOR i:=0 FOR DQM_BUS_WIDTH
WriteCycle(0,TOPDATA,0)();
WriteCycle(0,0,1<<i)();
ReadCycle(0)(data);
FOR j:= 0 FOR DQM_BUS_WIDTH
IF ((i != j)&&(dqmFailures[j]=0)) THEN
IF ( data[(8*(j+1)-1)..8*j] != 0 ) THEN
dqmTestFail := 1;
dqmFailures[j] := 1;
END;
ELSIF (( data[(8*(j+1)-1)..8*j] != ~0[7..0] )&&( dqmFailures[j] = 0 )) THEN
dqmTestFail := 1;
dqmFailures[j] := 1;
END;
END;
END;
IF (dqmFailures != ~(1<<DQM_BUS_WIDTH)) THEN
DQMLinePrint(FALSE,dqmFailures)();
ELSE
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN PRINT("DQM FAILURE\n"); END;
END;
END;
END;
DataBusTest()(INT dataFailures)
INT address WIDTH ROW_WIDTH;
INT data WIDTH DATA_BUS_WIDTH;
INT correctData WIDTH DATA_BUS_WIDTH;
INT failData WIDTH DATA_BUS_WIDTH;
INT i;
WriteCycle(TOPADDR,TOPDATA,0);
FOR i := 0 FOR 2*(DATABUSTESTNUM-1)
IF (i >= DATABUSTESTNUM - 1) THEN
Databustestvalue(i+1-DATABUSTESTNUM)(correctData);
correctData := ~correctData[(DATA_BUS_WIDTH-1)..0];
address := 0;
ELSE
Databustestvalue(i)(correctData);
address := TOPADDR;
END;
WriteCycle(address, correctData,0);
ReadCycle(address)(data);
failData := data ^ correctData;
IF ((MEMTEST_DEBUG_LEVEL = 0) && failData) THEN PRINT("Read 0x",HEX(data),", expected to read 0x",HEX(correctData),"\n"); END;
DO WHILE failData
dataFailures[LOG(failData)] := 1;
failData := failData ^ (1 << LOG(failData));
END;
END;
END;
ControlCheck(INT dataFailures WIDTH DATA_BUS_WIDTH)(INT failByteEnable, INT controlFailure)
INT i,j;
INT count := 0;
INT byteFailures := 0;
INT data1, data2;
IF DQM_BUS_WIDTH > 1 THEN
FOR i:=0 FOR DQM_BUS_WIDTH
count := 0;
FOR j:= 8*i FOR 8
IF (dataFailures[j] = 1) THEN
count := count + 1;
END;
END;
IF (count > 4) THEN
byteFailures[i] := 1;
END;
END;
END;
IF (byteFailures = ~0[(DQM_BUS_WIDTH-1)..0]) THEN
controlFailure := TRUE;
ELSIF (byteFailures !=0) THEN
failByteEnable := TRUE;
DQMLinePrint(TRUE, byteFailures)();
RETURN;
END;
count := 0;
controlFailure := FALSE;
WriteCycle(0,0,0);
ReadCycle(0)(data1);
WriteCycle(TOPADDR,TOPDATA,0);
ReadCycle(TOPADDR)(data2);
FOR i:=0 FOR DATA_BUS_WIDTH
count := count + (data1[i] = 1) + (data2[i] = 0);
END;
IF (count >= DATA_BUS_WIDTH/3) THEN
controlFailure := TRUE;
END;
END;
AddrDataShortTestDetail()(INT AddrDataShort)
INT data WIDTH DATA_BUS_WIDTH;
INT data2 WIDTH DATA_BUS_WIDTH;
INT failData WIDTH DATA_BUS_WIDTH;
INT address WIDTH ROW_WIDTH;
INT i;
INT count;
INT pinsfound := FALSE;
count := 0;
FOR i:=0 FOR 2
WriteCycle(TOPADDR,TOPDATA,0);
AddrDataShortTest(0)(count);
AddrDataShortTest(TOPDATA)(count);
END;
IF ((count = 2)||(count = 4)) THEN
AddrDataShort := TRUE;
END;
IF AddrDataShort THEN
address := 1<<COL_WIDTH;
FOR i:=0 FOR (ROW_WIDTH+BANK_BUS_WIDTH)
WriteCycle(0,0,0);
ReadCycle(0)(data);
WriteCycle(address,0,0);
ReadCycle(address)(failData);
IF (data != failData) THEN
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN
IF (MEMTEST_DEBUG_LEVEL = 0) THEN
PRINT("Wrote 0x0 to 0x",HEX(address)," read back 0x",HEX(failData)," expected to read 0x",HEX(data),"\n");
END;
IF (i<ROW_WIDTH) THEN
PRINT("Address bus bit ",i," pin: ");
PrintAddr(i)();
ELSE
PRINT("Bank bus bit ",i-ROW_WIDTH," pin: ");
PrintBank(i-ROW_WIDTH);
END;
PRINT(" shorted to data bus pin\n");
END;
pinsfound := TRUE;
END;
address := address << 1;
END;
data := 1;
FOR i:=0 FOR DATA_BUS_WIDTH
WriteCycle(0,0,0);
WriteCycle(0,data,0);
ReadCycle(0)(failData);
IF (failData[i] != data[i]) THEN
WriteCycle(TOPADDR,(1<<i),0);
ReadCycle(TOPADDR)(failData);
IF (failData[i] = 1) THEN
pinsfound := TRUE;
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN PRINT("Data line ",i," shorted to an address/bank line\n"); END;
END;
END;
data := data << 1;
END;
IF pinsfound = FALSE THEN
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN PRINT("Possible RAS, AP BIT or address line failure\n"); END;
END;
END;
END;
AddrDataShortTest(INT data)(INT count)
INT data1 WIDTH DATA_BUS_WIDTH;
INT data2 WIDTH DATA_BUS_WIDTH;
WriteCycle(0,data,0);
ReadCycle(0)(data1);
WriteCycle(TOPADDR,data,0 );
ReadCycle(TOPADDR)(data2);
IF data1!=data2 THEN
IF MEMTEST_DEBUG_LEVEL = 0 THEN
PRINT("Wrote 0x",HEX(data)," to 0x0 and 0xFF..FF, read back 0x",HEX(data1)," and 0x",HEX(data2)," respectively\n");
END;
count := count + 1;
END;
END;
DataBusTestPrint(INT dataFailures)()
INT i;
FOR i:=0 TO (DATA_BUS_WIDTH-1)
IF ((dataFailures[i] = 1) && (MEMTEST_DEBUG_LEVEL <= 1)) THEN
PRINT("Data bus failed on line ",i, " - pin: ");
PrintData(i)(); PRINT("\n");
END;
END;
END;
DataBusShortTest(INT dataFailures)()
INT i;
INT j;
INT data WIDTH DATA_BUS_WIDTH;
INT dataShortPossible WIDTH DATA_BUS_WIDTH;
WriteCycle(0,0,0);
ReadCycle(0)(data);
FOR i:=0 FOR DATA_BUS_WIDTH
IF (dataFailures[i] && !data[i]) THEN
dataShortPossible[i] := 1;
END;
END;
FOR i := 0 FOR DATA_BUS_WIDTH
FOR j := (i+1) TO (DATA_BUS_WIDTH-1)
IF (dataShortPossible[i] && dataShortPossible[j]) THEN
WriteCycle(0,(1<<i) + (1<<j),0);
ReadCycle(0)(data);
IF (data[i] && data[j]) THEN
dataFailures[i] := 0;
dataFailures[j] := 0;
dataShortPossible[i] := 0;
dataShortPossible[j] := 0;
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN
PRINT("Data bus line ",i," pin ");
PrintData(i); PRINT(" shorted to Data bus line ",j," pin ");
PrintData(j)(); PRINT("\n");
END;
END;
END;
END;
END;
IF (dataShortPossible != 0) THEN
WriteCycle(TOPADDR,TOPDATA,0);
ReadCycle(TOPADDR)(data);
FOR i:=0 FOR DATA_BUS_WIDTH
IF (dataShortPossible[i] && data[i]) THEN
dataFailures[i] := 0;
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN
PRINT("Data bus line ",i," pin ");
PrintData(i); PRINT(" shorted to another Data bus line\n");
END;
END;
END;
END;
DataBusTestPrint(dataFailures)();
END;
AddressTest()(INT addFailures, INT bankFailures)
INT address WIDTH ROW_WIDTH;
INT data WIDTH DATA_BUS_WIDTH;
INT correctData WIDTH DATA_BUS_WIDTH;
INT tempresult;
INT i;
INT dummyvar;
INT count;
WriteCycle(0,0,0);
address := 1<<COL_WIDTH;
FOR i:= 0 FOR (ROW_WIDTH+BANK_BUS_WIDTH)
Databustestvalue(i)(correctData);
CheckMemValue(address,correctData)(dummyvar,tempresult);
IF tempresult THEN
count := count + 1;
addFailures[i] := (i<ROW_WIDTH);
IF (i >= ROW_WIDTH) THEN
bankFailures[i-ROW_WIDTH] := 1;
END;
END;
address := address << 1;
END;
IF (count > ROW_WIDTH/3) THEN
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN PRINT("Possible RAS, AP BIT or address line failure\n"); END;
addFailures := 0;
ELSE
FOR i:=0 FOR ROW_WIDTH
IF ((MEMTEST_DEBUG_LEVEL <= 1)&&(addFailures[i] = 1)) THEN
PRINT("Address bus failure on line ",i, " - pin: ");
PrintAddr(i)(); PRINT("\n");
END;
END;
FOR i:=0 FOR BANK_BUS_WIDTH
IF ((MEMTEST_DEBUG_LEVEL <= 1)&&(bankFailures[i] = 1)) THEN
PRINT("Bank bus failure on line ",i, " - pin: ");
PrintBank(i)(); PRINT("\n");
END;
END;
END;
END;
InvertedAddressTest()(INT result)
INT bitUnderTest;
INT data;
INT i,address;
INT tempresult;
WriteCycle(TOPADDR,TOPDATA,0);
WriteCycle(0,0,0);
WriteCycle(0,TOPDATA,0);
bitUnderTest := 1<<COL_WIDTH;
FOR i := 0 FOR (ROW_WIDTH+BANK_BUS_WIDTH);
address := ~ bitUnderTest[(ADDR_WIDTH-1)..0];
WriteCycle(address, 0,0);
bitUnderTest := bitUnderTest << 1;
END;
CheckMemValue( 0,TOPDATA )( result, tempresult );
CheckMemValue( TOPADDR,TOPDATA )( result, tempresult);
END;
AddShortHighTest()()
INT i,data;
INT failData;
INT address;
INT bitUnderTest WIDTH ADDR_WIDTH;
WriteCycle(TOPADDR,TOPDATA,0);
data := (1 << (DATA_BUS_WIDTH - 1));
bitUnderTest := 1<<COL_WIDTH;
FOR i := 0 FOR (ROW_WIDTH + BANK_BUS_WIDTH)
address := ~ bitUnderTest;
WriteCycle(address, data,0);
ReadCycle(address)(data);
ReadCycle(TOPADDR)(failData);
IF (failData = data) THEN
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN
IF (i>=ROW_WIDTH) THEN
PRINT("Bank line ",i-ROW_WIDTH," pin - ");
PrintBank(i-ROW_WIDTH);
ELSE
PRINT("Address line ",failData - (1<<(DATA_BUS_WIDTH-1))," pin - ");
PrintAddr(failData - (1<<(DATA_BUS_WIDTH-1)));
END;
PRINT(" is shorted to another Address/Bank line that is listed\n");
END;
END;
data := data + 1;
bitUnderTest := bitUnderTest << 1;
END;
END;
AddShortLowTest(INT addFailures)()
INT i;
INT result;
InvertedAddressTest()(result);
IF (!result) THEN
IF (MEMTEST_DEBUG_LEVEL <= 1) THEN
PRINT("There are shorts between the listed faulty address and bank lines\n");
END;
END;
END;
CheckMemValue(INT address,INT correctData WIDTH DATA_BUS_WIDTH)(INT result, INT tempresult)
INT failData;
ReadCycle(address)(failData);
IF failData != correctData THEN
result := 1;
tempresult := 1;
IF (MEMTEST_DEBUG_LEVEL = 0) THEN
PRINT("Read 0x",HEX(failData)," from address: 0x",HEX(address), ", expected 0x",HEX(correctData),"\n");
END;
ELSE
tempresult := 0;
END;
END;
Databustestvalue( INT Iteration )(INT data)
IF (Iteration < DATABUSTESTNUM) THEN
DatabustestvalueA(Iteration)(data);
ELSE
DatabustestvalueB(Iteration - DATABUSTESTNUM)(data);
END;
END;
DatabustestvalueA( INT Iteration )(INT data)
INT bitpos ;
INT width := DATA_BUS_WIDTH;
IF (Iteration>= DATABUSTESTNUM-1) THEN
data := 2;
bitpos := 2;
ELSE
data := (1<<(1<<(Iteration)))-1;
bitpos := 2<<Iteration ;
END;
DO WHILE (bitpos < width)
data[(width-1)..bitpos] := data;
bitpos := bitpos<<1;
END;
END;
DatabustestvalueB(INT Iteration)(INT data)
INT width := DATA_BUS_WIDTH;
IF Iteration = 0 THEN
data := ( 1 << DATA_BUS_WIDTH/2 ) - 1;
RotateLeft()(data);
ELSIF ((Iteration+1)%width != 0) THEN
RotateLeft()(data);
ELSE
data[(width-1)..(width-2)] := (data >> 1)[(width-1)..(width-2)];
END;
END;
RotateLeft()(INT data)
data := ( (data << 1)[(DATA_BUS_WIDTH-1)..1] : data[DATA_BUS_WIDTH -1] );
END;