The built-in sequential parts — Register, ARegister, DRegister, PC, RAM
xx and
Screen —
do not behave the same as sequential parts written in HDL using DFFs.
The test interface does not display the same value as the part's out pin.
This is only an issue in tests that output values between tick and tock, which is
displayed as time "t+" in the test output.
This test output shows the difference between the test interface output and the out pin
for the built-in parts.
|time| in | addr |load |ARegister[]| Areg | PC[] | pc |RAM16K[1]| ram |Screen[1]| scr |
|0+ | 0| 0| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
|1 | 0| 0| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
|1+ | 1111| 1| 1 | 1111 | 0 | 1111 | 0 | 1111 | 0 | 1111 | 0 |
|2 | 1111| 1| 1 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 |
|2+ | 1111| 1| 0 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 |
|3 | 1111| 1| 0 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 |
If you have read the post
Tick, Tock, and the Hardware Simulator Output, you should recognize that the test interface
output is the input to the built-in part's internal DFF.
I recommend that you ignore the displayed output value from Register, ARegister, DRegister, PC,
RAMxx and Screen during time "t+".
If you are interested in the gory details, read on.
The HDL that is being tested is
SeqTest.hdl
CHIP SeqTest {
IN in[16],
addr[16],
load;
OUT Areg[16], // ARegister output
Dreg[16], // DRegister output
pc[16], // PC output
ram[16], // RAM16K output
scr[16]; // Screen output
PARTS:
ARegister(in=in, load=load, out=Areg);
DRegister(in=in, load=load, out=Dreg);
PC(in=in, load=load, inc=false, reset=false, out=pc);
RAM16K(in=in, load=load, address=addr[0..13], out=ram);
Screen(in=in, load=load, address=addr[0..12], out=scr);
}
The test script is
SeqTest.tst
load SeqTest.hdl,
output-file SeqTest.out,
output-list time%S0.4.0 in%D0.6.0 addr%D0.6.0 load%B2.1.2 ARegister[]%D3.6.2 Areg%D1.6.1
PC[]%D1.6.1 pc%D1.6.1 RAM16K[1]%D2.6.1 ram%D1.6.1 Screen[1]%D2.6.1 scr%D1.6.1;
tick, output; tock, output;
// tick-tock write
set addr 1, set in 1111, set load 1,
tick, output;
tock, output;
set load 0,
tick, output;
tock, output;
...
There's more in the script that tests other aspects of the built-in parts.
(This is esoterica that would only be important if these simulated parts were real hardware...)
An unexpected thing that I found is that the DFFs in the built-in parts are implemented as
master-slave flip-flops instead of edge-triggered flip-flops. The test interface is
showing the value of the master FF and the out pin is showing the value of the
slave FF. (I expected that the built-in parts were displaying the asynchronous inputs to
their DFFs.)
|time| in | addr |load |ARegister[]| Areg | PC[] | pc |RAM16K[1]| ram |Screen[1]| scr |
|6 | 0| 1| 0 | 3333 | 3333 | 3333 | 3333 | 3333 | 3333 | 3333 | 3333 |
Inputs changed but no TICK -- test interface does not change. I/F is not async.
|6 | 2222| 1| 1 | 3333 | 3333 | 3333 | 3333 | 3333 | 3333 | 3333 | 3333 |
TICK -- interface changes. Master FF loaded from 'in'. 'out' does not change.
|6+ | 1111| 1| 1 | 1111 | 3333 | 1111 | 3333 | 1111 | 3333 | 1111 | 3333 |
Inputs changed but no TOCK -- test interface does not change.
|6+ | 0| 1| 1 | 1111 | 3333 | 1111 | 3333 | 1111 | 3333 | 1111 | 3333 |
TOCK -- interface does not change. Slave FF loaded from Master. 'out' changes.
|7 | 0| 1| 1 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 | 1111 |
See
http://www.play-hookey.com/digital/sequential/d_nand_flip-flop.html to learn about the details
of a master-slave DFF.
There's also a test that explores the read functionality of the RAM* parts. If you study this
test's output, you will see that the RAM's 'out' pin changes on both TICK and TOCK.
--Mark