I'm working through the open Nand to Tetris course offered by Nissan and Schoken. I've just finished chapter 5, where we construct a 16-bit computer using a hardware description language and an instructor-provided hardware simulator.
The CPU that we build for the computer uses three clocked components: a program counter, an address register, and a data register. You can see a diagram of the CPU on page 94 of the PDF below, and a diagram of the whole computer on page 97:
The output of the program counter connects to an external ROM which instantly outputs the instruction at the address specified by the program counter. If the outputted instruction is a "set address" instruction, it propagates instantly to the CPU address register, where it will be stored on the next falling clock edge.
My question follows. Both the program counter and the address register are clocked components. They are connected in series, with the output from the program counter feeding (eventually) to the input of the address register, like so:
___________________ _____________ ____________________ | program counter | | ROM 32K | | address register | | ^ |--->| |----->| ^ | |___________________| |_____________| |____________________|
In a physical implementation of this circuit, how could I ensure that the ouput from ROM 32K would be stored successfully in the address register? Both components update on a falling clock edge. Imagine that the falling edge signal takes .2 clock cycles to reach the program counter, update it, and then propagate through the ROM, but takes .8 clock cycles to reach the address register. In this case, the output from the ROM would change before the falling clock edge reaches the address register.
The hardware simulator in our class solves this problem by storing new component states on falling clock edges and then propagating the new component state on rising clock edges. This ensures that component component B can capture component A's output before component A outputs a new state. I was wondering how this problem would be solved in a physical implementation.