Legal enable?

P

PatC

Guest
Hi folks,

A friend of mine wrote some component that includes an enable
construct that I haven't seen before. We discussed it and he swears that
it's legal code. Simulation and synthesis don't report any issues with
it, but now a functional issue came up in hw and it could be related to
this.
Paraphrasing, the code is similar to this:

process (reset, clk)
begin
if (reset = '1') then
state <= idle;
elsif (rising_edge(clk) and hold = '0') then
case (state) is
when idle => ...
when write => ...
end case
end if;
end process

Here, the /hold/ signal acts as an enable. Is this legal or should it
be recoded as a nested if?
Now that I look at it again, in case it's legal, shouldn't /hold/
need to be in the sensitivity list?

Thanks in advance,
-Pat
 
On Thu, 04 Sep 2008 23:12:34 -0700, PatC <pato@REMOVETHISpatocarr.com>
wrote:

Hi folks,

A friend of mine wrote some component that includes an enable
construct that I haven't seen before. We discussed it and he swears that
it's legal code. Simulation and synthesis don't report any issues with
it, but now a functional issue came up in hw and it could be related to
this.
Paraphrasing, the code is similar to this:

process (reset, clk)
begin
if (reset = '1') then
state <= idle;
elsif (rising_edge(clk) and hold = '0') then
case (state) is
when idle => ...
when write => ...
end case
end if;
end process

Here, the /hold/ signal acts as an enable. Is this legal or should it
be recoded as a nested if?
Now that I look at it again, in case it's legal, shouldn't /hold/
need to be in the sensitivity list?

Thanks in advance,
-Pat
I'm not a VHDL language lawyer but this looks perfectly fine to me.
There would be no logical difference between this style and nesting
the "if (hold..". There is no need for hold in the sensitivity list
because it's a synchronous enable so it's only evaluated on the
posedge of clk so changes to it outside that event are not meaningful.
 
PatC a écrit :
Hi folks,

A friend of mine wrote some component that includes an enable
construct that I haven't seen before. We discussed it and he swears that
it's legal code. Simulation and synthesis don't report any issues with
it, but now a functional issue came up in hw and it could be related to
this.
Paraphrasing, the code is similar to this:

process (reset, clk)
begin
if (reset = '1') then
state <= idle;
elsif (rising_edge(clk) and hold = '0') then
case (state) is
when idle => ...
when write => ...
end case
end if;
end process

Here, the /hold/ signal acts as an enable. Is this legal or should it
be recoded as a nested if?
Now that I look at it again, in case it's legal, shouldn't /hold/ need
to be in the sensitivity list?

Thanks in advance,
-Pat
Hi,

(Beginner look, so take it with care)
* I do not think that a nested if would change anything from a combined AND
condition. Both should produce exactely the same equation.
As a beginner, I would have written
elsif (rising_edge(clk) and (hold = '0')) then
to definitively ensure that (hold='0') is evaluated first before the and operator.

* Again, I do not think that Hold needs to be present in the sensitivity list
because it does not trigger any "start of update" of that process.

Maybe the problem is elsewhere ?
Can you describe more the HW issue ?

Pascal
 
On Thu, 04 Sep 2008 23:12:34 -0700, PatC wrote:

A friend of mine wrote some component that includes an enable
construct that I haven't seen before. We discussed it and he swears that
it's legal code. Simulation and synthesis don't report any issues with
it, but now a functional issue came up in hw and it could be related to
this.
Paraphrasing, the code is similar to this:

process (reset, clk)
begin
if (reset = '1') then
state <= idle;
elsif (rising_edge(clk) and hold = '0') then
case (state) is
when idle => ...
when write => ...
end case
end if;
end process

Here, the /hold/ signal acts as an enable. Is this legal
or should it be recoded as a nested if?
From a VHDL language point of view, the two forms are truly
identical. The logical "and" operator on booleans does
short-circuit evaluation, so if rising_edge(clk) is false
then it won't even evaluate the expression hold='0'.
As you correctly say, the hold signal is an (active-low)
clock enable.

Now that I look at it again, in case it's legal,
shouldn't /hold/ need to be in the sensitivity list?
As a synchronous input to the process, it certainly
should not be in the sensitivity list; you wouldn't expect
any activity if you wiggled "hold" while the clock was
inactive, would you?

The only possible problem might be with synthesis.
Nowadays (as has been discussed here at wearisome length)
most synthesis tools are quite good at recognizing alternative
forms of the standard clocked processes. However, it is
probably still safer to restrict synthesis coding style
to the standard template:

