New keyword 'orif' and its implications

J

Jonathan Bromley

<snip>
You did kind of the bait and switch on this one without really addressing
the question posed....what is the problem that Weng is trying to solve?

I thought/hoped that I had been fairly clear about that:
A situation in which knowledge of the dynamic, runtime
behaviour of a design is required in order to optimize
it effectively in hardware. The classic example (which,
it must be said, can easily be handled in other ways) is
the conversion of a one-hot coded bus to a binary
representation. Problems such as CPU instruction decoders
often lead to other, less straightforward examples.
Ummm.....like what? Certainly not Weng's outbus example. That one is best
coded by writing it in a sum of products form, but Weng dismisses that as
being the equivalent of assembler whereas the 'orif' is a high level
construct which is completely wrong. Other cases that have been brought up
can be handled by properly reformulating the problem using enumerated types.

I agree. It is often rather hard to capture the problem in the
form of an easily digestible example. Consequently,
advocates for such things commonly fall back on simple
examples; this stratagem is fatally flawed, because folk
like you can easily see how the simple problem can be
solved in a more elegant way.
From what I can tell, the only problem that 'orif' solves is how to
structure something into an 'if' statement instead of using other clearly
understandable statements that are already part of the language. Much like
the person who owns a hammer sees every problem as a nail, Weng sees the
'if' statement as his hammer but finds it somewhat deficient in that he
needs a modified one (one with an 'orif') to tackle a problem that has no
nail.

I have already pointed out that I regard Weng's "orif" formulation
as both flawed and inadequate. That doesn't mean that the problem
he's trying to tackle is irrelevant.
If you already have the complete logic description (which is encoded in all
of the 'non-assert' statements) the synthesis tool will not really have much
use for these unverifiable asserts that purport to give this supposedly
'higher level' information.

Sorry, this is nonsense. Synthesis tools generally cannot see
outside the boundary of the module they're currently compiling.
Suppose you have two quite independent modules, communicating
over a flat 32-bit data bus. Suppose, what's more, that there
is a "fetch" signal emitted by one module and received by the
other; and when this "fetch" signal is asserted, the source
module reliably produces an instruction code that is one-hot
coded. How can the destination (receiving) module's VHDL
code possibly capture that knowledge? - knowledge that is
very valuable for optimising the instruction decode logic.

In any case, the idea of an "unverifiable" assertion is surely
absurd. The whole point of assertions is that they continually
monitor the data whose properties they check; long after the
assertion's author has forgotten why he put it there, the
assertion continues to contribute to the verification effort.
Just what should happen if the logic
description says one thing but the assertion claim another...and the
supposedly impossible thing happens (i.e. the 'assert' fires)?

Then your verification effort correctly shows that you have made
unjustified assumptions that you must review. That's the whole
point: by capturing *in a single language construct* both an
assumption that you're making about runtime behaviour, and a
permission to the synthesis tool to share that assumption,
you have a safe way to capture knowledge of a system's
expected behaviour that cannot be described any other way.
Many times with uncontorted code as well....like the sum of products
solution to the outbus example.

Indeed so. Often there is a simple solution that
merely needs to be revealed and added to the folklore.
So we agree that the enumeration type solves the one class of mutual
exclusiveness. But I'm still waiting for the example of this 'common'
problem for which 'orif' is the solution.

OK, I promise I'll try to find some more compelling examples.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
K

KJ

The better method to distinguish orif from elsif and that will
ultimately fend off any future tough questions about it is to put the
two keywords in two keyword listing tables in text editor's file and
they will be shown in two different colors, one RED, another PINK, as
TextPad, Emac, or any text editors do without conventional indent
practise change. It is a trivial thing, but exaggerated to a
disadvantage and failure at a strategic level.

Wow....now you're suggesting color coding as a method to handle your
ambiguities?

process (reset, clk) is
begin
if reset = '1' then
outbus <= (others => '0');
elsif rising_edge(clk) then
for i in e'range loop
if e(i) = '1' then
outbus <= data(i);
exit;
end if;
end loop;
assert zero_one_hot(e); <-- useless and just waisting time !!!
end if;
end process;


With your above coding, it seems to me that you don't have a deep
insight why VHDL needs a mechanism to transfer mutually exclusive
information to VHDL compiler, neither does Jim.

You haven't demonstrated your insight either...but that's my opinion.
With your coding, it doesn't need to provide the information the
assertion provides. It is a well known popular practise before
introducing mutually exclusiveness.
I agree..almost. Sometimes you'll put in these assertions to check the code
you just wrote not so much as a check on what you've just written but as a
check down the road when the code gets modified for whatever reason and the
modifier is maybe unaware of why their change will cause a problem down the
road. A well crafted 'report' after the 'assert' will explain why it is
important and more importantly it will be in 'live code' that actually gets
checked, not in a comment where it is not.

In any case, the assert that was added can be considered a simulation time
waster or info from a maintability standpoint.

Andy's code does not assume mutual exclusiveness it is a priority encoding
to produce outbus.
VHDL COMPILERS NEED MUTUALLY EXCLUSIVE INFORMATION IN ORDER TO KEEP
'IF...END IF' STATEMENT STRUCTURE UNIQUITOUS AND MAKE IT POSSIBLE
WRITING HARDWARE IS JUST LIKE WRITING SOFTWARE C (all if statement
when writing software).

