cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Advisor
Advisor
4,255 Views
Registered: ‎10-10-2014

VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

 

In the past I wrote my counters using VHDL 93 syntax (at least I think it's 93, not 2002)

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity vhdl_93_cntr is
generic(
    kVALUE      : integer := 5
);
port (
    clk         : in std_logic;
    rst         : in std_logic;
    
    count_out   : out std_logic_vector(3 downto 0);
    value_match : out std_logic
);
end vhdl_93_cntr;

architecture Behavioral of vhdl_93_cntr is

    signal cntr : unsigned(3 downto 0);
    
begin

    proc_cntr : process(clk)
    begin
        if rising_edge(clk) then
            if rst = '1' then
                cntr <= (others => '0');
            else
                cntr <= cntr + 1;
            end if;            
        end if;
    end process proc_cntr;
    
    value_match <= '1' when cntr = to_unsigned(kVALUE, cntr'length) else '0';
    
    -- connect outputs (typecast unsigned to std_logic_vector)
    count_out <= std_logic_vector(cntr);

end Behavioral;

so I use an unsigned 'internal' counter, as std_logic_vector do not allow direct addition. Unless I would use the library 'std_logic_unsigned', but I read in many places that this should be considered a (non-standard) and depricated package, and I should be replaced with numeric_std, so I do that.

 

now I want to rewrite the above counter using proper VHDL-2008 syntax  (using Vivado 2017.2), and I came to this :

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.Numeric_Std_Unsigned.all;  -- <-- add this to do unsigned arithmetic with std_logic_vector
entity vhdl_2008_cntr is generic( kVALUE : integer := 5 ); port ( clk : in std_logic; rst : in std_logic; count_out : out std_logic_vector(3 downto 0); value_match : out std_logic ); end vhdl_2008_cntr; architecture Behavioral of vhdl_2008_cntr is -- signal cntr : unsigned(3 downto 0); <-- no longer needed begin proc_cntr : process(clk) begin if rising_edge(clk) then if rst = '1' then count_out <= (others => '0'); else count_out <= count_out + 1; -- <- std_logic_vector arithmetic is supported end if; end if; end process proc_cntr; -- VHDL-2008 allows a shorter syntax -- we can also read from count_out directly without using 'BUFFER' value_match <= count_out ?= std_logic_vector(to_unsigned(kVALUE, count_out'length)); end Behavioral;

Q1 : I'm  wondering : is it a good idea to drop the '93 style approach using an 'unsigned' counter and typecasting it to the std_logic_vector count_out, as in the first code example, and use the std_logic_vector arithmetic? I'm in doubt, because with my above code, it's clear that I want to use unsigned additions. I've read that  :

 

In the past this has mainly been achieved by using the non-standard std_logic_unsigned and std_logic_signed packages. VHDL-2008 addresses this issue by adding two new standard arithmetic packages, IEEE.Numeric_Std_Unsigned and IEEE.Numeric_Std_Signed.

 

Q2 : now as far as I can see, only Numeric_Std_Unsigned is currently supported in Vivado (2017.2), but Numeric_Std_Signed is not. Is that correct?

 

Q3 : if however Vivado will (in the future?) support Numeric_Std_Signed, and I would also add a 'use ieee.Numeric_Std_Signed.all' at the top of the filehow would the compiler know wether I want signed or unsigned additions in my code / counter?

 

 

 

 

 

 

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Scholar
Scholar
5,004 Views
Registered: ‎08-01-2012

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

Ok, lets clear a few things up.

There is hardly any difference between 2002 and 1993 code. The only difference is the introduction of protected types that are not synthesisable, and the rule that shared variables must be protected types (this is not a 2008 rule, like some xilinx 2008 documentation leads you to believe)

 

Std_logic_unsinged/signed and std_logic_arith have not and will never be depricated. They have become a bit of a defacto standard. Originally written by synopsys in the early 90s, other vendors wrote their own versions of the packages (with the same name, and compiled into the ieee library) that were not all compatible with each other - this is why many people recommend you dont use them. But in reality all tools just uses the synopsys versions now (from 1992), and they will all be compatible with each other. (std_logic_arith is besically a synopsys version of numeric_std, without as many functions)

 

Next, because of the above, and the general annoyance of (mostly Verilog engineers) creating counters with numeric_std, the VHDL standard committee capitulated and created the numeric_std_unsigned package. This isnt much more than a wrapper around numeric_std.

 

So, to answer the questions:

1. There is no numeric_std_signed package. If you're doing arithmatic, you should probably be using numeric_std. I see the only real use for numeric_std_unsigned is for small things like counters.

 

2. use numeric_std. For the old days of std_logic_unsigned/signed, the short answer is you couldnt, you could only do signed or unsigned logic, based on the package you imported. Long answer is you can, but you need to be explicit for each function call:

 

op_unsigned <= a ieee.std_logic_unsigned."+" b;
op_signed <= c ieee.std_logic_signed."+" d;

 

comments on the code:

 

 value_match <= '1' when cntr = to_unsigned(kVALUE, cntr'length) else '0';

Is a little excessive. You can compare an unsigned directly to and integer (since '93)

 

 value_match <= '1' when cntr = kVALUE else '0';

 For 2008 SLV version, you use the same code, as it has an "=" function to compare SLV and integer. But it also contains the to_slv function to convert integer to std_logic_vector.

 

-- to_slv function not needed, but included for demonstration.
value_match <= count_out ?= to_slv(kVALUE, count_out'length);

 

But here is a warning (as I found out myself). if you include numeric_std_unsigned, you can no longer check your bus for Meta Values (like 'X' or '-'), as this is treated as a non integer and therefore always false. eg.

 

if bus = "XXXX" then report "Bad values on bus"
else report "everything is fine".

Here, if you include numeric_std_unsigned, then it will always report "everything is fine", even if bus="XXXX" (and to top it off, you'll get warnings from numeric_std, not numeric_std_unsigned).

View solution in original post

8 Replies
Highlighted
Scholar
Scholar
5,005 Views
Registered: ‎08-01-2012

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

Ok, lets clear a few things up.

There is hardly any difference between 2002 and 1993 code. The only difference is the introduction of protected types that are not synthesisable, and the rule that shared variables must be protected types (this is not a 2008 rule, like some xilinx 2008 documentation leads you to believe)

 

Std_logic_unsinged/signed and std_logic_arith have not and will never be depricated. They have become a bit of a defacto standard. Originally written by synopsys in the early 90s, other vendors wrote their own versions of the packages (with the same name, and compiled into the ieee library) that were not all compatible with each other - this is why many people recommend you dont use them. But in reality all tools just uses the synopsys versions now (from 1992), and they will all be compatible with each other. (std_logic_arith is besically a synopsys version of numeric_std, without as many functions)

 

Next, because of the above, and the general annoyance of (mostly Verilog engineers) creating counters with numeric_std, the VHDL standard committee capitulated and created the numeric_std_unsigned package. This isnt much more than a wrapper around numeric_std.

 

So, to answer the questions:

1. There is no numeric_std_signed package. If you're doing arithmatic, you should probably be using numeric_std. I see the only real use for numeric_std_unsigned is for small things like counters.

 

2. use numeric_std. For the old days of std_logic_unsigned/signed, the short answer is you couldnt, you could only do signed or unsigned logic, based on the package you imported. Long answer is you can, but you need to be explicit for each function call:

 

op_unsigned <= a ieee.std_logic_unsigned."+" b;
op_signed <= c ieee.std_logic_signed."+" d;

 

comments on the code:

 

 value_match <= '1' when cntr = to_unsigned(kVALUE, cntr'length) else '0';

Is a little excessive. You can compare an unsigned directly to and integer (since '93)

 

 value_match <= '1' when cntr = kVALUE else '0';

 For 2008 SLV version, you use the same code, as it has an "=" function to compare SLV and integer. But it also contains the to_slv function to convert integer to std_logic_vector.

 

-- to_slv function not needed, but included for demonstration.
value_match <= count_out ?= to_slv(kVALUE, count_out'length);

 

But here is a warning (as I found out myself). if you include numeric_std_unsigned, you can no longer check your bus for Meta Values (like 'X' or '-'), as this is treated as a non integer and therefore always false. eg.

 

if bus = "XXXX" then report "Bad values on bus"
else report "everything is fine".

Here, if you include numeric_std_unsigned, then it will always report "everything is fine", even if bus="XXXX" (and to top it off, you'll get warnings from numeric_std, not numeric_std_unsigned).

View solution in original post

Highlighted
Advisor
Advisor
4,216 Views
Registered: ‎10-10-2014

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

thanks a lot @richardhead for that (historical) insight!

 

but I noticed that I'm only allowed to add 1 to the SLV in my counter process, if I add the numeric_std_unsigned library. 

 

So if I understand your recommendation, I should :

* not to use numeric_std_unsigned

* forget about adding '1' to the slv directly in my counter, and keep on using the '93 style of my counter?

 

because if I see code from people who use std_logic_unsinged and std_logic_arith, they can just add '1' to the SLV in the counter (which leads to a bit more compact code).

 

So such 'shorter' and direct SLV addition is not achievable with VHDL-2008 and numeric_std? I was asuming Numeric_Std_Unsigned (new in VHDL 2008?) allowed me just to do that, as the warning of '0' definitions found for operator '+' immediately disappeared when I added this library... ?

 

edit : sometimes I use this as a 'workaround' if I don't want to create the extra 'unsigned' cntr, and do the typecast (not sure if it's good code practice though) :

 

cntr(15 downto 0) <= std_logic_vector(unsigned(cntr(15 downto 0)) + 1);

 

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Highlighted
Scholar
Scholar
4,194 Views
Registered: ‎08-01-2012

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

@ronnywebers

There is nothing wrong with numeric_std_unsigned. It allows you to treat a slv in the same way you'd use an unsigned type, without all the type conversion.

 

std_logic_unsigned defined a "+" function for slv + std_logic. Im not sure if this exists in numeric std_unsigned. But whats wrong with - its more compact than adding '1':

 

signal cnt : std_logic_vector(7 downto 0);

....

cnt <= cnt + 1;

If you want to use numeric_std, just declare cnt unsigned:

 

signal cnt : unsigned(7 downto 0);

...

cnt <= cnt + 1;

This code:

cntr(15 downto 0) <= std_logic_vector(unsigned(cntr(15 downto 0)) + 1);

Is a pretty standard one liner for those that like to keep it standard. But now its not needed with numeric_std_unsigned.

 

Highlighted
Advisor
Advisor
4,169 Views
Registered: ‎10-10-2014

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

thanks @richardhead I just checked the VHDL 2008 standard, now I understand where my confusion comes from : 

 

some sites that talk about VHDL-2008 like this Doulos page (at the bottom) mention also a 'IEEE.Numeric_Std_Signed' library :

 

-- quote --

Arithmetic on std_logic_vector

VHDL has a well-designed package IEEE.Numeric_Std which creates two new data types unsigned and signed. However it would sometimes be convenient to do arithmetic on std_logic_vector directly - treating it as either two's complement or unsigned.

In the past this has mainly been achieved by using the non-standard std_logic_unsigned and std_logic_signed packages. VHDL-2008 addresses this issue by adding two new standard arithmetic packages, IEEE.Numeric_Std_Unsigned and IEEE.Numeric_Std_Signed.

-- end quote --

 

Now I checked the current VHDL-2008 standard, and there is no mention at all of a IEEE.Numeric_Std_Signed library... ! So it seems that it's left out of the standard, and the Doulos page is incorrect about that.

 

it looks like when you perform arithmetic on an slv in VHDL-2008 using numeric_std_unsigned, the slv s always interpreted as unsigned value (?). So if you want the slv to be interpreted as signed value, you need to typecast it like :  'signed(slv)' ?

 

my final VHDL-2008 code now looks like this :

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.Numeric_Std_Unsigned.all;  -- <-- add this to do unsigned arithmetic with std_logic_vector

entity vhdl_2008_cntr is
generic(
    kVALUE      : integer := 5
);
port (
    clk         : in std_logic;
    rst         : in std_logic;
    
    count_out   : out std_logic_vector(3 downto 0);
    value_match : out std_logic
);
end vhdl_2008_cntr;

architecture Behavioral of vhdl_2008_cntr is
    
begin

    proc_cntr : process(clk)
    begin
        if rising_edge(clk) then
            if rst = '1' then
                count_out <= (others => '0');
            else
                -- VHDL-2008 : '+' on slv is defined in ieee.numeric_std_unsigned
                count_out <= count_out + 1;
            end if;            
        end if;
    end process proc_cntr;
    
   -- 1) VHDL-2008 allows us to read from the out port 'count_out' directly
-- without using 'BUFFER' (or an intermediate/internal)
-- 2) VHDL-2008 ieee.numeric_std_unsigned allows to interprete the slv 'count_out' as unsigned value
-- 3) ieee.numeric_std allows to compare that unsigned value to the integer kVALUE value_match <= '1' when count_out = kVALUE else '0'; end Behavioral;

 

note : if I replace the value_match with (VHDL 2008) :

 

value_match <= count_out ?= to_slv(kVALUE, count_out'length);

or

value_match <= count_out ?= std_logic_vector(to_unsigned(kVALUE, count_out'length));

I get this synthesis warnings :

---------------------------------------------------------------------------------
Start Cross Boundary and Area Optimization
---------------------------------------------------------------------------------
WARNING: [Synth 8-6014] Unused sequential element count_out_reg was removed.  [/home/zynqdev/Zynq/2017_2/video_v1.0/video_1.0/hdl/experiments/vhdl_2008_cntr.vhd:50]
WARNING: [Synth 8-3917] design vhdl_2008_cntr has port value_match driven by constant 1
---------------------------------------------------------------------------------

-> so value_match is 'stuck' at '1' ... that looks like an issue with Vivado to me ? this VHDL 2008 construct seems not to be supported.

 

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Highlighted
Scholar
Scholar
4,159 Views
Registered: ‎08-01-2012

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

Not sure whats going wrong?

Im using ?= just fine with numeric_std. I have one where an unsigned compared to an integer, and another where it compares to another unsigned. Both working ok in 2017.2. Could be a bug with numeric_std_unsigned?

 

--both work as expected:

op0 <= (count ?= 0);
op1 <= (count ?= some_control_reg);
Highlighted
Advisor
Advisor
4,108 Views
Registered: ‎10-10-2014

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

sorry @richardhead, I  switched to another project for a few days. 

 

I did the following : commented out Numeric_Std_Unsigned, so I only use numeric_std as you did, and compare for example as unsigned values :

 

value_match <= unsigned(count_out) ?= to_unsigned(kVALUE, count_out'length);

that works just fine, as you said!

 

So indeed this looks like a bug in Numeric_Std_Unsigned

 

-> any idea how I should report this? Just on the forum and hope someone from Xilinx picks this up? (I checked UG901, Numeric_Std_Unsigned is officially not yet supported, but guess they better check this)

 

 

 

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
Highlighted
Scholar
Scholar
4,081 Views
Registered: ‎08-01-2012

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

Just an update - the matching relation operator is just broken in 2017.2

The elaborated schematic is correct, but the synthesised schematic is just wrong - it ties the result to '1'.

Most annoying when you're using a counter to check for start and end of line!!! Your lines appear to be very short!

 

It's fixed in 2017.4.

Highlighted
Advisor
Advisor
4,070 Views
Registered: ‎10-10-2014

Re: VHDL 2008 & IEEE.Numeric_Std_Unsigned questions

Jump to solution

ok thanks for that update! Intersting to know :-)

 

I hope they catch up with their VHDL 2008 support, and fix all that kind of bugs quickly ...

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos