How to write an integer to stdout as hexadecimal in VHDL?
Asked Answered
C

3

9

I can print an integer as decimal to stdout with:

library std;
use std.textio.all;

entity min is
end min;

architecture behav of min is
begin
    process is
        variable my_line : line;
    begin
        write(my_line, 16);
        writeline(output, my_line);
        wait;
    end process;
end behav;

which outputs:

16

But how to output instead either:

10
0x10
Clapperclaw answered 17/6, 2016 at 11:2 Comment(2)
@downvoters: please explain so I can learn and improve ;-)Clapperclaw
Each hexadecimal digit represents four binary digits (bits). An integer scalar is a discrete type with a position that is an integer value (IEEE Std 1076-2008, 5.2 Scalar types) - and integr doesn't have bits. You could write a function to convert an integer value to base16 amenable to a string notation with a based literal equivalent (15.5.3), or convert an integer value to a type that does represent binary bits numerically and whose string representation has a bit string equivalent (15.8).Haihaida
A
14

Assuming an integer i, and VHDL-2008, you could use:

write(output, integer'image(i) & LF);  -- Plain integer value
write(output, "0x" & to_hstring(to_signed(i, 32)) & LF);  -- Hexadecimal representation

You need to have use std.textio.all; for this to work. Change the 32 to reduce the length of the hex value. I chose 32 so that it can represent any integer value in most simulators.

These will also work for report statements, e.g.

report "i = 0x" & to_hstring(to_signed(i, 32));
Agonize answered 17/6, 2016 at 14:48 Comment(2)
Can we extract that 32 computationally from the input? I know about the integer'high attribute, but is there something more direct?Clapperclaw
Yes, you could use an answer like this one to compute the width required: #12750507Agonize
D
4

There is no standard library implementation, but for example our PoC-Libary has several formatting function in the PoC.Strings package. On top of that, we have a to_string(...) function, which accepts a format character like h for hexadecimal outputs.

How to write such an integer to hex conversion?

  1. Convert the INTEGER into a binary representation
  2. Group the binary value into 4-bit groups
  3. translate each group into an integer/alpha in range 0..F
  4. prepend 0x if wished

So here is a wrapper to convert the integer to a binary representation:

-- format a natural as HEX string
function raw_format_nat_hex(Value : NATURAL) return STRING is
begin
  return raw_format_slv_hex(std_logic_vector(to_unsigned(Value, log2ceil(Value+1))));
end function;

And now the grouping and transformation

-- format a std_logic_vector as HEX string
function raw_format_slv_hex(slv : STD_LOGIC_VECTOR) return STRING is
  variable Value                : STD_LOGIC_VECTOR(4*div_ceil(slv'length, 4) - 1 downto 0);
  variable Digit                : STD_LOGIC_VECTOR(3 downto 0);
  variable Result               : STRING(1 to div_ceil(slv'length, 4));
  variable j                    : NATURAL;
begin
  Value := resize(slv, Value'length);
  j             := 0;
  for i in Result'reverse_range loop
    Digit       := Value((j * 4) + 3 downto (j * 4));
    Result(i)   := to_HexChar(unsigned(Digit));
    j           := j + 1;
  end loop;
  return Result;
end function;

-- convert an unsigned value(4 bit) to a HEX digit (0-F)
function to_HexChar(Value : UNSIGNED) return CHARACTER is
  constant HEX : STRING := "0123456789ABCDEF";
begin
  if (Value < 16) then
    return HEX(to_integer(Value)+1);
  else
    return 'X';
  end if;
end function;

-- return TRUE, if input is a power of 2
function div_ceil(a : NATURAL; b : POSITIVE) return NATURAL is  -- calculates: ceil(a / b)
begin
  return (a + (b - 1)) / b;
end function;

-- return log2; always rounded up
function log2ceil(arg : positive) return natural is
  variable tmp : positive;
  variable log : natural;
begin
  if arg = 1 then   return 0; end if;
  tmp := 1;
  log := 0;
  while arg > tmp loop
    tmp := tmp * 2;
    log := log + 1;
  end loop;
  return log;
end function;

Note: These functions do not prepend 0x.

Dzoba answered 17/6, 2016 at 12:19 Comment(1)
What, no function div_ceil?Haihaida
Z
3

You could use the hwrite procedure in the IEEE.std_logic_textio package:

library IEEE;                                                   -- ADDED
use IEEE.std_logic_1164.all;                                    -- ADDED
use IEEE.numeric_std.all;                                       -- ADDED
use IEEE.std_logic_textio.all;                                  -- ADDED

library std;
use std.textio.all;

entity min is
end min;

architecture behav of min is
begin
    process is
        variable my_line : line;
    begin
        hwrite(my_line, std_logic_vector(to_unsigned(16,8)));   -- CHANGED
        writeline(output, my_line);
        wait;
    end process;
end behav;

The hwrite procedure writes a std_logic_vector to a file. So, you do have to convert your integer into a std_logic_vector, however (which also needs you to specify a number of bits in the to_unsigned function).

http://www.edaplayground.com/x/exs

Zakaria answered 17/6, 2016 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.