That's your 2 cents about what you think compilers need. Do you have ANY
references or evidence to back up that claim? If not, stop shouting it.
We provide EXTRA mutually exclusive information to VHDL compiler and
let the compiler do better job with the "if...end if" statement
structure than what you and we have traditionally done. Because
"if...end if" statements are the simplest and unified way to express
logic ideas. Any advantages current hardware writing style (shown as
in your code) would dissapear and become unnecessary if mutually
exclusive information is given.

Personally I prefer enumerated types to express mutual exclusiveness where
appropriate and sum of products formation (as shown in Jim's example that
you've posted below a bit) where there are things that 'should' be mutually
exclusive but can not be formally shown to be. There are other constructs
besides the 'if' statement that are quite understandable; your assertion
that 'if...endif' is the 'simplest and unified way' represents your opinion
not some grand truth. The fact that you think that it needs to be augmented
with a new 'orif' keyword suggests that the 'if' statement is not quite so
unified after all.
Why the above statement is waistful? You have already written the code
with the knowledge how it behaves and adding the assertion statement
just let simulator waisting time to do what you and I never do it
before. No assertion statement in your code works well and nobody adds
the assertion statements to confirm it now.

I agree, but as mentioned before, the assert statement with a descriptive
report allows for passing of obscure design information from one design time
to another...sort of a 'heads up' for the designer picking up the code 1
year down the road.
3. My opinion is when VHDL compilers get more information about
mutually
exclusive information, what you can do, the VHDL compilers can do
better.

And they generally do. Looking at the technology map view of synthesized
code is generally enlightening. In any case, your opinioin has not yet been
substantiated in fact with anything you've posted so far.
VHDL compilers can generate all coding you showed for one level of
mutually exclusiveness. You may not write efficiently for code with
two levels or even three levels of mutually exclusiveness. Personal
power is limited and VHDL compilers can be trained to do more
mechanical things better than any human.
What do you mean my 'two levels' or 'three levels' of mutual exclusiveness?
-- It is Jim's coding
OutBusA : process(RESET, CLK)
begin
if(RESET = '1') then
OutBus <= (others=>'0');
elsif rising_edge(CLK) then
if (E0 or E1 or E2 or E3 or E4 or E5) = '1' then
OutBus <=
(E0 and Data0) or (E1 and Data1) or (E2 and Data2) or
(E3 and Data3) or (E4 and Data4) or (E5 and Data5) ;
end if ;
end if ;
end process;


-- It is my coding
A : process(RESET, CLK)
begin
if(RESET = '1') then
OutBus <= (others=>'0');
elsif rising_edge(CLK) then
if(E0 = '1') then
OutBus <= Data0;
orif(E1 = '1') then
OutBus <= Data1;
orif(E2 = '1') then
OutBus <= Data2;
orif(E3 = '1') then
OutBus <= Data3;
orif(E4 = '1') then
OutBus <= Data4;
orif(E5 = '1') then
OutBus <= Data5;
else
OutBus <= OutBus;
end if;
end if;
end process;


The above equation would be implemented in Xilinx chip with carry
chain with initial input data to the carry chain being OutBus. The
following enable equation would be eliminated from Jim's coding:
(E0 or E1 or E2 or E3 or E4 or E5) = '1'
I don't think so, unless you assume the various 'E' are one hot encoded.
Had Jim made that assumption he would have written it without the "if (E0 or
E1 or E2 or E3 or E4 or E5) = '1'" as well I'm sure. In any case, as
written, Jim's handles the case where none of the 'E' happen to be set.
Whether or not this is appropriate depends on what assumptions there are
with 'E'; personally I would think that the condition where none is set is
probably the more common case when bringing together various external
signals and trying to say that they are in some sense mutually exclusive.
It is not a LUT or two saving as some suggesed. For a up to 400MHz
project, every extra logic would kill a design. Because it takes more
route resources. When route resources exhausted, the running
frequency would drop dramatically and would kill a otherwise successfu
design.
LUT is less than a cent in a FPGA.

But you've presented nothing to indicate that 'orif' would map to anything
different. In fact, you can not. The rules of boolean logic require only
'and', 'or' and 'not', they do not require 'orif'. You claim (but present
no evidence) that the new 'orif' keyword could in some cases present some
resource or timing improvement but you have no basis for that claim and
nothing at all to back it up. Looking at source code examples and
suggesting that it would improve anything is naive at best.

