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\$ 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\$ 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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.