I'd rather switch than fight!

A

Andy

Cliff's paper is about avoiding race conditions. However, in vhdl
"blocking assignements" (to unshared variables) are limited to local
process/subprogram scope anyway, so you never have problems with race
conditions with them. That is why it is safe and even beneficial to
use blocking assignments (to unshared variables) in VHDL clocked
processes. Combine that with the flexibility afforded in describing
both combinatorial and sequential logic in the same process, and it
makes for an extremely powerful, yet safe concept. While some may
struggle with identifying where the registers are located in relation
to the combinatorial logic, understanding the cycle-based behavior is
more intuitive, since the code "reads and executes like SW". Given the
increasing use of retiming optimizations, knowing where registers are
located in your RTL is rapidly becoming useless anyway.

For the remaining < 1% of the time when I need an in-to-out
combinatorial logic path through a module/entity, I'll go ahead and
use a combinatorial process (implied by a concurrent assignment or
otherwise). That doesn't mean I'm going to throw away the benefits of
using only clocked processes for the other > 99%, just for purity's
sake.

Andy
 
P

Patrick Maupin

Cliff's paper is about avoiding race conditions. However, in vhdl
"blocking assignements" (to unshared variables) are limited to local
process/subprogram scope anyway, so you never have problems with race
conditions with them. That is why it is safe and even beneficial to
use blocking assignments (to unshared variables) in VHDL clocked
processes. Combine that with the flexibility afforded in describing
both combinatorial and sequential logic in the same process, and it
makes for an extremely powerful, yet safe concept. While some may
struggle with identifying where the registers are located in relation
to the combinatorial logic, understanding the cycle-based behavior is
more intuitive, since the code "reads and executes like SW". Given the
increasing use of retiming optimizations, knowing where registers are
located in your RTL is rapidly becoming useless anyway.

For the remaining < 1% of the time when I need an in-to-out
combinatorial logic path through a module/entity, I'll go ahead and
use a combinatorial process (implied by a concurrent assignment or
otherwise). That doesn't mean I'm going to throw away the benefits of
using only clocked processes for the other > 99%, just for purity's
sake.

Yes, the two process model probably isn't nearly as useful in VHDL.

As others have been quick to point out, you don't need a combinatorial
process in verilog either, but then you have to be careful about
blocking vs. non-blocking, not using variables which have blocking
assignments to them from other processes, etc. The two process model
is simply an organizing principle that provides a separation of
concerns and simplifies the rules a bit, making it easier to reason
about the code. Extremely simple code doesn't gain anything from
using this model, but a lot of real-world code does.

Regards,
Pat
 
R

rickman

I have to wonder if *that* is the reason the two-process model refuses
to die in VHDL textbooks, tutorials, and example designs worldwide.

Perhaps too many educators focus on comparing the languages, showing how
the same thing is done *the same way* in both languages.

I would prefer to see each language shown off at its best.

Then VHDL could be illustrated with the (much less verbose) single
process model, functions and procedures to raise the abstraction level
and simplify the main process, and proper use of the type system to help
rather than frustrate the user.

(e.g. recently here, there was an example where someone frustrated
himself by using a type with integer semantics when he really wanted a
type with modular semantics, so he had to code all the wrap-arounds by
hand. Easy pitfall for someone used to C which doesn't have any types
with integer semantics.)

Likewise best practice in Verilog could be illustrated.
(I have no idea what that is; hearsay suggests it would include avoiding
races, avoiding problems with signed arithmetic, implicit declarations
and so on. But Verilog must have real strengths too)

- Brian

I don't agree that the two process model is inherently less
desirable. Or maybe I should say that I don't think describing
combinatorial logic outside of clocked processes is inherently less
desirable. I seldom put a lot of combinatorial logic in processes,
clocked or unclocked, mainly because the structures in processes and
combinatorial logic are rather weighty (a synonym for verbose I
guess). But it always depends on the logic. Lacking the conditional
expression, VHDL concurrent logic can be a PITB to write complex
expressions in a clear manner. This means sometimes I put
combinatorial in unclocked processes because it is more clear. Simple
logic goes in with the clocked process, but when possible, I put
combinatorial logic in concurrent statements.