The only claim you could possibly make is that 'orif' is a productivity
enhancer perhaps because it is fewer lines of code (but by perusing Andy,
Jim and your code it would seem that 'orif' is the longest) or because it is
less error prone in use (doesn't appear to be).

In case you're interested, Andy's version consumes 9 logic elements and has
four levels of logic; Jim's version consumes 6 logic elements and has three
levels of logic. The difference comes about because Jim's version take full
advantage of the supposed knowledge that the data inputs are all mutually
exclusive whereas Andy's makes no such assumption. These were benchmarked
using Quartus targetting a Cyclone II which has 4 input LUTs as the logic
primitive. Code I used posted at the end of this posting.
5. orif or other similar spelling OIF, _ORIF, is not replacable with
assertion function.

Actually that's a good thing about 'orif'. Logic should be described by
logic functions not assertions. Those that are proposing using assertions
to drive the synthesized code in some fashion are barking up a bad
tree....what happens when the supposedly impossible happens and the asserted
condition is no longer met? What will the synthesized result produce? It
better be what is described in the logic description which therefore implies
that the asserted statements really should be ignored during synthesis for
the purposes of optomizing any logic functions.
6, My another keyword method: Exclusive(or other name, no problem).

Here is an example how Exclusive is used:

signal A : unsigned(5 downto 0) ; -- to store mutually exclusive data

Exclusive : (A); -- it indicates that signal A of its bits is mutually
exclusive.
What guarantees the exclusiveness? The engineer's code of honor? If it is
reeeeeally mutually exclusive it could be described by an enumerated type.
Exclusive : (StateRead, StateWrite); -- indicate two state machines
are mutually exclusive with their intial states being common. This
function extends mutually exclusive funtion to more than 2 state
machines.

Kind of looks like an enumerated type definition too....hmmm
If you need, I can send my paper to you: "HDL Code Inefficiency
Sources and Its Solutions".

Jim,

I am going to publish 6 articles in a batch within next 6 months in
one of three forms: websites, patent applications or international
conferences. One of them has a very good example how 'orif' is used, a
brand new usage. No special report to you is under consideration until
you are pursuaded in advance. You may have to wait for next 6 months
to get the files.
Hopefully you'll present actual results to back up your so far baseless
claims, it would make for a much stronger case for 'orif'. Good luck with
your work.

KJ

Jim and Andy's versions implemented below. Uncomment out the one you'd like
to synthesize with. By the way, Jim, Andy and Weng's code as presented in
this thread are all flawed and not compilable. In some cases, 'outbus' is
treated as a vector, in others it is treated as a single bit. I modified
each so that 'outbus' is a single bit which appears to be the real intent
here....apologies if it's not.

--------- CODE USED TO IMPLEMENT ANDY AND JIM'S VERSION ----------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity test is
port (
clk: in std_ulogic;
reset: in std_ulogic;
e: in std_ulogic_vector(7 downto 0);
data: in std_ulogic_vector(7 downto 0);
outbus: out std_ulogic);
end entity test;

architecture rtl of test is
begin
-- Andy's code
-- process (reset, clk) is
-- begin
-- if reset = '1' then
-- outbus <= '0';
-- elsif rising_edge(clk) then
-- for i in e'range loop
-- if e(i) = '1' then
-- outbus <= data(i);
-- exit;
-- end if;
-- end loop;
-- -- assert zero_one_hot(e); -- useless and just waisting time !!!
-- end if;
-- end process;

-- It is Jim's coding
OutBusA : process(RESET, CLK)
begin
if(RESET = '1') then
OutBus <= '0';
elsif rising_edge(CLK) then
if (E(0) or E(1) or E(2) or E(3) or E(4) or E(5)) = '1' then
OutBus <=
(E(0) and Data(0)) or (E(1) and Data(1)) or (E(2) and Data(2)) or
(E(3) and Data(3)) or (E(4) and Data(4)) or (E(5) and Data(5)) ;
end if ;
end if ;
end process;

end architecture rtl;
--------- END CODE USED TO IMPLEMENT ANDY AND JIM'S VERSION ----------
 
K

KJ

I agree. It is often rather hard to capture the problem in the
form of an easily digestible example. Consequently,
advocates for such things commonly fall back on simple
examples; this stratagem is fatally flawed, because folk
like you can easily see how the simple problem can be
solved in a more elegant way.
And we end up in the situation where one person is claiming superiority of a
new solution to an unstated problem or making unfounded claims. This thread
has droned on for a bit and Michael asked a very straightforward question
about just what problem is being solved in the OP?
I have already pointed out that I regard Weng's "orif" formulation
as both flawed and inadequate. That doesn't mean that the problem
he's trying to tackle is irrelevant.
Or that it hasn't been tackled already.
Sorry, this is nonsense. Synthesis tools generally cannot see
outside the boundary of the module they're currently compiling.

Which optomization boundary are you talking about? The entity? I see cross
entity optomizations all the time. A trivial example that most here can
probably relate to is when you don't connect an entity input correctly or
don't connect the outputs to anything and you run it through and find the
whole entity has been optomized out. How do you explain that behaviour if
the entity represents any sort of actual optomization boundary.
Suppose you have two quite independent modules, communicating
over a flat 32-bit data bus. Suppose, what's more, that there
is a "fetch" signal emitted by one module and received by the
other; and when this "fetch" signal is asserted, the source
module reliably produces an instruction code that is one-hot
coded. How can the destination (receiving) module's VHDL
code possibly capture that knowledge? - knowledge that is
very valuable for optimising the instruction decode logic.

Here's two (assuming that we're living all within one FPGA/Asic design)
1. If the data bus is a point to point connection, then don't use a flat 32
bit bus, but use an enumerated type to pass the data between the modules.
2. If modules must use std_logic_vector busses to communicate (like if you
use Wishbone or Avalon, etc. as your preferred way to stitch together
modules) then an enumerated type coupled with a 'To_Std_Logic_Vector' and a
'From_Std_Logic_Vector' function.

I haven't run into any lack of optomization across the entity boundaries
when I've done either of the above and it makes for very concise and easily
maintainable code. Not only that but the mutual exclusivity (if that's a
word ;) is directly coded it's not an assumption that may or may not be
guaranteed, new things can easily be added/subtracted from the list, blah,
blah, blah....in other words enumerated types are the solution to this one.

Optomizations (or lack thereof) could be a tool dependent issue though but I
haven't run across it to be a problem with Quartus or Synplify.