if <asynch_reset is asserted> then
<do asynch reset actions>
elsif <active clock edge> then
<do synchronous actions>
end if;

In other words, use a nested "if". It will prevent
raised eyebrows from colleagues and linting tools,
and will assure portability among synthesis tools.
--
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
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Jonathan Bromley wrote:
On Thu, 04 Sep 2008 23:12:34 -0700, PatC wrote:

A friend of mine wrote some component that includes an enable
construct that I haven't seen before. We discussed it and he swears that
it's legal code. Simulation and synthesis don't report any issues with
it, but now a functional issue came up in hw and it could be related to
this.
Paraphrasing, the code is similar to this:

process (reset, clk)
begin
if (reset = '1') then
state <= idle;
elsif (rising_edge(clk) and hold = '0') then
case (state) is
when idle => ...
when write => ...
end case
end if;
end process

Here, the /hold/ signal acts as an enable. Is this legal
or should it be recoded as a nested if?

From a VHDL language point of view, the two forms are truly
identical. The logical "and" operator on booleans does
short-circuit evaluation, so if rising_edge(clk) is false
then it won't even evaluate the expression hold='0'.
As you correctly say, the hold signal is an (active-low)
clock enable.

Now that I look at it again, in case it's legal,
shouldn't /hold/ need to be in the sensitivity list?

As a synchronous input to the process, it certainly
should not be in the sensitivity list; you wouldn't expect
any activity if you wiggled "hold" while the clock was
inactive, would you?

The only possible problem might be with synthesis.
Nowadays (as has been discussed here at wearisome length)
most synthesis tools are quite good at recognizing alternative
forms of the standard clocked processes. However, it is
probably still safer to restrict synthesis coding style
to the standard template:

if <asynch_reset is asserted> then
do asynch reset actions
elsif <active clock edge> then
do synchronous actions
end if;

In other words, use a nested "if". It will prevent
raised eyebrows from colleagues and linting tools,
and will assure portability among synthesis tools.
Thanks Jonathan for your quick & insightful reply.

For the record, I tried the nested if and xst synthesized it in the
exact same way as before.
As you mentioned, adding it to the sensitivity list wouldn't make sense.

Cheers,
-Pat
 
On Fri, 05 Sep 2008 13:19:49 +0100, Brian Drummond wrote:

I just want to ask what drives "hold".
If (a) "hold" is used as an enable by more than one process, and (b)
"hold" is NOT driven by a FF or register clocked by "clk", you have a
problem, whichever coding style you use. (Different processes sample
"hold" at different times according to routing delays in the FPGA; if it
is asynchronous, they may see it at different levels in the same clock
cycle).
For sure; but the same concern (input hazard) applies to
any and all of the synchronous inputs to any clocked process.
A synchronous clock enable is nothing special in that regard.
--
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
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
On Fri, 05 Sep 2008 08:43:59 +0100, Jonathan Bromley
<jonathan.bromley@MYCOMPANY.com> wrote:

On Thu, 04 Sep 2008 23:12:34 -0700, PatC wrote:

A friend of mine wrote some component that includes an enable
construct that I haven't seen before. We discussed it and he swears that
it's legal code. Simulation and synthesis don't report any issues with
it, but now a functional issue came up in hw and it could be related to
this.
Paraphrasing, the code is similar to this:

process (reset, clk)
begin
if (reset = '1') then
state <= idle;
elsif (rising_edge(clk) and hold = '0') then
case (state) is
when idle => ...
when write => ...
end case
end if;
end process

Here, the /hold/ signal acts as an enable. Is this legal
or should it be recoded as a nested if?

The only possible problem might be with synthesis.
Nowadays (as has been discussed here at wearisome length)
most synthesis tools are quite good at recognizing alternative
forms of the standard clocked processes. However, it is
probably still safer to restrict synthesis coding style...
Agreed to all the above, especially the potential for differences
between synth tools (though they are continually improving).

I just want to ask what drives "hold".
If (a) "hold" is used as an enable by more than one process, and (b)
"hold" is NOT driven by a FF or register clocked by "clk", you have a
problem, whichever coding style you use. (Different processes sample
"hold" at different times according to routing delays in the FPGA; if it
is asynchronous, they may see it at different levels in the same clock
cycle).

- Brian
 
Jonathan Bromley wrote:

....
In other words, use a nested "if". It will prevent
raised eyebrows from colleagues and linting tools,
and will assure portability among synthesis tools.
I prefer the standard template style as well,
for the same reasons.

But if I had to defend Pat's friend in court of vhdl,
I would point out that that his
"anded enable" style does save one level of indentation
over the "nested if" enable style.