A foolish consistency is the hobgoblin of little minds, but there are
times when consistency is a good thing in engineering, other times
not. I guess I'm consistently inconsistent.

Rick
 
B

Bernd Paysan

Brian said:
Where there are combinatorial outputs to be described, I agree, I'll
describe them outside the main process.

But I can't remember the last time I had one so complex it needed a
process of its own.

In my code, multiplexers (e.g. a number of registers driving the same bus)
end up as process of their own. It is possible to get around that by using
a wire array, though, so

always @*
begin
bus_data = 0;
if(bus_enable)
case(bus_addr)
0: bus_data = xxx;
1: bus_data = yyy;
....
15: bus_data = zzz;
esac
end

converts to

wire [x:0] bus_data_array [0:15];

assign bus_data_array[0] = xxx;
assign bus_data_array[1] = yyy;
....
assign bus_data_array[15] = zzz;

assign bus_data = bus_enable ? bus_data_array[bus_addr] : 0;

but this has a severe simulation disadvantage (the simulator has to
recalculate all bus_data_array elements when the dependencies change, even
when the bus is not used at all).
 
A

Andy

then you must surely allow similar expressions with other enumerations,
for instance:
---------------------------------
Type NTSC_Color is (red, green, blue);  
Signal Channel_Color : NTSC_Color;
Signal Channel_Gain  : real;

Channel_Gain <= Channel_Color ? 0.11 : 0.55 : 0.34;  
-- nice and compact, but descending order to remain compatible with Boolean
---------------------------------

Now I believe that ascending order, like every other positional list in the
language (port lists, argument lists, etc), would be less surprising:

Channel_Gain <= Channel_Color ? 0.34 : 0.55 : 0.11;  

The problem with this approach is that the action depends not only on
the enumerated values defined in the type, but also on their order of
definition. Especially when the type is often defined in a package,
not immediately visible to the user/reviewer, I would much prefer a
more explicit (yes, verbose!) coding of what action is desired. Using
an array indexed by the enumerated type, or using the aforementioned
function, we can do this already, without the conditional operator
(I'm probably in the minority, but this was not a wise addition to the
language in 2008).

By adding such ambiguous shortcut features to the language, we are
only deterring the use of a universally accepted solution to code
complexity: subprograms (functions and/or procedures).

Consistently inconsistent here too...

BTW, WRT combinatorial outputs of clocked processes, many synthesis
tools now support the following:

process (clk, rst) is
variable myvar : ...
begin
if rst then
myvar := ...
elsif rising_edge(clk) then
myvar := myfunc(inputs);
end if;
combout <= outfunc(myvar);
end process;

Combout is then the combinatorial output of outfunc() applied to the
output of the register inferred by the access to myvar.

This gives us the ability to describe combinatorial output logic
without the simulation penalty, latches, and signal overhead
associated with a separate combinatorial process, implied or explicit.

Andy
 
A

Andy Peters

LoL.  Note that there are further difficulties to understand this separated
code due to the fact that things which conceptually belong together are
spread apart over the file.  This is just too messy.


I'm fully on your side.

Same here. In the over one hundred posts in this thread, I still
haven't figured out exactly what benefits Patrick sees in the two-
process model.

Unless he likes the names of his machine's states to line up with the
signal assignments in the waveform view, as opposed to seeing the new
assignments in the _next_ state.

-a
 
R

rickman

That is one long reply...

Where there are combinatorial outputs to be described, I agree, I'll describe
them outside the main process.

No, I am talking about logic that drives the registers. For example,
I have a PLL circuit which has a few registers, but several adders and
a few shift operations (mult/div). I give each a separate concurrent
statement to facilitate debugging. I could put it all inside the
register process, but I can do things with signals I can't do with
variables, such as bring them to the outside world. By giving each
one a separate concurrent assignment it is very easy to monitor and
debug each one individually. Yeah, it may look more verbose, but I
just don't see that as a problem.