If the two modules are in different physical parts and the bus is a device
I/O then I think it would be totally inappropriate to have any code that
assumes that the PCBA and the solder connections and such would feel bound
by the idea of any sort of mutual exclusion which is why my two examples are
within the constraints of being inside one physical device.
In any case, the idea of an "unverifiable" assertion is surely
absurd. The whole point of assertions is that they continually
monitor the data whose properties they check; long after the
assertion's author has forgotten why he put it there, the
assertion continues to contribute to the verification effort.
In simulation yes. If the synthesized logic is somehow 'different' because
of the inclusion or not of the assert statement in the source code then how
does the physical part behave when the asserted condition fails? That was
my basic point. I would expect it to behave as defined by the the logic
description completely.

Having synthesis check assertions that are statically determined things is
appropriate. Dynamically though? Not convinced that it could or even
should attempt this.
Then your verification effort correctly shows that you have made
unjustified assumptions that you must review. That's the whole
point: by capturing *in a single language construct* both an
assumption that you're making about runtime behaviour, and a
permission to the synthesis tool to share that assumption,
you have a safe way to capture knowledge of a system's
expected behaviour that cannot be described any other way.

The logic function though is described though by the logic that is written
not by the assert. Maybe we're not understanding what the other is saying
on this particular point though..
Indeed so. Often there is a simple solution that
merely needs to be revealed and added to the folklore.

Definitely agree...that's one good thing about newsgroups. Not every day do
you get a useful nugget, but often enough you do.
OK, I promise I'll try to find some more compelling examples.

Look forward to it....but I'm guessing that there may be better things to
do.

KJ
 
M

Marcus Harnisch

Hi KJ

KJ said:
2. If modules must use std_logic_vector busses to communicate (like if you
use Wishbone or Avalon, etc. as your preferred way to stitch together
modules) then an enumerated type coupled with a 'To_Std_Logic_Vector' and a
'From_Std_Logic_Vector' function.

That way you will shift the issue (given that there be any) to a
different stage. What about the supposed if/else construct in
'From_Std_Logic_Vector'? Again, how's synthesis to know that the input
parameter is *always* -- say -- one-hot? You could of course use an
enumerated type to work around that...
In simulation yes. If the synthesized logic is somehow 'different' because
of the inclusion or not of the assert statement in the source code then how
does the physical part behave when the asserted condition fails? That was
my basic point. I would expect it to behave as defined by the the logic
description completely.

Having synthesis check assertions that are statically determined things is
appropriate. Dynamically though? Not convinced that it could or even
should attempt this.

What about formal verification?
The logic function though is described though by the logic that is written
not by the assert. Maybe we're not understanding what the other is saying
on this particular point though..

That's why an assertion is not appropriate for that particular
purpose. A language feature that is very similar to an assertion but
not quite the same.

What about attributes? I think these are totally underused in VHDL. I
guess the fact that their point of declaration is normally not very
close to the place where they'd be used later on, doesn't really make
them very popular. Emacs' vhdl-mode could solve that (if it doesn't
already) by displaying attribute values for the current language
construct.

Regards,
Marcus
 
K

KJ

Hi KJ



That way you will shift the issue (given that there be any) to a
different stage. What about the supposed if/else construct in
'From_Std_Logic_Vector'? Again, how's synthesis to know that the input
parameter is *always* -- say -- one-hot? You could of course use an
enumerated type to work around that...

The to/from std_logic_vector functions would convert the enumerated
type to/from std_logic_vectors simply for communicating over the
presumed 32 bit data bus. There would be no need for any if
statements in either of these functions. The encoding and decoding
functions can be lots of things but they could simply be a one hot
coding of the enumeration list or a binary coding or whatever.
Synthesis unrolls the functions and the net result of converting an
enumerated type to a std_logic_vector and then back to an enumerated
type on the other end is zero logic cells (as it should be since the
one function is the inverse of the other)....and yes it really does do
this with real tools, not just an academic 'well it should do this'.

KJ
 
A

Andy

P.S.: Here is another coding style, assuming the inputs and Es are in
arrays:

output := (others =>'-'); -- this line allows the compiler to do the
optimization, most compilers DECIDE against it
for i in input'range loop
if e = (i=>'1', others=>'0') then output := intput(i);
end loop;

if you know the optimization and want to force it:
for i in input'range loop
if e(i) = '1' then output := output or intput(i);
end loop;

