0
\$\begingroup\$

I am writing code that behaves as a rudimentary register file. I have created the register file as a module reg_file.v. The code instantiates a module, describing a register with loading capabilities, using generate with a simple 'for' loop.

When trying to implement the register module, I get the forementioned error. Here is the register module:

    `timescale 1ns / 1ps

module simple_register_load
    #(parameter N = 4)(
        input clk,
        input load,
        input [N - 1:0] I,
        output [N - 1:0] Q        
    );
    
    reg [N - 1:0] Q_reg, Q_next;
    
    always @(posedge clk)
    begin
        Q_reg <= Q_next;
    end
    
    // Next State logic
    always @(load, I, Q_reg)
    begin
        if (load)
            Q_next = I;
        else
            Q_next = Q_reg;
    end
    
    // Output logic
    assign Q = Q_reg;
endmodule

Within the "Next State Logic" the line associated with Q_reg <= Q_next gets flagged for the error.

always @(posedge clk)
    begin
        Q_reg <= Q_next;
    end

I have searched the forums and have found others with similar issues, and they all point to modifying an output in multiple 'always' statements. But here, I only modify Q_reg in one of the 'always' blocks. Q_next is also only modified in one 'always' block. I am puzzled.

This is the register file module code for reference:

`timescale 1ns / 1ps

module reg_file
    #(parameter N = 4, BITS = 4)(
    input clk,
    input [N - 1:0] address_w, address_r, //write address, read address
    input WE, //write enable
    input [BITS - 1:0] data_w, // write data
    output [BITS - 1:0] data_r // read data
    
    ,
    input read_write_sel
    );  
    
    wire [2**N - 1:0] address_w_dec, address_r_dec;
    wire [BITS - 1:0] reg_data;
    
    // WRITE PORT
    decoder_generic #(.N(N)) write_decoder( // N x 2^N decoder
        .w(address_w),
        .en(WE),
        .y(address_w_dec)
    );
    
    // READ PORT
    decoder_generic #(.N(N)) read_decoder( // N x 2^N decoder
        .w(address_r),
        .en(~WE),
        .y(address_r_dec)
    );

    // REGISTERS
    genvar k;
    generate
        for(k = 0; k < 2**N; k = k + 1)
        begin: register
            simple_register_load #(.N(BITS)) R(
                .clk(clk),
                .load(address_w_dec[k]),
                .I(data_w),
                .Q(reg_data)
            );
            assign data_r = address_r_dec[k] ? reg_data : 'bz;
        end
    endgenerate
    
endmodule

The errors if I run for N = 1 (generate 2^N = 2 registers):

[DRC MDRV-1] Multiple Driver Nets: Net nolabel_line34/register[1].R/Q[1] has multiple drivers: nolabel_line34/register[0].R/Q_reg_reg[1]/Q, and nolabel_line34/register[1].R/Q_reg_reg[1]/Q.

[DRC MDRV-1] Multiple Driver Nets: Net nolabel_line34/register[1].R/Q[2] has multiple drivers: nolabel_line34/register[0].R/Q_reg_reg[2]/Q, and nolabel_line34/register[1].R/Q_reg_reg[2]/Q.

[DRC MDRV-1] Multiple Driver Nets: Net nolabel_line34/register[1].R/Q[3] has multiple drivers: nolabel_line34/register[0].R/Q_reg_reg[3]/Q, and nolabel_line34/register[1].R/Q_reg_reg[3]/Q.

I feel like there is a really simple issue that I am missing, and I would be very grateful if someone could point it out.

\$\endgroup\$
3
  • \$\begingroup\$ You have all of your registers tied directly to the same output bus, reg_data. This needs to be a separate bus for each instance of a register. \$\endgroup\$
    – Dave Tweed
    Commented Feb 28, 2023 at 4:54
  • \$\begingroup\$ One way to fix this is to put the declaration for reg_data inside the generate loop. See here for an example. \$\endgroup\$
    – Dave Tweed
    Commented Feb 28, 2023 at 5:22
  • \$\begingroup\$ Thank you Dave Tweed for all the helpful tips. What I ended up using for this particular case was your suggestion of generating the wire each cycle in the for loop, and the error disappeared. I had no idea you could generate new wire like that (I’m in the very early stages of learning verilog) It ends up using a lot of wire, but as you’ve already explained, there are much simpler ways than my current rendition. Thanks again. \$\endgroup\$ Commented Feb 28, 2023 at 21:28

1 Answer 1

1
\$\begingroup\$

If you want to have a bank of registers, it's really much simpler to use an array. Something like this:

module register_bank #(
  parameter AWP = 3,       // address width parameter
  parameter DWP = 3        // data width parameter
) (
  input wire           clk,        // write clock
  input wire   [AWP:0] addr_w,     // write address
  input wire   [AWP:0] addr_r,     // read address
  input wire           we,         // write enable
  input wire   [DWP:0] din,        // write data
  output wire  [DWP:0] q           // read data
);

  reg [DWP:0] mem [0:2**(AWP+1)-1];

  always @(posedge clk) if (we) mem[addr_w] <= din;
  assign q = mem[addr_r];

endmodule

Not too long ago, I used an extended version of this module to create a dual-port register array for a custom CPU design. This mapped directly to a dual-port hardware block RAM (BRAM) on the FPGA that I was using.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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