When can a module drive a 'reg' type, and when must it drive

B

benn

Guest
After much trial and error, I *THINK* I see a rule emerging but I'm
not sure why. It seems that if I instantiate a module, I can feed
it's an input port with either a 'reg'ister type or a wire type.

However, if that same instantiated module has an output port, I must
connect that port with a wire type, not a reg type.


If these rules are correct, why is this the case?
 
On 2008-12-16, benn <benn686@hotmail.com> wrote:
After much trial and error, I *THINK* I see a rule emerging but I'm
not sure why. It seems that if I instantiate a module, I can feed
it's an input port with either a 'reg'ister type or a wire type.

However, if that same instantiated module has an output port, I must
connect that port with a wire type, not a reg type.


If these rules are correct, why is this the case?
Some of the Verilog wizards on this group could probably give you an
explanation using the correct terminology but here is how I think about
this:


When you instantiate a module the output ports will be driven by a
continuous assignment. Think of it like the following:


adder myadder(.clk(clk),.opa(opa),.opb(opb),.Q(add_result));

In this case the Q port of the adder module is an output and the rest
are inputs. Behind the scene the simulator is creating a driver for
add_result looking something like this:

assign add_result = myadder.Q;


Since the rules are that an assign statement can only drive a wire and
not a reg, this is the reason why you are only allowed to use a wire for
the outputs.


(If I understand correctly, the original distinction between wire and reg
was to help simulator writers, but I may be totally wrong about this. This
is IMNSHO a mistake in the original Verilog standard that we are still
paying for. Luckily SystemVerilog will fix this issue for us. :))

/Andreas
 
benn <benn686@hotmail.com> wrote:
After much trial and error, I *THINK* I see a rule emerging but I'm
not sure why. It seems that if I instantiate a module, I can feed
it's an input port with either a 'reg'ister type or a wire type.

However, if that same instantiated module has an output port, I must
connect that port with a wire type, not a reg type.
Consider the difference between reg and wire inside a module.

a wire is driven by a continuous assignment, as the name
implies, continuously. It doesn't have any memory.

A reg is driven by assignment in behavioral model verilog
where assignments are not continuous, at least not conceptually.
The reg is how the node keeps its value between assignments.

That is really just conceptual, though. The reg may be
inside an unclocked always block such that it changes whenever
its source changes. A reg may also be part of a clocked always
block such as a flip-flop where it does keep state between
clock edges.

The connection from output ports to the instatiating module
is like continuous assignment, so should be wire in the
instantiating module.

-- glen
 
On Wed, 17 Dec 2008 10:36:30 +0000 (UTC), glen herrmannsfeldt wrote:
The connection from output ports to the instatiating module
is like continuous assignment, so should be wire in the
instantiating module.
Here's another way of thinking about it that may be
helpful. I'm not trying to claim it's perfect, but
it serves well for most practical purposes.

In Verilog there are two different ways to give something
a value: by CONNECTION or by WRITING TO IT. It is this
distinction that forces you to choose whether to use
a net or a variable, as follows:

- Nets (wires) are given their value by connection.

- Variables (regs, integers, reals) are given their value
by writing to them.

Note that we're talking here about how to GIVE something
its value - how it is DRIVEN. By contrast, when you USE
the value of something, it doesn't matter a scrap whether
you are using the value on a net or the value in a
variable - you simply get the value.

Now let's take a closer look at what those two things,
CONNECTION or WRITING, mean in practice:

CONNECTION:
- If you have a module instance, and you connect a signal
to an output or inout port of that instance, then that
signal gets its value from the module instance by
connection. So it must be a net.
- If your module has an input or inout port, then the
corresponding signal inside the module gets its value
from outside the module by connection. So the signal
within the module must be a net, if it's an input or
inout port of the module.
- If you make a continuous assignment to a signal, using
the "assign" keyword at the module level, then that
signal gets its value from the continuous driver by
connection. So it must be a net.