If it works with with xst as Pat claims,
it likely works with the other popular fpga synthesis tools also,
as xst tends to lag the others in vhdl language coverage.

The defense rests;)

-- Mike Treseler
 
On Sep 5, 12:41 pm, Mike Treseler <mtrese...@gmail.com> wrote:
Jonathan Bromley wrote:

...

In other words, use a nested "if".  It will prevent
raised eyebrows from colleagues and linting tools,
and will assure portability among synthesis tools.

I prefer the standard template style as well,
for the same reasons.

But if I had to defend Pat's friend in court of vhdl,
I would point out that that his
"anded enable" style does save one level of indentation
over the "nested if" enable style.

If it works with with xst as Pat claims,
it likely works with the other popular fpga synthesis tools also,
as xst tends to lag the others in vhdl language coverage.

The defense rests;)

              -- Mike Treseler
Agreed. But just to muddy the waters a bit, I thought I'd look up what
1076-6.1999 had to say. Three things stood out for me:

(1) 1076-6 doesn't explicitly mention that "gating" the clock edge
with an (... and something) clause is legal. So I'd argue that the
nested if() statement, while redundant according to the language
semantics, is safer to use.

(2) There's a technical inconsistency in sec 6.1.1. "only the values
'0' and 1' shall be used in expressions representing clock levels".
Then it says that the rising_edge() function is an allowable form of
clock edge specification, but rising_edge (when elaborated as per LRM
semantics), uses the To_X01 function which references both 'H' and
'L'. Nit-picking, to be sure, but that's what digital designers live
for :)

