Forum Discussion
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, Keith13 Replies
- Altera_Forum
Honored Contributor
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.
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// 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 - Altera_Forum
Honored Contributor
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. - Altera_Forum
Honored Contributor
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....
Thanks again, Keith// 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 - Altera_Forum
Honored Contributor
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 - Altera_Forum
Honored Contributor
AHH-HA... I never thought of it that way..
Thanks for helping me look at things a little bit differently!!! Keith - Altera_Forum
Honored Contributor
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 - Altera_Forum
Honored Contributor
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 - Altera_Forum
Honored Contributor
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.
- Altera_Forum
Honored Contributor
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 - Altera_Forum
Honored Contributor
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