Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Honored Contributor I
4,175 Views

Error (10028): Can't resolve multiple constant drivers for net <name> at <??>

All, Here is one of my Verilog trial-learning code: 

 

============================================================== 

// Verilog learning example module SRAM_Read_Write_Sync ( nrst, Writeclk, Readclk, EQ, write_addr, read_addr); input nrst, Writeclk, Readclk; output EQ, write_addr, read_addr; // Declare the address counters as 9-bit counters reg write_addr; reg read_addr; reg EQ; // reset address to 0 if NRST goes LO always @ (negedge nrst) begin write_addr = 0; read_addr = 0; end // increment Write address always @ (posedge Writeclk) begin write_addr = write_addr + 1; end // increment Read address always @ (posedge Readclk) begin read_addr = read_addr + 1; if (read_addr == write_addr) EQ = 1'b1; else EQ = 1'b0; end endmodule  

================================================================== 

All, (the text in RED) when I try to use the negative edge of my nrst as a reset for my address counters I get the  

Error (10028): Can't resolve multiple constant drivers for net "read_addr[3]" at SRAM_Read_Write_Sync.v(26) 

If I remove the RED code it compiles fine. 

 

How should I implement a nrst signal that take precedence over any other signals that reset the address counters? 

 

Thanks, 

Keith
0 Kudos
13 Replies
Highlighted
Honored Contributor I
230 Views

All, I figured it out.  

Following is code that seems to compile, don't know about the EQ yet, but I think I figured a way to reset my counters and increment my counters. 

 

// Verilog learning example module SRAM_Read_Write_Sync ( nrst, Writeclk, Readclk, EQ, write_addr, read_addr); input nrst, Writeclk, Readclk; output EQ; output write_addr; output read_addr; // Declare the address counters as 9-bit counters reg write_addr; reg read_addr; reg EQ; // increment Write address or Read address or do a reset always @ (posedge Writeclk or posedge Readclk or negedge nrst) begin if (!nrst) begin write_addr = 0; read_addr = 0; end else if (Writeclk) write_addr = write_addr + 1; else if (Readclk) read_addr = read_addr + 1; end always @ (posedge Readclk) begin if (read_addr == write_addr) EQ = 1'b1; else EQ = 1'b0; end endmodule 

 

So I needed to add all 3 checks in the first "ALWAYS" then check for active LO (!nrst) to reset the counters. Then complete the other edge clocks to increment the appropriate address_counter. Then start another "ALWAYS" and start expanding from here with more behavior!! 

 

Thanks all, 

Keith
0 Kudos
Highlighted
Honored Contributor I
230 Views

Be aware that this design is likely to have problems as you are reading the write_address with the readclk, as you may violate the setup and hold time of the write_addr when reading causing metastability - look into safe clock domain crossing techniques. 

I would also be wary of putting both read and write clock in the same always block. there are several issues: 

1. You may accidentally put a variable in both clocks, which is not supported in an FPGA 

2. In a simulation, in your code, if the read and write clocks are exactly aligned then only the write_addr will be incremented (as you have given precedence to the writeclk over the readclk)  

3. It can be confusing for others.
0 Kudos
Highlighted
Honored Contributor I
230 Views

Ok, I see your point... and that would definitely come back and bite me sooner or later... but the following code gives me the same Error 10028, so how do I: 

1) check for a negative edge on nrst to reset my counters 

2) increment my 9-bit counters on their appropriate rising clock edges 

 

I've been trying to go through several tutorials and examples and I thought I understood some of it, but..... 

 

What/where can I find what is being meant by the "multiple constant drivers for ?????" 

As you can see I am very "green" to Verilog programming.. Hard for me to see the "hardware behavior picture" since I usually do schematic entry.... 

 

// Verilog learning example module SRAM_Read_Write_Sync_Verilog ( nrst, Writeclk, Readclk, EQ, write_addr, read_addr); input nrst, Writeclk, Readclk; output EQ; output write_addr; output read_addr; // Declare the address counters as 9-bit counters reg write_addr; reg read_addr; reg EQ; // increment Write address or Read address or do a reset always @ (negedge nrst) begin if (!nrst) begin write_addr <= 0; // non-blocking read_addr <= 0; // non-blocking end end always @ (posedge Writeclk) begin write_addr = write_addr + 1; end always @ (posedge Readclk) begin read_addr = read_addr + 1; end endmodule 

 

Thanks again, 

Keith
0 Kudos
Highlighted
Honored Contributor I
230 Views

The reset must be in the same always block as the clock. You're actually not checking for a negative edge of reset - you're waiting for when the reset is low in real hardwarfe - the negedge is a quirk of verilog and the way it is event driven. 

 

always @(posedge Writeclk or negedge nrst) begin if(!nrst) write_addr <= 0; else write_addr <= write_addr + 1; end always @(posedge readclk or negedge nrst) begin if(!nrst) read_addr <= 0; else read_addr <= read_addr + 1; end
0 Kudos
Highlighted
Honored Contributor I
230 Views

AHH-HA... I never thought of it that way.. 

 

Thanks for helping me look at things a little bit differently!!! 

 

Keith
0 Kudos
Highlighted
Honored Contributor I
230 Views

Keith - 

 

There's a difference between code that is legal verilog and will compile without errors in a simulator, and code that will synthesize to hardware, which is usually the ultimate goal unless you're just trying to model behavior in simulation. Your second post has an always block that is sensitive to the rising edge of two different clocks. This doesn't make much sense even for modeling, and it would definitely not synthesize. This might work better: 

 

// Verilog learning example module SRAM_Read_Write_Sync ( nrst, Writeclk, Readclk, EQ, write_addr, read_addr); input nrst, Writeclk, Readclk; output EQ; output write_addr; output read_addr; // Declare the address counters as 9-bit counters reg write_addr; reg read_addr; reg EQ; // increment Write address or do a reset always @ (posedge Writeclk or negedge nrst) begin if (!nrst) write_addr <= 9'h0; else // Unlike VHDL, you don't need to check for Writeclk high here. write_addr <= write_addr + 1; end // increment Read address or do a reset always @ (posedge Readclk or negedge nrst) begin if (!nrst) read_addr <= 9'h0; else // Unlike VHDL, you don't need to check for Readclk high here. read_addr <= read_addr + 1; end // read_addr and write_addr are generated from different clocks so // you probably don't want to compare them directly in one clock domain. // Maybe just do a combinational compare (not clocked). always @* begin if (read_addr == write_addr) EQ = 1'b1; else EQ = 1'b0; end endmodule
0 Kudos
Highlighted
Honored Contributor I
230 Views

Thanks for the info rsefton. I see you set write_addr <= 9'h0.... why would you prefer that over write_addr <= 0? 

 

Also, you answered one of my other questions I have currently been trying to figure out, by using the combinational compare always @*. 

 

Thanks, 

 

Keith
0 Kudos
Highlighted
Honored Contributor I
230 Views

Comparing both addresses asynchronously is potentially worse than in a clock domain as it will be very glitchy, especially as you're using a count and not a grey code.

0 Kudos
Highlighted
Honored Contributor I
230 Views

Keith - 

 

In verilog integers are always 32 bits wide, so when you assign 0 (32 bits) to write_addr (9 bits) you'll always get a synthesis warning about the size mismatch. It can be safely ignored, but assigning the size correctly will eliminate that warning. 

 

I always try to be explicit with size in reset assignments, partly because it shows you clearly the size of the variable you're resetting (so you don't have to go up to the declaration to find out). Kind of a self-documentation practice. But it has the side-benefit of reducing the number of synthesis warnings, which can get into the many thousands for a large design. On the other hand, when I code counters (counter <= counter + 1) I'm almost never explicit about the size just because I like the look of "counter + 1" better than "counter + 9'h1". 

 

To each his own. Most of us are creatures of habit, some good some bad! 

 

In the early days of FPGA/CPLD design I would try to eliminate all compile warnings, and back then it was usually possible. But now with rtl design and IP used everywhere it's virtually impossible to eliminate all warnings and I don't even try. But I always review the synthesis, fitter, and timing reports. 

 

Bob
0 Kudos
Highlighted
Honored Contributor I
230 Views

OK, now I am trying to expand on the mess I've made. Now I want to do some control with the EQ signal, (either in a clocked or unclocked domain). I am wanting to reset the read address under certain conditions,.... make the read address=write address.... and once again.... I get the (multiple constant drivers....) so it has to be back in the always @ portion. There is getting to be quite a few ORs in it, just so that I can change my read_address. 

 

Example: always @(posedge Readclk or negedge nrst or negedge Read_RST or posedge Read_EQ_Write or negedge EQ) 

 

and then a ton of if () else if () else if () else.... 

 

Is this correct or am I using the proper technique here or is there some other statement I should be using? I know what I want to do schematically (mostly) but wanting to try using Verilog at this project. 

 

Thanks again, 

Keith
0 Kudos
Highlighted
Honored Contributor I
230 Views

if you have a clock, the the only thing that should be in the sensitivity list (inside the brackets of the always) are the Readclk and nrst. You only care what happens on the clock edge, hence you dont want anything else. If you are trying to do logic with the clock, you are going to fail as this wont be possible in an FPGA. at the top level you should have: 

 

always @(posedge Readclk or negedge nrst) begin if(~nrst) begin // asynchronous reset goes here else begin // this is for synchronous logic end // NOTHING ELSE HERE end
0 Kudos
Highlighted
Honored Contributor I
230 Views

OK Thanks Tricky, I'll concentrate on this approach!! If I can't get the hang of it I will go back to schematic entry just so that i can get the design done and out the door. 

 

Thanks again, 

Keith
0 Kudos
Highlighted
Honored Contributor I
230 Views

 

--- Quote Start ---  

Comparing both addresses asynchronously is potentially worse than in a clock domain as it will be very glitchy, especially as you're using a count and not a grey code. 

--- Quote End ---  

 

 

Of course you're right, Tricky. I was just trying to solve one problem at a time. I was not going to get into safe clock domain crossing.
0 Kudos