In the (Jim's?) original example, the output was unchanged if no
enable bits were set. Therefore the additional check on e1 or e2 or
e3... is necessary to make sure that only if any enable bit is set
does the output get a new value.

An initial assignment to (others => '-') only takes care of the case
if no enables are set. The order of execution of the loop provides
priority coding, in that the rightmost bit of enable that is set will
win (in the first example), no matter how many are set.

Andy
 
A

Andy

3. I know nothing about PSL and just printed VHDL-1993 and VHDL-2002
today and started reading them. I have no interest to learn PSL. I am
more interested in algorithms and circuit development, not the VHDL
language. For my personal use, VHDL-1993 standard plus 'orif' is
enough. That I am pushing for 'orif' adoption is only for my personal
use. Now I don't need it as desperately as before.

So you are not interested in what VHDL already has, you just want to
blindly add duplicative, invasive new features to the language so that
you don't have to learn these existing, more powerful methods?

This is not a language issue. The language already supports
communicating mutual exclusivity and many more powerful notions.
Existing synthesis tools do not use the information; that is the
problem. It would help them if there was "a standard way" to
communicate this to them (which is possible within the existing
language). Just like there is a standard way to communicate a
synchronous process that implies flip flops: there are lots of ways to
describe that behavior in VHDL, but only certain ones are universally
accepted by synthesis tools.

Andy
 
W

Weng Tianxiang

So you are not interested in what VHDL already has, you just want to
blindly add duplicative, invasive new features to the language so that
you don't have to learn these existing, more powerful methods?

This is not a language issue. The language already supports
communicating mutual exclusivity and many more powerful notions.
Existing synthesis tools do not use the information; that is the
problem. It would help them if there was "a standard way" to
communicate this to them (which is possible within the existing
language). Just like there is a standard way to communicate a
synchronous process that implies flip flops: there are lots of ways to
describe that behavior in VHDL, but only certain ones are universally
accepted by synthesis tools.

Andy

Hi Andy,
I accept your advice and will learn PSL

I have ordered one of 3 books Colin suggested, and found that they
don't contain PSL. I will print VHDL-2006 today.

Are you sure that Jim's assertion method in communicating mutually
exclusivity to VHDL compiler is good enough without need for 'orif'
introduction?

1. As I described before, if you use Jim's method and want to get the
information to compiler, you must insist the 'if...end if' structure
to get the benefits, otherwise it is useless, meaningless and wasting
time.

2. When you use 'if...end if' structure, 'orif' is the best choice, no
question! You can add the information line by line at any levels as
you want.

3. My goal is to make writing VHDL for a hardware engineer as easy as
writing C for a software engineer using 'if...end if' structure with
mixing 'elsif' and 'orif'.

Thank you.

Weng
 
A

Andy

If you already have the complete logic description (which is encoded in all
of the 'non-assert' statements) the synthesis tool will not really have much
use for these unverifiable asserts that purport to give this supposedly
'higher level' information. Just what should happen if the logic
description says one thing but the assertion claim another...and the
supposedly impossible thing happens (i.e. the 'assert' fires)? The
synthesis tool generated logic will have no way to flag this and, I'm
guessing, is free to implement this case however it wants to independent of
the logic description....I think I'll pass on such a tool, the supposedly
'impossible' happens, 'specially as code gets reused in new applications.

If you've ever used integer types for synthesis, then you've already
used "built-in" assertions, and seen the synthesis tools' ability to
infer information from them, and optimize the logic to take advantage
of input combinations that cannot exist in the simulation:

signal my_int : integer range 0 to 255;

This is an integer, which if it's value ever exceeds the range of 0 to
255, inclusive, will cause a simulation halt, with an unrecoverable
error.

The synthesis tool recognizes this, and decides it does not need all
32 signed bits to represent all possible values of my_int, it only
needs 8 unsigned bits. What happens to the circuit if some value is
attempted to be stored that is greater than 255 (or less than 0)? It
does not matter, because the simulator will not describe it either.
So, for a counter, the most efficient implementation would be for it
to roll over, even though that would not happen in the simulation code
(nothing would happen, it would be an error). In effect, an assignment
that cannot happen in the simulator is treated as a don't care in the
circuitry.

So indeed there is precedence for synthesis tools using information
that is in the form of built-in assertions to allow optimization of
logic.

If you doubt this, consider the following code:

process (clk, reset) is
variable count : integer range 0 to 255;
begin
if reset = '1' then
count := 0;
elsif rising_edge(clk) then
if count - 1 < 0 then
count := 255;
else
count := count - 1;
end if;
end if;
end process;

Since count is an integer, it cannot take on a value of less than
zero, otherwise a simulation error would occur. However, the integer
expression (count - 1) can have a value less than zero (so long as the
result is not stored back in count), and therefore is a legitimate
comparison. This same code would not work for numeric_std.unsigned,
since a the subtraction operator with an unsigned and a natural always
returns unsigned. The synthesis tool is aware of all this, and
correctly optimizes the two subtractions into one (shares them), and
extracts the carry (borrow) bit for the comparison. The fitter may
perform additional optimizations or transformations, based on the
technology being targeted.

Andy
 
K

KJ

If you've ever used integer types for synthesis, then you've already
used "built-in" assertions, and seen the synthesis tools' ability to
infer information from them, and optimize the logic to take advantage
of input combinations that cannot exist in the simulation:

signal my_int : integer range 0 to 255;

This is an integer, which if it's value ever exceeds the range of 0 to
255, inclusive, will cause a simulation halt, with an unrecoverable
error.

The synthesis tool recognizes this, and decides it does not need all
32 signed bits to represent all possible values of my_int, it only
needs 8 unsigned bits.

Not at all. Synthesis tools key off the range definition that is
typed in as being from 0 to 255 to calculate that an 8 bit
representation is needed. Assertions have nothing to do with it.
So indeed there is precedence for synthesis tools using information
that is in the form of built-in assertions to allow optimization of
logic.
And how can you say with any certainty that this is not just
precedence for using the defined range of an integer and has
absolutely nothing to do with assertions?

KJ
 
A

Andy

Not at all. Synthesis tools key off the range definition that is
typed in as being from 0 to 255 to calculate that an 8 bit
representation is needed. Assertions have nothing to do with it.




And how can you say with any certainty that this is not just
precedence for using the defined range of an integer and has
absolutely nothing to do with assertions?

KJ

The way the synthesis tool recognizes it is in fact, as you say. What
gives it the permission to is the built in assertion, thus specifying
that conditions which would result in a value outside the declared
range are don't care. After all, I guarantee that the simulator
implements "integer range 0 to 512" as a 16 or 32 bit value, not a
nine bit value!

My point is that the simulator and synthesis tool have "different"
behavior. Because the simulator errors out, the synthesis tool is free
to optimize the hardware for those conditions. It would be very
difficult for a synthesis tool to come up with an error routine in
hardware, so it does not try. It assumes (rightly so) that the user is
not interested in implementing cases where the simulation does not
complete.

Andy
 
A

Andy

KJ,

Thanks for pointing out that my example, without the assertion,
assumes priority encoding, and not mutual exclusivity. This is often
forgotten in sequential code.

The only problem with enumerated types is that they are not applicable
to an arbitrary (i.e. parameterizable) number of values. So a uniform
way of encoding a arbitrary length vector as enumerated values does
not exist. However, one could choose binary encoding of a one hot
value as an alternative. The trick is doing binary encoding in a way
that takes advantage of mutual exclusivity. It can be done, but I have
not experimented to find out if the encode/decode is able to be
optimized out.

output <= data(to_integer(unsigned(one_hot_encode(e))));

Where one_hot_encode() is a function that optimally (without priority)
converts a one_hot slv to a smaller, binary value slv.

Additional code is needed to handle the zero_hot case.

If one was willing to assume that vector lengths could be limited to
2**31 bits, then one_hot_encode() could return an integer, making its
use a little simpler:

output <- data(one_hot_encode(e));

The optimal coding of one_hot_encode() is left as an excercise for the
user. ;^)

