Ghdl: Bug: Attribute `last_value` doesn't always return the expected value.

Created on 18 Aug 2020  路  5Comments  路  Source: ghdl/ghdl

Description
Attribute last_value doesn't always return the expected value.

Expected behaviour
See attached log.
I expect:

tb_last_value_bug.vhd:18:9:@30ns:(report note): cnt:  value = 00000010  last_value = 00000001
tb_last_value_bug.vhd:18:9:@40ns:(report note): cnt:  value = 00000011  last_value = 00000010

Actual behaviour:

tb_last_value_bug.vhd:18:9:@30ns:(report note): cnt:  value = 00000010  last_value = 00000001
tb_last_value_bug.vhd:18:9:@40ns:(report note): cnt:  value = 00000011  last_value = 00000000

How to reproduce?

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity tb_last_value_bug is
end entity;

architecture tb of tb_last_value_bug is
    signal cnt : std_logic_vector(7 downto 0) := (others=>'0');
begin
    process
    begin
        wait for 10 ns;
        cnt <= std_logic_vector(unsigned(cnt) + 1);
        report "cnt:  value = " & to_string(cnt) & "  last_value = " & to_string(cnt'last_value) ;
    end process;
end architecture;
ghdl.exe -a --std=08 tb_last_value_bug.vhd
ghdl.exe --elab-run --std=08 tb_last_value_bug --stop-time=1us

Context
Please, provide the following information:

C:\tools\GHDL\nightly-mingw32-mcode\bin>ghdl --version
GHDL 1.0-dev (v0.37.0-965-g8789de96) [Dunoon edition]
 Compiled with GNAT Version: 9.1.0
 mcode code generator
Written by Tristan Gingold.

Copyright (C) 2003 - 2020 Tristan Gingold.
GHDL is free software, covered by the GNU General Public License.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Additional context

tb_last_value_bug.vhd:18:9:@10ns:(report note): cnt:  value = 00000000  last_value = 00000000
tb_last_value_bug.vhd:18:9:@20ns:(report note): cnt:  value = 00000001  last_value = 00000000
tb_last_value_bug.vhd:18:9:@30ns:(report note): cnt:  value = 00000010  last_value = 00000001
tb_last_value_bug.vhd:18:9:@40ns:(report note): cnt:  value = 00000011  last_value = 00000000
tb_last_value_bug.vhd:18:9:@50ns:(report note): cnt:  value = 00000100  last_value = 00000011
tb_last_value_bug.vhd:18:9:@60ns:(report note): cnt:  value = 00000101  last_value = 00000010
tb_last_value_bug.vhd:18:9:@70ns:(report note): cnt:  value = 00000110  last_value = 00000001
tb_last_value_bug.vhd:18:9:@80ns:(report note): cnt:  value = 00000111  last_value = 00000000
tb_last_value_bug.vhd:18:9:@90ns:(report note): cnt:  value = 00001000  last_value = 00000111
...
LRM reading

Most helpful comment

Yes, you're right. I missed the change past vhdl 1987!

All 5 comments

I think ghdl is correct. The last value is the last value of individual bits.

So when the counter goes from 10 to 11, the last value of bit 0 is 0. The bit 1 hasn't changed, so its last value is also 0.

Last value is the value before the last event.

I don't understand why the individual bits are evaluated instead of the whole vector as one signal. According to the LRM last_value returns the previous value of a signal.

LRM VHDL-2000:

S'LAST_VALUE
    Kind:           Function.
    Prefix:         Any signal denoted by the static signal name S.
    Result Type:    The base type of S.
    Result:         The previous value of S, immediately before the last change of S.

From my understanding the whole vector is the signal S, hence last_value should return the previous value of the whole vector and not just the last value of the individual bits.

Is there another reference for the GHDL behaviour? Maybe I overlooked something.

I found the following information in the book The Designers Guide to VHDL by Peter Ashenden:

In VHDL-87, the 'last_value attribute for a composite signal returns the aggregate of
last values for each of the scalar elements of the signal. For example, suppose a bitvector
signal s initially has the value B"00" and changes to B"01" and then B"11" in
successive events. After the last event, the result of s'last_value is B"00" in VHDL-87.
In VHDL-93 and VHDL-2002 it is B"01", since that is the last value of the entire composite
signal.

I found the differences in the LRMs. The current implementation is indeed the VHDL-87 implementation.
But the non-VHDL-87 implementation is missing. In the test above VHDL-2008 is used.

LRM VHDL-87 (p. 14-8):

S'LAST_VALUE
Kind:           Function
Prefix:         Any signal denoted by the static signal name S.
Result Type:    The base type of S.
Result:         The previous value of S, immediately before the last
                change of S. Specifically:

For a scalar signal S, S'LAST_VALUE = S'DELAYED(T) where T >= Ons is the
smallest value such that S'STABLE(T) is FALSE. If no such T exists, then
S'LAST_VALUE is equal to S.
For a composite signal S, S'LAST_VALUE is equal to the aggregate of the previous
values of each element of S.

(Note that:

(1)     if S'STABLE(T) is FALSE, then by definition,
        for some t where Ons <= t <= T, S'DELAYED(t) /= S; and

(2)     if Ts is the smallest value such that S'STABLE (TS) is FALSE, then for all
        t where Ons <= t < Ts, S'DELAYED(t) = S.)

LRM VHDL-2008 (p. 247):

S'LAST_VALUE 
Kind:           Function.
Prefix:         Any signal denoted by the static signal name S.
Result type:    The base type of S.
Result:         For a signal S, if an event has occurred on S in any simulation cycle,
                S'LAST_VALUE returns the value of S prior to the update of S in the
                last simulation cycle in which an event occurred; otherwise,
                S'LAST_VALUE returns the current value of S.
NOTE 8鈥擣or a composite signal S, if an event on S as a whole is caused by an event on a subelement of S, the value of
S'LAST_VALUE is the whole value of S before the update of the subelement. That value includes subelement values
that may not have changed.

Yes, you're right. I missed the change past vhdl 1987!

Was this page helpful?
0 / 5 - 0 ratings