[sv-bc] Errata: Complex Data Types of Wires

From: Jonathan Bradford;Freiburg <bradford@micronas.com>
Date: Thu Aug 26 2004 - 09:58:25 PDT

Complex Data Types of Wires

Motivation

This is a request based on usage of System Verilog for an extension to
System Verilog for accessing wires with complex data structures implied
by their driving registers or data destinations.
The examples have been modified to the proposed syntax in the summary.

In System Verilog the interface can have signals declared as wires or
variables.

The wires can be declared as vectors or vectors of vectors or arrays of
vectors, reflecting whether they are packed or unpacked data types. The
wire can also be of various resolved types,
such as tri1 (pullup) or trireg (holding) etc. The wire can also be in
signed or unsigned (default) arithmetic.

The variables can also be declared as vectors and vectors of vectors and
arrays of vectors. They can also be defined as many other data types, as
packed types for implementation such as
structures etc, or unpacked for verification such as dynamic arrays etc.
Again these may have attributes for signed or unsigned arithmetic and
packed or unpacked data storage.

But there is no resolution capability. i.e. they may be written to
discretely by assignments in procedural code or a single structural
assignment (continuous or connectivity).

When implementing an RTL design it is safe to model states in the design
using variables in the interfaces, so long as there is a single
direction of signal flow and no multiple drivers.

There are a number of constructs in System Verilog language to ensure
this, such as interface modports with output statements for the variable
to be written and the use of always_ff to
constrict the assignments to these interface variables. These constructs
restrict structural and procedural assignment to the state variables and
implicate registered outputs in the single
driving blocks.

This allows the use of variables with complex data definitions such as
structs etc in RTL implementation.

However there are scenarios in RTL implementation where it is necessary
to allow bidirectionality or at least multiple drivers (and enables)
onto a common bus.

This implies that only wires can be used for these interface signals.
The driving variables are then explicitly assigned to, from the modules
interfaced to the bus.

But wires cannot be defined with such complex data structures as
variables. Hence once a value is on the wires in the bus in the
interface, it is not possible to use those signal values as easily
as in the original variables. This is especially the case for structs.

There are two main problems

   o wires containing values driven by variables of complex type must be

     correctly sized, throughout the interface hierarchy.

   o components of values on wires implied by the 'shape' of the driving

     variable need to be made accessible wrt those `shapes' rather than
     the explicit 'shape' of the wire.

i.e.

   // a register driving the bus might be :-

   typedef struct packed { logic ecc; logic [7:0] data; } MemLoc;

   MemLoc mem_r;

   // whereas the signal in the interface - driven by multiple modules
(enabled) :-

   wire [8:0] memsig;

   modport driver (inout [8:0] memsig);

   // a user of the interface signal needs to know where ecc and data
are !

   my_ecc = memsig[8];
   my_data = memsig[7:0];

If the definition of the structure were changed, the design hierarchy
must be worked through to change all these structural references to the
wires that transport signal values.

One way to do this particular example is to use casting:

   my_ecc = MemLoc'(memsig).ecc
   my_data = MemLoc'(memsig).data

However a cast cannot be an lvalue or an output port, so a more general
facility is needed. A language extension to allow a packed data type to
be associated with a wire vector can provide
this generality and reduce the typing:

The structure must be packed. The structure can be either 4-state or
2-state, but 4-state is recommended to maintain compatibility between
variables and wires of the same type. There is
one wire for each bit or logic, and the wire can have the normal range
of strength values. The wire can be of type tri1, tri0, trireg,
supply0, supply1 etc.

Example

   // wire and interface definition

   wire <MemLoc> memsig;

   modport driver (inout <MemLoc> memsig);

   // this is similar to
   // wire [$bits(MemLoc)-1:0] memsig;

   // wire element of `shape` access

   my_ecc = memsig.ecc;

   my_data = memsig.data;

   assign memsig = mem_r;

   assign memsig.ecc = ^mem_r.data;

Hence if the structure MemLoc changes, the slice access routines for the
wire signals remain unchanged.

In reality there is nothing changed in the behaviour of variables and
wires, only in how their content is perceived.

This perception of the shape is also independent of the driver, as there
can be multiple drivers of the aggregate wire. The same wire may
therefore be perceived in multiple ways :-

   typedef struct packed {logic [1:0] ignore, logic [6:0] ascii}
CharLoc;

   my_data [7:0] = memsig.data;
   my_data [7:0] = CharLoc'(memsig).ascii;
   // msb becomes 0

   typedef union packed {MemLoc ML; CharLoc CL;} AnyLoc;
   AnyLoc anysig;

   my_data [7:0] = {anysig.ML.ecc, anysig.CL.ascii};

Furthermore if the structure definition contains attributes such as
signed for the arithmetic of its members, this is maintained for a
member access, but not for the corresponding slice.

   typedef struct packed { logic signed [7:0] a; logic [7:0] b; } Slog;

   wire <Slog> slog_sig;

   if (slog_sig.a >>1 == slog_sig[15:8] >>1)
      $display ("Not all the time, No");

The problem with respect to overloaded operators can be exemplified by
considering a user defined structure to represent a fixed point number
with fields for mantissa and exponent.
Currently when a wire is used as an argument to such an operator, there
is no way to infer that the value within the wire should be the mantissa
and exponent as opposed to the integral integer
value of a wire. However this is resolved when a wire has a structure
definition.

Summary

A proposal for a collection of wires to be treated as a structure, as
explained above.

This proposal is to allow a type identifier to be used instead of
signing and packed dimensions in net declarations.

net declaration ::= net_type_or_trireg
                       [ drive_strength | charge_strength ]
                       [ vectored | scalared ]
                       [ signing ] { packed_dimension } [ delay3 ]
                          list_of_net_decl_assignments
                  | net_type_or_trireg
                       [ drive_strength | charge_strength ]
                       [ vectored | scalared ]
                       < type_identifier > [ delay3 ]
                          list_of_net_decl_assignments ;

The type_identifier should be limited to packed types.

The < > characters are used to remove ambiguity.

--
________________________________________________________________________________
     /\      Jonathan Bradford                   mailto:bradford@micronas.com
     \/
    /\/\     MICRONAS GmbH                       http://www.micronas.com
   /\/\/\
   \/\/\/    Hans-Bunte-Str.19                   Tel: +49 (0)761 517 2884
    \/\/     D-79108 Freiburg                    Fax: +49 (0)761 517 2880
     \/      Germany
Received on Thu Aug 26 09:58:52 2004

This archive was generated by hypermail 2.1.8 : Thu Aug 26 2004 - 09:59:03 PDT