BTW, I assumed "data" was an array of std_logic_vector in my example;
so my version worked as was with the appropriate declaration.

Andy
 
A

Andy

Weng,

First you don't like using additional signals (one signal per
conditional expression), and using the same signal in the condition as
the assertion. So I demonstrate that additional signals are not
necessary. I never said that using duplicate expressions to avoid
additional signals/variables was a good idea, I just showed you how
you could use them to avoid your dreaded extra signals (which, by the
way, is almost always more self-documenting than the expression, even
if it is not used in more than one place).

It really isn't hard to use arrays and loops if you think about it.

Most data bus driving circuits are based on decoding some sort of
address with qualifiers (read_enable, etc.). Therefore I have as
inputs either the address and enable, or I pre-decode (for timing
reasons) the address into an array of strobes. Thus there are not
separate lines for assigning array elements with individual signals,
because I avoid the individual signals in the first place. Even if
there are individual signals, they are often passed in on ports.
Rather than have individual ports for the individual signals, I have
an array port, with the signals bound to elements of the array port in
the instantiation. No more code required to use an array than
individual signals, and even less code in the entity declaration.

I used to design fpgas with a big, centralized address decode module.
That leads to lots of individual signals. Now I distribute the address
and enables to individual modules, along with a generic for base
address, etc. and let each module decode its own enables and determine
when to drive the data bus with what. I also use a lot of tri-state
logic that gets converted to multiplexers automatically, simply
because it lets me decentralize the data bus loading. This also has
the added benefit that the synthesis tool automatically assumes that
the tri-state enables are mutually exclusive (otherwise the simulation
would not have worked anyway), and optimizes the multiplexers
automatically.

You have to think about avoiding the individual signals in the first
place, not just how to convert them into arrays.

Andy
 
M

Marcus Harnisch

KJ said:
Synthesis unrolls the functions and the net result of converting an
enumerated type to a std_logic_vector and then back to an enumerated
type on the other end is zero logic cells (as it should be since the
one function is the inverse of the other)....and yes it really does do
this with real tools, not just an academic 'well it should do this'.

Care to provide a working example? This sounds really interesting.

Regards,
Marcus
 
A

Andy

KJ,
In simulation yes. If the synthesized logic is somehow 'different' because
of the inclusion or not of the assert statement in the source code then how
does the physical part behave when the asserted condition fails? That was
my basic point. I would expect it to behave as defined by the the logic
description completely.

The guiding principle of HDL-logic synthesis is this: The behavior
exhibited by the simulator should determine the behavior exhibited by
the hardware synthesized by the same code.

An assertion is a way to force the simulation to stop if certain
conditions occur. Since functional behavior due to those conditions is
not handled in the simulation, it is reasonable to expect that the
synthesized hardware should not have to handle them either. The "logic
description" you refer to is the sum total of the behavior of the
simulator when simulating that code, and therefore includes the
assertions.
Having synthesis check assertions that are statically determined things is
appropriate. Dynamically though? Not convinced that it could or even
should attempt this.

This may only be a matter of semantics, but the synthesis tool would
not be "checking" assertions, but merely using the information
provided by them to identify "don't care" conditions. Assertions may
provide information like: "if more than one of these bits is set, I
don't care what the hardware does, because that won't happen (and did
not happen in simulation)." The assertion gives permission to optimize
out any additional logic related to those don't care conditions.

Again, the assertion causes the simulation to not handle the
condition, so there is no behavior related to that condition to
emulate in hardware. Since there is no behavior to emulate, the
synthesis tool is free to optimize out any additional hardware related
to the condition that would fire the assertion. The behavior of the
simulator was a "don't care," as should be the behavior of the
synthesized hardware.

The assertion IS a part of the logic description!
The logic function though is described though by the logic that is written
not by the assert. Maybe we're not understanding what the other is saying
on this particular point though..

Repeat after me; "The 'logic function' is determined by the
simulator's behavior, which includes the assertions."

Andy
 
K

KJ

KJ said:
Synthesis unrolls the functions and the net result of converting an
enumerated type to a std_logic_vector and then back to an enumerated
type on the other end is zero logic cells (as it should be since the
one function is the inverse of the other)....and yes it really does do
this with real tools, not just an academic 'well it should do this'.