WRITING:
- Within an always or initial block, or the body of a
task or function, any assignment does a write operation
to the target (left-hand side) of the assignment.
So that left-hand side must be a variable.
- When your task or function has an input or inout
argument, that argument gets its value by copying
when you call the task or function. So, inevitably,
the arguments of a function or task are all variables.
(You can't declare nets inside a task or function.)
- When you call a task that has output or inout arguments,
that task will copy (write) results to your signals
when it returns. So those signals - the "actual arguments"
of the task - must be variables. There is no such
restriction for the input actual arguments of a function
or task; they are just values, and can be any expression.

Sorry, that ended up being longer than I wanted it to be...
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Jonathan Bromley <jonathan.bromley@MYCOMPANY.com> writes:

On Wed, 17 Dec 2008 10:36:30 +0000 (UTC), glen herrmannsfeldt wrote:

The connection from output ports to the instatiating module
is like continuous assignment, so should be wire in the
instantiating module.

Here's another way of thinking about it that may be
helpful. I'm not trying to claim it's perfect, but
it serves well for most practical purposes.

In Verilog there are two different ways to give something
a value: by CONNECTION or by WRITING TO IT. It is this
distinction that forces you to choose whether to use
a net or a variable, as follows:

- Nets (wires) are given their value by connection.

- Variables (regs, integers, reals) are given their value
by writing to them.
To simplify the connection concept even further. If you are writing
to variable in an always block in this module, it should be declared a
reg. Otheriwse, i.e. if the variable is being written to by another
module (or by soemthing not in an always block), the variable should
be declared as a net (wire).
 
On Dec 17, 1:30 pm, Chris F Clark <c...@shell01.TheWorld.com> wrote:
Jonathan Bromley <jonathan.brom...@MYCOMPANY.com> writes:
On Wed, 17 Dec 2008 10:36:30 +0000 (UTC), glen herrmannsfeldt wrote:

The connection from output ports to the instatiating module
is like continuous assignment, so should be wire in the
instantiating module.  

Here's another way of thinking about it that may be
helpful.  I'm not trying to claim it's perfect, but
it serves well for most practical purposes.

In Verilog there are two different ways to give something
a value: by CONNECTION or by WRITING TO IT.  It is this
distinction that forces you to choose whether to use
a net or a variable, as follows:

- Nets (wires) are given their value by connection.

- Variables (regs, integers, reals) are given their value
  by writing to them.

To simplify the connection concept even further.  If you are writing
to variable in an always block in this module, it should be declared a
reg.  Otheriwse, i.e. if the variable is being written to by another
module (or by soemthing not in an always block), the variable should
be declared as a net (wire).
Better add initial blocks to that. Sometimes these are synthesizable,
too.
 
On Dec 15, 6:59 pm, benn <benn...@hotmail.com> wrote:
After much trial and error, I *THINK* I see a rule emerging but I'm
not sure why. It seems that if I instantiate a module, I can feed
it's an input port with either a 'reg'ister type or a wire type.

However, if that same instantiated module has an output port, I must
connect that port with a wire type, not a reg type.

If these rules are correct, why is this the case?
Every post so far has useful information. I view the difference
between REG and WIRE a little differently.

Every signal starts out as a REG. That is, the origin is always a
REG. A WIRE is used to connect that REG to something.

You can't connect a REG to a REG; one thing can't originate in two
places. That's why your output ports must connect to WIREs.

An input port can connect to a REG or a WIRE. If you look closely
(follow the WIRE) you will always find a REG eventually, the WIRE is
used to connect it to that REG.

Hope that Helps,
AL
 
gabor <gabor@alacron.com> writes:

On Dec 17, 1:30 pm, Chris F Clark <c...@shell01.TheWorld.com> wrote:
....
To simplify the connection concept even further.  If you are writing
to variable in an always block in this module, it should be declared a
reg.  Otheriwse, i.e. if the variable is being written to by another
module (or by soemthing not in an always block), the variable should
be declared as a net (wire).

Better add initial blocks to that. Sometimes these are synthesizable,
too.
Yes, I almost added them, but I hit send before I thought of it. And
there are some other issues, like procedural continuous assignments
(probably not synthesizable) which write to a net from within an
always block. Tasks would be another complicating factor. However, I
was trying to make it as simple as I could.

So, for example, when is someone likely to write a reg that is only
set in an initial block and never set in an always block--perhaps to
represent a ROM?

Thus, I think to a first cut, for a beginning user, saying write a reg
if you are going to write to it in an always block and a net (wire)
otherwise, gets them writing relatively correct code to start with.
Amending that to always or initlal block, would also be reasonable.

They can learn the other cases as their sophistication grows. The
hard part is divorcing the idea of "reg" from a register or flip-flop,
which was probably the Verilog designers intent. But with the need to
use case statements (inside always blocks) to repesent complex muxes
and priority encoders, the intent got muddied very quickly.
 
On Sat, 20 Dec 2008 22:51:17 -0500, Chris F Clark wrote:

So, for example, when is someone likely to write a reg that is only
set in an initial block and never set in an always block
Ummm, in a testbench or a component model, maybe?

I can't say I feel very comfortable with any description
of something as central to (traditional) Verilog as the
net/variable distinction, if that description is locked
entirely to the RTL mindset - which surely must account
for much less than half of the total Verilog codebase.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Jonathan Bromley <jonathan.bromley@MYCOMPANY.com> writes:

I can't say I feel very comfortable with any description
of something as central to (traditional) Verilog as the
net/variable distinction, if that description is locked
entirely to the RTL mindset - which surely must account
for much less than half of the total Verilog codebase.
While you may not feel confortable with it, it is clearly there in the
design of the language. If you are doing structural or gate-level
verilog you don't need regs, everything you declare will be some net
type. The net types form a kind-of dataflow language, where results
flow from sources to sinks. That data flow language can support
expressions via continuous assignments. However, in the dataflow
language there is no way to preserve state, except via forces. Data
alwasy flows in the dataflow portion of the Verilog language, except
where a force breaks that flow.

The reg type solves that problem, it holds state, and one explicitly
changes it, by assignments to it. So, another way of looking at it,
is a reg is the only legal target of an assignment (or a non-blocking
assignment). Procedural continus assignments are a way of forcing
wires, but they generally aren't synthesizable, although they would be
reasonable in testbench or other behavioral code. But
synthesizability aside, if you want to assign to a variable using a
normal (block or non-blocking) assignment statement (and not a
continuous assignment), that variable needs to be a reg. And, if that
variable is a reg, the only way to give it a value is via an
assignment statement.

Now, where can one write such assignment statements. You can't write
them directly inside a module. You can only write them inside an
always block or an initial block or a task or a function. And, as far
as I can recall a task can only be invoked from an always block or an
initial block (or another task)--or perhaps from PLI. You certainly
cannot instantiate a task from a module.

Now, you can call a function from a continuous assignment statment,
but as far as I can recall a reg in a function is purely local, so it
doesn't preserve state there, and I will ignore functions from here
out.

Thui, one only writes a reg when one wants to control when something
changes state and the only place to exert such control is always
blocks and initial blocks. Thus, one only declares a reg when one
expects to write an assignment to it in one of those two kinds of
blocks (or inside a task that will be invoked from one of those
blocks--ignoring functions here).

And that gets back to the original posters question, which was why the
poster couldn't use a reg as an input parameter to a function. And
the answer is that one doesn't write the assignment to an input
parameter, that connection is made when the module is instantiated.
And, since one doesn't write an assignment to an input parameter, it
certainly isn't written in an always block (or an initial block or
even a task or a function). And, thus it is not a reg.

