Useful IEEE Functions
Practical VHDL functions from std_logic_1164, numeric_std, std.env, textio and math_real.
Why this chapter
IEEE libraries do more than declare std_logic or unsigned. They also provide functions that make VHDL safer, clearer and easier to test.
The goal is not to memorize everything. The goal is to know which function to use in common situations.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;Keep this simple rule: for arithmetic, use numeric_std. Avoid old non-standard packages such as std_logic_arith, std_logic_unsigned or std_logic_signed.
std_logic_1164
The std_logic_1164 package defines std_logic, std_logic_vector and functions related to 9-state logic values.
| Function | Use |
|---|---|
rising_edge(i_clk) | Detect a rising clock edge |
falling_edge(i_clk) | Detect a falling edge |
Is_X(w_bus) | Detect an unknown value ('U', 'X', etc.) |
To_01(w_bus) | Map a vector back to 0/1 values |
to_hstring(w_bus) | Print a vector in hexadecimal during simulation |
Clock edges
For FPGA synchronous logic, the standard idiom remains:
p_reg : process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_count <= (others => '0');
else
r_count <= r_count + 1;
end if;
end if;
end process p_reg;rising_edge is preferable to i_clk'event and i_clk = '1', because it follows the valid transitions of the std_logic system.
Detect unknowns in simulation
Is_X is useful in testbenches. It prevents a test from accepting a result that still contains an unknown value.
assert not Is_X(o_data)
report "o_data contains an unknown value: " & to_hstring(o_data)
severity error;In synthesis, this kind of check has no direct hardware meaning. It mainly protects simulations.
numeric_std
numeric_std adds numeric interpretation through unsigned and signed.
| Function | Use |
|---|---|
to_unsigned(i, n) | Convert a natural integer to unsigned(n-1 downto 0) |
to_signed(i, n) | Convert a signed integer to signed(n-1 downto 0) |
to_integer(x) | Convert unsigned or signed to integer |
resize(x, n) | Adapt the width of an unsigned or signed value |
shift_left(x, n) | Shift left |
Clean conversions
signal r_count : unsigned(7 downto 0);
signal w_index : integer range 0 to 255;
w_index <= to_integer(r_count);
r_count <= to_unsigned(42, r_count'length);The width must be explicit. This removes ambiguity between an abstract number and a real hardware bus.
resize and result width
resize adapts the size while respecting the type:
- with
unsigned, it extends with0; - with
signed, it sign-extends.
signal r_a : unsigned(7 downto 0);
signal r_b : unsigned(7 downto 0);
signal r_sum : unsigned(8 downto 0);
r_sum <= resize(r_a, r_sum'length) + resize(r_b, r_sum'length);For an addition that must keep the carry, widen the operands before the operation.
Display functions
In a testbench, hexadecimal output makes failures much easier to read.
report "data = 0x" & to_hstring(o_data) severity note;For a wide bus, to_hstring is usually clearer than a full binary string.
std.env
Since VHDL-2008, the std.env package can stop a simulation cleanly.
library STD;
use STD.ENV.ALL;
-- end of testbench
report "Test completed" severity note;
finish;finish is more explicit than a plain wait; when the testbench is really done.
textio
textio reads and writes files during simulation. It is useful to:
- load stimuli;
- compare expected results;
- generate a simulation log.
For logic vectors, hread and hwrite work directly in hexadecimal.
library STD;
use STD.TEXTIO.ALL;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
file f_vectors : text open read_mode is "vectors.txt";
variable v_line : line;
variable v_data : std_logic_vector(7 downto 0);
variable v_ok : boolean;
readline(f_vectors, v_line);
hread(v_line, v_data, v_ok);
assert v_ok
report "Invalid stimulus line"
severity error;This code is for simulation. Do not use it inside synthesizable RTL.
math_real
math_real provides mathematical functions on the real type: sqrt, ceil, floor, sin, cos, uniform, etc.
In FPGA work, this package is mostly useful for testbenches and constants computed at elaboration. Do not use it as real-time hardware logic.
Example pseudo-random stimulus:
library IEEE;
use IEEE.MATH_REAL.ALL;
variable v_seed1 : positive := 101;
variable v_seed2 : positive := 203;
variable v_rand : real;
uniform(v_seed1, v_seed2, v_rand);Key takeaways
| Need | Typical function |
|---|---|
| Detect an edge | rising_edge |
| Convert an integer to a bus | to_unsigned, to_signed |
| Convert a numeric bus to integer | to_integer |
| Change width | resize |
| Print a bus in hexadecimal | to_hstring |
| Read a hexadecimal vector in simulation | hread |
| End a testbench | finish |
| Generate random stimuli | uniform |
📝 Test your knowledge - Chapter quiz