Care to provide a working example? This sounds really interesting.

Regards,
Marcus

--
note that "property" can also be used as syntaxtic sugar to reference
a property, breaking the clean design of verilog; [...]

(seen onhttp://www.veripool.com/verilog-mode_news.html)

Sure. See code below. What I've done is defined an enumerated type
('My_Type') with 8 values and To/From conversion functions that
convert this enumerated type into a std_ulogic_vector format. For
simplicity, the std_ulogic_vector is simply an unsigned binary
representation of the position within the enumerated type list. Since
I had 8 enumeration values, I need three bits to represent a signal of
that type. Other vector representations are permissable (like perhaps
an 8 bit 'one hot' representation). The vector representation itself
is not important, the key thing is that the To_Std_Ulogic_Vector()
function is the inverse of the From_Std_ULogic_Vector() function...in
other words each one 'undoes' the other.

To demonstrate cross entity optomizations I've created a 'Transmitter'
entity that takes a vector in and spits out a signal of 'My_Type'.
Similarly, I've created a 'Receiver' entity that takes a signal of
'My_Type' in and spits out a std_ulogic_vector. Lastly, I've created
the top level entity called 'Junk' which instantiates both of these
entities, creating an intermediate signal 'My_Type_Signal' that is an
enumerated type.

The expected result would be that the output of the top level maps
directly to the inputs since the two entities undo what the other has
done. Running this through Quartus and looking at the 'Technology
Map' viewer this is exactly what you'll see, so what gets implemented
is 0 logic cells (which is also was Quartus report).

Enjoy.

KJ

-- START OF CODE --
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package pkg_My_Package is
type My_Type is (s0, s1, s2, s3, s4, s5, s6, s7);
function To_Std_ULogic_Vector(L: My_Type) return
std_ulogic_vector;
function From_Std_ULogic_Vector(L: std_ulogic_vector) return
My_Type;
end package pkg_My_Package;
package body pkg_My_Package is
function To_Std_ULogic_Vector(L: My_Type) return std_ulogic_vector
is
variable RetVal: std_ulogic_vector(2 downto 0);
begin
RetVal := std_ulogic_vector(to_unsigned(My_Type'pos(L),
RetVal'length));
return(RetVal);
end function To_Std_ULogic_Vector;

function From_Std_ULogic_Vector(L: std_ulogic_vector) return
My_Type is
variable RetVal: My_Type;
begin
RetVal := My_Type'val(to_integer(unsigned(L)));
return(RetVal);
end function From_Std_ULogic_Vector;
end package body pkg_My_Package;

library ieee;
use ieee.std_logic_1164.all;
entity Transmitter is port(
Gazinta: in std_ulogic_vector(2 downto 0);
Gazouta: out work.pkg_My_Package.My_Type);
end Transmitter;
architecture RTL of Transmitter is
begin
Gazouta <= work.pkg_My_Package.From_Std_ULogic_Vector(Gazinta);
end RTL;

library ieee;
use ieee.std_logic_1164.all;
entity Receiver is port(
Gazinta: in work.pkg_My_Package.My_Type;
Gazouta: out std_ulogic_vector(2 downto 0));
end Receiver;
architecture RTL of Receiver is
begin
Gazouta <= work.pkg_My_Package.To_Std_ULogic_Vector(Gazinta);
end RTL;


library ieee;
use ieee.std_logic_1164.all;

entity Junk is port(
Gazinta: in std_ulogic_vector(2 downto 0);
Gazouta: out std_ulogic_vector(2 downto 0));
end Junk;

architecture RTL of Junk is
signal My_Type_Signal: work.pkg_My_Package.My_Type;
begin
XMIT : entity work.Transmitter port map(Gazinta, My_Type_Signal);
RCV : entity work.Receiver port map(My_Type_Signal, Gazouta);
end RTL;
-- END OF CODE --
 
A

Andy

Are you sure that Jim's assertion method in communicating mutually
exclusivity to VHDL compiler is good enough without need for 'orif'
introduction?

It depends on the definition of "good enough", but there is not a
single situation where an assertion could not reasonably be used, but
where 'orif' could be. Conversely, there are several situations where
'orif' is not an option, but an assertion would be.
1. As I described before, if you use Jim's method and want to get the
information to compiler, you must insist the 'if...end if' structure
to get the benefits, otherwise it is useless, meaningless and wasting
time.

Not necessarily. There are many mutual exclusivity situations that
might even span different processes. Consider two processes that both
use multipliers. If both processes' uses of their multipliers are
enabled by specific conditions that can be shown to be mutually
exclusive, the synthesis tool has enough information to enable them to
share one multiplier. Of course whether or not current synthesis
tools share resources across processes is beyond the scope of this
argument.

Another example is two state machines that are never both in a state
that uses a multiplier (or some other expensive, shareable resource).

Both of these situations are certainly possible with if-then code
structures, but they don't have to be, and can still take advantage of
an assertion to verify and communicate the mutual exclusivity.
2. When you use 'if...end if' structure, 'orif' is the best choice, no
question! You can add the information line by line at any levels as
you want.

'Orif' is only an option if you can code the function in an if-ELSIF
structure, which cannot be done for a parameterized loop of if-then
structures.
3. My goal is to make writing VHDL for a hardware engineer as easy as
writing C for a software engineer using 'if...end if' structure with
mixing 'elsif' and 'orif'.

Ouch! Then just use verilog; it is already as "easy to use as C" (and
to get into trouble with). ;^)

The way I see it is thus: The barrier to new syntactical changes in
VHDL, particularly those that affect the synthesizable subset of VHDL,
should be quite high because of the problems that occur until every
tool in the chain can even read the new syntax. Therefore, syntactical
changes should only be made to allow functionality that cannot be
reasonably supported within the existing syntax. Of course, that
depends on the definition of "reasonably", but I just don't think
'orif' exceeds the barrier.

Thanks,

Andy
 
J

Jonathan Bromley

Sure. See code below.
[snip]

Sorry Kevin, this has not even slightly convinced me. Your Receiver
has statically-guaranteed mutual exclusivity because the communication
path from transmitter to receiver was an enumeration.
Rather than converting enum->SLV->enum as you claim, you're
doing SLV->enum->SLV (with the enum re-coded as SLV by the tool)
which is quite different.

I have a counter-example that multiplexes a 9-value enumeration or
an 8-bit std_logic_vector onto an 8-bit SLV bus, the enum being
one-hot-zero coded by a function, and the mux control being conveyed
on a separate std_logic. My receiver uses the mux control to
either drive the 8-bit SLV on to an 8-bit output port, or
drive the 8-bit one-hot-zero code on to the same 8-bit output
port using this bit of code:

if mode_i = '0' then -- receive an operation code
if data_i(0) = '1' then opr_o <= X"01" ;
elsif data_i(1) = '1' then opr_o <= X"02" ;
elsif data_i(2) = '1' then opr_o <= X"04" ;
elsif data_i(3) = '1' then opr_o <= X"08" ;
elsif data_i(4) = '1' then opr_o <= X"10" ;
elsif data_i(5) = '1' then opr_o <= X"20" ;
elsif data_i(6) = '1' then opr_o <= X"40" ;
elsif data_i(7) = '1' then opr_o <= X"80" ;
else opr_o <= X"00";
end if;
else -- receive an 8-bit value
opr_o <= data_i;
end if;

And, surprise surprise, NO synth tool I've yet tried can
automatically infer that the various branches of the long
if-elsif are mutually exclusive, even though I've put all
the relevant modules in a single file and, taking the
design as a whole, the mutual exclusivity can easily be
proven. I get truckloads of redundant logic.

Replace my "elsif" with Weng's hypothetical "orif" and...
(1) simulation behaviour would be identical if the
"one-hot-zero" property holds good;
(2) simulation would throw a runtime error if the
"one-hot-zero" property were false at any moment
when the if-orif is executed;
(3) synthesis would rely on (2) to justify an assumption
that the various branches of the if-orif are
mutually exclusive, and therefore the gates can be
simplified to wires exhibiting exactly the behaviour
specified in (1).

Now, I am fully aware that I could easily re-code this
no-op decoder in a different way that would give me
the wires-only hardware I desire. But any such coding
would inherently capture my knowledge of the mutual
exclusivity. What Weng is very reasonably trying to
do is to find a way to capture known mutual exclusivity
in situations that are much less self-evident than
my example, and in which no simple re-coding could
capture the required knowledge. The results of my
little synthesis experiment shows that this is worth
trying to achieve.

Note, for the avoidance of any confusion, that I am
NOT hereby advocating the "orif" proposal.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
W

Weng Tianxiang

It depends on the definition of "good enough", but there is not a
single situation where an assertion could not reasonably be used, but
where 'orif' could be. Conversely, there are several situations where
'orif' is not an option, but an assertion would be.




Not necessarily. There are many mutual exclusivity situations that
might even span different processes. Consider two processes that both
use multipliers. If both processes' uses of their multipliers are
enabled by specific conditions that can be shown to be mutually
exclusive, the synthesis tool has enough information to enable them to
share one multiplier. Of course whether or not current synthesis
tools share resources across processes is beyond the scope of this
argument.

Another example is two state machines that are never both in a state
that uses a multiplier (or some other expensive, shareable resource).

Both of these situations are certainly possible with if-then code
structures, but they don't have to be, and can still take advantage of
an assertion to verify and communicate the mutual exclusivity.




'Orif' is only an option if you can code the function in an if-ELSIF
structure, which cannot be done for a parameterized loop of if-then
structures.




Ouch! Then just use verilog; it is already as "easy to use as C" (and
to get into trouble with). ;^)

The way I see it is thus: The barrier to new syntactical changes in
VHDL, particularly those that affect the synthesizable subset of VHDL,
should be quite high because of the problems that occur until every
tool in the chain can even read the new syntax. Therefore, syntactical
changes should only be made to allow functionality that cannot be
reasonably supported within the existing syntax. Of course, that
depends on the definition of "reasonably", but I just don't think
'orif' exceeds the barrier.

Thanks,

Andy

Hi Andy,
"Conversely, there are several situations where
'orif' is not an option, but an assertion would be. "

NEVER !

If you have an example to support your opinion, I would recall my
propose forever.

Weng
 
W

Weng Tianxiang

Hi Andy,
Now it is clear to me, if not to you,


What assertion onehot0() can do, orif can do better !


"You can NEVER use a parameterized loop of if-then structures"

It is wrong now after our long discussions.

Whenever you write a loop and try to transfer mutually exclusive
information into it, you must remember that you must clearly write
'if..elsif..." structure, then each elsif is a perfect candatate to be
replaced within your loop.

REMEMBER: if you want to use assertion onehot0() to transfer mutually
exclusive information, all signals in onehot() entries must be used
after keywords if and elsif. Other coding short cut would leave the
information useless and wastful.

Weng
 

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,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top