Clocks for Software Engineers
One of my favorite undergrad electrical engineering classes [0] took an innovative approach to introducing this. Instead of learning about clocks/pipelines and HDL at the same time, we only looked at the former. We created our own simulators for an ARM subset, fully in C, where there was only a single for/while loop allowed in the entire codebase, representing the clock ticks. Each pipeline stage, such as Instruction Fetch, would read from a globally instantiated struct representing one set of registers, and write to another one. If you wanted to write to the same place you read from, you could only do so once, and you'd better know exactly what you were doing.<p>Because we didn't need to learn a new language/IDE/environment at the same time that we learned a new paradigm, we were able to keep our feet on solid ground while working things out; we were familiar with the syntax, so as soon as we realized how to "wire something up," we could do so with minimal frustration and no need/ability to Google anything. Of course, it was left to a subsequent course to learn HDL and load it on real hardware, but for a theoretical basis, this was a perfect format. Much better than written tests!<p>[0] <a href="http://www.cs.princeton.edu/courses/archive/fall10/cos375/descrip.html" rel="nofollow">http://www.cs.princeton.edu/courses/archive/fall10/cos375/de...</a> - see links under Design Project, specifically <a href="http://www.cs.princeton.edu/courses/archive/fall10/cos375/Cproject10.pdf" rel="nofollow">http://www.cs.princeton.edu/courses/archive/fall10/cos375/Cp...</a>