The control signals for the registers get evaluated in concurrent
logic. I could add more conditionals (ifs) to the clocked process to
incorporate the full expression as the enable on the register, but by
keeping it external, it is more clear what the evaluation is doing and
again, I have a separate signal I can more easily debug it in the
simulator and in the chip.

Maybe this is a reflection of how we think differently for both design
and debug. I am an old school hardware designer and I think in terms
of registers and logic blocks. So my design reflects that I guess.

But I can't remember the last time I had one so complex it needed a process of
its own.


I think you are referring to the ?: conditional operator inherited from C?

Yes, Verilog and C I believe.

I just use VHDL's conditional signal assignments for that purpose. As it's
purely combinational, I have never found the need for an equivalent that I can
use inside a process.

Heck, that is very limited. You can't even use in inside of a
separate signal assignment. Try combining the conditional signal
assignment with anything else. I would like to be able to use it
inside the conditional for an if (sometimes) or combine it is ways
that allows the assignment to more directly state the logic of the
problem rather than my having to convert the logic to suit the flow of
the structure.

I eventually figured out what I heartily detest about that (?:) - it's the ONE
construct across all the languages I've encountered that expects the list of
choices in descending order.

(And does so implicitly as opposed to explicitly, with a "downto" or "step -1"
or "when true else..." or some visible indication that it's doing something
quaint)

If VHDL is to adopt a conditional operator I hope it can do better than that!
Something less surprising, and generalisable to other discrete types or at least
other enums.

If you are going to allow
---------------------------------
Signal Flag : Boolean := True;
Signal Int_val : Integer;

Int_val <= Flag?1:0;
---------------------------------
then you must surely allow similar expressions with other enumerations,
for instance:
---------------------------------
Type NTSC_Color is (red, green, blue);
Signal Channel_Color : NTSC_Color;
Signal Channel_Gain : real;

Channel_Gain <= Channel_Color ? 0.11 : 0.55 : 0.34;
-- nice and compact, but descending order to remain compatible with Boolean
---------------------------------

I think this is a rather trivial example. Why not use the selected
signal assignment? It may be more verbose, but it *is* explicit. The
mnemonic for a boolean conditional operator is pretty simple, it is
the same as an IF statement. But to extrapolate that to descending
order for other data types is a bit of a reach. I guess this makes
some sense for an enumerated type, but where else could you use the
conditional operator? An integer range type would be a possible use,
but potentially difficult to use effectively, or maybe I should say,
seldom useful. I think the utility of the conditional operator is
that it can be used in many places and allows a better expression of
the logic (closer to the problem) as well as more compact.

Now I believe that ascending order, like every other positional list in the
language (port lists, argument lists, etc), would be less surprising:

Channel_Gain <= Channel_Color ? 0.34 : 0.55 : 0.11;

There would of course be an associative form of the expression
Channel_Gain <= Channel_Color ? red =>0.34 : green =>0.55 : blue=>0.11;
to make the bugs harder to bury.

Isn't this just a selected signal assignment?

In this context, is anyone still happy with the C-compatible version?

However...

in today's VHDL, if I ever needed ?: I would resort to a trivial function, and
replace

Int_val <= Flag?1:0;
with
Int_val <= cond(Flag,1,0);
or even
Int_val <= cond( test=>Flag, T=>1, F=>0 );

YMMV but for the sake of keeping the language relatively free of warts, I don't
mind typing six extra characters.

It's precisely that wart-free-ness that lets you extend it (e.g. by adding
functions) in simple ways that actually work, instead of frustrating you.

I don't get why you think the conditional operator would be a wart.
It is just an operator. It is a trinary operator rather than uniary
or binary, but it is still an operator and would violate nothing about
VHDL.

And it's precisely the remaining warts that limit the ability to extend it
further. For example, the closed set of operators (a wart shared with most
not-quite-object-oriented languages like C++) stops you naming the
above function "?:" and writing
Int_val <= "?:"( Flag,1, 0 );
to look that little bit more like Verilog or C.

Or a better example: if you allowed types as generics, as Ada does, you could
write the "?:" function once and use it to return different types. (Newer
versions of C++ have this, as the template).


Oh I'm inconsistent too, just not consistently so.

