Creating new operators

R

rickman

In VHDL an operator can be overloaded. But can a new operator be
created? There is more than once I would like to use the very concise
notation available in Verilog such as the select operator. Is there a
way to create the selection operator in VHDL? Looking at the
structure, I guess it just doesn't fit the mold for VHDL with three
operands.

I know I can create a function for this such as select(sel,a,b), but I
like the form of the notation sel ? a : b, very clear and concise. I
guess I could always switch to Verilog... :^)

Rick
 
R

rickman

More dynamic OO languages support arbitrary operator creation; Smalltalk
would be an example, or the old Linn Lingo.

It's not VERY complicated _in_that_environment_ where static typing is
almost non-existent (strong typing can be rigorous, but implemented at
runtime) BUT ...
(1) you are limited to the creation of binary operators; so ?: is still
tricky, to put it mildly, and
(2) operator precedence is usually predetermined and deeply embedded in
the parser. The above languages solved this problem by allocating
precisely one precedence level to all operators - in other words, use
brackets.

I suspect extensible operator precedence was the main complexity in
ALGOL-68.

But anyway I suspect you'd have to destroy VHDL to add extensible
operators...


It may be personal preference, but I find if-then-else MUCH easier to
read in somebody else's code.

?: does save a few of those precious characters though.

- Brian

The problem is not so much reading the code, but is writing. I think
in the terms of the logic, usually a schematic/block diagram. Then I
try to express that logic in the language. It is not uncommon that it
is simply impossible to express the logic in the form I have drawn
it. Then I have to convolute it to come up with something that is
what I have drawn, or at least I hope so.

Example: A data mux controlled by the output of an AND of a signal and
the output of a mux. This is four control signals gated together to
drive the control on the data mux. Here is what I ended up with.

BERTEn <= '0' when BERTSel = '0' else
not SyncPOSSel when GenEn = '0' else
not GenPOSSel;

I don't think that the diagram I drew comes to mind when you see this
code. Maybe a process with an IF statement would be slightly more
clear, but the verbosity presents an obfuscation of its own from the
"clutter" created.

process ( BERTSel, SyncPOSSel, GenEn, GenPOSSel) begin
if (BERTSel = '0') then
BERTEn <= '0';
elsif (GenEn = '0') then
BERTEn <= not SyncPOSSel
else
BERTEn <= not GenPOSSel;
end if;
end process;

The clutter is from the sheer size of the code. The first three line
example is a bit obtuse, the 9 line example is large enough to make it
hard to see the rest of the code and so to see how it fits into the
big picture. Compare the two examples to this code...

BERTEn <= BERTSel and GenEn ? not SyncPOSSel : not GenPOSSel;

This is what I expect a concurrent statement to look like, not to
mention that it represents exactly the image I had in my head and on
the whiteboard, making it much easier to write.

I am sure there are those who disagree and much prefer the verbose
process. Maybe I'm just not cut out for the regimen of VHDL.

Rick
 
M

Mike Treseler

rickman said:
BERTEn <= BERTSel and GenEn ? not SyncPOSSel : not GenPOSSel;

if BERTSel and GenEn then
BERTEn <= not SyncPOSSel;
else
BERTEn <= not GenPOSSel;
end if;
 
K

KJ

..
I know I can create a function for this such as select(sel,a,b), but I
like the form of the notation sel ? a : b, very clear and concise.

This is nearly as concise and what I use.

x<= sel(Condition, a, b);

You would have to overload 'sel' to handle all the data types that you deal
with (std_(u)logic(_vector), integer, real, time, etc). These could be
written once and then put into a common package that you use with wild
abandon. More specialized types that are application specific like records
would then need similar overrides (if needed).
I
guess I could always switch to Verilog... :^)

If that's the best reason you got, then you cna have it.

KJ
 
F

Frank Buss

rickman said:
BERTEn <= BERTSel and GenEn ? not SyncPOSSel : not GenPOSSel;

This is not the same logic as you described with your initial example.
This is what I expect a concurrent statement to look like, not to
mention that it represents exactly the image I had in my head and on
the whiteboard, making it much easier to write.

What about this one:

