1

I am attempting to create a program counter for a RISC processor, but I am unsure why the test bench isn't working as expected. There might be something wrong with the way the test bench is written, but I can't seem to find it. In the simulation of the test bench, the counter value doesn't seem to increment by one as expected. Any help would be much appreciated.

module ProgramCounter 

// identify inputs and outputs, define if the input/output is signed. 
(
input Clock,
input logic Reset,
input logic [15:0] LoadValue,
input logic LoadEnable,
input logic signed [8:0] Offset,
input logic OffsetEnable,
output logic signed [15:0] CounterValue
);

// Clock, Reset, LoadEnable and OffsetEnable triggered at positive edge of clock.
    always_ff@(posedge Clock)
    begin
        if (Reset) CounterValue <= '0; //if reset is TRUE, CounterValue is zero.
        else if (LoadEnable) CounterValue <= LoadValue; //if LoadEnable is TRUE, CounterValue is equal to LoadValue.
        else if (OffsetEnable) CounterValue <= CounterValue + Offset;//if OffsetEnableEnable is TRUE, CounterValue is CounterValue plus Offset.
        else CounterValue <= CounterValue + 1;//otherwise, CounterValue increases with the clock.
    end


endmodule

// ProgramCounterTestBench
//
//
// This module implements a testbench for 
// the Program Counter 
//

module ProgramCounterTestBench();

    // These are the signals that connect to 
    // the program counter
    logic               Clock = '0;
    logic               Reset;
    logic signed       [15:0]   LoadValue;
    logic               LoadEnable;
    logic signed  [8:0] Offset;
    logic                   OffsetEnable;
    logic signed  [15:0]    CounterValue;

    // this is another method to create an instantiation
    // of the program counter
    ProgramCounter uut
    (
        .Clock,
        .Reset,
        .LoadValue,
        .LoadEnable,
        .Offset,
        .OffsetEnable,
        .CounterValue
    );
    

    default clocking @(posedge Clock);
    endclocking
        
    always  #10  Clock++;

    initial
    begin
        Reset = 0;
        LoadEnable = 0;
        OffsetEnable = 0;
        LoadValue = 16'b0000000000000000;
        Offset = 9'b000000000;
        CounterValue = 16'b0000000000000010;

        #60

        #10     Reset = 0;
                LoadEnable = 1;
                LoadValue = 16'b0101010101010101;

        #10     Reset = 1;
                LoadEnable = 0;
                OffsetEnable = 0;
                LoadValue = 16'b0101010101010101;
                Offset = 9'b000000000;

        #10     Reset = 0;
                LoadEnable = 1;
                OffsetEnable = 0;
                LoadValue = 16'b0101010101010101;
                Offset = 9'b000000000;  

        #10     Reset = 0;
                LoadEnable = 0;
                OffsetEnable = 0;
                                        

        #10     Reset = 0;
                LoadEnable = 0;
                OffsetEnable = 1;
                LoadValue = 16'b0101010101010101;
                Offset = 9'b101000000;
    end
endmodule

toolic
  • 57,801
  • 17
  • 75
  • 117
Bram
  • 17
  • 2

1 Answers1

0

I get compile errors with multiple simulators. For example, the Cadence simulator generates this error:

        .CounterValue
                    |
xmelab: *E,ICDPAV : Illegal combination of driver and procedural assignment to variable CounterValue detected (procedural assignment found in initial block

You can try your code on multiple simulators on edaplayground when you sign up for a free account.

The problem is in the testbench with this line:

    CounterValue = 16'b0000000000000010;

The CounterValue signal in the testbench has multiple drivers:

  1. The instance output port connection
  2. The above line in the initial block

You should only allow the instance to drive this signal. When you delete the line above, you will see the counter increment as expected.

toolic
  • 57,801
  • 17
  • 75
  • 117