support@xjtag.com
DEVICE NAME := "LAN91C111-113"
COMPAT_VERSION := 1;
DESCRIPTION := "";
PINS
DATA := 70, 71, 72, 73, 75, 76, 77, 78,
101, 102, 103, 104, 106, 107, 108, 109;
ADDR := 94, 93, 92, 91, 90, 89, 88, 87, 96, 85, 84, 83, 82, 81, 80;
nRD := 33;
nWR := 34;
ARDY := 40;
INTR0 := 31;
RESET := 32;
nBE := 97, 96;
AEN := 43;
TPO_POS := 16;
TPO_NEG := 17;
TPI_POS := 19;
TPI_NEG := 20;
nADS := 39;
LEDa := 24;
LEDb := 25;
XTALI := 1;
END;
DISABLE DEVICE
nRD := 1;
INTR0 := Z;
END;
TEST COVERAGE
DATA := OPEN SHORTS LO HI;
ADDR := OPEN SHORTS LO HI;
nRD := OPEN LO HI;
nWR := OPEN LO HI;
INTR0 := OPEN LO HI;
nBE := HI;
AEN := OPEN HI;
TPO_POS := FUNCTIONAL;
TPO_NEG := FUNCTIONAL;
TPI_POS := FUNCTIONAL;
TPI_NEG := FUNCTIONAL;
XTALI := FUNCTIONAL;
END;
END;
CONST INT BANK_SELECT := 0xe;
CONST INT B0_TRANSMIT_CONTROL := 0x0;
CONST INT B0_EPH_STATUS := 0x2;
CONST INT B0_RECEIVE_CONTROL := 0x4;
CONST INT B0_COUNTER := 0x6;
CONST INT B0_MEMORY_INFO := 0x8;
CONST INT B0_RXPHY_CONTROL := 0xa;
CONST INT B1_CONFIG := 0x0;
CONST INT B1_BASE_ADDRESS := 0x2;
CONST INT B1_ADDRESS_0 := 0x4;
CONST INT B1_ADDRESS_2 := 0x6;
CONST INT B1_ADDRESS_4 := 0x8;
CONST INT B1_GEN_PUPOSE := 0xa;
CONST INT B1_CONTROL := 0xc;
CONST INT B2_MMU_COMMAND := 0x0;
CONST INT B2_PACKET_NUMBER := 0x2;
CONST INT B2_FIFO_PORTS := 0x4;
CONST INT B2_POINTER := 0x6;
CONST INT B2_DATA := 0x8;
CONST INT B2_INTERRUPT := 0xc;
CONST INT B3_MII := 0x8;
CONST INT B3_REVISION := 0xa;
CONST INT PHY_MII_CONTROL := 0x0;
CONST INT PHY_MII_STATUS := 0x1;
CONST INT PHY_MII_ID0 := 0x2;
CONST INT PHY_MII_ID1 := 0x3;
CONST INT PHY_MII_ADVERT := 0x4;
CONST INT PHY_MII_REMCAP := 0x5;
CONST INT PHY_MII_CONFIG1 := 0x16;
CONST INT PHY_MII_CONFIG2 := 0x17;
CONST INT PHY_MII_STATUS_OUT := 0x18;
CONST INT PHY_MII_MASK := 0x19;
CONST INT DEBUG := FALSE;
CONST INT PASS := FALSE;
CONST INT FAIL := TRUE;
INT current_bank := 0xffff;
INT BE_16 := 0b1100[WIDTHOF(nBE) - 1 .. 0];
Test()(INT result)
INT base_address;
INT loopback_mode WIDTH 1 := 0;
PRINT("Testing Ethernet controller ", DEVICE_REF, " on board ", BOARD_NAME, "\n");
Reset()(result);
IF (result != PASS) THEN
RETURN;
END;
GetBaseAddress()(base_address);
IF (base_address != 0x0300) THEN
PRINT("Invalid base address found: 0x", HEX(base_address), "\n");
result := FAIL;
RETURN;
END;
RamTest(256)(result);
IF (result != PASS) THEN
RETURN;
END;
IF WIDTHOF(DATA) = 32 THEN
RamTest32(256)(result);
IF (result != PASS) THEN
RETURN;
END;
END;
PRINT("Testing transmitter and interrupts...\n");
TxPacket(loopback_mode)(result);
IF (result != PASS) THEN
RETURN;
END;
PRINT("Internal loopback test...\n");
LoopbackTest(TRUE)(result);
IF (result != PASS) THEN
RETURN;
END;
PRINT("External loopback test...\n");
LoopbackTest(FALSE)(result);
IF (result != PASS) THEN
PRINT("Is the loopback cable installed correctly?\n");
RETURN;
END;
result := PASS;
END;
GetBaseAddress()(INT result)
INT base_address;
IF DEBUG THEN PRINT("Reading device Base Address\n"); END;
Read(1, B1_BASE_ADDRESS)(base_address);
result := 0;
result[15..13] := base_address[15..13];
result[9..5] := base_address[12..8];
IF DEBUG THEN PRINT("Base address = 0x", HEX(result), "\n"); END;
END;
LoopbackTest(INT internal_loopback WIDTH 1)(INT result)
INT data WIDTH 16;
INT loopback_mode WIDTH 1 := 1;
INT stoptime;
result := FAIL;
ResetMmu()(result);
IF result THEN
PRINT("MMU initial reset failed.\n");
RETURN;
END;
IF internal_loopback THEN
Write(0, B0_TRANSMIT_CONTROL, 0x2001);
ELSE
PhyWrite(PHY_MII_CONTROL,0x100);
stoptime := NOW() + 2000;
DO
PhyRead(PHY_MII_STATUS)(data);
UNTIL (data[2] | NOW() > stoptime) END;
IF (data[2]=0) THEN
IF DEBUG THEN PRINT ("No Link..\n"); END;
result := 1;
RETURN;
END;
Write(0, B0_TRANSMIT_CONTROL, 0x0801);
Write(0,B0_RXPHY_CONTROL, 0x0800);
END;
Write(0, B0_RECEIVE_CONTROL, 0x0100);
Read(1, B1_CONTROL)(data);
Write(1, B1_CONTROL, (data | 0x4000));
TxPacket(loopback_mode)(result);
IF (result != PASS) THEN
PRINT("Packet transmit failed in LoopbackTest.\n");
RETURN;
END;
RxPacket(loopback_mode)(result);
IF (result != PASS) THEN
PRINT("Packet receive failed in LoopbackTest.\n");
RETURN;
END;
result := PASS;
IF (DEBUG) THEN PRINT("Loopback test completed OK.\n"); END;
END;
PhyWrite( INT address WIDTH 5, INT data WIDTH 16 )()
INT i;
FOR i := 0 FOR 32
Write(3,B3_MII, 0x3339);
Write(3,B3_MII, 0x333D);
END;
PhyWriteBit(0)();
PhyWriteBit(1)();
PhyWriteBit(0)();
PhyWriteBit(1)();
PhyWriteBit(0)();
PhyWriteBit(0)();
PhyWriteBit(0)();
PhyWriteBit(0)();
PhyWriteBit(0)();
FOR i := 0 FOR 5
PhyWriteBit( address[4] )();
address := address << 1;
END;
PhyWriteBit(1)();
PhyWriteBit(0)();
FOR i := 0 FOR 16
PhyWriteBit( data[15] )();
data := data << 1;
END;
Write(3,B3_MII, 0x3330 );
END;
PhyWriteBit(INT bit WIDTH 1)()
Write(3,B3_MII, 0x3338 | bit );
Write(3,B3_MII, 0x333C | bit );
Write(3,B3_MII, 0x3338 | bit );
END;
PhyRead( INT address WIDTH 5)(INT result)
INT i;
INT data;
IF DEBUG THEN PRINT ("Writing to Phy...\n"); END;
FOR i := 0 FOR 32
Write(3,B3_MII, 0x3339);
Write(3,B3_MII, 0x333D);
END;
PhyWriteBit(0)();
PhyWriteBit(1)();
PhyWriteBit(1)();
PhyWriteBit(0)();
PhyWriteBit(0)();
PhyWriteBit(0)();
PhyWriteBit(0)();
PhyWriteBit(0)();
PhyWriteBit(0)();
FOR i := 0 FOR 5
PhyWriteBit( address[4] )();
address := address << 1;
END;
PhyWriteZ()();
PhyWriteBit(0)();
result := 0;
FOR i := 0 FOR 16
result := result << 1;
Write(3,B3_MII, 0x3330 );
Write(3,B3_MII, 0x3334 );
Read(3, B3_MII)(data);
IF data[1] THEN
result := (result | 1);
END;
END;
result := result >>1;
PhyWriteZ()();
END;
PhyWriteZ()()
Write(3,B3_MII, 0x3330 );
Write(3,B3_MII, 0x3334 );
Write(3,B3_MII, 0x3330 );
END;
TxPacket( INT loopback_mode WIDTH 1)( INT result )
INT packet_number;
INT i;
INT data WIDTH 16;
INT stoptime, timeout;
INT interrupt WIDTH 1;
IF DEBUG THEN PRINT ("Testing transmitter and interrupts...\n"); END;
Read(2, B2_INTERRUPT)(data);
IF (data[1]) THEN
Write(2, B2_INTERRUPT, 0x02);
END;
AllocPacket()(result, packet_number);
IF (result != PASS) THEN
PRINT("Unable to allocate a TX packet.\n");
RETURN;
END;
Write(2, B2_PACKET_NUMBER, packet_number);
Write(2, B2_POINTER, (1 << 14));
Write(2, B2_DATA, 0x0000);
Write(2, B2_DATA, 76);
Write(2, B2_DATA, 0xffff);
Write(2, B2_DATA, 0xffff);
Write(2, B2_DATA, 0xffff);
Write(2, B2_DATA, 0x1234);
Write(2, B2_DATA, 0x5678);
Write(2, B2_DATA, 0xabcd);
Write(2, B2_DATA, 0x0040);
FOR i := 0 FOR 23
data := i[3..0]:~i[3..0]:i[3..0]:~i[3..0];
Write(2, B2_DATA, data);
END;
Write(2, B2_DATA, (1 << 12));
Read(2, B2_POINTER)(result);
result := result & 0x7f;
IF (result != 0x042) THEN
PRINT("Pointer register error, reads 0x", HEX(result), "\n");
result := FAIL;
RETURN;
END;
IF (loopback_mode = 0) THEN
Write(0, B0_TRANSMIT_CONTROL, 1);
END;
Write(2, B2_MMU_COMMAND, (6 << 5));
stoptime := NOW() + 1000;
timeout := 0;
DO
Read(2, B2_INTERRUPT)(data);
IF (NOW() > stoptime) THEN timeout := 1; END;
UNTIL (data[1] || timeout) END;
IF (timeout) THEN
PRINT("Timeout waiting for TX_INT in TxPacket.\n");
result := FAIL;
RETURN;
END;
SET interrupt := INTR0;
IF interrupt = 1 THEN
PRINT("Interrupt incorrectly asserted.\n");
result := FAIL;
RETURN;
END;
Write(2, B2_INTERRUPT, 0x0200);
SET interrupt := INTR0;
IF interrupt = 0 THEN
PRINT("Interrupt pin not asserted.\n");
result := FAIL;
RETURN;
END;
Write(2, B2_INTERRUPT, 0x0000);
Write(2, B2_INTERRUPT, 0x02);
Write(2, B2_POINTER, 0x6000);
Read(2, B2_DATA)(data);
Write(2, B2_MMU_COMMAND, 0x00a0);
IF (data[15] != 0) THEN PRINT("Transmitter underrun error\n"); END;
IF (data[11] != 0) THEN PRINT("Transmitter excessive deferral error\n"); END;
IF (data[10] != 0) THEN PRINT("Transmitter lost carrier error\n"); END;
IF (data[9] != 0) THEN PRINT("Late collision detect error\n"); END;
IF (data[4] != 0) THEN PRINT("Too many collisions error\n"); END;
IF (data[2] != 0) THEN PRINT("Multiple collisions error\n"); END;
IF (data[1] != 0) THEN PRINT("Single collision error\n"); END;
IF (data[0] != 1) THEN
PRINT("Transmitter fatal error detected, status ", HEX(data), "\n");
RETURN;
END;
WaitMmu()(result);
IF (result != PASS) THEN
PRINT("MMU busy error in TxPacket.\n");
RETURN;
END;
PRINT ("Transmitted Packet OK.\n");
result := PASS;
END;
RxPacket(INT loopback_mode WIDTH 1)(INT result)
INT stoptime, timeout;
INT data WIDTH 16;
INT packet_number, packet_size;
INT i, expectedValue;
IF DEBUG THEN PRINT("Receiving a packet...\n"); END;
result := FAIL;
IF (loopback_mode = 0) THEN
Write(0, B0_RECEIVE_CONTROL, 0x0100);
END;
timeout := 0;
stoptime := NOW() + 1000;
DO
Read(2, B2_INTERRUPT)(data);
IF (NOW() > stoptime) THEN
timeout := 1;
END;
UNTIL (timeout || data[0]) END;
IF (timeout != 0) THEN
PRINT("Timeout waiting for receiver interrupt in RxPacket\n");
RETURN;
END;
Read(2, B2_FIFO_PORTS)(packet_number);
IF DEBUG THEN PRINT("Rx packet number ", packet_number[15..8], "\n"); END;
Write(2, B2_POINTER, 0xe000);
Read(2, B2_DATA)(data);
Read(2, B2_DATA)(data);
Read(2, B2_DATA)(data);
Read(2, B2_DATA)(data);
Read(2, B2_DATA)(data);
Read(2, B2_DATA)(data);
Read(2, B2_DATA)(data);
Read(2, B2_DATA)(data);
Read(2, B2_DATA)(packet_size);
packet_size := (packet_size/2)-10;
FOR i := 0 FOR packet_size
Read(2, B2_DATA)(data);
expectedValue := i[3..0]:~i[3..0]:i[3..0]:~i[3..0];
IF data != expectedValue THEN
PRINT("Receive packet data error, expected 0x", HEX(result), " but received 0x", HEX(data), "\n");
result := FAIL;
RETURN;
END;
END;
Read(2, B2_DATA)(data);
Read(2, B2_POINTER)(data);
data := data & 0x7f;
IF (data != 0x40) THEN
PRINT("Pointer register error, reads 0x", HEX(data), "\n");
result := FAIL;
RETURN;
END;
Write(2, B2_MMU_COMMAND, 0x0080);
WaitMmu()(result);
IF (result != PASS) THEN
PRINT("MMU busy error in TxPacket.\n");
RETURN;
END;
PRINT("Packet received OK.\n");
result := PASS;
END;
RamTest(INT test_length)(INT result)
INT data, expected_data WIDTH 16;
INT byte_number;
INT packet_number WIDTH 16;
INT i;
PRINT("Testing RAM buffer...\n");
result := FAIL;
ResetMmu()(result);
IF (result != PASS) THEN
PRINT("MMU initial reset failed.\n");
RETURN;
END;
FOR i := 0 TO 3
AllocPacket()(result, packet_number);
IF (result != PASS) THEN
PRINT("Unable to allocate a packet.\n");
RETURN;
END;
Write(2, B2_PACKET_NUMBER, packet_number);
IF DEBUG THEN PRINT("Writing test Patterns...\n"); END;
byte_number := 0;
Write(2, B2_POINTER, 0x4000);
DO
Write(2, B2_DATA, 0x2345 * byte_number);
byte_number := byte_number + 2;
UNTIL byte_number >= test_length END;
IF DEBUG THEN PRINT("Checking test Patterns...\n"); END;
byte_number := 0;
Write(2, B2_POINTER, 0x6000);
DO
Read(2, B2_DATA)(data);
expected_data := (0x2345 * byte_number)[15..0];
IF (data != expected_data) THEN
PRINT("RAM buffer test readback error at test ", byte_number/2, ", write 0x", HEX(expected_data), ", read 0x", HEX(data), "\n");
ResetMmu()(result);
result := FAIL;
RETURN;
END;
byte_number := byte_number + 2;
UNTIL byte_number >= test_length
END;
END;
ResetMmu()(result);
IF (result != PASS) THEN
PRINT("MMU final reset failed.\n");
result := FAIL;
RETURN;
END;
PRINT("RAM buffer tests completed OK.\n");
result := PASS;
END;
RamTest32(INT test_length)(INT result)
INT data, expected_data WIDTH 32;
INT byte_number;
INT packet_number WIDTH 16;
INT i;
PRINT("Testing RAM buffer...\n");
result := FAIL;
ResetMmu()(result);
IF (result != PASS) THEN
PRINT("MMU initial reset failed.\n");
RETURN;
END;
FOR i := 0 TO 3
AllocPacket()(result, packet_number);
IF (result != PASS) THEN
PRINT("Unable to allocate a packet.\n");
RETURN;
END;
Write(2, B2_PACKET_NUMBER, packet_number);
IF DEBUG THEN PRINT("Writing test Patterns...\n"); END;
byte_number := 0;
Write(2, B2_POINTER, 0x4000);
DO
Write32(2, B2_DATA, 0x23456789 * byte_number);
byte_number := byte_number + 4;
UNTIL byte_number >= test_length END;
IF DEBUG THEN PRINT("Checking test Patterns...\n"); END;
byte_number := 0;
Write(2, B2_POINTER, 0x6000);
DO
Read32(2, B2_DATA)(data);
expected_data := (0x23456789 * byte_number)[31..0];
IF (data != expected_data) THEN
PRINT("RAM buffer test readback error at test ", byte_number/4, ", write 0x", HEX(expected_data), ", read 0x", HEX(data), "\n");
ResetMmu()(result);
result := FAIL;
RETURN;
END;
byte_number := byte_number + 4;
UNTIL byte_number >= test_length
END;
END;
ResetMmu()(result);
IF (result != PASS) THEN
PRINT("MMU final reset failed.\n");
result := FAIL;
RETURN;
END;
PRINT("RAM buffer tests completed OK.\n");
result := PASS;
END;
WaitMmu()(INT result)
INT stoptime, timeout;
INT data WIDTH 16;
result := FAIL;
stoptime := NOW() + 1000;
timeout := 0;
DO
Read(2, B2_MMU_COMMAND)(data);
IF (NOW() > stoptime) THEN timeout := 1; END;
WHILE (data[0]=1 && timeout=0)
END;
IF (timeout) THEN
PRINT("Timeout waiting for MMU not busy in TxPacket.\n");
RETURN;
END;
IF (DEBUG) THEN PRINT("MMU not busy.\n"); END;
result := PASS;
END;
AllocPacket()(INT result, INT packet_number)
INT stoptime;
INT timeout WIDTH 1;
INT data WIDTH 16;
IF DEBUG THEN PRINT("Allocating a packet...\n"); END;
result := FAIL;
packet_number := 0;
Write(2, B2_MMU_COMMAND, (1 << 5));
WaitMmu()(result);
IF (result != PASS) THEN
PRINT("Packet allocate failed.\n");
RETURN;
END;
stoptime := NOW() + 1000;
timeout := 0;
DO
Read(2, B2_INTERRUPT)(data);
IF (NOW() > stoptime) THEN timeout := 1; END;
WHILE (data[3]=0 && timeout=0) END;
IF (timeout) THEN
PRINT("Timeout waiting for alloc INT in AllocPacket.\n");
RETURN;
END;
Read(2, B2_PACKET_NUMBER)(data);
IF data[15]=1 THEN
PRINT("Allocate packet failed.\n");
result := FAIL;
RETURN;
END;
packet_number := 0;
packet_number[5..0] := data[13..8];
IF DEBUG THEN PRINT("Packet 0x", HEX(packet_number[5..0]), " allocated OK.\n"); END;
result := PASS;
END;
ResetMmu()(INT result)
IF DEBUG THEN PRINT("Resetting MMU...\n"); END;
Write(2, B2_MMU_COMMAND, (2<<5));
WaitMmu()(result);
IF (result != PASS) THEN
PRINT("MMU not ready after reset.\n");
RETURN;
END;
IF DEBUG THEN PRINT("MMU reset completed OK.\n"); END;
result := PASS;
END;
Reset()(INT result)
INT data WIDTH 16;
INT bank WIDTH 16;
IF (DEBUG) THEN PRINT("Resetting device...\n"); END;
result :=FAIL;
SET RESET :=1, nWR:=1, nRD:=1;
FLUSH;
SLEEP(2);
SET RESET :=0;
FLUSH;
SLEEP(2);
ReadCycle(BANK_SELECT)(data);
IF data !=0x3300 THEN
PRINT("Failed to read BANK SELECT register of LAN91C11x, expected 0x3300, found 0x",HEX(data),"\n");
RETURN;
END;
FOR bank := 0 TO 7
SetBank(bank)();
ReadCycle(BANK_SELECT)(data);
IF data != (0x3300 + bank) THEN
PRINT("Failed to read BANK SELECT register of LAN91C11x, expected ", HEX(0x3300+bank),", but read 0x",HEX(data),"\n");
RETURN;
END;
END;
ResetMmu()(result);
IF (result != PASS) THEN
PRINT("MMU reset failed.\n");
RETURN;
END;
Write(2, B2_INTERRUPT, 0x0000);
IF DEBUG THEN PRINT("Reset completed OK.\n"); END;
result := PASS;
END;
Write(INT bank, INT address, INT data)()
SetBank(bank)();
WriteCycle(address, data);
END;
Read(INT bank, INT address)(INT data )
SetBank(bank)();
ReadCycle(address)(data);
END;
SetBank(INT bank)()
IF (bank != current_bank) THEN
WriteCycle(BANK_SELECT, bank);
current_bank := bank;
IF DEBUG THEN PRINT("Bank ", bank, " selected.\n"); END;
END;
END;
WriteCycle( INT address, INT data )()
IF DEBUG THEN PRINT("Write 0x", HEX(data), " to bank ", current_bank, " address 0x", HEX(address), "\n"); END;
SET ADDR:=(address + 0x300)>>1, AEN := 0, nADS := 0, nBE := BE_16;
SET nWR := 0, DATA := data;
SET nWR := 1, DATA := I, AEN := 1, nADS := 1;
END;
ReadCycle( INT address )( INT data )
SET ADDR := (address + 0x300)>>1, AEN :=0, DATA := I, nADS := 0, nBE := BE_16;
SET nRD := 0;
SET nRD := 1, data := DATA, AEN := 1, nADS := 1;
data[31..16] := 0;
IF DEBUG THEN PRINT("Read 0x", HEX(data), " from bank ", current_bank, " address 0x", HEX(address), "\n"); END;
END;
Write32(INT bank, INT address, INT data)()
SetBank(bank)();
WriteCycle32(address, data);
END;
Read32(INT bank, INT address)(INT data )
SetBank(bank)();
ReadCycle32(address)(data);
END;
WriteCycle32( INT address, INT data )()
IF DEBUG THEN PRINT("Write 0x", HEX(data), " to bank ", current_bank, " address 0x", HEX(address), "\n"); END;
SET ADDR:=(address + 0x300)>>1, AEN := 0, nADS := 0, nBE := 0x0;
SET nWR := 0, DATA := data;
SET nWR := 1, DATA := I, AEN := 1, nADS := 1;
END;
ReadCycle32( INT address )( INT data )
SET ADDR := (address + 0x300)>>1, AEN :=0, DATA := I, nADS := 0, nBE := 0x0;
SET nRD := 0;
SET nRD := 1, data := DATA, AEN := 1, nADS := 1;
IF DEBUG THEN PRINT("Read 0x", HEX(data), " from bank ", current_bank, " address 0x", HEX(address), "\n"); END;
END;