Subject: [sv-bc] RE: [sv-ec] Question: logic & reg - what is the difference?
From: Kevin Cameron (sv-xx@grfx.com)
Date: Mon Jun 09 2003 - 15:05:42 PDT
> From: Steven Sharp <sharp@cadence.com>
> 
> >A "reg" is actually a composite object, it is the combination of a driver
> >and a wire. When you write to it you are assigning to the driver and when
> >you read you get the wire value (the resolution of all the drivers of the
> >wire). "logic" is the (default) type of the driver.
> 
> I am afraid you are confused here.  A reg is not resolved.  When you write
> to it, you write to the actual value.  When you read from it, you get the
> last value that was written.  It works just like a variable in a normal
> programming language.  There are no drivers, no resolution, and no
> separation of "driving value" and "effective value" (to use non-Verilog
> terminology).
>
> Now, if you attach a reg to a port, then there is an implicit continuous
> assignment from the reg to the net on the other side of the port.  That
> net may have multiple drivers, and if you read that net you will get the
> resolution of all the drivers.  But this is not a property of a reg.  It
> is the property of the port with the reg attached, or of any port that
> has a port expression attached that is not collapsed.  (Note that I am
> talking about Verilog here, which doesn't have variable or reference ports
> or anything else that SV may have added to ports.)
> 
> Perhaps you have only used regs attached to ports.
I'm not confused. The unattached case is just a degenerate case that behaves
as you describe - the driving value and effective value are the same, and
since propogation is immediate there is no difference between a reg and
a variable as far as ther user is concerned. 
> 
> >In order to extended the type system to handle signals with multiple
> >data, strength and certainty values (user defined types) you need to be able
> >to declare similar wire/driver pairs but with a different driver types, e.g.:
> >
> >  typedef my_logic;
> >  ...
> >  reg my_logic foo; // create wire foo and driver of type my_logic
> 
> If you want a wire in Verilog, you declare a wire.  If you want a driver,
> you declare a module that drives the wire through a port, or a gate, or
> a continuous assignment.
I meant "wire" in a more physical sense. A port is not really a driver, it's
just connectivity - viewing it as a driver leads to bad modelling semantics. 
In general a driver should map to some active piece of circuitry i.e. a
transistor for ICs, ports don't.
> >An alternative approach is to declare and bind drivers explicitly, which
> >would allow you to have multiple drivers shared by multiple processes e.g.:
> >
> >   wire            foo;
> >   driver logic    d1(foo);  // bind driver d1 to wire foo
> >   driver my_logic d2(foo);
> >
> >   initial d1 = 1'bz;
> >
> >   initial d2 = ml_inactive;  
> 
> In Verilog, your "driver" things would be continuous assignments:
> 
> assign foo = d1;
> assign foo = d2;
> 
> Verilog already has this covered.
Not really. You can use a single explicit driver from multiple processes, each
assign statement creates a seperate driver.
> 
> >That approach has some advantages if you want to attach a driver to single
> >element of a composite object e.g.:
> >
> >   struct foo {
> >     logic b1;
> >     logic b2;
> >   } bar;
> >
> >   driver logic fb1(bar.b1);
> >
> >   initial fb1 = 1'b1;
> 
> Under the Cadence datatype proposal to the IEEE, which allows nets of struct
> type, this could be done in a way consistent with existing Verilog:
> 
> wire foo bar;
> assign bar.b1 = fb1;
> 
> Again, to get a net, you declare a net.  To drive the net or a subpart of
> the net, you declare a continuous assignment.
That would be equivalent if you can do all that is needed with a single process,
the explicit driver approach allows you to break the behavior up e.g. you could
add:
    always @(clk)   fb1 = data;
    always @(reset) fb1 = 1'b0;
bar.b1 gets the last value assigned to fb1, no resolution is performed as would be
with three assign statements.
It's more like:
    struct foo {
      logic b1;
      logic b2;
    } bar;
    reg fb1;
    alias fb1 = bar.b1;
    initial fb1 = 1'b1;
    ...
except that creates a wire (fb1) with an implicit driver, rather than just the driver.
Kev.
    
> >Resolving multiple/user-defined types on a wire is a seperate discussion :-)
> 
> Indeed so.
> 
> Steven Sharp
> sharp@cadence.com
> 
This archive was generated by hypermail 2b28 : Mon Jun 09 2003 - 15:07:31 PDT