BERTEn <= (not SyncPOSSel) when (BERTSel='1' and GenEn='1')
else (not GenPOSSel);

The parantheses are not necessary, but helps reading it.

I don't like elsif and I would write your initial example like this:

process (BERTSel, SyncPOSSel, GenEn, GenPOSSel) begin
if BERTSel = '0' then
BERTEn <= '0';
else
if GenEn = '0' then
BERTEn <= not SyncPOSSel;
else
BERTEn <= not GenPOSSel;
end if;
end if;
end process;

Some more code, but you don't have to think about when reading it, because
it shows the hierarchically structure, which is only implicit in your code.
 
R

rickman

if BERTSel and GenEn then
BERTEn <= not SyncPOSSel;
else
BERTEn <= not GenPOSSel;
end if;

One of us doesn't understand the precedence (I'm not sure which
one...). That is always a good reason for not allowing precedence
defaults to define an expression...

BERTEn <= BERTSel and (GenEn ? not SyncPOSSel : not GenPOSSel);

Is that more clear?

Rick
 
R

rickman

This is not the same logic as you described with your initial example.


What about this one:

BERTEn <= (not SyncPOSSel) when (BERTSel='1' and GenEn='1')
else (not GenPOSSel);

The parantheses are not necessary, but helps reading it.

I don't like elsif and I would write your initial example like this:

process (BERTSel, SyncPOSSel, GenEn, GenPOSSel) begin
if BERTSel = '0' then
BERTEn <= '0';
else
if GenEn = '0' then
BERTEn <= not SyncPOSSel;
else
BERTEn <= not GenPOSSel;
end if;
end if;
end process;

Some more code, but you don't have to think about when reading it, because
it shows the hierarchically structure, which is only implicit in your code.

You got the same result as Mike, so I assume I had the precedence
default wrong. No, I guess there is *no* precedence since there is no
selection operator. This is what I intended. To make it more VHDL
like, I need to add an equivalence operator too.

BERTEn <= BERTSel and ((GenEn = '1') ? not GenPOSSel : not
SyncPOSSel);

The process based description is not immediately clear to me at first
glance. I *do* have to think about it since that is not what I
picture in my mind. I visualize a MUX controlled by GenEn feeding an
AND gate with BERTSel. The Verilog like assignment maps exactly to
that visualization. The others require me to mentally convert the
syntax from and IF statement to the AND gate not to mention the length
of the code. But like I said, it is not that this is hard to
understand, it is not what I pictured in my mind and so I had to
perform a conversion from the logic to the syntax. That takes time
and is a distraction from making my work accurate.

I have no doubt that others may find that verbose code is easier for
them to read. But I find concise code is best (but not too!
concise). There are any number of different logic forms to be
expressed and each is expressed best in different ways. I think the
selection statement is an operator that has a useful place in VHDL.
I'm just sorry it wasn't included. I guess it would have been hard to
provide for overloading since it does not fit the standard uniary or
binary format.

Rick
 
R

rickman

So why do you not use schematic capture tools for your designs - or is that
too uncool?

Icky

Is this a serious question? Or are you just playing devil's
advocate?

Probably the single biggest reason to use an HDL instead of schematics
is the portability it provides. Schematics have always locked you
into a manufacturer unless you are willing to reenter your design for
every company's chips you wish to try.

But I was a diehard on schematics. Just like Ray Andraka, I saw a lot
of utility in them. He finally switched when he found that he could
instantiate primitives and achieve the same degree of control over the
design details that he got with schematics. I switched when I found
out how handy it was to have text based designs instead of proprietary
formatted schematics. But there are any number of other reasons. Do
you really not understand what they are? I don't think I ever
considered schematics "uncool". In fact, one of the cooler things
about being an engineer is having an E sized print of a schematic
design hanging on your wall.

Rick
 
F

Frank Buss

Icky said:
If you are making the best use of the internal FPGA resources an HDL cannot
give you portability, as soon as you instantiate a higher level hardware
function integrated into the device (I am specifically talking DSP/SERDES
type integration here) you are straight away locked into an vendor.