And, that brings us full circle. One only writes a reg declaration
for a variable if one intends to write an assignment to it in an
always block (or an initial block or a task or a function), and only
then. You do not write regs and assign to them with continuous
assignments, nor connect them to output ports of a module you
instantiate, nor to a gate-level primitive, etc., etc. You only write
them when you are using them in explicit assignments in always blocks
et. al.

And, that is not an RTL centric view of the language, it is the
underlying nature of the language. (And to be precise, my knowledge
of that fact did not come from writing RTL level Verilog, it came from
writing a Verilog interpreter (aka simulator) and reading the
standard.)

This post is now as long as your post that I was condensing, but the
point of it is that there is still one simple rule for when you write
a reg declaration. The reg declaration only serves to demarcate
certain variables, the ones that are targets of assignments in always
blocks, initial blocks, tasks, and functions. Everything else is a
net, whether explicitly declared or not. If you are writing one of
those assignments, you write a reg declaration, otherwise, you don't.

At the fundamental level, it really is that simple.

Now, if boiling those asignments down to ones in always blocks is RTL
centric, I am guilty as charged. It's just that the Verilog I've read
has used far more always blocks than any of the other constructs, and
perhaps I've seen more RTL Verilog.
 
On Mon, 22 Dec 2008 23:46:21 -0500, Chris F Clark wrote:
[...]

