VHDL-2008 to_01 conversion
Asked Answered
R

3

5

I am getting some unexpected behavior when using the to_01 conversion function in VHDL-2008. My expectation would be that vector bits that can clearly be interpreted as high or low are mapped to '1' and '0' respectively. The remaining vector bits should be converted to '0' bits. However, with the code depicted below, I get the whole vector converted to all '0's.

Is this behavior correct? Or is this a bug in the simulator software (ALDEC Riviera-PRO)?

Is there any IEEE function that meets my expectations or do I have to write my own function to achieve that?

library ieee;
use ieee.std_logic_1164.all;

entity test_to_01 is
end entity test_to_01;

architecture rtl of test_to_01 is
    signal s_test_in    : std_logic_vector(8 downto 0)  := "UX01ZWLH-";
    signal s_test_out   : std_logic_vector(8 downto 0);
begin
    s_test_out  <=  to_01(s_test_in);
end architecture rtl;

enter image description here

Raphaelraphaela answered 22/11, 2017 at 9:10 Comment(2)
The to__01 function has a test for metalogical values (or 'Z'). When finding any it returns an array value comprised of the (in this case default '0') xmap parameter. You can download the -2008 Supplemental Material which includes the source to IEEE packages, this in the zip, 1076-2008_machine_readable/ieee/std_logic_1164-body.vhdl. You have a typo listing 'Z' twice in the initial value of s_test_in). Updated - going to point at Jim's source I noticed the link was incorrect.Fiorin
There is to_X01 which will map the other values to an X rather than 0.Unthoughtof
U
5

The observed behavior is the correct behavior. A little history about this follows.

In 2008, we propagated all of the strength reduction operations to all std_logic family packages. For better or worse, the historical implementation of to_01 comes from numeric_std and was implemented exactly as it is now. The following is an older implementation I was able to find on the web:

function TO_01(S : SIGNED ; xmap : STD_LOGIC:= '0') return SIGNED is
variable RESULT: SIGNED(S'length-1 downto 0);
variable bad_element : boolean := FALSE;
alias xs : SIGNED(s'length-1 downto 0) is S;
begin
  for i in RESULT'range loop
    case xs(i) is
      when '0' | 'L' => RESULT(i):='0';
      when '1' | 'H' => RESULT(i):='1';
      when others => bad_element := TRUE;
      end case;
    end loop;
  if bad_element then
    assert NO_WARNING
      report "numeric_std.TO_01: Array Element not in {0,1,H,L}"
      severity warning;
    for i in RESULT'range loop
      RESULT(i) := xmap;        -- standard fixup
      end loop;
    end if;
  return RESULT;
  end TO_01;

One of the prime directives of the VHDL WG is to not break old code. In this case it looks like this objective put forward an implementation that perhaps is less desirable.

If you want something different, you can always put it forward for the next revision of the standard. It would have to have a different name. Note we are currently closing on VHDL-2018 now, so it would be the revision after that.

Note that IEEE P1076 WG is an individual based working group. This means experienced users, such as yourself, are participating. Typically the amount of work done in a standards revision is overwhelming. As a result, we always need more active participants. Particularly working on the packages. See eda-twiki.org and http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/WebHome

Unthoughtof answered 22/11, 2017 at 16:25 Comment(5)
You could note the numeric_std function TO_01 (S: UNSIGNED; XMAP: STD_LOGIC := '0') return UNSIGNED (Id: T.1) from pre -2008 matches the behavior in -2008 package std_logic_1164 for std_ulogic_vector (used in the OP's question). The package numeric_std TO_01 in -2008 calls TO_01 in package std_logic_1164 for signed and unsigned. The behavior is as intended. The original behavior of the signed version would be considered incorrect.Fiorin
The present behavior has been specified since P1076.3 Rev. 1.7 (Nov. 23 1994) which would have been released in 1996.Fiorin
I cannot derive from this answer why his code is not working.Gnathic
@Gnathic In the code (posted above) if there is a UXZW- then it returns all of the XMAP value which is 0 - which correlates with the OP's observed behavior. So yes the values he observed are the correct ones.Unthoughtof
@Fiorin From the post, "For better or worse, the historical implementation of to_01 comes from numeric_std and was implemented exactly as it is now." Yes I could have referenced the precise versions of 1076.3 that created this, but I don't really think that would have added anything useful to the post.Unthoughtof
R
6

I found a workaround:

s_test_out  <=  to_stdlogicvector(to_bitvector(s_test_in));

enter image description here

Raphaelraphaela answered 22/11, 2017 at 9:58 Comment(0)
U
5

The observed behavior is the correct behavior. A little history about this follows.

In 2008, we propagated all of the strength reduction operations to all std_logic family packages. For better or worse, the historical implementation of to_01 comes from numeric_std and was implemented exactly as it is now. The following is an older implementation I was able to find on the web:

function TO_01(S : SIGNED ; xmap : STD_LOGIC:= '0') return SIGNED is
variable RESULT: SIGNED(S'length-1 downto 0);
variable bad_element : boolean := FALSE;
alias xs : SIGNED(s'length-1 downto 0) is S;
begin
  for i in RESULT'range loop
    case xs(i) is
      when '0' | 'L' => RESULT(i):='0';
      when '1' | 'H' => RESULT(i):='1';
      when others => bad_element := TRUE;
      end case;
    end loop;
  if bad_element then
    assert NO_WARNING
      report "numeric_std.TO_01: Array Element not in {0,1,H,L}"
      severity warning;
    for i in RESULT'range loop
      RESULT(i) := xmap;        -- standard fixup
      end loop;
    end if;
  return RESULT;
  end TO_01;

One of the prime directives of the VHDL WG is to not break old code. In this case it looks like this objective put forward an implementation that perhaps is less desirable.

If you want something different, you can always put it forward for the next revision of the standard. It would have to have a different name. Note we are currently closing on VHDL-2018 now, so it would be the revision after that.

Note that IEEE P1076 WG is an individual based working group. This means experienced users, such as yourself, are participating. Typically the amount of work done in a standards revision is overwhelming. As a result, we always need more active participants. Particularly working on the packages. See eda-twiki.org and http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/WebHome

Unthoughtof answered 22/11, 2017 at 16:25 Comment(5)
You could note the numeric_std function TO_01 (S: UNSIGNED; XMAP: STD_LOGIC := '0') return UNSIGNED (Id: T.1) from pre -2008 matches the behavior in -2008 package std_logic_1164 for std_ulogic_vector (used in the OP's question). The package numeric_std TO_01 in -2008 calls TO_01 in package std_logic_1164 for signed and unsigned. The behavior is as intended. The original behavior of the signed version would be considered incorrect.Fiorin
The present behavior has been specified since P1076.3 Rev. 1.7 (Nov. 23 1994) which would have been released in 1996.Fiorin
I cannot derive from this answer why his code is not working.Gnathic
@Gnathic In the code (posted above) if there is a UXZW- then it returns all of the XMAP value which is 0 - which correlates with the OP's observed behavior. So yes the values he observed are the correct ones.Unthoughtof
@Fiorin From the post, "For better or worse, the historical implementation of to_01 comes from numeric_std and was implemented exactly as it is now." Yes I could have referenced the precise versions of 1076.3 that created this, but I don't really think that would have added anything useful to the post.Unthoughtof
O
0

You may use a generate statement

gen_to_01 : for i in 0 to s_test_in'length-1 generate
begin
    s_test_out(i) <= to_01(s_test_in(i));
end generate;
Outspread answered 31/5 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.