Behavioral Verilog Testbench for Pipelined P37X (Lab 3)

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

Overview

This testbench is a modified version of the one you used to verify your design in Lab 2. Testing a pipelined design is slightly more complicated because each instruction is executed over five cycles. For instance, the program counter's value is available in the fetch stage, the memory address for a store instruction is available in the memory stage, and the data for a register write instruction, such as add, is available at the end of the execute stage, or in both the memory and writeback stages.

The testbench we are giving you tests the PC, instruction memory output, and register write enable/data for each instruction in the writeback stage. Therefore, it will be necessary for you to carry data such as the PC and instruction memory to the writeback stage through latches. Even though carrying these signals to the writeback stage may not be necessary for your processor to function, adding a few latches should only increase your code by a minimal number of lines.

Requirements

The pipeline testbench. Note that the .tf file extension causes Xilinx to automatically recognize the file as a Verilog test fixture. Drew has provided a variety of unique test programs, benchmarks some of which will attain substantially higher IPC depending on how far you have progressed in designing your processor.

You may also use the random-insns hex and trace files that we gave you to test your single-cycle datapath. Since some other benchmark programs begin in a busy loop waiting for input they are not ideal first test cases for your pipeline. Use these random instruction files to test your design first.

Instructions

Simulator Instructions

PennSim can still be used to generate hex files and traces as in Lab2.

Testbench Instructions

As before, you will modify the MEMORY_IMAGE_FILE macro at the top of the memory module bram.v to accomodate the hex file containing the instructions you want your processor to execute. Similarly, use the macro TESTBENCH_TRACE in this testbench to specify the corresponding trace.

The following block of code initiates your pipelined processor:

// Instantiate your processor here!
pipeline_datapath datapath (.CLK(CLK), 
                      .RST(RST),
                      .GLOBAL_WE( GLOBAL_WE ),
                      .IMEM_ADDR(IMEM_ADDR), 
                      .IMEM_OUT(IMEM_OUT), 
                      .DMEM_ADDR(DMEM_ADDR), 
                      .DMEM_IN(DMEM_IN), 
                      .DMEM_OUT(DMEM_OUT), 
                      .DMEM_WE(DMEM_WE),
                      // These test signals are from the writeback stage of pipeline
                      ._TEST_W_PC(_TEST_W_PC),
                      ._TEST_W_REGFILE_DATA_IN(_TEST_W_REGFILE_DATA_IN),
                      ._TEST_W_REGFILE_WE(_TEST_W_REGFILE_WE),
                      ._TEST_W_IMEM_OUT(_TEST_W_IMEM_OUT),
                      // Set this signal high for a stall/flush
                      ._TEST_W_NOP_IMPLICIT(_TEST_W_NOP_IMPLICIT)
                      );

The signals beginning with _TEST_W must come from the writeback stage of your pipeline. For example, _TEST_W_PC contains the address of the instruction that is currently in the writeback stage of your pipeline. The next three signals should operate on the same principle.

The signal _TEST_W_NOP_IMPLICIT shall go high whenever the writeback stage contains a "bubble" or no-op due to a load stall, branch mis-predict, or any other situation in which you want to tell the testbench to ignore the W stage in the cycle. Be warned that placing a no-op into the W instruction, _TEST_W_IMEM_OUT will not cause the testbench to ignore that instruction; it will assume that an explicit no-op instruction was executed from the .hex file, and will spit out an error if the current instruction isn't a no-op. The signal _TEST_W_NOP_IMPLICIT clears up any ambiguity that might exist between implicit and explicit no-op's.

For your convenience, every cycle that the testbench executes will spit out a line containing information about what signals are present in the writeback stage. This may be useful for early debugging with small programs, but could become cumbersome later on when you want to simulate longer programs. Simply comment out the following lines:

// Display all W-stage data. Comment this line out to suppress unwanted output
$display ("Line: %d, PC: %h, Instruction: %h, regWrite?: %d, regData: %h",
        lineno, _TEST_W_PC, _TEST_W_IMEM_OUT, _TEST_W_REGFILE_WE, _TEST_W_REGFILE_DATA_IN);

to suppress line-by-line testbench output.

This testbench counts the errors in simulation and will present you with an error total upon completion of the simulation.

Addenda