STD_U/ LOGIC ???

E

ec

Hi all

I am not sure when to define inputs and outputs in the
entity as STD_LOGIC and when as STD_ULOGIC

The same question applies about siganls
declared in the architecture .

what is the "rule" for this ?

Thanks in advance
ec
 
R

Ralf Hildebrandt

ec said:
I am not sure when to define inputs and outputs in the
entity as STD_LOGIC and when as STD_ULOGIC

Use std_logic for signals with more than one driver (e.g. a
tri-state-bus) and std_ulogic for all other ones.

The type std_logic has a resolution function, that computes witch value
will be the result at the signal if different drivers drive a value.
This costs some computing time - not much, but a little bit.
But the most important advantage of using std_ulogic for all signals
with only one driver is the fact, that a compiler can detect if there is
more than one driver for a signal. Therefore small mistakes leading to
multiple drivers are detected easily.

Ralf
 
A

Andy

Most modern simulators have an optional optimization that if there is
only one driver on a signal, the resolution function is not called.
This assumes the resolution function is reflexive (output = input for
only one input), which it is for std_logic.

Still, the compiler will catch more errors for you if you use
std_ulogic on non-tristateable ports, since you want to make sure
nobody else can drive that signal/port.

In the past, std_ulogic_vector was not so easy, since std_logic_vector
was not a subtype of std_ulogic_vector, and they could not be
interconnected. In the next release, they've finally decided to
formally make std_logic_vector (and numeric_std.signed and unsigned) a
resolved subtype of std_ulogic_vector (rather than relying on the
std_logic resolution function for the individual bits, they now have a
resolution function for the entire vector), so we will be able to
interconnect them the same way we can now with std_ulogic and
std_logic.

Note that, IINM, the bits of a std_logic_vector will now be std_ulogic,
which might get interesting for some existing designs (aliases of bits
of an slv would be?) See LRM 4.3.3.1 b) 3) (2000 edition is the
latest I have at hand).

Example of existing code:
signal a : std_logic_vector(7 downto 0);
alias amsb : std_logic is a(7);

In the example, a(7) is SUL (unresolved), but the amsb alias of it is
SL (resolved). Will this work? Can one declare resolved aliases of
unresolved objects? The LRM appears to say so...

Andy
 
K

KJ

ec said:
Hi all

I am not sure when to define inputs and outputs in the
entity as STD_LOGIC and when as STD_ULOGIC
If you have (or could have) multiple drivers of a signal you must use
std_logic. If there is only one driver for a signal you can use either
std_logic or std_ulogic. More on this at the end.
The same question applies about siganls
declared in the architecture .
Same as above.
what is the "rule" for this ?

When a signal has only one driver, there is no 'rule' just a few guidlines.
- First off, in general, most signals have only one driver, they are not
tri-statable so they have no reason to be of type std_logic.
- If you use std_ulogic types and you inadvertantly have two statements or
processes driving the same signal then this error will get caught
immediately when you compile the file for simulation. The compiler will
also generally point you to the lines of code that are driving the same
signal and you have immediate and accurate feedback of where you have a
problem.
- If you use std_logic types and you inadvertantly have two statements or
processes driving the same signal then this error won't be caught until
you....
- Debug down to the cause using a simulator
- Run the tool through synthesis where the fitter will complain about
multiple drivers for a signal.

For the reasons mentioned above it is generally desirable to use std_ulogic
as your first choice and std_logic for signals that really are tri-statable
and potentially driven by multiple sources (like a bi-directional data bus
for instance).

