December 29, 2008
An important aspect of doing a large design of any sort, whether it is building a chip, a log cabin, or a space shuttle, is to use good design practices.
In today's digital design environment, where multi-million-gate designs are not uncommon, it is especially important to use good design practices because there are so many things to track and there often many people on the team. You can usually get away with an ad hoc approach to do a typical project in a course, but it will never work for larger systems.
Most people are never exposed to these good practices until they go to industry, and only if that company is on the ball!
Learning good practices is typically easiest with an example. Here, a fairly simple design is implemented to try and illustrate some of those concepts.
Look at this as an example of how to do a good design in terms of coding style for hdl, assembler, and C as well as for file organization. It is important to read through the files. I don't claim to have the best coding style, but it is better than most student code I've seen :-)
This design uses a Booth bit-pair recoded multiplier block that was created previously and interfaces it to the 68K bus in the FPGA on the old UofT gizmo board, which is no longer used, so you can no longer try this on real hardware. You can use the example to see how to create an interface for the bus. This example can also generate interrupts.
You can find the design tree for the example at:
Look at the readme files in the various directories. I've structured the design in a manner that separates all the various activities that you might do, like rtl, synthesis, simulation, etc. This is typical of what you might find in industry for ASIC designs.
RCS was used for revision control, but the directories are not included here.
In the src directory, you will find a 68k program and a C program. They are used to drive the multiplier via the bus interface. The C program does an exhaustive test since it was much easier to code than in 68K assembly language :-)
An important aspect of all designs is to do simulation. A motto that has been proven again and again is:
If you don't simulate it, it won't work.
If you do simulate it, it might work!
ModelSim was used as the simulator. Some simple scripts were used to simulate each of the blocks. More sophisticated testbenches would typically be used but I haven't the time yet to build some examples.
The multiplier was copied from a previous working design so it was not simulated here on its own again. The bus interface was simulated on its own and then the system, multiplier and bus interface, was simulated as a whole.
Just to demonstrate the value of simulation in this case, the multiplier worked first time, i.e., no changes had to be made to it.
The interface block had a few problems before it started to work in the actual hardware, but none of them had to do with the actual functional design intent of the logic:
In the design tree there are zip and tar files of the full tree. I encourage you to download the tree and look at it that way. Note that it uses symbolic links, which will work in Unix/Linux, but not in a Windows system.