Chris,

I didn't in any way mean to challenge your understanding
of Verilog; my concern (which you acknowledge at the end of
your post) was that the description, and more particularly
the guidelines, that you gave were to my mind much too
RTL-centric to be robust for someone who wishes to use
the full language. For the most part, I reckon we are
in "violent agreement".

However, being the boring old pedantic git that I am,
I can't but pick a few nits in your post....

If you are doing structural or gate-level
verilog you don't need regs, everything you declare will be some net
type. The net types form a kind-of dataflow language, where results
flow from sources to sinks. That data flow language can support
expressions via continuous assignments. However, in the dataflow
language there is no way to preserve state, except via forces.
I beg to differ. This bit of "dataflow" does a pretty good
job of preserving state when inputs set,reset are both false:

wire q, qbar;
assign q = ~qbar | set;
assign qbar = ~q | reset;


as far as I can recall a reg in a function is purely local, so it
doesn't preserve state there
In "Verilog-Classic" (<=95) that was absolutely untrue; local
variables of a function (and, indeed, the function's return
value) are static variables that retain their state from
invocation to invocation, and have a hierarchical name.
Verilog >=2001 has automatic functions in which the variables
truly are local; this is a safer match for synthesis semantics,
and is preferred for almost any RTL use of functions.

And, that brings us full circle.
[...]
And, that is not an RTL centric view of the language, it is the
underlying nature of the language. (And to be precise, my knowledge
of that fact did not come from writing RTL level Verilog, it came from
writing a Verilog interpreter (aka simulator) and reading the
standard.)
And, I fancy, the clearest and most concise way to express that
is to say that variables get their values by procedural assignment
and nets get their value by connection. But beginners often,
not unreasonably, find it a shade tricky to work out what a
"connection" is in this context. Which is why my original
response ended up far longer than I would have wished.

This post is now as long as your post that I was condensing
The unavoidable curse of trying to explain something carefully;
I know it well :)

Thanks for the challenges. Since part of my day-job is
explaining precisely this sort of thing to trainees, it's
excellent to have other views on it.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Jonathan Bromley <jonathan.bromley@MYCOMPANY.com> writes:

For the most part, I reckon we are in "violent agreement".
And, I can understand why my simplifications seem like over-
simplications. Each one has a counter-example depending on
perspective.

I wrote a longer reply, but it got lost, which is just as well.

My main point is that I liked your point about connections. I tried
to further illustrate that point with the fact that there was a
difference in the language between connections and assignments to
regs, which occur only in certain syntactic contexts, always blocks,
intial blocks, tasks, and functions. However, due to the nature of
Verilog, it is hard to make that point without getting involved in
lots of exceptions--e.g. continuous assignments and their kin
procedural continuous assignments assign to nets, and the later can
occur in the same places as assignments to regs.

In any case, I meant no disrespect and took no offense having not felt
that I had been disrespected either (misunderstood a bit, but only
that). We were just dancing around whether there is a useful simple
rule to explain this one aspect of Verilog or not. I think there is a
simple core to Verilog, it's just buried in a lot of complexity......
 

Welcome to EDABoard.com

Sponsor

Back
Top