You can encapsulate vendor specific hardware functions in different
entieties in VHDL. I've seen this e.g. for memory on OpenCores projects,
which works for Altera and Xilinx without needing to change the main VHDL
entities.
 
P

Paul Taylor

BERTEn <= BERTSel and GenEn ? not SyncPOSSel : not GenPOSSel;

This is what I expect a concurrent statement to look like, not to
mention that it represents exactly the image I had in my head and on
the whiteboard, making it much easier to write.

I am sure there are those who disagree and much prefer the verbose
process. Maybe I'm just not cut out for the regimen of VHDL.

I'm not _entirely_ cut out for the regimen of VHDL, which is why I have
the imaginary BerryHDL which is considerably more terse than VHDL, eg:

http://myweb.tiscali.co.uk/pault/example.html

The main thrust of it is to represent schematic type blocks efficiently
with text. A general mux is as follows:

node muxOutput = [a, b, c, d][sel];

That's a mux with four inputs. Your example would be:

node BERTEn = BERTSel & [!GenPOSSel, !SyncPOSSel][GenEn];

Which I think is better than a ternary type operator.

Doesn't python allow you to do something like that? You may find that
MyHDL will do something similar to the above? And MyHDL isn't imaginary.

Regards,

Paul.
 
M

Mike Treseler

Jonathan said:
Somehow I don't see the original designers of VHDL
expecting you to do _anything_ in VHDL with "wild
abandon". Politely and thoughtfully, and preferably
with tea taken from fine bone china cups, is nearer
the mark.

In Seattle, it's French roast coffee ground fine,
but not fine enough to fit through the filter mesh.
China cups are much too small for long coding sessions.
"Wild abandon" is for Verilog users who,
as we all know, have more facial hair than VHDL
programmers, and lifestyles less constrained by
conventional civilities.

Sounds like Red Bull, no tea cup ;)

-- Mike Treseler
 
M

Mike Treseler

rickman said:
BERTEn <= BERTSel and (GenEn ? not SyncPOSSel : not GenPOSSel);

Is that more clear?

Yes.
In any case, I agree with KJ on this one.
Take it out of time with a function:

function sel (choice : boolean;
a, b : std_logic_vector)
return std_logic_vector is
begin
if choice then return a; else return b; end if;
end function sel;


-- Mike Treseler
 
D

diogratia

On Jul 26, 7:56 am, Brian Drummond <[email protected]>
wrote:
BERTEn <= '0' when BERTSel = '0' else
not SyncPOSSel when GenEn = '0' else
not GenPOSSel;

I don't think that the diagram I drew comes to mind when you see this
code. Maybe a process with an IF statement would be slightly more
clear, but the verbosity presents an obfuscation of its own from the
"clutter" created.

process ( BERTSel, SyncPOSSel, GenEn, GenPOSSel) begin
if (BERTSel = '0') then
BERTEn <= '0';
elsif (GenEn = '0') then
BERTEn <= not SyncPOSSel
else
BERTEn <= not GenPOSSel;
end if;
end process;

The clutter is from the sheer size of the code. The first three line
example is a bit obtuse, the 9 line example is large enough to make it
hard to see the rest of the code and so to see how it fits into the
big picture. Compare the two examples to this code...

BERTEn <= BERTSel and GenEn ? not SyncPOSSel : not GenPOSSel;

This is what I expect a concurrent statement to look like, not to
mention that it represents exactly the image I had in my head and on
the whiteboard, making it much easier to write.

There's also combinatoric expression in a concurrent statement:

BERTEn <= (BERTSel and not GenEN and not SyncPOSSel) or
(BERTSel and GenEN and not GenPOSSel );

This also shows it's a two input multiplexer with a select line and an
enable, which you could do as a block statement, component or
subprogram and invoke like a component or subprogram.

Seriously, you can always write a preprocessor that recognizes your
preferred syntax and translates it into correct VHDL for analysis.
Some of us are old enough to remember WATFOR and the like, adding
things like case statements to Fortran.

A preprocessor for the above preferred syntax could recognize a
concurrent signal assigment with a right hand side containing '?' and
':' in matching numbers..The associativity precedence can be a right
royal pain, requiring lookahead or recursion.

