( insert really basic question disclaimer here )
More specifically, I have the following declaration:
output reg icache_ram_rw
And in some point of the code I need to put the zero value in this reg. Here's what I've tried and the outcomes:
assign icache_ram_rw = 1'b0;
( declarative lvalue or port sink reg icache_ram_rw must be a wire )
icache_ram_rw <= 1'b0;
( instance gate/name for type "icache_ram_rw" expected - <= read )
How do I do it after all?!
Remove "reg" from the output declaration and the code should work (defaults to wire output type).
There are two things that most self-taught or poorly-taught engineers find difficult to understand in Verilog: (1) blocking -vs- nonblocking assignments (see my paper on this topic: http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf) and (2) reg -vs- wire. Let's clear up the latter topic right now.
Anything on the Left-Hand-Side (LHS) or a procedural assignment (always, initial, task, function) must be declared as a variable type (typically a reg). Everything else in the language is a net (typically a wire). No exceptions. It's really that simple. I don't know of any Verilog book that says it that simply.
How did this happen? I asked Phil Moorby, good friend and inventor of the Verilog language, "why reg??" Phil told me that when he invented Verilog, there were no synthesis tools and he thought everything coming out of an always block was going to be a register. He was wrong, and now we are stuck with this "reg" keyword.
I have tried to get this changed on the Veirlog and SystemVerilog committees for more than a decade. I would like to declare everything as wire and first usage would determine if the "wire" behaves like a reg (first assignment from a procedural block and last assignment wins) or behaves like a wire (first assignment is from a driving source such as a module output or continuous assignment and multiple drivers are resolved as in Verilog today) and it would be illegal to make both procedural assignments and driver assignments to the same signal. Alas, I have not had enough votes on the committee to succeed in passing this proposal.
This is the mistake I make most often in my own code. Just get used to error messages like, "illegal LHS assignment" or "illegal assignment to wire." They both mean the same thing, you forgot to declare your regs.
Regards - Cliff Cummings - Verilog & SystemVerilog Guru
The
assign
statement is used for drivingwire
s.If you've somethings declared as a
reg
, then you have to give it values inside a procedure (always
orinitial
blocks ). It's best practice to only set values ofreg
s in the samealways
block. eg:There are important differences between
reg
s andwire
s that you should read up on.I've a feeling though that you'll need some clocked logic if you're driving RAM signals. In this case, you'll need code that looks something like this:
Note that you can also assign an initial value to a reg when you declare it, like this:
output reg icache_ram_rw = 1'b0;
This will ensure it starts with the zero value in simulation. For synthesis, your results will depend on the synthesis tool and target technology (for FPGAs, you can generally assign an initial value for hardware; for ASIC, that's not the case).