Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

concurrent assertion statement and delta races

124 views
Skip to first unread message

Allan Herriman

unread,
Feb 11, 2013, 5:45:24 AM2/11/13
to
Hi,

I occasionally come across a situation in which I have an architecture
with many if-generate constructs to select different options for some
design. Exactly one of the if-generates must evaluate to true and be
"generated".

In a big design I like to test this by having an unresolved signal
(initialised to false) that is set to true inside each of the if-
generates. I then need to use an assertion to check that the signal is
indeed true, indicating that exactly one of the if-generates is active.

I know I could do this in VHDL-2008 using if-else generate, but I'm using
tools from Xilinx :( so I am restricted to using 20th century versions
of VHDL.


This has been working fine for me for years, but I just realised today
that my assertions hadn't actually been checking anything. (Which is
fine, 'cause my code never has bugs...)


I'm looking for pointers on the best way to express my assertion in VHDL
'93 or '01.
Alternatively, I'm looking for any other ways to test this aspect of my
design without using a signal.



E.g.

-- The remainder of this post is in VHDL
-- and can be compiled and simulated.

entity foo is
end entity foo;

architecture bar of foo is

signal sig : boolean := FALSE;

begin

sig <= TRUE; -- (inside an if-generate)
-- comment out previous line to test assertions


-- need to assert that sig is TRUE here

attempt_1 : assert sig
report "sig is false #1"
severity note;

-- attempt_1 fails
-- it indicates that sig is always FALSE,
-- regardless of its actual value, due to the
-- attempt_1 equivalent process running before
-- the delta in which sig gets its value


attempt_2 : assert sig or now = 0 ns
report "sig is false #2"
severity note;

-- attempt_2 fails
-- it indicates that sig is always TRUE,
-- regardless of its actual value
-- because the equivalent process runs when now = 0 ns
-- then does a wait on sig, which never has an event.


attempt_3 : postponed assert sig
report "sig is false #3"
severity note;

-- attempt_3 fails as well.
-- Postponed is meant to fix the delta race
-- we had with attempt_1, but it doesn't,
-- indicating that sig is always FALSE
-- regardless of its actual value.
-- (In which case, what is the point of having
-- postponed assert as part of the language? I must
-- be missing something here.)


attempt_5 : process
begin
wait for 0 ns;
assert sig
report "sig is false #5"
severity note;
wait;
end process attempt_5;

-- attempt_5 works correctly, but is really ugly


end architecture bar;

-- Regards,
-- Allan

Tricky

unread,
Feb 11, 2013, 11:39:56 AM2/11/13
to
I wouldnt use a signal at all - I would just XOR all of the conditions together, or have a single assert based on the different conditions:

assert (a xor b xor c)
report "Only ONE of A or B or C may be set"
severity failure;

But you may be bummed in the end by how the tool actually handle's asserts. IIRC, a few years ago some people did a test with asserts forcing a synthesisor to stop. The only one that actually stopped was Quartus, with Synplify giving just a warning (and carrying on), and others not doing anything at all (Cannot remember the ISE result).

Another problem with the signal approach is that even if it is non-resolved, some compilers may simply just remove the net unless it drives an output.

Rob Gaddi

unread,
Feb 11, 2013, 2:44:59 PM2/11/13
to
On Mon, 11 Feb 2013 08:39:56 -0800 (PST)
Tricky <Trick...@gmail.com> wrote:

> I wouldnt use a signal at all - I would just XOR all of the conditions together, or have a single assert based on the different conditions:
>
> assert (a xor b xor c)
> report "Only ONE of A or B or C may be set"
> severity failure;
>
> But you may be bummed in the end by how the tool actually handle's asserts. IIRC, a few years ago some people did a test with asserts forcing a synthesisor to stop. The only one that actually stopped was Quartus, with Synplify giving just a warning (and carrying on), and others not doing anything at all (Cannot remember the ISE result).
>
> Another problem with the signal approach is that even if it is non-resolved, some compilers may simply just remove the net unless it drives an output.

Integers and addition, not bits and XORs. Otherwise 3=1.

--
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order. See above to fix.

Allan Herriman

unread,
Feb 11, 2013, 4:35:26 PM2/11/13
to
Quite apart from the bug with xor, that doesn't work for me at a
practical level. The conditions are complicated and there are a lot of
them. Copying and pasting them to two places in the code (the if-
generate and the assert) may introduce errors and makes maintenance
harder. Creating constants for the conditions (to avoid the copy and
paste) makes the code messy.


> But you may be bummed in the end by how the tool actually handle's
> asserts. IIRC, a few years ago some people did a test with asserts
> forcing a synthesisor to stop. The only one that actually stopped was
> Quartus, with Synplify giving just a warning (and carrying on), and
> others not doing anything at all (Cannot remember the ISE result).
>
> Another problem with the signal approach is that even if it is
> non-resolved, some compilers may simply just remove the net unless it
> drives an output.

I'm only interested in the simulation behaviour. I run the regression
tests in the simulator. What happens in synthesis doesn't matter to me
for the purposes of this thread.
I'm using Modemsim 10.1d (the latest version).

Regards,
Allan

Alan Fitch

unread,
Feb 11, 2013, 7:00:09 PM2/11/13
to
On 11/02/13 10:45, Allan Herriman wrote:
> Hi,
>
> I occasionally come across a situation in which I have an architecture
> with many if-generate constructs to select different options for some
> design. Exactly one of the if-generates must evaluate to true and be
> "generated".
>
> In a big design I like to test this by having an unresolved signal
> (initialised to false) that is set to true inside each of the if-
> generates. I then need to use an assertion to check that the signal is
> indeed true, indicating that exactly one of the if-generates is active.
>
> I know I could do this in VHDL-2008 using if-else generate, but I'm using
> tools from Xilinx :( so I am restricted to using 20th century versions
> of VHDL.
>
>
> This has been working fine for me for years, but I just realised today
> that my assertions hadn't actually been checking anything. (Which is
> fine, 'cause my code never has bugs...)
>
>
> I'm looking for pointers on the best way to express my assertion in VHDL
> '93 or '01.
> Alternatively, I'm looking for any other ways to test this aspect of my
> design without using a signal.
>
>
I don't know if Xilinx would support this, but could you write a custom
resolution function?

The resolution function could contain an assert if the number of drivers
was 0. Because the drivers are determined at elaboration, this wouldn't
require any time to pass (I think). I haven't tried it though...

regards
Alan



--
Alan Fitch

HT-Lab

unread,
Feb 12, 2013, 3:49:12 AM2/12/13
to
On 11/02/2013 21:35, Allan Herriman wrote:
..
> I'm only interested in the simulation behaviour. I run the regression
> tests in the simulator. What happens in synthesis doesn't matter to me
> for the purposes of this thread.
> I'm using Modemsim 10.1d (the latest version).
^^^^^^^^^^^^^^^^^
Not since yesterday :-)

10.2 has more suppulent VHDL2008 support and DE users get access to the
FLI (C/C++ interface for VHDL users),

Hans
www.ht-lab.com


>
> Regards,
> Allan
>

Allan Herriman

unread,
Feb 12, 2013, 4:44:41 AM2/12/13
to
I should clarify:

I'm using Modelsim for simulation. All my testing happens in Modelsim.
The assertions only need to run correctly in Modelsim.

The code is synthesisable, targetting a number of different tools. The
Xilinx tools are the worst case, meaning I can't use VHDL 2008.
I don't care whether the assertions are handled by the synth tools, as
long as it still compiles.

Regards,
Allan

Tricky

unread,
Feb 12, 2013, 8:59:56 AM2/12/13
to
If you're only interested in simulation, how about the use of a shared variable?

shared varaible n_insts : integer := 0;

impure function add_inst return boolean is
begin
n_insts := n_insts + 1;

assert (n_insts <= 1)
report "Too many instances"
severity failure;

return true;
end function;


And then in each generate statement, just have the folowing constant declaration:

constant A_CONST : boolean := add_inst;

This will then count up the number of instances right at the start of the vsim, so you dont even need to run it. Each activated generate will add 1 to the n_insts variable and bomb out when it goes above 1. This way you never even need to know what the generics are, or do you care. current code just needs the constants adding.

Allan Herriman

unread,
Feb 12, 2013, 10:20:12 AM2/12/13
to
That's an interesting solution to the problem and I thank you for your
efforts.

However, even though the assertions only need to work in simulation, the
code still needs to be synthesisable and portable over a number of
tools. I believe this rules out the use of shared variables.

The basic problem with shared variables is that one version of VHDL
supports shared variables but not protected types. A different version
of VHDL also supports shared variables, but requires that they be
protected types. Both versions of the language are currently in use.

Regards,
Allan

Andy

unread,
Feb 12, 2013, 10:24:00 AM2/12/13
to
On Tuesday, February 12, 2013 7:59:56 AM UTC-6, Tricky wrote:
> If you're only interested in simulation, how about the use of a shared variable? shared varaible n_insts : integer := 0; impure function add_inst return boolean is begin n_insts := n_insts + 1; assert (n_insts <= 1) report "Too many instances" severity failure; return true; end function; And then in each generate statement, just have the folowing constant declaration: constant A_CONST : boolean := add_inst; This will then count up the number of instances right at the start of the vsim, so you dont even need to run it. Each activated generate will add 1 to the n_insts variable and bomb out when it goes above 1. This way you never even need to know what the generics are, or do you care. current code just needs the constants adding.

Right idea, wrong implementation. Since 2002 (?) shared variables must be of a protected type. The functions/procedures (methods) defined in the protected type are guaranteed to execute atomically (one call must complete before another call can start). Otherwise, a compliant simulator could execute two or more of your unprotected initializations at the same time (different threads/cores), and one or more of them could see the same current value (e.g. 0), and set the new value to 1. This would lead you to believe that only one generate statement was enabled, when in fact more than one had been enabled.

This is really a good application of a shared protected variable, and it is easy to implement, to sort of get your feet wet. Warning: once you learn how to do this, you'll find lots of other places where it makes sense to use!

Define a protected type with a local (protected) integer, and within the type, define a method serialize() that increments the protected variable and returns the updated value.

You could just call the serialize in an assertion and make sure the updated value is 2 (1 + this), or define another method, value(), that simply returns the current count without incrementing it.

Then declare a shared variable of the protected type, and call its serialize() method in your constant initialization (use an integer constant) in each generate's declarative region.

This is also handy because it makes the unique serial number avaialble to each generate. This can be useful for lots of other things that require a unique value. Just remember that the order in which the various calls to serialize() are executed is not defined, so it can change from simulator to simulator on the same code, or within the same simulator with seemingly unrelated changes to the code.

Andy

Andy

unread,
Feb 12, 2013, 11:02:43 AM2/12/13
to
You can use synthesis directives (meta-comments) to turn off translation of problematic code in synthesis. Look in the synthesis user- or reference-guide to determine what those meta-comments are for your tool.

The simulator ignores the meta-comments, and compiles/executes the code, but the synthesis tool ignores the code.

Andy

Allan Herriman

unread,
Feb 12, 2013, 4:30:48 PM2/12/13
to
-- synthesis translate_off

(code not to be synthesised here)

-- synthesis translate_on

Tricky

unread,
Feb 13, 2013, 4:36:34 AM2/13/13
to
I was going to suggest protected types (I love them) but for this instance I thought it a bit ott, but didnt think about your points.


Tricky

unread,
Feb 13, 2013, 4:48:03 AM2/13/13
to
And just to add - protected types were introduced in 2002. And yes, by the LRM shared variables must be a protected type. But the default stance for modelsim is to only throw a warning for this and technically not be LRM compliant. There is an enforcement switch on the compiler to make it an error instead.

Going back to Andy's point about unique IDs - this method is only "guaranteed" in simulation. Quartus (I havent tried other synthesis tools) will throw an error saying a Constant must be constant if you use the shared variable method above, and it doesnt even accept the keyword "Protected".

valtih1978

unread,
Feb 13, 2013, 6:35:21 AM2/13/13
to
> -- Postponed
> -- indicating that sig is always FALSE
> -- regardless of its actual value.

This is curious. Is it a bug in tools or expected behavior of postponed?
IMO, regardless assignment is considered a process in the body of
architecture or its submodule, postponed must be fired only after all
delta cycles have finished and driving signals updated.

Allan Herriman

unread,
Feb 14, 2013, 4:55:41 AM2/14/13
to
I think the problem is that the equivalent process must run at the start
of simulation as well as whenever there's an event on the signal.

Postponed can help with the ordering of things when there's an event, but
it can't do anything about the first time the process runs at the start
of simulation, and that's when the assertion fails.

Regards,
Allan

valtih1978

unread,
Feb 14, 2013, 5:50:43 AM2/14/13
to

> Postponed can help with the ordering of things when there's an event, but
> it can't do anything about the first time the process runs at the start
> of simulation, and that's when the assertion fails.

The spec treats both cases: postponed are executed once all normal
processes catched in the wait during simulation start, at time 0 and,
secondly, prior to time advance (you call it event case). So, if you
have a single assignment

process begin
singleton <= generate_x_value;
wait;
end process;

Since this process generates an event and postponed processes start
after it suspends in the wait, for both of these reasons your postponed
assertion

assert postponed check(singleton)

must work as postponed.

Postponed assertion has only one flaw because start case is treated
specifically. Executing postponed once all processes started, as opposed
to time advance event, creates situation that there are delta frames to
be executed, yet, specification forces your postponed to run once
simulation starts. This requires an ugly workaround,
http://computer-programming-forum.com/42-vhdl/3edcb21668330593.htm
HardLook at that workaround and note that your workaround is not that
ugly. I would live with your workaround. Yet, IMO, no workarounds are
needed in your case since postponed must do its job. That is why I am
asking.

Allan Herriman

unread,
Feb 14, 2013, 7:34:17 AM2/14/13
to
On Thu, 14 Feb 2013 12:50:43 +0200, valtih1978 wrote:

> I would live with your workaround. Yet, IMO, no workarounds are
> needed in your case since postponed must do its job. That is why I am
> asking.


I guess it must be a tool bug if what you say is true.
I really don't know - I've been using VHDL since the mid '90s and that's
the first time I've ever used postponed, so I can't claim to have any
experience in this area.


Regards,
Allan
0 new messages