For full integration with a tool environment you might need to write
an analyzer wrapper that invokes the preprocessor, as is done for
cpp. In and environment where you can use make files, you can hide
the complexity there.

Instant language syntax extensions.
 
C

Colin Paul Gloster

On Sun, 27 Jul 2008, diogratia wrote:

|------------------------------------------------------------------------|
|"[..] |
| |
|Seriously, you can always write a preprocessor that recognizes your |
|preferred syntax and translates it into correct VHDL for analysis. |
|Some of us are old enough to remember WATFOR and the like, adding |
|things like case statements to Fortran. |
| |
|A preprocessor for the above preferred syntax could recognize a |
|concurrent signal assigment with a right hand side containing '?' and |
|':' in matching numbers..The associativity precedence can be a right |
|royal pain, requiring lookahead or recursion. |
| |
|For full integration with a tool environment you might need to write |
|an analyzer wrapper that invokes the preprocessor, as is done for |
|cpp. In and environment where you can use make files, you can hide |
|the complexity there. |
| |
|Instant language syntax extensions." |
|------------------------------------------------------------------------|

I would prefer to use one tool which supports the language I am using
instead of a preprocessor which supports some of it by replacing
strings by other strings to be given to another tool which tries to
cope with another part of the language.

Would you suggest that someone who does not want to use such a
preprocessor should write an entire extended language frontend
(perhaps written by reusing code from a full proper BNF-based VHDL
frontend)?
 
C

Colin Paul Gloster

On Sat, 26 Jul 2008, Brian Drummond wrote:

|------------------------------------------------------------------------|
|"On Sat, 26 Jul 2008 10:31:32 +0100, Jonathan Bromley |
| |
|>On Fri, 25 Jul 2008 22:46:26 -0700 (PDT), rickman wrote: |
|> |
|>>In VHDL an operator can be overloaded. But can a new operator be |
|>>created? There is more than once I would like to use the very concise|
|>>notation available in Verilog such as the select operator. Is there a|
|>>way to create the selection operator in VHDL? Looking at the |
|>>structure, I guess it just doesn't fit the mold for VHDL with three |
|>>operands. |
|> |
|>No, you can't create new VHDL operators. Apart from |
|>introducing new pseudo-keywords into the language, this would |
|>also raise the nasty difficulty that operators have many other |
|>hidden properties apart from their function signature. |
|>Operators have precedence and associativity. And of course, |
|>as you say, VHDL has no notion of 3-ary operators like ?: |
|>in any case. |
|> |
|>Algol-68 tried to make it possible to create arbitrary |
|>user-defined operators, and it was VERY complicated... |
| |
|More dynamic OO languages support arbitrary operator creation; Smalltalk|
|would be an example, or the old Linn Lingo. |
| |
|It's not VERY complicated _in_that_environment_ where static typing is |
|almost non-existent (strong typing can be rigorous, but implemented at |
|runtime)" |
|------------------------------------------------------------------------|

Dynamic strong typing instead of static strong typing is not very
useful. Smalltalk programs crash. Lisp programs crash. Statically
typed programs also crash, but are less prone to having their crashes
caused by things which could have been detected during compilation.

|------------------------------------------------------------------------|
|" BUT ... |
|(1) you are limited to the creation of binary operators; so ?: is still |
|tricky, to put it mildly, and" |
|------------------------------------------------------------------------|

I do not remember whether this is true with PROLOG.

|------------------------------------------------------------------------|
|"(2) operator precedence is usually predetermined and deeply embedded in|
|the parser." |
|------------------------------------------------------------------------|

In Prolog one can choose any precedence and any location (viz. prefix;
infix; and postfix) and probably (but I do not remember for sure) any
associativity for user-defined operators (and even worse, allows these
to be redefined for standard operators).

|------------------------------------------------------------------------|
|" The above languages solved this problem by allocating |
|precisely one precedence level to all operators - in other words, use |
|brackets." |
|------------------------------------------------------------------------|

A good choice. Operators which are otherwise identical have different
precedences in different languages so people shall make mistakes
according to what they are used to.

