如何在 vhdl 中将整数转换为带前导零的字符串?

How to convert integer to string with leading zeros in vhdl?

如何在 VHDL 中打印带前导零的整数?

本质上实现与 C 或 Python:

相同
printf("%05d", number);
str(number).zfill(5)

当然,这将仅用于模拟(写入文件或报告等)。

到目前为止,我想到的最好的方法是这个函数:

-- Range is limited to from 1 to 9 as 10 digit
-- integer can already overflow in VHDL
function fIntToStringLeading0 (a : natural; d : integer range 1 to 9) return string is
  variable vString : string(1 to d);
begin
  if(a >= 10**d) then
    return integer'image(a);
  else
    for i in 0 to d-1 loop
      vString(d-i to d-i) := integer'image(a/(10**i) mod 10);
    end loop;
    return vString;
  end if;
end function;

例如:

  process  is
    variable number : integer := 42;
  begin
    report fIntToStringLeading0(number, 5);
    wait;
  end process;

输出:

# ** Note: 00042

这里有一条双线:

  ZEROES := (others => '0');
  ZEROES(ZEROES'length-integer'image(N)'length+1 to ZEROES'length) := integer'image(N);

例如

entity LEADING_ZEROES is
end entity ;

architecture LEADING_ZEROES of LEADING_ZEROES is
begin

  process
    constant MAXLENGTH : integer := 10;
    variable N : integer;
    variable ZEROES : string(1 to MAXLENGTH);
  begin
    N := 1234;
    ZEROES := (others => '0');
    ZEROES(ZEROES'length-integer'image(N)'length+1 to ZEROES'length) := integer'image(N);
    report ZEROES;
    wait;
  end process;

end architecture LEADING_ZEROES;

https://www.edaplayground.com/x/4B84

最好将它包装在像您这样的函数中并添加您的检查:

  function fIntToStringLeading0 (a : natural; d : integer range 1 to 9) return string is
    variable vString : string(1 to d) := (others => '0');
  begin
    if(a >= 10**d) then
      return integer'image(a);
    else
      return vString(1 to vString'length-integer'image(a)'length) & integer'image(a);
    end if;
  end function;

例如

entity LEADING_ZEROES is
end entity ;

architecture LEADING_ZEROES of LEADING_ZEROES is
  function fIntToStringLeading0 (a : natural; d : integer range 1 to 9) return string is
    variable vString : string(1 to d) := (others => '0');
  begin
    if(a >= 10**d) then
      return integer'image(a);
    else
      return vString(1 to vString'length-integer'image(a)'length) & integer'image(a);
    end if;
  end function;
begin

  process
  begin
    report fIntToStringLeading0(1234,5);
    report fIntToStringLeading0(12345,6);
    report fIntToStringLeading0(12345,3);
    wait;
  end process;

end architecture LEADING_ZEROES;

https://www.edaplayground.com/x/255x

这是另一个想法,它通过使用 TEXTIO 写入过程来取消检查以确保需要任何前导零,该过程会进行此类检查。问题是,写入程序在前导空格中放置的不是零,并且用零代替空格很笨拙:

  function fIntToStringLeading0 (a : natural; d : integer range 1 to 9) return string is
    variable L : line;
  begin
    write(L,a,right,d);
    for I in 1 to L.all'length loop
      if L.all(I) = ' ' then
        L.all(I) := '0';
      end if;
    end loop;
    return L.all;
  end function;

例如

use std.textio.all;

entity LEADING_ZEROES is
end entity ;

architecture LEADING_ZEROES of LEADING_ZEROES is
  function fIntToStringLeading0 (a : natural; d : integer range 1 to 9) return string is
    variable L : line;
  begin
    write(L,a,right,d);
    for I in 1 to L.all'length loop
      if L.all(I) = ' ' then
        L.all(I) := '0';
      end if;
    end loop;
    return L.all;
  end function;
begin

  process
  begin
    report fIntToStringLeading0(1234,5);
    report fIntToStringLeading0(12345,6);
    report fIntToStringLeading0(12345,3);
    wait;
  end process;

end architecture LEADING_ZEROES;

https://www.edaplayground.com/x/39di

有一个针对 C 风格格式化的开源包。你会在这里找到它 https://github.com/suoto/hdl_string_format

有 VHDL 方式。编写一个通用的 to_dstring 函数:

use std.textio.all;

entity rightjustd is
end entity;

architecture foo of rightjustd is
    type filltype is (NOFILL, ZEROFILL);
    function to_dstring (
        value:      in integer;
        field:      in width := 0;
        just:       in side := RIGHT;
        fill:       in filltype := NOFILL
    ) return string is
        variable retstr: string (1 to field);
    begin
        if field = 0 then
            return integer'image(value);
        elsif field < integer'image(value)'length then 
            retstr := (others => '#');
        elsif fill = NOFILL  or just = LEFT then
            retstr := justify (integer'image(value), just, field);
        else  -- fill = ZEROFILL and just = RIGHT, field >= image length
            retstr  := justify (integer'image(abs value), just, field);
            for i in retstr'range loop
                if retstr(i) = ' ' then
                    retstr(i) := '0';
                end if;
            end loop;
            if value < 0 then
                retstr(1) := '-';
            end if;
        end if;
        return retstr;
    end function to_dstring;
begin
    process
    begin
        report to_dstring(-2456, 12, RIGHT, ZEROFILL);
        report to_dstring(-2456, 4, RIGHT, ZEROFILL);
        report to_dstring(-2456);
        report to_dstring(-2456, 12, LEFT, ZEROFILL) & '.';
        report to_dstring(-2456, 12, RIGHT);
        wait;
    end process;
end architecture;

这还没有经过彻底的测试。测试用例产生:

rightjustd.vhdl:38:9:@0ms:(report note): -00000002456
rightjustd.vhdl:39:9:@0ms:(report note): ####
rightjustd.vhdl:40:9:@0ms:(report note): -2456
rightjustd.vhdl:41:9:@0ms:(report note): -2456       .
rightjustd.vhdl:42:9:@0ms:(report note):        -2456

(class 常量)输入的初始值意味着您可以从右到左离开参数,一直到只提供一个整数值。

justify 函数调用需要 -2008 并在包 textio 中声明。

如果我没理解错的话,你只是想

printf("%05d", number);  // in C

进入

print("%05d" % number)   # in python