One of the downsides to this though is, when interfacing to other people's
code, the standard practice is to use std_logic type (at least for the
outermost exposed entity) whether it needs it or not. If you connect up
your std_ulogic_vector types to their std_logic_vector you will have to
perform a type conversion (i.e. Their_slv_signal <=
std_logic_vector(My_sulv_signal). Note: This is only for vectors, not for
the basic std_ulogic/std_logic discrete signals.

The pragmatic approach is to make your 'top level' entity have only
std_logic types, and from there on down use std_ulogic where appropriate.
This will force you to put any required type conversions inside the
architecture of your own code so that you're not burdening the user of your
code with this operation.

This brings up the question of what is the 'top level'? If you think of a
design as consisting of a bunch of nested entities one could say that each
lower level entity is a 'top level' of something and by that reasoning the
interface to those should follow the standard practice of using std_logic.
If you do that then, you'll never end up using std_ulogic so you'll never
gain the benefit of having the compiler catch those inadvertant multiple
drivers so you'll spend time debugging down to each one over the entire
course of your career that you write code. If that's how you choose to
spend your time that's up to you.

In order to gain the benefit of the compiler catching things and still write
code per industry practice you simply make the pragmatic decision about what
really is the 'top level' in your design and if someone wants to use your
lower level entities (the ones where you use std_ulogic) than it's up to
them to interface to your std_ulogic interface.

Again, the only time type conversions come into play that create any sort of
nuisance, is when you have a vector (std_logic_vector/std_ulogic_vector);
the base types themselves cause no interfacing issues at all.

Hope this helps.

KJ

KJ
 
A

Andy

I just thought of another issue with the new subtype definition of
std_logic_vector.

I typically have regiter arrays that are sparsely populated, and then I
try to drive them onto a tri-stat bus (even though the tri-state bus
gets converted to muxes in synthesis). However, to avoid creating
tri-state buffers for non-existent register bits (i.e. always driving
zeroes or ones), I use a constant mask vector to determine which bits
are driven, and do it with a generate loop as follows:

reg_ts: for i in reg'range generate -- foreach register in reg
db_ts: for j in dbus'range generate -- foreach bit in bus
msk: if mask(i)(j) = '1' generate -- mask off unused bits
dbus(j) <= reg(i)(j) when reg_read = '1' else 'Z';
end generate msk;
end generate db_ts;

I have used this structure in multiple designs over the years.

The problem is I'm creating multiple drivers for each bit of dbus, but
each bit will now be sul, and not resolved sl! Will this code be
broken under the new subtype definition of slv?

Andy
 
J

Jim Lewis

Andy,
Most modern simulators have an optional optimization that if there is
only one driver on a signal, the resolution function is not called.
This assumes the resolution function is reflexive (output = input for
only one input), which it is for std_logic.

Still, the compiler will catch more errors for you if you use
std_ulogic on non-tristateable ports, since you want to make sure
nobody else can drive that signal/port.
Above and beyond language requirements, some simulators
seem to catch std_logic signals with multiple drivers
when there is not a condition under which a 'Z' is
assigned.

I have often wondered if the optimizations for std_logic would
make it simulate faster than std_ulogic. Not logical, but
it is possible. Has anyone tested this?
In the past, std_ulogic_vector was not so easy, since std_logic_vector
was not a subtype of std_ulogic_vector, and they could not be
interconnected. In the next release, they've finally decided to
formally make std_logic_vector (and numeric_std.signed and unsigned) a
resolved subtype of std_ulogic_vector (rather than relying on the
std_logic resolution function for the individual bits, they now have a
resolution function for the entire vector), so we will be able to
interconnect them the same way we can now with std_ulogic and
std_logic.

Note that numeric_std.signed will be a subtype of numeric_std.unresolved_signed
and not a subtype of std_ulogic_vector. Similarly numeric_std.unsigned will
be a subtype of numeric_std.unresolved_unsigned.
Note that, IINM, the bits of a std_logic_vector will now be std_ulogic,
which might get interesting for some existing designs (aliases of bits
of an slv would be?) See LRM 4.3.3.1 b) 3) (2000 edition is the
latest I have at hand).

Example of existing code:
signal a : std_logic_vector(7 downto 0);
alias amsb : std_logic is a(7);

In the example, a(7) is SUL (unresolved), but the amsb alias of it is
SL (resolved). Will this work? Can one declare resolved aliases of
unresolved objects? The LRM appears to say so...

I submitted both your issue here and the one in your follow-up
post directly to the bug tracking system.

Cheers,
Jim
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis
Director of Training mailto:[email protected]
SynthWorks Design Inc. http://www.SynthWorks.com
1-503-590-4787

Expert VHDL Training for Hardware Design and Verification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top