|------------------------------------------------------------------------|
|"[..] |
| |
|But anyway I suspect you'd have to destroy VHDL to add extensible |
|operators... |
| |
|[..]" |
|------------------------------------------------------------------------|

I do not approve of user-defined operators. Operators at all are
debatable. Functions or conditional statements should be enough.

Thank you for the interesting observations.

Regards,
Colin Paul Gloster
 
D

diogratia

I would prefer to use one tool which supports the language I am using
instead of a preprocessor which supports some of it by replacing
strings by other strings to be given to another tool which tries to
cope with another part of the language.

Would you suggest that someone who does not want to use such a
preprocessor should write an entire extended language frontend
(perhaps written by reusing code from a full proper BNF-based VHDL
frontend)?

Mr. Rickman expressed concern from a language point of view in terms
of syntax more directly modeling his ideal representation not being
present in VHDL, not whether or not he was willing to use a
preprocessor.

The BNF for VHDL 93 for instance, isn't semantically complete, nor is
it non-ambiguous. You actually have to understand the language to
contemplate making changes to it, and the BNF isn't sufficient. It
seems a bit overkill to start anew then replicate most of VHDL.

A preprocessor sufficient for Mr. Rickman's preferred concurrent
assignment statement form could easily be written in a small AWK or
Perl script, passing through elements of a source file not affected.
You'd probably be well served maintaining line count between the two
versions, making VHDL a bit more ugly.

You could also conceivably translate to your preferred syntax from
VHDL in an editor like emacs or joe, write in your preferred syntax
abstraction and store the file in VHDL. It would be embarrassing to
stumble over understanding VHDL in printed form. The question is
whether or not someone else could read it comfortably if you did the
obverse and made the extended version normative. The point being that
in Domain Specific Language, no two domains have perfect
intersections, and somewhere, someone is making a compromise.

The idea of using a preprocessor was meant as a gauge of how serious
Mr. Rickman was for his syntax, a way of actually implementing it
without breaking anything, using a method shared with the first C++
implementation.

--
“Blindness can take many forms other than the inability to see.
Fanatics are often blinded in their thoughts. Leaders are often
blinded in their hearts.”
 
R

rickman

This may be a cheap shot, but I think it's telling that, even in the
presence of a clear text specification ...>Example: A data mux controlled by the output of an AND of a signal and

and a correct VHDL description...


... the one-line Verilog implementation is either wrong, or confusing to
several industry experts! (I don't know which; I'm definitely not cut
out for Verilog)

But it is *not* a Verilog implementation. It is VHDL with a new
construct thrown in. The error (btw, who made the error???) is
because this is not a defined function and since I didn't use
parenthesis, it was open to interpretation with no guidelines. If you
really think that the cause of the misinterpretation by one of us
shows it is a poor construct, then you deserve the verbosity of
VHDL.

A language does not need to protect you from yourself if you are any
good. I realized a long time ago that computer tools were initially
designed for computer designers. But there aren't enough good
designers to go around. So the tools were dumbed down so that the
masses could use them. I don't agree that this is even needed. What
is needed is a bit of education in how to write code that is not hard
to debug and then getting people to use those principles as well as
the principles of good test techniques.

The bottom line is that I don't need to turn a one line statement into
a 9 line program in order to make its meaning clear.

I don't believe this was a deliberate plot on Jonathan's or Mike's part
to diss Verilog, but YMMV.


If you mean the brevity rather than the form, I actually agree, though
as written I couldn't tell you what it does. (Rewritten with
parentheses, I could figure it out eventually)

Eventually??? It has two operators. One maps exactly to a mux and
the other maps exactly to an AND gate. Why would that take more than
a second to understand???
___
|\ ---| \
---| \ | |------
| |----------|__/
---| /
|/

Why would it be hard to translate the code into this diagram?
(assuming that you can view the diagram in a non-proportional font)?
But I don't see what's wrong with

BERTEn <= BERTSel and ( not SyncPOSSel when GenEn = '1'
else not GenPOSSel);
which I believe does the same thing.

Are you sure that this is valid syntax? I was under the impression
that a conditional signal assignment was just that, an assignment, not
an expression to be mixed in with other expressions. I can't get the
Active-HDL compiler to accept it. Did I mess it up or does this not
work?