I like "consistently inconsistent" - I suspect it would make the best
description of the underlying design principles of C.
(I don't know Verilog at all well, so won't extend the same courtesy to it!)

I've been warned about verilog, mostly in this thread, and I've been
told once I try it I won't go back. We'll see later this summer...
maybe.

Rick
 
N

Niklas Holsti

Brian said:
A better solution all round would be to replace it with an if-expression (in
which "if", "then", "else" are explicit, (don't rely on the reader knowing C)
and a case-expression for the (n>2) enumeration and integer subrange cases.

But that seems to have fallen out of favour since Algol-W.

Conditional expressions in the "if-then-else" syntax are being proposed
for the next Ada standard, and are already implemented in the GNU Ada
compiler. See http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00327.html.
 
R

rickman

I'm unclear why you say a separate concurrent statement facilitates debugging;
are you stepping through code in the simulator? (I haven't done that in over ten
years)

Not for stepping, although I sometimes do that. It is so I can put up
each result in the simulator...

DCO <= DCO + (Integrated / INTG_GAIN) + (ErrorReg * PROP_GAIN);

This is overflowing an intermediate result. How do you debug? In the
process of debugging I also found the intermediate results need
saturating arithmetic, at least in test. By using separate
assignments for each step I can see what each operator is doing and
why it is crapping out. Once I split it up, I am leaving it, although
I am removing the saturation logic.

As you said above; because it isn't combinable - e.g. in a process - yet.

I am refering to the situation where it is available. It may be in
VHDL 2008, but I guess my machine is still running in 2003.

A better solution all round would be to replace it with an if-expression (in
which "if", "then", "else" are explicit, (don't rely on the reader knowing C)
and a case-expression for the (n>2) enumeration and integer subrange cases.

But that seems to have fallen out of favour since Algol-W.

I'm not sure what you are referring to. An if is a sequential control
flow structure. I guess you are saying to give it a dual use. The
boolean operator is in common usage and there is no good reason to not
include it in VHDL. I don't know what the syntax is, but I assume it
is similar or the same as in Verilog.

Essentially yes - the difference (which, I confess I didn't know, had gone in
VHDL-2008) being that you can use it in a process.

In a process this is a case statement. The real difference is that
you can use it inside an assignment while the case statement or
selected signal assignment can't.

foo <= ralph + (('1' = Mode) ? A : B);

compared to

with Mode select
foo <= ralph + A when '1',
ralph + B when '0',
(others => '-') when others;

Both can get very unreadable if they get more complex. However, there
have been many times I have had to write very messy code or at a
minimum had to think hard about how to make it clear using the current
constructs.

I suppose I'm just saying I appreciate the VHDL-2008 changes which don't break
the language, rather than adding ?: which would.

I don't get the "break" part. I think that is a subjective opinion.

For a start, what would the syntax for overloading it look like?

Why would it be any different from what we currently use??? What does
it look like?

My guess is: horrible.

And definitely not worth rewriting half the parser for one operator on one
specific enumerated type.

Ok, now you are going off to unsubstantiated claims. I doubt anyone
would agree to go with a feature that required rewriting half the
compiler.

I'd certainly be interested to know how you get on.

My prejudices are my own; I'd rather spend the time learning how to push VHDL
harder for more productivity. I have the feeling we've barely scratched the
surface yet.

We'll see. First I have to finish my current project. I am at the
final few bugs and each one is a trip back and forth to the customer.

Rick
 
M

Martin Thompson

Andy Peters said:
Same here.

Me too.
In the over one hundred posts in this thread, I still
haven't figured out exactly what benefits Patrick sees in the two-
process model.

I may be entirely wrong, but I *think* it's a Verilog thing - it's a
way to make it easy to check that the rules about sharing "variables"
don't go wrong, giving you races.

We VHDLers don't have to worry about it, so the discussion made little
sense within this newsgroup.

Cheers,
Martin
 
A

Andy

I have used two home-grown functions for years for this: is1() and
is0(). Both handle metavalues, etc.

if is1(A and B) then

No silly syntax or language "improvements" required.

Andy
 
R

rickman

Sometimes, not very well...

But for this situation I would assert properties of the expression, or better,
of each intermediate term.

So for example, (ErrorReg * PROP_GAIN) might have its own intermediate signal -
(in my code it almost certainly would - within the main process - so I can
control its pipelining but that's another story * ) - I could assert the output
sign matches the input sign (knowing, or asserting, PROP_GAIN is positive).

Pipelining is not possible. This is a PLL and adding register delays
changes the nature of the equation. Yes, you can assert things in
simulation, but what do you do in the chip? I had to debug a problem
in the board when the simulation worked perfectly. In fact, I am very
happy with the PLL, it locks in fast and holds the lock tightly. The
problem ended up being a configuration (real time, not compile)
mistake. But it took some real debugging of the PLL to figure that
out.

(* I've had summer interns exploring register retiming tools;  they didn't beat
my hand-timed results. Which may say something about the tools, or not)

Then either I get a pinpoint report of the problem, or the testbench is
inadequate...

Actually, yes, in this case a 100% test bench would have caught the
real problem. I wasn't simulating the configuration module which
received the serial config commands. This has bitten me twice, but it
is one of those things where the customer was beating on me to get
something to him to test and I didn't have time to get the last
touches into the top level test bench. Sometimes working the "right"
way appears to be "slow". In this case it cost us about a week of lab
test time vs. about a week of additional test bench design and use. I
am working on the 100% simulation now mainly because I still have to
build a test fixture, the hardware kind, and that uses an FPGA which
the test bench will be programming. The other bug was actually a bug
in the config code which didn't disable multiple use of the same
register bits between two modes. A squelch circuit was activated in a
mode where there wasn't supposed to be any squelch.

I'm not sure what you are referring to.  An if is a sequential control
flow structure.  

Maybe in some languages, but it doesn't have to be.

I used to be able to write code of the form
----
   a := if <expr1> then <expr2> [ else <expr3>];
----
(the assignment being skipped if expr1 was false and there was no else clause)
and similarly, case expressions with semantics like case statements.

And I am delighted to hear it's on the way back in a mainstream language and one
of the main influences on VHDL.
foo <= ralph + (('1' = Mode) ? A : B);
compared to
with Mode select
 foo <= ralph + A when '1',
        ralph + B when '0',
        (others => '-') when others;

I think a closer translation would be

foo <= ralph + A when Mode = '1' else ralph + B;

and I don't get the objection to that.

Yeah, but in simulation I always use the others to catch "illegal"
states in controls. In your code a value of 'u' in Mode results in
foo <= ralph + B and the circuit continues with no problem. I want to
propagate crap with crap. Typically operators do that with std_logic
while your simpler logic doesn't.

In fact, it is only a warning when you have two drivers of an
std_logic signal. I would like to make that an error by using
std_ulogic, but I'm not sure how that works with the other types. I
need to investigate that sometime.

I doubt there's a synthesis tool alive that would duplicate the adder!
But if there were, I would mux A or B onto  an intermediate signal .



What we currently use and overload are unary and binary operators. In neither of
these do you have to split the operator symbol in half and insert an argument in
the middle.

There is no syntax for expressing that, in VHDL.

That is what I mean by "break". I suspect we'd have to try writing the BNF for a
grammar that would handle its use and overloading to settle the question.

If it is a part of VHDL 2008, isn't it done? I can't imagine they
would have added it to the standard if vendors didn't know how to make
it work yet.

Maybe so, my compiler writing days are long ago. But something about adding
*one* trinary operator sets off alarm bells.

I guess we can ask the vendors about it. Does anyone have VHDL in
their tools yet? Mine don't seem to include it, but that may be a
switch I need to throw.

Rick
 
A

Andy

Yeah, but in simulation I always use the others to catch "illegal"
states in controls.  In your code a value of 'u' in Mode results in
foo <= ralph + B and the circuit continues with no problem.  I want to
propagate crap with crap.  Typically operators do that with std_logic
while your simpler logic doesn't.

I replied earlier about using trivial, home-grown is1() and is0()
functions that will let you know about metavalues with an assertion
warning (default, can be altered with optional arg), as well as
appropriately handle a weak logic value. This is the main reason I
wrote them and have used them for years. If you set severity
appropriately, the debugger will stop exactly where the meta-value was
detected, rather than waiting until you notice garbage data, and trace
it back to its cause.

foo <= ralph + A when is1(Mode) else ralph + B;

I'm beginning to wonder how pleased you will be with verilog, given
some of the features of vhdl you already use.

Andy
 
K

KJ

How many times have you wanted to write something like this:
if A and B then
where A and B are STD_LOGIC? ... You have to write this instead:
if A = '1' and B = '1' then

You don't HAVE to write it that way...it can also be written (just as
clearly in my opinion, but a few more taps on the keyboard then
VHDL-2008)

if (A and B) = '1' then

KJ
 
K

KJ

I suspect there may be some tools issues in the less-well-trodden path
of std_ulogic. And I have a nagging suspicion that numeric_std is
compatible with std_logic and may be harder to use with its unresolved
cousin. (But I hope not)

Again, if you get a chance to investigate, I would be interested to hear
how you get on.

I've been using std_ulogic/std_ulogic_vector for a while...no issues
with Quartus or Synplify on the synthesis front. The only downside is
some extra type conversions to convert between the vectors where you
have to for some reason have std_logic_vector. The upside of course
is that the compiler immediately flags when you have multiple drivers
on a net, you don't have to sim/debug to find that out.

The main place the mixing of std_logic_vector and std_ulogic_vector
occurs is instantiating some outside widget that uses std_logic_vector
on the interface. Once I learned that type conversions can be put
into the port map and you didn't need to create std_ulogic 'wrappers',
or use intermediate signals to connect the vectors, it all came
together rather nicely.

Example:

Inst_Some_Widget : entity work.widget
port map(
Gazinta_slv => std_logic_vector(Gazinta_sulv),
std_logic_vector(Gazouta_slv) => Gazouta_sulv
);

std_logic and std_ulogic can be freely assigned without any type
conversions

Kevin Jennings
 
P

Paul Uiterlinden

Alan said:
On 28/04/2010 11:56, Brian Drummond wrote:

And VHDL 2008 provides various matching operators that allow std_logic,
bit and so on to be interpreted as Boolean - see
http://www.doulos.com/knowhow/vhdl_designers_guide/vhdl_2008/vhdl_200x_ease/

If you're interested in VHDL 2008, I recommend the book "VHDL 2008 -
Just the New Stuff" by Peter Ashenden and Jim Lewis.

Indeed: highly recommended.
Now if only the tools supported ...

Again: indeed. I asked Mentor Graphics when to expect full support for VHDL
2008 in ModelSim/QuestaSim. This was their answer:
There isn't a set date/revision for full support for VHDL 2008
at this point. Some of the reasons are due ambiguity in the
spec and and the resulting work between customers and the
standards committee, and the priority/usefulness/convenience of
the still to-do features. I see some are not scheduled until
6.7 towards the end of the year and no doubt some will come
later than that.

Seems it is going to take a while....

I sent in my wish list, highest priority first:
- generic types
- generic lists in packages
- generic lists in subprograms
- generic subprograms
- local packages
- context declarations
- unconstrained element types
- signal expressions in port maps
- all signals in sensitivity list
- std_logic_1164: std_logic_vector is a subtype of std_ulogic_vector
- if and case generate
- condition operator ("??")
- matching relational operators ("?=", "?/=", "?<", ...)
- matching case statements ("case?")

The matching operators are low in the list, as I'm mainly interested in
improvements in the area of behavioral VHDL for verification
(testbenches/testcases/BFMs).
 
R

rickman

I've been using std_ulogic/std_ulogic_vector for a while...no issues
with Quartus or Synplify on the synthesis front.  

My concern is compatibility with numeric_std types. I almost never
use std_logic_vector, if for no other reason, the name is soooooo long
to type. I much prefer signed/unsigned types. I guess the real issue
is that if I am using signed/unsigned, I am using slv, not sulv... end
of story, right? Would I need to make my own library to use ulogic
based signed/unsigned types?

The main place the mixing of std_logic_vector and std_ulogic_vector
occurs is instantiating some outside widget that uses std_logic_vector
on the interface.  Once I learned that type conversions can be put
into the port map and you didn't need to create std_ulogic 'wrappers',
or use intermediate signals to connect the vectors, it all came
together rather nicely.

Example:

Inst_Some_Widget : entity work.widget
port map(
   Gazinta_slv => std_logic_vector(Gazinta_sulv),
   std_logic_vector(Gazouta_slv) => Gazouta_sulv
);

std_logic and std_ulogic can be freely assigned without any type
conversions

I know I have run into trouble with this in the past. In fact, I
thought there were some limitations in the standard, not just tool
limitations. Rather than learn to work around the limitations, I have
always used "wrapper" signals for the conversion.

Rick
 
K

KJ

I guess the real issue
is that if I am using signed/unsigned, I am using slv, not sulv... end
of story, right?

No, start of story...but it's the story of strong typing that you
object to that started this thread so I'm guessing you won't like the
story, but here it is anyway.

The definition of the types 'signed', 'unsigned', 'std_logic_vector'
and 'std_ulogic_vector' are...

type signed is array (NATURAL range <>) of std_logic;
type unsigned is array (NATURAL range <>) of std_logic;
type std_logic_vector is array ( NATURAL RANGE <>) of std_logic;
type std_ulogic_vector is array ( NATURAL RANGE <> ) of std_ulogic;

As you can see, they all have the same definition...but that doesn't
make them the same from the perspective of the language. They are
different types, none of them are subtypes of anything that is more
general.

If you have a signal or variable of any of the above types, and you
want to assign it to something of any of the other types, you will
need to do a type conversion because they are different *types* not
just different *subtypes*.

Now let's take a look at the definition of std_logic for a moment. It
is...
SUBTYPE std_logic IS resolved std_ulogic;

Since std_logic is defined as a *subtype* of the more general
std_ulogic type then you can freely assign two signals/variables
without the type conversion.

Note though that while std_logic is a subtype of std_ulogic, the
previously mentioned definition of std_ulogic_vector is NOT a subtype
of std_logic_vector. That is why std_logic and std_ulogic can be
freely assigned without type conversions, but std_logic_vector and
std_ulogic_vector can not.

I don't know why the vector versions were defined this way, and maybe
whoever decided this wishes they had done it differently, but in any
case it is the way it is...but before completely throwing in the towel
on the language itself, also recognize that the definitions of those
types are in packages that are outside of the language definition
itself. If you want to create your own types and subtypes without
this limitation, you can do so.
 Would I need to make my own library to use ulogic
based signed/unsigned types?

No.



I know I have run into trouble with this in the past.  In fact, I
thought there were some limitations in the standard, not just tool
limitations.  Rather than learn to work around the limitations, I have
always used "wrapper" signals for the conversion.

I've never had any problems with this approach. Tool limitations
though are not only a function of which tool you are using but it also
changes over time. Perhaps if you can find and dust off your example
where you thought this was a limitation of either the tool, the
standard or both you might find that it was something different. In
my case, the fact that you can put a type conversion on the left side
of the port map was my "learn something new every day" moment several
years back...and the end of any need for wrappers for conversions on
entity outputs.

Kevin Jennings
 
R

rickman

Everything snipped...

That is why I am going to take a good look at Verilog. I've been
using VHDL for some 12 years and I still don't feel like I completely
understand even basic things like how signed/unsigned relate to
std_ulogic and how closely related types... well, relate!

When you convert slv to unsigned or unsigned using unsigned(), this is
not really a conversion is it? It is not the same as using
to_integer() to convert signed to integer. In the std_numeric library
they include conversion functions between integer and signed/
unsigned. But there are no functions to convert slv and these types.
So it would seem this is not a conversion by function. So what is
it?

At one time I thought I understood all this, but it is so far removed
from getting work done that I typically adopt standard practices and
forget the details. Then when I need to figure out something new I
have to go back to basics. It just gets so time consuming. I want to
focus on the work, not the method.

Rick
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top