I wrote some fairly simple code in Verilog to implement a 32-bit deep, 8-bit wide register file. However, when I actually run a behavioral simulation of the thing the two data-read lines (rd0_data and rd1_data, respectively) seem to be utterly nonreactive.

I think it's possible I made some mistake in how I built out the inputs and outputs or the "mem" variable, but after fiddling with it for hours I'm sort of lost.

module reg_file#(
        parameter DATA_WIDTH = 8,
        parameter ADDR_WIDTH = 5
        input rst, clk, wr_en,
        input [ADDR_WIDTH-1:0] rd0_addr,
        input [ADDR_WIDTH-1:0] rd1_addr,
        input [ADDR_WIDTH-1:0] wr_addr,
        input [DATA_WIDTH-1:0] wr_data,
        output [DATA_WIDTH-1:0] rd0_data,
        output [DATA_WIDTH-1:0] rd1_data

    integer i; //For the reset operation
    reg [DATA_WIDTH-1:0] mem [0:31];

    assign rd0_data = mem[rd0_addr];
    assign rd1_data = mem[rd1_addr];

    //Update w. synchronus reset
    always @(posedge clk) begin
        if(rst) begin 
            for (i = 0; i < 32; i = i + 1) mem[i] <= 0;
        end else begin
            if(wr_en) begin
                mem[wr_addr] <= wr_data;


Behavioral Simulation output:

Behavioral Simulation

My test bench code is as follows:

module reg_file_tb;
    reg rst, wr_en, clk;
    reg [4:0] rd0_addr, rd1_addr, wr_addr;
    reg [7:0] wr_data;

    wire [7:0] rd0_data, rd1_data;

    // Instantiate the register file (using positional-association for instantiation)
    reg_file dut
        rst, wr_en, clk, rd0_addr, rd1_addr, wr_addr, wr_data, rd0_data, rd1_data

    integer i;

    initial begin
        // Initial values
        wr_en = 1;
        rd0_addr = 5'd0;
        rd1_addr = 5'd0;
        wr_addr = 5'd0;
        wr_data = 8'd255;
        i = 0;

        // Pulse the reset signal for only one clock cycle
        clk = 0;
        rst = 1;
        clk = 1;
        clk = 0;
        rst = 0;

        for (i = 0; i < 16; i = i + 1)
            // Sample conditional stimulus: if i equals 4, set the write enable to HIGH
            /*if (i == 32'd4)
                wr_en = 1;

            // Sample conditional stimulus: when i equals 5, change the rd1_addr to 10
            if (i == 32'd5)
                rd1_addr = 5'd10;

            // Pulse the clock in this for-loop
            clk = 0;
            clk = 1;

            wr_addr = wr_addr + 5'd1;
            rd0_addr = rd0_addr + 5'd1;


Any helpful guesses or tips would be very much appreciated.

  • \$\begingroup\$ How are you testing it? What results are you actually getting? \$\endgroup\$ – Dave Tweed Oct 9 '19 at 3:34
  • 1
    \$\begingroup\$ mem should only be assigned in one always block. Separate is not synthesizible and prone to race conditions in behavioral simulations. \$\endgroup\$ – Greg Oct 9 '19 at 4:45
  • \$\begingroup\$ @Greg: While it's true that that's an issue, the actual question is about simulation. \$\endgroup\$ – Dave Tweed Oct 9 '19 at 12:41
  • \$\begingroup\$ @DaveTweed I added the output of my behavioral simulation and the test bench that resulted in it to the post. Sorry for not thinking to include it earlier. \$\endgroup\$ – S-Flo Oct 9 '19 at 16:26
  • \$\begingroup\$ @Greg Re-coded the always block to reflect your advice. Although it didn't resolve the issue at hand, I appreciate you catching my mistake. \$\endgroup\$ – S-Flo Oct 9 '19 at 16:27

I accidentally swapped "wr_en" and "clk" when instantiating a module of the register in the test bench. The module itself is fine, I'm just dumb.

Thanks to everyone who looked at it though.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.