Autumn 1996

Solutions

There are a whole bunch of clever and interesting ways that you can
drive the `d12`

pin to determine what sort of sequential
logic element is behind `q1`

and `q2`

. Most
everyone caught on to the basic ideas: assert `d12`

near
a rising edge, look for a response; assert `d12`

near a
falling edge, watch what happens; pulse `d12`

high during
the positive or negative cycle of the clock, watch the result. The
waveform below shows many of these situations.

Marked in the waveform are four points where we can deduce information about the logic elements:

**a** Are we driving a positive clocked latch? If
so, then the latch should follow `d12`

at this edge.
`q2`

does, so we guess that it's a positive clocked
latch.

**b** Is either element a negative edge trigged
flip-flop? If so, then at this falling clock edge, with
`d12`

asserted, the flip-flop should change from 0 to 1.
`q1`

doesn't change, so it's not a negative edge triggered
device.

**c** What about positive edge triggered devices?
`d12`

is asserted, and here is a positive edge. In fact,
`q1`

*does* go high when this edge comes along, so
`q1`

is probably a positive edge triggered device.

**d** Do we have a negative clocked latch? If we
had such a device, it would reflect changes in `d12`

when
the clock was *low*. `d12`

changes here, but
nothing happens on our devices, so they aren't negative clocked
latches.

The device has an asynchronous clear which resets the output to 0 whenever clr is 1. The output remains 0 until the input is high at a positive edge of the clock. Thereafter, the output will remain high, regardless of what the input does. The 1 on the input has been "caught".

MODULE shift1 interface (di, sr, sl, s0, s1, clk -> z); TITLE 'One-bit shift register' "Inputs di, sr, sl, s0, s1 pin; clk pin; "Output z pin istype 'reg, buffer'; "Alias EQUATIONS z.clk = clk; WHEN ( s1 & s0) THEN z := di; ELSE WHEN ( s1 & !s0) THEN z := sr; ELSE WHEN (!s1 & s0) THEN z := sl; ELSE WHEN (!s1 & !s0) THEN z := z.fb; END

MODULE shift4 interface (clk, i3..i0, s2..s0 -> q3..q0); TITLE 'Universal 4-bit shift register' clk, i3..i0, s2..s0 pin; q3..q0 pin istype 'com'; shift1 interface (di, sr, sl, s0, s1, clk -> z); sh3..sh0 functional_block shift1; EQUATIONS [sh3..sh0].clk = clk; [q3..q0] = [sh3..sh0].z; [sh3..sh0].di = [i3..i0]; sh3.sr = (sh3.z & s2) # (sh0.z & !s2 & !s1); sh2.sr = sh3.z; sh1.sr = sh2.z; sh0.sr = sh1.z; sh3.sl = sh2.z; sh2.sl = sh1.z; sh1.sl = sh0.z; sh0.sl = !s2 & sh3.z; [sh3..sh0].s1 = s0; [sh3..sh0].s0 = (s2 & s1) # ((s2 $ s1) & !s0); ENDUnfortunately, ABEL also lets you have very cumbersome code. Many of you had in your EQUATIONS block a big

`WHEN THEN ELSE ... `

block that switched on the shift control signals `s2..s0`

.
Certainly, this strategy is not wrong, but probably not ideal. In
particular, it is easy to make mistakes with this approach; there are
scores of lines of code, anyone of which you might mistype. Further,
it is difficult for someone to look over the code and discern that the
blocks are, in fact, closely related (i.e., logical shift left and
arithmetic shift left both
Many of you who opted for the ABEL approach built separate modules for
flip-flops. Again, this strategy was not incorrect, but probably
excessive. To create a flip-flop in an ABEL module, you need only
declare a pin to be a `reg`

:

q3..q0 pin istype 'reg, buffer';

`sl`

and `sr`

blocks are on opposite sides.

This schematic uses an additional ABEL block to generate the miscellaneous control signals:

MODULE control interface (s2..s0 -> c1..c0, m0_0, m3_0, m3_1); TITLE 'Shifter control' "Inputs s2..s0 pin; "Outputs c1..c0 pin istype 'com'; " Shift cell control m0_0 pin istype 'com'; " Control for bit 0 mux m3_0, m3_1 pin istype 'com'; " Control for bit 3 mux "Aliases s = [s2..s0]; c = [c1..c0]; m3 = [m3_1..m3_0]; hold = 0; shiftLeft = 1; shiftRight = 2; load = 3; EQUATIONS WHEN (s == 0) THEN c = hold; "Hold ELSE WHEN (s == 1) THEN c = shiftRight; "Circular shift right ELSE WHEN (s == 2) THEN c = shiftLeft; "Circular shift left ELSE WHEN (s == 3) THEN c = shiftRight; "Logical shift right ELSE WHEN (s == 4) THEN c = shiftLeft; "Logical shift left ELSE WHEN (s == 5) THEN c = shiftRight; "Arithmetic shift right ELSE WHEN (s == 6) THEN c = shiftLeft; "Arithmetic shift left ELSE WHEN (s == 7) THEN c = load; "Parallel load WHEN (s == 2) THEN m0_0 = 1; "Use out3 ELSE m0_0 = 0; "Use 0 WHEN (s == 1) THEN m3 = 0; "Use out0 ELSE WHEN (s == 5) THEN m3 = 1; "Use out3 ELSE m3 = 2; "Use 0 ENDRegardless of the approach you took, the waveforms for the solution should resemble those shown below:

(For more information about using buses in Synario, see Tip #4 on the Synario Tips page).

MODULE graycntr interface(clk, reset, en -> c2..c0); TITLE 'Gray code counter' "Inputs clk, reset, en pin; "Outputs c2..c0 pin istype 'reg, buffer'; "Alias c = [c2..c0]; EQUATIONS c.clk = clk; WHEN (en) THEN { WHEN (reset) THEN c := ^b110; ELSE WHEN (c == ^b000) THEN c := ^b001; ELSE WHEN (c == ^b001) THEN c := ^b011; ELSE WHEN (c == ^b011) THEN c := ^b010; ELSE WHEN (c == ^b010) THEN c := ^b110; ELSE WHEN (c == ^b110) THEN c := ^b111; ELSE WHEN (c == ^b111) THEN c := ^b101; ELSE WHEN (c == ^b101) THEN c := ^b100; ELSE WHEN (c == ^b100) THEN c := ^b000; } ELSE c := c; ENDThe notation

`^b001`

is an alternate notation for a binary
value.
Several solutions were presented where the equations for each c2, c1,
and c0 were simply equations from the previous values of c. This
certainly is a valid approach, but probably not the best one. In
particular, if you have used a K-map to derive these equations by
hand, then you are not using the tools to their full capacity. The
motivation to a Hardware Description Language such as ABEL is to allow
the designer to state his or her intentions at a high level and let
the *tools* translate these intentions into equations.

A sample waveform for the Gray code counter is:

Besides writing ABEL for the Gray code counter, you were also asked to draw a state machine for the device, and show how the counter would be mapped onto an EO320. A state machine for the counter is:

The most common mistakes on the state machine were forgetting to label
the transitions, or forgetting to show the transitions for when
`en`

was low.

Finally, we have the EO320 fuse map. If you peeked inside the .jed
file that Synario created, you could see exactly which fuses were made
or blown. However, you could also have gotten the gist of the story
from looking at the equations that Synario produced. One thing to
watch out for on the Fuse Map is that the top minterm on each output
pin is *not* part of the pin's value. Instead, this minterm
controls the tristate buffer associated with the pin.

*(See following page)*