I guess that is the difference between the VHDL construct and the
selection operator. The selection operator is an expression and the
VHDL construct is an assignment not to be mixed with other
expressions.

Rick
 
A

Andy

A language does not need to protect you from yourself if you are any
good. I realized a long time ago that computer tools were initially
designed for computer designers. But there aren't enough good
designers to go around. So the tools were dumbed down so that the
masses could use them. I don't agree that this is even needed. What
is needed is a bit of education in how to write code that is not hard
to debug and then getting people to use those principles as well as
the principles of good test techniques.

Rick

If you're so in love with Verilog's capabilities, use verilog.

The rest of us, who are apparently not any good since we prefer a
strong language like VHDL, will continue to use VHDL.

BTW, just in case you want to risk taking our inferior advice, if you
are dead set on a more concise notation in currently legal vhdl, then
create an array type indexed by boolean (or std_logic). Then create a
signal/variable and assign the two elements appropriately. Now you can
implement your concise expression by indexing the array with your
selection expression.

Andy
 
N

Nico Coesel

rickman said:
The problem is not so much reading the code, but is writing. I think
in the terms of the logic, usually a schematic/block diagram. Then I
try to express that logic in the language. It is not uncommon that it
is simply impossible to express the logic in the form I have drawn
it. Then I have to convolute it to come up with something that is
what I have drawn, or at least I hope so.

I don't think drawing logic is a good way to start. Using flow charts
usually leads to more simple solutions because it is easier for a
human to optimize a flow chart than a bunch of logic symbols.
Example: A data mux controlled by the output of an AND of a signal and
the output of a mux. This is four control signals gated together to
drive the control on the data mux. Here is what I ended up with.

BERTEn <= '0' when BERTSel = '0' else
not SyncPOSSel when GenEn = '0' else
not GenPOSSel;

I don't think that the diagram I drew comes to mind when you see this
code. Maybe a process with an IF statement would be slightly more
clear, but the verbosity presents an obfuscation of its own from the
"clutter" created.

process ( BERTSel, SyncPOSSel, GenEn, GenPOSSel) begin
if (BERTSel = '0') then
BERTEn <= '0';
elsif (GenEn = '0') then
BERTEn <= not SyncPOSSel
else
BERTEn <= not GenPOSSel;
end if;
end process;

The clutter is from the sheer size of the code. The first three line
example is a bit obtuse, the 9 line example is large enough to make it
hard to see the rest of the code and so to see how it fits into the
big picture. Compare the two examples to this code...

BERTEn <= BERTSel and GenEn ? not SyncPOSSel : not GenPOSSel;

This construction wouldn't be very clear for people that are
relatively new to a programming language. I'd try to avoid it.

How about:

process ( BERTSel, SyncPOSSel, GenEn, GenPOSSel) begin
if (BETRSel and Genen)='0' then
BERTEn <= not SyncPOSSel
else
BERTEn <= not GenPOSSel;
end if;
end process;

The code above makes perfectly clear what you are doing. Besides, I
doubt your examples are describing the same logic.
This is what I expect a concurrent statement to look like, not to
mention that it represents exactly the image I had in my head and on
the whiteboard, making it much easier to write.

I am sure there are those who disagree and much prefer the verbose
process. Maybe I'm just not cut out for the regimen of VHDL.

I see your point and I agree. I would like to write my programmable
logic in C as well. Neither VHDL or Verilog are easy to use.

Yet, you could run your VHDL code through a C pre-processor. This
would allow macro substitution.
 
M

Mike Treseler

Nico said:
This construction wouldn't be very clear for people that are
relatively new to a programming language. I'd try to avoid it.

How about:

process ( BERTSel, SyncPOSSel, GenEn, GenPOSSel) begin
if (BETRSel and Genen)='0' then
BERTEn <= not SyncPOSSel
else
BERTEn <= not GenPOSSel;
end if;
end process;

Thread recursion has begun,
and there may be no exit condition ;)

-- Mike Treseler
 

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,777
Messages
2,569,604
Members
45,227
Latest member
Daniella65

Latest Threads

Top