Testing Your Non-Pipelined Processor (Lab 2)

CSE 372 (Spring 2007): Digital Systems Organization and Design Lab


Testing your processor is accomplished by comparing its output to the simulator's output. "Output" in this case means comparing the PC, the current instruction, the data memory signals and the data going into the register file on every cycle. The output generated by a particular run of a program is known as a trace. Your single-cycle processor should produce the same exact trace as the simulator for a given program.


The testbench itself. Note that the .tf file extension causes Xilinx to automatically recognize the file as a Verilog test fixture. You'll also need two of the files from the zip archive available in the hardware tutorial.

You'll also need the most recent version of PennSim.


Simulator Instructions

You can generate a trace from the simulator by using the simulator's aptly-named trace command.

  • First, load your program into the simulator.
  • Set the PC to the instruction at which you want tracing to begin. Optionally, you can set a breakpoint at which you want tracing to stop. You can only turn tracing off after the simulator has halted, or hit a breakpoint.
  • Now that you've loaded the program into memory, you need to save an image of memory that you can load into your processor's memory. Run the dump -readmemh <start> <end> <filename> command in the simulator.
  • start and end specify the range of memory to dump; typically you'll want to grab 0x0000 all the way up to 0xFFFF. Creating a memory dump is fast, as is loading this dump into the simulated memory. The dump is written to the file you specify; the -readmemh flag ensures the memory dump is in the correct format for Verilog's $readmemh() function.
  • The dumped memory image gets loaded into your processor's memory starting at address 0x0000, so you can't just dump the 5 words of memory that actually constitute your program - you need to begin at 0x0000 and capture all the memory that your program uses. It's easiest to just always dump the entire contents of memory.
  • Run the trace on <filename> command in the simulator. This will send trace output to the specified file, in the directory in which the simulator is located.
  • Use the continue to set the simulator going. For every instruction executed, a line will be printed to the trace file.
  • When the program finishes, or hits your breakpoint, run the command trace off. This is necessary to ensure all trace output is flushed to the trace file.

Testbench Instructions

You will need to modify your processor to accept your newly-created memory image and trace file. This requires editing the value of the MEMORY_IMAGE_FILE macro at the top of the memory module bram.v. This memory module is used both for simulation and for synthesis, so if you change it in one place it will affect the other.

You also need to edit which trace file is used by the testbench. This line is clearly marked in test_sc_datapath.v with a comment.

Running the testbench in ModelSim will then load the memory with your program, and then let your processor begin executing. On every cycle, the simulator's trace output is compared with the real signals coming out of your processor, and errors are printed accordingly. No news is good news!

Suggestions for Testing

Start small - a big program (such as breakout or snake) isn't the ideal first test case. Write some code to test just one kind of instruction at a time (e.g. ALU operations, loads, branches) and build up as you go. A larger program may also not actually test every instruction; for example, our reference implementation of breakout doesn't use any JSRR instructions, for example.