( insert really basic question disclaimer here )
More specifically, I have the following declaration:
output reg icache_ram_rw
And
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 driving wire
s.
If you've somethings declared as a reg
, then you have to give it values inside a procedure ( always
or initial
blocks ). It's best practice to only set values of reg
s in the same always
block. eg:
always @( * ) begin // combo logic block
if( some_condition ) begin
icache_ram_rw = 1'b0;
end else begin
icache_ram_rw = something_else;
end
There are important differences between reg
s and wire
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:
// some parameter definitions to make logic 'read' clearer.
localparam READ = 1'b0;
localparam WRITE = 1'b1;
// standard clocked logic 'template' that synthesis tools recognise.
always @( posedge clk or negedge resetb )
if( !resetb ) begin // asynchronous active low reset
icache_ram_rw <= READ;
end else if( some_enable_condition ) begin
icache_ram_rw <= WRITE;
end else begin
icache_ram_rw <= READ;
end
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).