DEVICE NAME := "Philips SCC2691 UART"
PINS
RDN := 2;
RXD := 3;
TXD := 4;
MPO := 5;
MPI := 6;
NC := 7,8,23,26;
ADDR := 9,10,11;
X1 := 12;
X2 := 13;
RESET := 14;
GND := 15;
INTRN := 16;
CEN := 17;
DATA := 18,19,20,21,22,24,25,27;
WRN := 28;
END;
DISABLE DEVICE
CEN :=1;
END;
TEST COVERAGE
RESET := OPEN LO;
CEN := OPEN HI;
WRN := OPEN HI;
RDN := OPEN HI;
ADDR := SHORTS OPEN HI LO;
DATA := SHORTS OPEN HI LO;
MPO := FUNCTIONAL;
MPI := FUNCTIONAL;
TXD := FUNCTIONAL;
RXD := FUNCTIONAL;
END;
END;
CONST INT DEBUG := FALSE;
CONST INT USE_RESET := FALSE;
STRING TAB := " ";
CONST INT RESULT_PASS := 0;
CONST INT RESULT_FAIL := 0xFFFF;
CONST INT REG_MR := 0;
CONST INT REG_SR := 1;
CONST INT REG_CSR := 1;
CONST INT REG_BRG := 2;
CONST INT REG_CR := 2;
CONST INT REG_RHR := 3;
CONST INT REG_THR := 3;
CONST INT REG_TST := 4;
CONST INT REG_ACR := 4;
CONST INT REG_ISR := 5;
CONST INT REG_IMR := 5;
CONST INT REG_CTU := 6;
CONST INT REG_CTL := 7;
CONST INT ACR_MPO_RTSN := 0x00;
CONST INT ACR_MPO_CTO := 0x01;
CONST INT ACR_MPO_TXCX1 := 0x02;
CONST INT ACR_MPO_TXCX16 := 0x03;
CONST INT ACR_MPO_RXCX1 := 0x04;
CONST INT ACR_MPO_RXCX16 := 0x05;
CONST INT ACR_MPO_TXRDY := 0x06;
CONST INT ACR_MPO_RXRDY := 0x07;
CONST INT ACR_POWERDOWN := 0x00;
CONST INT ACR_POWERUP := 0x08;
CONST INT ACR_COUNT_MPI := 0x00;
CONST INT ACR_COUNT_MPI16 := 0x10;
CONST INT ACR_COUNT_TXC := 0x20;
CONST INT ACR_COUNT_XTAL := 0x30;
CONST INT ACR_TIMER_MPI := 0x40;
CONST INT ACR_TIMER_MPI16 := 0x50;
CONST INT ACR_TIMER_XTAL := 0x60;
CONST INT ACR_TIMER_XTAL16 := 0x70;
CONST INT ACR_BRG_SET1 := 0x00;
CONST INT ACR_BRG_SET2 := 0x80;
CONST INT CSR_TX_50_75 := 0x0;
CONST INT CSR_TX_110_110 := 0x1;
CONST INT CSR_TX_135_135 := 0x2;
CONST INT CSR_TX_200_150 := 0x3;
CONST INT CSR_TX_300_300 := 0x4;
CONST INT CSR_TX_600_600 := 0x5;
CONST INT CSR_TX_1200_1200 := 0x6;
CONST INT CSR_TX_1050_2000 := 0x7;
CONST INT CSR_TX_2400_2400 := 0x8;
CONST INT CSR_TX_4800_4800 := 0x9;
CONST INT CSR_TX_7200_1800 := 0xA;
CONST INT CSR_TX_9600_9600 := 0xB;
CONST INT CSR_TX_38K4_19K2 := 0xC;
CONST INT CSR_TX_TIMER := 0xD;
CONST INT CSR_TX_MPIX16 := 0xE;
CONST INT CSR_TX_MPIX1 := 0xF;
CONST INT CSR_RX_50_75 := 0x00;
CONST INT CSR_RX_110_110 := 0x10;
CONST INT CSR_RX_135_135 := 0x20;
CONST INT CSR_RX_200_150 := 0x30;
CONST INT CSR_RX_300_300 := 0x40;
CONST INT CSR_RX_600_600 := 0x50;
CONST INT CSR_RX_1200_1200 := 0x60;
CONST INT CSR_RX_1050_2000 := 0x70;
CONST INT CSR_RX_2400_2400 := 0x80;
CONST INT CSR_RX_4800_4800 := 0x90;
CONST INT CSR_RX_7200_1800 := 0xA0;
CONST INT CSR_RX_9600_9600 := 0xB0;
CONST INT CSR_RX_38K4_19K2 := 0xC0;
CONST INT CSR_RX_TIMER := 0xD0;
CONST INT CSR_RX_MPIX16 := 0xE0;
CONST INT CSR_RX_MPIX1 := 0xF0;
CONST INT CR_ENABLE_RX := 0x01;
CONST INT CR_DISABLE_RX := 0x02;
CONST INT CR_ENABLE_TX := 0x04;
CONST INT CR_DISABLE_TX := 0x08;
CONST INT CMD_NULL := 0x00;
CONST INT CMD_RESET_MR := 0x10;
CONST INT CMD_RESET_RX := 0x20;
CONST INT CMD_RESET_TX := 0x30;
CONST INT CMD_RESET_ERROR := 0x40;
CONST INT CMD_RESET_BCINT := 0x50;
CONST INT CMD_START_BREAK := 0x60;
CONST INT CMD_STOP_BREAK := 0x70;
CONST INT CMD_START_CT := 0x80;
CONST INT CMD_STOP_CT := 0x90;
CONST INT CMD_ASSERT_RTSN := 0xa0;
CONST INT CMD_NEGATE_RTSN := 0xb0;
CONST INT CMD_RESET_MCINT := 0xc0;
CONST INT MR1_5BIT := 0x0;
CONST INT MR1_6BIT := 0x1;
CONST INT MR1_7BIT := 0x2;
CONST INT MR1_8BIT := 0x3;
CONST INT MR1_EVEN_PARITY := 0x0;
CONST INT MR1_ODD_PARITY := 0x4;
CONST INT MR1_WITH_PARITY := 0x00;
CONST INT MR1_FORCE_PARITY := 0x08;
CONST INT MR1_NO_PARITY := 0x10;
CONST INT MR1_SPEC_PARITY := 0x18;
CONST INT MR1_ERROR_CHAR := 0x00;
CONST INT MR1_ERROR_BLOCK := 0x20;
CONST INT MR1_RXINT_RXRDY := 0x00;
CONST INT MR1_RXINT_FFULL := 0x40;
CONST INT MR1_RXRTS_OFF := 0x00;
CONST INT MR1_RXRTS_ON := 0x80;
CONST INT MR2_STOP1 := 0x07;
CONST INT MR2_STOP2 := 0x0f;
CONST INT MR2_CTSENBTX_OFF := 0x00;
CONST INT MR2_CTSENBTX_ON := 0x10;
CONST INT MR2_TXRTS_OFF := 0x00;
CONST INT MR2_TXRTS_ON := 0x20;
CONST INT MR2_NORMAL := 0x00;
CONST INT MR2_AUTO_ECHO := 0x40;
CONST INT MR2_LOCAL_LOOP := 0x80;
CONST INT MR2_REMOTE_LOOP := 0xC0;
CONST INT ISR_TXRDY := 0x01;
CONST INT ISR_TXEMT := 0x02;
CONST INT ISR_RXRDY := 0x04;
CONST INT ISR_DELTA_BREAK := 0x08;
CONST INT ISR_COUNTER_RDY := 0x10;
CONST INT ISR_UNUSED := 0x20;
CONST INT ISR_MPI_STATE := 0x40;
CONST INT ISR_MPI_CHANGE := 0x60;
Test()(INT result)
INT data;
INT errors;
Initialise()();
TestDataBus()(result); IF result != 0 THEN errors := errors + 1; END;
TestIo()(result); IF result != 0 THEN errors := errors + 1; END;
TestInt()(result); IF result != 0 THEN errors := errors + 1; END;
LoopbackTest()(result); IF result != 0 THEN errors := errors + 1; END;
IF errors != 0 THEN
result := RESULT_FAIL;
PRINT(TAB, "One or more tests failed.\n");
ELSE
result := RESULT_PASS;
PRINT(TAB, "All tests passed.\n");
END;
END;
LoopbackTest()(INT result)
INT isr WIDTH 8;
INT timeout;
INT txdata WIDTH 8 := 0x5A;
INT data WIDTH 8;
INT pass;
PRINT(TAB, "Data loopback test.");
WriteCycle(REG_CR, CMD_RESET_MR + CR_DISABLE_TX + CR_DISABLE_RX);
WriteCycle(REG_MR, MR1_RXINT_RXRDY + MR1_8BIT + MR1_NO_PARITY + MR1_RXRTS_OFF);
WriteCycle(REG_MR, MR2_STOP1 + MR2_CTSENBTX_OFF + MR2_TXRTS_OFF + MR2_NORMAL);
WriteCycle(REG_CR, CMD_STOP_CT);
WriteCycle(REG_CR, CMD_RESET_ERROR);
WriteCycle(REG_CR, CMD_RESET_RX);
WriteCycle(REG_CR, CMD_RESET_TX);
WriteCycle(REG_ACR, (ACR_POWERUP + ACR_BRG_SET1));
WriteCycle(REG_CSR, (CSR_TX_50_75 + CSR_RX_50_75));
WriteCycle(REG_CR, (CMD_NULL + CR_DISABLE_TX + CR_DISABLE_RX));
WriteCycle(REG_CR, (CMD_NULL + CR_ENABLE_TX + CR_ENABLE_RX));
timeout := NOW() + 1000;
DO
ReadCycle(REG_ISR)(isr);
IF DEBUG THEN
PRINT("ISR = 0x", HEX(isr), "\n");
END;
WHILE !(isr & ISR_TXRDY) && (NOW() < timeout)
END;
IF !(isr & ISR_TXRDY) THEN
PRINT("Failed to read TXRDY bit in ISR.\n");
result := RESULT_FAIL;
RETURN;
END;
FOR pass := 0 FOR 16
WriteCycle(REG_THR, txdata + pass);
timeout := NOW() + 1000;
DO
ReadCycle(REG_ISR)(isr);
IF DEBUG THEN PRINT("ISR = 0x", HEX(isr), "\n"); END;
WHILE !(isr & ISR_RXRDY) && (NOW() < timeout)
END;
IF !(isr & ISR_RXRDY) THEN
PRINT("Timeout waiting for RXRDY bit in ISR.\n");
result := RESULT_FAIL;
RETURN;
END;
ReadCycle(REG_RHR)(data);
IF data != (txdata + pass) THEN
PRINT("Receive data error 0x", HEX(data), ", expected 0x", HEX(txdata), "\n");
result := RESULT_FAIL;
RETURN;
END;
PRINT(".");
END;
PRINT("passed OK.\n");
result := RESULT_PASS;
RETURN;
END;
TestIo()(INT result)
INT ctur, ctlr, isr WIDTH 8;
INT startTime, endTime, period;
INT cycles := 50;
PRINT(TAB, "Testing IO pins and baud rate generator...");
WriteCycle(REG_CR, CMD_RESET_MR + CR_DISABLE_TX + CR_DISABLE_RX);
WriteCycle(REG_MR, MR1_8BIT + MR1_NO_PARITY + MR1_RXRTS_OFF);
WriteCycle(REG_MR, MR2_STOP1 + MR2_CTSENBTX_OFF + MR2_TXRTS_OFF + MR2_NORMAL);
WriteCycle(REG_CR, CMD_RESET_ERROR);
WriteCycle(REG_CR, CMD_RESET_RX);
WriteCycle(REG_CR, CMD_RESET_TX);
WriteCycle(REG_ACR, (ACR_COUNT_MPI + ACR_POWERUP + ACR_BRG_SET1 + ACR_MPO_TXCX1));
WriteCycle(REG_CSR, (CSR_TX_50_75 + CSR_RX_50_75));
WriteCycle(REG_CR, (CMD_STOP_CT));
WriteCycle(REG_CTU, ((cycles-1) >> 8));
WriteCycle(REG_CTL, ((cycles-1) & 0xff));
startTime := NOW();
WriteCycle(REG_CR, (CMD_START_CT + CR_ENABLE_TX + CR_ENABLE_RX));
DO
ReadCycle(REG_ISR)(isr);
IF DEBUG THEN
ReadCycle(REG_CTU)(ctur);
ReadCycle(REG_CTL)(ctlr);
PRINT("ISR = 0x", HEX(isr), "CT = ", (ctur*256 + ctlr), "\n");
END;
WHILE !(isr & ISR_COUNTER_RDY) && (NOW() < (40 * cycles) + startTime)
END;
endTime := NOW();
period := (endTime - startTime)/cycles;
IF (period > 21) || (period < 19) THEN
PRINT("Failed, elapsed time for ", cycles, " cycles was ", (endTime - startTime), "mSec\n");
result := RESULT_FAIL;
RETURN;
END;
PRINT("Passed, CLK period = ", period, "mSec\n");
result := RESULT_PASS;
RETURN;
END;
TestDataBus()(INT result)
INT bit;
INT data WIDTH 8;
INT testData WIDTH 8;
PRINT(TAB, "Testing data bus...\n");
FOR bit := 0 TO 7
testData := 1 << bit;
IF DEBUG THEN PRINT("Test bit ", bit, ", test data 0x", HEX(testData), "\n"); END;
WriteCycle(REG_CR, CMD_RESET_MR + CR_DISABLE_TX + CR_DISABLE_RX);
WriteCycle(REG_MR, testData)();
WriteCycle(REG_MR, ~testData)();
WriteCycle(REG_CR, CMD_RESET_MR + CR_DISABLE_TX + CR_DISABLE_RX);
ReadCycle(REG_MR)(data);
IF data != testData THEN
PRINT(TAB, "Failed testing bit ", bit, " in mode register 1.\n");
result := RESULT_FAIL;
RETURN;
END;
ReadCycle(REG_MR)(data);
IF data != ~testData THEN
PRINT(TAB, "Failed testing bit ", bit, " in mode register 2.\n");
result := RESULT_FAIL;
RETURN;
END;
END;
result := RESULT_PASS;
END;
TestInt()(INT result)
INT interrupt;
PRINT(TAB, "Testing interrupt pin...");
WriteCycle(REG_IMR, 0);
SET interrupt := INTRN;
IF (interrupt = 0) THEN
PRINT("Interrupt pin stuck at 0.\n");
result := RESULT_FAIL;
RETURN;
END;
WriteCycle(REG_IMR, 0xFF);
SET interrupt := INTRN;
IF (interrupt != 0) THEN
PRINT("Interrupt not detected.\n");
result := RESULT_FAIL;
RETURN;
END;
WriteCycle(REG_IMR, 0);
PRINT("Interrupt active & inactive detected OK.\n");
result := RESULT_PASS;
RETURN;
END;
WriteCycle(INT address, INT data)()
SET ADDR := address[2..0], DATA := data[7..0], CEN := 0, WRN := 0;
SET WRN := 1, CEN := 1, DATA := I;
IF DEBUG THEN PRINT("Write 0b", BIN(data), " to address 0x", HEX(address), "\n"); END;
END;
ReadCycle(INT address)(INT data)
SET ADDR := address[2..0], DATA := I, CEN := 0, RDN := 0;
SET RDN := 1, CEN := 1, data[7..0] := DATA;
IF DEBUG THEN PRINT("Read 0b", BIN(data), " from address 0x", HEX(address), "\n"); END;
END;
Initialise()()
INT timeout;
SET WRN := 1, RDN := 1, CEN := 1, ADDR := 0, DATA := I;
IF (USE_RESET) THEN
SET RESET := 1;
SLEEP(10);
SET RESET := 0;
END;
WriteCycle(REG_CR, CMD_RESET_MR + CR_DISABLE_TX + CR_DISABLE_RX);
WriteCycle(REG_CR, CMD_STOP_CT);
WriteCycle(REG_CR, CMD_RESET_ERROR);
WriteCycle(REG_CR, CMD_RESET_RX);
WriteCycle(REG_CR, CMD_RESET_TX);
WriteCycle(REG_IMR, 0);
WriteCycle(REG_ACR, ACR_POWERUP);
END;