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:
ghdl-nightly-mingw32-mcode.zip from https://github.com/ghdl/ghdl/releasesC:\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
...
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!
Most helpful comment
Yes, you're right. I missed the change past vhdl 1987!