(3) More interestingly, though, in sec 6.1.2 which defines the
expected form of clock edge specification. In addition to the usual
(clk'event and clk='1') and (rising/falling_edge(clk)), the form

if (not (clk'stable) and clk='1')

is also allowed! Has anyone ever written or seen this form of clock
edge specification? Was this a common form back in the 80's when the
language was young and standard coding forms were competing for
viability?

Cheers,

- Kenn
 
On Fri, 5 Sep 2008 15:14:06 +0100, "Symon" <symon_brewer@hotmail.com>
wrote:

"Brian Drummond" <brian_drummond@btconnect.com> wrote in message
news:2j82c4d1t0nuqqmito1lp35qlgkgoqr347@4ax.com...

I just want to ask what drives "hold".
If (a) "hold" is used as an enable by more than one process, and (b)
"hold" is NOT driven by a FF or register clocked by "clk", you have a
problem, whichever coding style you use. (Different processes sample
"hold" at different times according to routing delays in the FPGA; if it
is asynchronous, they may see it at different levels in the same clock
cycle).

- Brian

Hi Brian,
I don't think it's a problem if 'hold' is driven by combinationial logic,
iff the combinatorial logic is driven by FFs in the domain of 'clk'. In this
case, the FPGA static timing analysis tools will alert the designer to any
timing issues.
Agreed... I should have added the rider "through combinational logic" to
my statement. I was raising the question because a "functional issue"
(love it!) exists with _something_ in the design, and it doesn't sound
like the synthesis style.

- Brian
 
Brian Drummond wrote:
I just want to ask what drives "hold".
If (a) "hold" is used as an enable by more than one process, and (b)
"hold" is NOT driven by a FF or register clocked by "clk", you have a
problem, whichever coding style you use. (Different processes sample
"hold" at different times according to routing delays in the FPGA; if it
is asynchronous, they may see it at different levels in the same clock
cycle).
A fair question. I should've added that hold is a registered signal
in the same clock domain.

-P@
 
On Sep 6, 5:22 am, kennheinr...@sympatico.ca wrote:
(2) There's a technical inconsistency in sec 6.1.1. "only the values
'0' and 1' shall be used in expressions representing clock levels".
Then it says that the rising_edge() function is an allowable form of
clock edge specification, but rising_edge (when elaborated as per LRM
semantics), uses the To_X01 function which references both 'H' and
'L'. Nit-picking, to be sure, but that's what digital designers live
for :)
1076.6:

6.1.1 Clock signal type

The allowed types for clock signals shall be: BIT, STD_ULOGIC and
their
subtypes (e.g. STD_LOGIC) with a minimum subset of '0' and '1'. Only
the
values ‘0' and ‘1' from these types shall be used in expressions
representing
clock levels and clock edges (See 6.1.2).

(Actual language can be important)

Only '1' and '0' are used in expressions representing clock (signal s)
levels in the rising_edge() function:


-------------------------------------------------------------------
-- edge detection

-------------------------------------------------------------------
FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS
BEGIN
RETURN (s'EVENT AND (To_X01(s) = '1') AND
(To_X01(s'LAST_VALUE) = '0'));
END;

FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS
BEGIN
RETURN (s'EVENT AND (To_X01(s) = '0') AND
(To_X01(s'LAST_VALUE) = '1'));
END;

------------------------------------------------------------------

Nary an 'U', 'X', 'Z', 'L', 'H', 'W' nor '-' in there.

rising_edge()/falling_edge() uses To_X01() which calls the
cvt_to_x01() to convert state values to logic values.

----------------------------------------------------------
CONSTANT cvt_to_x01 : logic_x01_table := (
'X', -- 'U'
'X', -- 'X'
'0', -- '0'
'1', -- '1'
'X', -- 'Z'
'X', -- 'W'
'0', -- 'L'
'1', -- 'H'
'X' -- '-'
);

----------------------------------------------------------

The implication is that a signal state 'L' is a logic value of '0'
and a logic value of 'H' maps to a state value of '1'. And yes, 'X'
is present as a signal value (the left hand column in the
logic_x01_table). A lookup table is a type conversion function.

Note that no where are 'U','Z', 'W', 'L', 'H' or '-' expressed as
signal values only as signal states.

B.95 expression: A formula that defines the computation of a value.(§
7.1 )

Further an expression has a left side and a right side or is a factor/
term (including function calls and type conversions).

Nowhere in the rising_edge()/falling_edge() elaboration is a constant
value evaluated as a left hand side of an expression.

Nowhere in the rising_edge()/falling_edge() elaboration is a constant
value of 'U', 'X', 'Z', 'L','H', 'W', or '-' evaluated as the right
hand side of an expression.

Is the logic_x01_table an expression by itself? It doesn't match the
definition above, it's not a formula.

Note that neither value nor formula are defined in the glossary of the
LRM.

From websters for formula:

3 a: a general fact, rule, or principle expressed in usually
mathematical symbols b: a symbolic expression of the chemical
composition or constitution of a substance c: a group of symbols (as
letters and numbers) associated to express facts or data (as the
number and kinds of teeth in the jaw) concisely d: a combination of
signs in a logical calculus

A table hits definition c., above for formula, a group of symbols
associated to express facts or data.

By this (twisted) chain of logic, 'X' shows up in the elaborated
expression (but not 'U', 'X', 'Z', 'L','H', 'W', or '-').

You were right there was something creeping around in there contrary
to the statement in 6.1.1. It wasn't the 'L' or 'H', though. They
only show up in comments, and while you could have a comment embedded
in an expression:

LRM 13.8:
Furthermore, comments do not influence the execution of a simulation
module; their sole purpose is to enlighten the human reader.

Note that the language doesn't indicate that comments don't have
meaning for synthesis. There appears to be more angels dancing on the
head of that pin, yet.
 
On Sep 6, 5:22 am, kennheinr...@sympatico.ca wrote:
(2) There's a technical inconsistency in sec 6.1.1. "only the values
'0' and 1' shall be used in expressions representing clock levels".
Then it says that the rising_edge() function is an allowable form of
clock edge specification, but rising_edge (when elaborated as per LRM
semantics), uses the To_X01 function which references both 'H' and
'L'. Nit-picking, to be sure, but that's what digital designers live
for :)
1076.6:

6.1.1 Clock signal type

The allowed types for clock signals shall be: BIT, STD_ULOGIC and
their subtypes (e.g. STD_LOGIC) with a minimum subset of '0' and '1'.
Only the values ‘0' and ‘1' from these types shall be used in
expressions representing clock levels and clock edges (See 6.1.2).

(Actual language can be important)

Only '1' and '0' are used in expressions representing clock (signal s)
levels in the rising_edge() function:


-------------------------------------------------------------------
-- edge detection

-------------------------------------------------------------------
FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS
BEGIN
RETURN (s'EVENT AND (To_X01(s) = '1') AND
(To_X01(s'LAST_VALUE) = '0'));
END;

FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS
BEGIN
RETURN (s'EVENT AND (To_X01(s) = '0') AND
(To_X01(s'LAST_VALUE) = '1'));
END;

------------------------------------------------------------------

Nary an 'U', 'X', 'Z', 'L', 'H', 'W' nor '-' in there.

rising_edge()/falling_edge() uses To_X01() which calls the
cvt_to_x01() to convert state values to logic values.

----------------------------------------------------------
CONSTANT cvt_to_x01 : logic_x01_table := (
'X', -- 'U'
'X', -- 'X'
'0', -- '0'
'1', -- '1'
'X', -- 'Z'
'X', -- 'W'
'0', -- 'L'
'1', -- 'H'
'X' -- '-'
);

----------------------------------------------------------

The implication is that a signal state 'L' is a logic value of '0'
and a signal state of 'H' maps to a logic value of '1'. And yes,
'X' is present as a signal value (the left hand column in the
logic_x01_table). A lookup table is a type conversion function.

Note that no where are 'U','Z', 'W', 'L', 'H' or '-' expressed as
signal values only as signal states.

B.95 expression: A formula that defines the computation of a value.(§
7.1 )

Further an expression has a left side and a right side or is a factor/
term (including function calls and type conversions).

Nowhere in the rising_edge()/falling_edge() elaboration is a constant
value evaluated as a left hand side of an expression.

Nowhere in the rising_edge()/falling_edge() elaboration is a constant
value of 'U', 'X', 'Z', 'L','H', 'W', or '-' evaluated as the right
hand side of an expression.

Is the logic_x01_table an expression by itself?

Note that neither value nor formula are defined in the glossary of the
LRM.

From websters for formula:

3 a: a general fact, rule, or principle expressed in usually
mathematical symbols b: a symbolic expression of the chemical
composition or constitution of a substance c: a group of symbols (as
letters and numbers) associated to express facts or data (as the
number and kinds of teeth in the jaw) concisely d: a combination of
signs in a logical calculus

A table hits definition c., above for formula, a group of symbols
associated to express facts or data.

By this (twisted) chain of logic, 'X' shows up in the elaborated
expression (but not 'U', 'X', 'Z', 'L','H', 'W', or '-').

You were right there was something creeping around in there contrary
to the statement in 6.1.1. It wasn't the 'L' or 'H', though. They
only show up in comments, and while you could have a comment embedded
in an expression:

LRM 13.8:
Furthermore, comments do not influence the execution of a simulation
module; their sole purpose is to enlighten the human reader.

Note that the language doesn't indicate that comments don't have
meaning for synthesis. There appears to be more angels dancing on the
head of that pin, yet.
 
On Sep 6, 5:33 pm, diogratia <diogra...@gmail.com> wrote:
rising_edge()/falling_edge() uses To_X01() which calls the
cvt_to_x01() to convert state values to logic values.

    ----------------------------------------------------------
    CONSTANT cvt_to_x01 : logic_x01_table := (
                         'X',  -- 'U'
                         'X',  -- 'X'
                         '0',  -- '0'
                         '1',  -- '1'
                         'X',  -- 'Z'
                         'X',  -- 'W'
                         '0',  -- 'L'
                         '1',  -- 'H'
                         'X'   -- '-'
                        );

    ----------------------------------------------------------
D'oh... that's where I was getting ahead of myself. I mixed up the
text while paging through the file and somehow mentally associated the
explicit check written "case ... when '1' | 'H' return ('1')" in the
To_bit function with the definition of cvt_to_ux01, which is only a
few lines earlier. My bad.

<snip>

 There appears to be more angels dancing on the
head of that pin, yet.
My pin, my head :)

- Kenn
 
On Sep 5, 2:43 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
In other words, use a nested "if".  It will prevent
raised eyebrows from colleagues and linting tools,
and will assure portability among synthesis tools.
I respectfully disagree. Preventing "raised eyebrows" by avoiding such
constructs may serve a short term goal, but also severely dampens the
advancement of the state of the art in logic synthesis. Where would we
be if nobody had ever wanted to raise eyebrows by using single process
coding styles (combo logic and reg's in same clocked process)?

As for tool portability, those tools that do not support this need a
good public flogging! This very style was proposed in '01 or '02 by a
paper at SNUG. By pushing the envelope on individual tools, we create
competition ("brand Y does it!") to raise the bar everywhere. If we
are continually limited to the least common denominator, progress is
halted.

Andy
 
On Sep 8, 10:02 am, Andy <jonesa...@comcast.net> wrote:

As for tool portability, those tools that do not support this need a
good public flogging!
Opening service requests to the tool vendors with the ("brand Y does
it!") statement is likely to be a more effective approach to advancing
the tools than public flogging ;)

KJ
 
On Sep 9, 8:05 am, KJ <kkjenni...@sbcglobal.net> wrote:
Opening service requests to the tool vendors with the ("brand Y does
it!") statement is likely to be a more effective approach to advancing
the tools than public flogging ;)

KJ
I agree wholeheartedly! Unfortunately, some vendors don't care about
what the competition is doing, they see themselves as the de-facto
standard bearers anyway. Public flogging probably would not do any
good either, but at least you would feel better after administering
it.

Andy
 

Welcome to EDABoard.com

Sponsor

Back
Top