I built a 4-bit version of Counter.hdl using 74LS74 flip-flops and a 74LS83 adder to be able to demonstrate the timing of real world synchronous sequential logic. 74LS74s are positive edge-triggered DFFs. The adder is wired as an incrementer.
This first oscilloscope trace show the clock on the top trace, with bits 0, 1 and 2 on the lower traces. Horizontal scale is 20 milliseconds per major tick mark. Vertical scale is 5 volts per major tick mark. The clock is running at 60 hertz, so the clock period is 16.7 milliseconds.
You can see that all the flip-flop outputs change with the leading edge of the clock (tick in Nand2Tetris nomenclature).
So, when do the D inputs to the flip-flops change?
This next trace shows, from top to bottom, the clock, flip-flop output Q0 and flip-flop input D0. Same horizontal scale as the first trace.
The input, D0, is the output of the incrementer. When a number is incremented, its least significant bit is always complimented. This trace shows that the incremented value of the DFF output appears on the DFF input at the same time as the leading edge of the clock.
Absolutely nothing happens in this circuit at the falling edge of the clock (tock in Nand2Tetris nomenclature).
To see when the DFF input changes relative to the clock and DFF output, we must zoom in on the time scale 1,000,000 times.
This shows the detail of what happens when the clock ticks. From top to bottom, clock, Q0, D0. The horizontal scale is now 20 nanoseconds per major tick mark. (To appreciate how fast this is, light travels 6 meters in 20ns.)
The first thing to notice is that there is no such thing as instantaneous in hardware. It takes a significant amount of time for the signals to change from 0v to 5v (this is called rise time). Timing measurements are usually made from the midpoints of the rise time interval. The DFF output changes 16.4 nanoseconds after the clock. The adder only takes 15.8 nanoseconds after Q0 changes to output the incremented value.
32.2 nanoseconds after the clock tick, signal propagation is complete and nothing will change until the next clock tick.
This final trace shows that there is no such thing as simultaneous in hardware. For this trace we have zoomed in a bit more. The time scale is now 10 nanoseconds per major tick mark. Signals from top to bottom are clock, Q0 and Q2.
There is a 6.1 nanosecond difference between when Q0 and Q2 change, even though they are controlled by the same clock.
In this circuit Q0 and Q2 are handled by two different ICs, U1 and U2, respectively. U1 is quite a bit slower than U2. Datasheets for ICs only specify the longest time they will take to perform their operation. Nothing is said about how fast the might be. (I did cheat a bit here by intentionally choosing one of the slowest and one of the fastest 74LS74s from my parts box; I wanted a good skew demonstration.)
This is just the tip of the hardware iceberg. I hope you've found this interesting and educational.
--Mark