Yes. On average with NRZ data it is off 50% of the time.
22V10 state machine (done in 1999, compiled with CUPL):
Name GAL;
Partno V1.7;
Date 10/05/99;
Revision 1.7;
Designer P;
Company X Ltd;
Assembly ;
Location ICXX;
Device P22V10LCC;
/*
GAL FOR FIBRE LINE DRIVER.
Implements both encoder and decoder.
NOTE: the Partno field above is used for the UES. However, to get
the UES you need to use G22V10LCC and this needs CUPL4 because CUPL3
has a bug on that device.
MOD RECORD
1.0 1/11/98 Created.
1.1 3/11/98 TEST_ENA & TMD inverted.
1.2 6/11/98 DEC_OUT forced to 0 if Test switch pressed.
1.4 28/12/98 In TMD, ENC_OUT *not* taken from DEC_IN if switch
is pressed. Comments changed re external sync.
1.5 21/4/99 Decoder redesigned.
1.6 22/4/99 Decoder changed, TMD now sets Dout=1 and triggers
the invalid decode data watchdog.
1.7 10/5/99 Encoder & decoder redesigned, to properly terminate
TMD mode.
*/
/* Inputs */
pin 2 = CLK; /* Clock */
pin 3 = RESET; /* Global Reset */
pin 4 = PRESET; /* Global Preset */
pin 5 = SPARE2; /* Unused input */
pin 6 = SPARE3; /* Unused input */
pin 7 = SPARE4; /* Unused input */
pin 9 = SPARE5; /* Unused input */
pin 10 = SPARE6; /* Unused input */
pin 11 = SPARE7; /* Unused input */
pin 12 = !ENC_IN; /* Encoder input, inverted due to MAX232 */
pin 13 = !TEST_ENA; /* Test Mode (loopback) switch, active-low */
pin 16 = DEC_IN; /* Decoder input */
/* Outputs */
pin 27 = EQ0; /* Encoder state machine */
pin 26 = EQ1; /* Encoder state machine */
pin 25 = EQ2; /* Encoder state machine */
pin 24 = DQ0; /* Decoder state machine */
pin 23 = DQ1; /* Decoder state machine */
pin 21 = DQ2; /* Decoder state machine */
pin 20 = DQ3; /* Decoder state machine */
pin 19 = !TMD; /* Test Mode detect LED, active-low */
pin 18 = ENC_OUT; /* Encoder output */
pin 17 = !DEC_OUT; /* Decoder output, inverted due to MAX232 */
/* Definitions */
/* One does need to give the encoder & decoder states different names */
$DEFINE est_0 'b'000 /* All possible encoder states */
$DEFINE est_1 'b'001 /* See NOTES for explanation of bits */
$DEFINE est_2 'b'010
$DEFINE est_3 'b'011
$DEFINE est_4 'b'111
$DEFINE est_5 'b'101
$DEFINE est_6 'b'110
$DEFINE est_7 'b'100
$DEFINE dst_0 'b'0000 /* All possible decoder states */
$DEFINE dst_1 'b'0001 /* See NOTES for explanation of bits */
$DEFINE dst_2 'b'0011
$DEFINE dst_3 'b'0111
$DEFINE dst_4 'b'0110
$DEFINE dst_5 'b'1111
$DEFINE dst_6 'b'1110
$DEFINE dst_7 'b'1001
$DEFINE dst_8 'b'0101
$DEFINE dst_9 'b'0010
$DEFINE dst_10 'b'1011
$DEFINE dst_11 'b'1010
$DEFINE dst_12 'b'1101
$DEFINE dst_13 'b'1000
$DEFINE dst_14 'b'0100
$DEFINE dst_15 'b'1100
/* D-types forming the two state machines. These must both be ZERO-based, due
to a "feature" of CUPL */
FIELD encoder = [EQ2..0];
FIELD decoder = [DQ3..0];
/* Equations */
EQ0.AR = RESET; /* All D-types are reset with RESET */
EQ1.AR = RESET;
EQ2.AR = RESET;
DQ0.AR = RESET;
DQ1.AR = RESET;
DQ2.AR = RESET;
DQ3.AR = RESET;
EQ0.SP = PRESET; /* All D-types are preset with PRESET */
EQ1.SP = PRESET;
EQ2.SP = PRESET;
DQ0.SP = PRESET;
DQ1.SP = PRESET;
DQ2.SP = PRESET;
DQ3.SP = PRESET;
/* ********************** ENCODER *************************** */
SEQUENCE encoder
{
/* wait for Din=1, SW=0 */
PRESENT est_0
IF TEST_ENA NEXT est_7; /* test mode */
IF ENC_IN NEXT est_1; /* Din=1 */
DEFAULT NEXT est_0;
/* nothing happens here */
PRESENT est_1
NEXT est_2;
/* nothing happens here */
PRESENT est_2
IF TEST_ENA NEXT est_6; /* test mode */
IF !ENC_IN NEXT est_3; /* Din=0 */
DEFAULT NEXT est_2;
/* nothing happens here */
PRESENT est_3
NEXT est_4;
/* nothing happens here */
PRESENT est_4
NEXT est_5;
/* nothing happens here */
PRESENT est_5
NEXT est_0; /* return to S0 */
/* switch pressed - generate a 101010101.... output while switch pressed */
/* exit only if switch released and incoming (decoder i/p) data has stopped */
PRESENT est_6
NEXT est_7;
PRESENT est_7
IF TEST_ENA NEXT est_6; /* stay in test mode */
IF !TEST_ENA & !DEC_IN & !TMD NEXT est_0; /* exit test mode */
DEFAULT NEXT est_7;
}
/* Decode Encoder state machine Q2..0 D-types into ENC_OUT output */
TABLE encoder => enc /* enc = internal encoder o/p, before mux */
{
est_0 => 0;
est_1 => 1;
est_2 => 0;
est_3 => 1;
est_4 => 0;
est_5 => 1;
est_6 => 1;
est_7 => 0;
}
/*
Switch ENC_OUT output according to whether test mode detected by decoder.
The final encoder output is taken from the decoder output if the following
condition is true:
tmd=1 and sw=0 and !s7(encoder)
The following statement could have been done as encoder:[enc_0..enc_6] but
that might not work if the states had funny binary codings. All depends on
how CUPL implements the enc_0..enc_6 range stuff.
*/
enc_not_s7 = encoder:est_0 #
encoder:est_1 #
encoder:est_2 #
encoder:est_3 #
encoder:est_4 #
encoder:est_5 #
encoder:est_6;
enc_out_mux = TMD & !TEST_ENA & enc_not_s7;
ENC_OUT = ( enc & !enc_out_mux ) # ( DEC_IN & enc_out_mux );
/* ********************** DECODER *************************** */
SEQUENCE decoder
{
/* wait for Din=1, then S1 */
PRESENT dst_0
IF DEC_IN NEXT dst_1;
DEFAULT NEXT dst_0;
/* wait for Din=0, then S2 */
PRESENT dst_1
IF !DEC_IN NEXT dst_2;
DEFAULT NEXT dst_8;
/* To S3, unless Din=1 so we have 101... & we have to test for TMD */
PRESENT dst_2
IF DEC_IN NEXT dst_9;
DEFAULT NEXT dst_3;
/* wait for Din=1, then S4 */
PRESENT dst_3
IF DEC_IN NEXT dst_4;
DEFAULT NEXT dst_3;
/* To S5 */
PRESENT dst_4
NEXT dst_5;
/* if Din=1 now then it is a normal end (S6) & we go back to start (via S7) */
PRESENT dst_5
IF DEC_IN NEXT dst_6;
DEFAULT NEXT dst_10;
/* back to start */
PRESENT dst_6
NEXT dst_7;
PRESENT dst_7
NEXT dst_0;
/* Get here from S1 if we got 11 */
PRESENT dst_8
IF !DEC_IN NEXT dst_3; /* 110, OK */
DEFAULT NEXT dst_11; /* 111 i.e. crap */
/* 101 detected, check for a 0, to make 1010 */
PRESENT dst_9
IF !DEC_IN NEXT dst_12;
DEFAULT NEXT dst_0;
/* Get here from S5 if S5 just missed Din=1 so we recheck */
PRESENT dst_10
IF !DEC_IN NEXT dst_3;
DEFAULT NEXT dst_6;
/* Get here from S8 if we see 111... - wait here until Din=0; this
prevents a persisting Dout=1 condition when a long Din=1 input
has ended */
PRESENT dst_11
IF !DEC_IN NEXT dst_0;
DEFAULT NEXT dst_11;
/* Get here from S9, having detected 1010, check for a 1 to make 10101 */
PRESENT dst_12
IF DEC_IN NEXT dst_13;
DEFAULT NEXT dst_0;
/* TMD mode is 1 all the time we are in S13-S15. Any pattern is OK but
we exit to S0 on two consecutive 0 samples */
PRESENT dst_13
IF DEC_IN NEXT dst_15;
DEFAULT NEXT dst_14;
PRESENT dst_14
IF DEC_IN NEXT dst_15;
DEFAULT NEXT dst_0; /* exit */
PRESENT dst_15
IF DEC_IN NEXT dst_13;
DEFAULT NEXT dst_14;
}
/* Decode Decoder state machine Q3..0 D-types into DEC_OUT output */
TABLE decoder => dec /* dec = internal decoder o/p, before switch */
{
dst_0 => 0;
dst_1 => 0;
dst_2 => 0;
dst_3 => 1;
dst_4 => 1;
dst_5 => 1;
dst_6 => 0;
dst_7 => 0;
dst_8 => 0;
dst_9 => 0;
dst_10 => 0;
dst_11 => 0;
dst_12 => 0;
dst_13 => 0;
dst_14 => 0;
dst_15 => 0;
}
/* Decode Decoder state machine Q3..0 D-types into TMD (Test Mode) output */
TABLE decoder => TMD
{
dst_0 => 0;
dst_1 => 0;
dst_2 => 0;
dst_3 => 0;
dst_4 => 0;
dst_5 => 0;
dst_6 => 0;
dst_7 => 0;
dst_8 => 0;
dst_9 => 0;
dst_10 => 0;
dst_11 => 0;
dst_12 => 0;
dst_13 => 1;
dst_14 => 1;
dst_15 => 1;
}
/*
Switch DEC_OUT output according to whether test mode detected by decoder.
We force it to 0 if the Test switch is ON; this stops muck coming
out of the DEC_OUT output if we are doing a *local* loopback, and it stops
muck coming out of the local unit with remote loopback.
Should not be necessary.
*/
DEC_OUT = dec & !TEST_ENA;
/*
NOTES
The RESET input is not really necessary, since the P3Z22V10 has a
power-on reset (which works provided Vcc rise is monotonic). RESET
must be grounded on the package, or driven from a reset circuit.
21/4/99: RESET is driven for a circuit which detects a break-level
decoder output exceeding about 100ms; normally this would indicate a
decoding fault.
The PRESET input is also not necessary, but CUPL warns that the .SP
signals are undefined, and we have lots of spare inputs anyway.
PRESET must be grounded on the package.
To avoid logic hazard problems, the state bit patterns are arranged
so that whenever there is an asynchronous input (e.g. ENC_IN) only
*one* D-type in the state machine changes state, i.e. Gray code.
HOWEVER this scheme is not sufficient to avoid problems because when
CUPL compiles the state expressions it still generates equations
where we have both "input" and "!input" affecting the same D-type,
and there is an uncontrolled skew inside some 22V10 devices in their
internal true/complement input generation. So external
synchronisation is still required, is done with an HC74, so we may
not have bothered with the Gray code encoding. But its use does
improve reliability, in fact the Philips P3Z22V10 was highly reliable
without the HC74. The gray-code was abandoned in some places because
there aren't enough states. Only some states actually need the
gray-coded patterns anyway.
Test Mode (TMD) is detected by initially looking for a 10101 pattern
and then hanging in there regardless of the data until a 00 is
sampled. The need to initially detect a 1010.. assumes a certain
mismatch between the crystals of the two converters; otherwise a
constant 1111.. sampling is possible but this mismatch will always
occur within a fraction of a second. It is no good looking for a 111..
because this can occur at power-up.
There are big problems exiting TMD, because of the way the signal is
looped back in each of the two units. The things just keep looping
back to each other for ever. It is not enough to just stop the
encoder encoding the 01010101... pattern when the button is not
pressed any more, because of the pattern which is already in transit
through the remote unit and which will continue to return to us for a
few us longer, thus causing our local unit to remain in TMD mode.
It was solved by the encoder waiting for button release, and by the
decoder testing for 101010... (not just a long high level) to detect
TMD, and by bringing encoder state S7 into the encoder output mux.
It is not necessary to use "SEQUENCED" (with "D" on the end) because
CUPL knows the flip-flop type from the device name.
*/
It even has a LINE TEST feature which sends a special pattern which is looped back.