【问题标题】:vhdl: convert vector to stringvhdl:将向量转换为字符串
【发布时间】:2013-03-02 15:52:12
【问题描述】:

如何将 std_logic 向量、bit_vector 或任何其他向量转换为字符串?

Signal a,b          : UNSIGNED(7 DOWNTO 0);
SIGNAL x,y,z    : BIT_VECTOR(7 DOWNTO 0);

...

report "value: " & BIT_VECTOR'Image(x) severity note;
report "and this one: " & to_string(a) severity note;

这不起作用,那么如何将向量转换为字符串?

【问题讨论】:

    标签: arrays string vector type-conversion vhdl


    【解决方案1】:

    这是我的解决方案:

    function to_string (arg : std_logic_vector) return string is
         variable L : line;
         variable result : string(1 to arg'length);
    begin
        write(L, arg);
        read(L, result);
        return result;
    end function;
    

    请查看它,这只是一个概念验证。 也许这就是@PlayDough 的意思。

    【讨论】:

      【解决方案2】:
      function slv_to_string ( a: std_logic_vector) return string is
          variable b : string (a'length-1 downto 1) := (others => NUL);
      begin
              for i in a'length-1 downto 1 loop
              b(i) := std_logic'image(a((i-1)))(2);
              end loop;
          return b;
      end function;
      

      【讨论】:

      • 此解决方案不正确。参数a的范围是多少?一般来说,它可以是任何合法范围。如果您想假设它是某物,则需要使用别名使其如此。
      【解决方案3】:
      function slv_to_string ( a: std_logic_vector) return string is
          variable b : string (a'length downto 1) := (others => NUL);
          variable c : integer := 1;
      begin
              for i in a'range loop
              b(c) := std_logic'image(a((i-1)))(2);
              c := c + 1;
              end loop;
          return b;
      end function;
      

      Jason's 函数的小修复,这个确实打印整个 std_logic_vector 而不是除了最后一个元素 a(a'length'-1) 之外的所有内容。

      【讨论】:

      • 此解决方案不正确。参数a的范围是多少?一般来说,它可以是任何合法范围。如果您想假设它是某物,则需要使用别名使其如此。
      • @JimLewis 我修复了范围的一些问题,这是您的意思是错误的还是还有更多错误?
      • 模拟它。尝试不同范围的 a。说从 7 到 0,从 0 到 7。提示,阅读别名。这是一个好地方,比如: alias new_a : std_logic_vector(a'length downto 1) is a ;
      • @JimLewis 是的,我做到了。随着新的变化,从 7 到 0、从 0 到 7、从 8 到 1、从 1 到 8、从 0 到 0 等等,都可以完美运行。
      • 这是你测试的代码吗?此代码具有 (i-1)。假设范围是 7 到 0。对于 i = 0,那么这将索引 a(-1) 对吗?此外,阅读代码时,您正在从左到右的方向迭代 a。您正在从右到左的方向遍历 b - 因此反转数组。
      【解决方案4】:

      我最终编写了将 std_logic_vector 转换为字符串的函数。

      它们在in this gist 或以下可用。

      util_str.vhd

      -- Mathieu CAROFF
      -- 2018-11-20
      -- util_str.vhd
      -- Utilitary functions to convert vectors to strings
      
      -- Test:
      -- ```bash
      -- ghdl -a util_str.vhd
      -- ghdl -r util_str_tb
      -- ```
      
      -- The answer from Jonathan Bromley to the toopic "std_logic_vector to string in hex format"
      -- asked by Mad I.D. helped to write the functions below.
      -- https://groups.google.com/forum/#!topic/comp.lang.vhdl/1RiLjbgoPy0
      
      library ieee;
      use ieee.std_logic_1164.all;
      
      package util_str is
      
      function bin (lvec: in std_logic_vector) return string;
      function hex (lvec: in std_logic_vector) return string;
      
      end package;
      
      
      package body util_str is
      
          function bin (lvec: in std_logic_vector) return string is
              variable text: string(lvec'length-1 downto 0) := (others => '9');
          begin
              for k in lvec'range loop
                  case lvec(k) is
                      when '0' => text(k) := '0';
                      when '1' => text(k) := '1';
                      when 'U' => text(k) := 'U';
                      when 'X' => text(k) := 'X';
                      when 'Z' => text(k) := 'Z';
                      when '-' => text(k) := '-';
                      when others => text(k) := '?';
                  end case;
              end loop;
              return text;
          end function;
      
          function hex (lvec: in std_logic_vector) return string is
              variable text: string(lvec'length / 4 - 1 downto 0) := (others => '9');
              subtype halfbyte is std_logic_vector(4-1 downto 0);
          begin
              assert lvec'length mod 4 = 0
                  report "hex() works only with vectors whose length is a multiple of 4"
                  severity FAILURE;
              for k in text'range loop
                  case halfbyte'(lvec(4 * k + 3 downto 4 * k)) is
                      when "0000" => text(k) := '0';
                      when "0001" => text(k) := '1';
                      when "0010" => text(k) := '2';
                      when "0011" => text(k) := '3';
                      when "0100" => text(k) := '4';
                      when "0101" => text(k) := '5';
                      when "0110" => text(k) := '6';
                      when "0111" => text(k) := '7';
                      when "1000" => text(k) := '8';
                      when "1001" => text(k) := '9';
                      when "1010" => text(k) := 'A';
                      when "1011" => text(k) := 'B';
                      when "1100" => text(k) := 'C';
                      when "1101" => text(k) := 'D';
                      when "1110" => text(k) := 'E';
                      when "1111" => text(k) := 'F';
                      when others => text(k) := '!';
                  end case;
              end loop;
              return text;
          end function;
      
      end package body;
      
      
      library ieee;
      
      use ieee.std_logic_1164.all;
      use work.util_str.all;
      
      entity util_str_tb is
      end entity;
      
      architecture util_str_tb_arch of util_str_tb is
      begin
          process is
              variable byte: std_logic_vector(12-1 downto 0) := "000001001111";
          begin
              report "bin " & bin(byte);
              report "hex " & hex(byte);
              wait;
          end process;
      end architecture;
      

      【讨论】:

      • 此解决方案不正确。参数lvec的范围是多少?一般来说,它可以是任何合法范围。如果您想假设它是某物,则需要使用别名使其如此。
      【解决方案5】:

      这里是std_logic_vector类型变量的范围对返回值没有影响的解决方案:

      function to_string ( a: std_logic_vector) return string is
      variable b : string (1 to a'length) := (others => NUL);
      variable stri : integer := 1; 
      begin
          for i in a'range loop
              b(stri) := std_logic'image(a((i)))(2);
          stri := stri+1;
          end loop;
      return b;
      end function;
      

      【讨论】:

      • Botond,为什么 std_logic'image(a(i))(2) 中的 (2)?
      • 我想通了。例如,当我们使用 bit'image 时,我们有 '0''1'。所以,我们有: bit'image(something)(1) --> ' | bit'image(something)(2) --> 0 or 1 | bit'image(something)(3) --> '
      【解决方案6】:

      VHDL-2008 标准为std_logic_vectorstd_ulogic_vector 定义了to_string,以及各种其他类型。使用 VHDL-2008 模式可能最容易(现在大多数模拟器都支持 2008)。

      【讨论】:

        【解决方案7】:

        正如您所发现的,'image 属性仅针对标量类型声明,而不是数组或记录:通常的方法是创建自己的测试实用程序库,包括 to_stringimage设计的开始,并在整个过程中使用它。

        完全有可能将这些库标准化,您可能会发现许多潜在的“测试实用程序”包,但没有一个真正流行到足以成为标准的程度。

        话虽如此,您可能会发现以下软件包是一个有用的起点。

        它封装了几个自定义数据类型,并对它们进行操作。没有泛型,但由于重载,您可以像使用泛型一样使用包。 (你会注意到函数体是不完整的!)扩展它并添加类型在大多数情况下很容易剪切和粘贴;并且避免了主要设计的混乱。

        最好将 declns 类型和(仅限 testbench)函数分离到两个单独的包中; TypesTypes_Test_Utils。然后在整个设计中使用 Types,而测试实用程序只暴露给测试台。

        library IEEE;
        use IEEE.numeric_std.all;
        
        package Types is
          subtype SmallNum is UNSIGNED(7 DOWNTO 0);
          subtype BiggerNum is UNSIGNED(19 DOWNTO 0);
          subtype Bits is BIT_VECTOR(7 DOWNTO 0);
        
          -- and operations on these types
          -- Simulate generic procedures using overloading
        
          function to_string(N : Unsigned) return String;
          function to_string(N : Bits) return String;  
        
          procedure eq_checker (name : string; sig,should : SmallNum; at : time);
          procedure eq_checker (name : string; sig,should : Bits; at : time);
        
        end Types;
        
        package body Types is
        
        function to_string(N : Unsigned) return String is
        variable temp : string(1 to (N'length + 3)/4) := (others => 'x');
        begin
           -- not finished!
           return temp;
        end to_string;
        
        function to_string(N : Bits) return String is
        begin
           return "hello";
        end to_string;
        
        procedure eq_checker(name : string; sig,should : SmallNum; at : time) is
        begin
          if (at = now) then
            if sig = should then
              report to_string(sig) & "has same value" severity note;
            else
              report to_string(sig) & "has not same value as " & to_string(should) severity note;
            end if;
          end if;
        end procedure eq_checker;
        
        procedure eq_checker(name : string; sig,should : Bits; at : time) is
        begin
           null;
        end procedure eq_checker;
        
        end Types;
        

        还有一个简单的测试器...

          use Work.Types.all;
        
          ENTITY tester IS
          END tester;
        
          ARCHITECTURE behavior OF tester IS 
        
          Signal a,b      : SmallNum := X"AA";
          Signal c        : BiggerNum := X"ABCDE";
          SIGNAL x,y      : Bits := X"BB";
        
          BEGIN
        
          process(a,x) is
          begin
             report "value: " & to_string(X) severity note;
             report "and this one: " & to_string(a) severity note;
             report "this one too: " & to_string(c) severity note;
          end process;
        
          END;
        

        【讨论】:

          【解决方案8】:
          package package_x is 
            subtype any_type is UNSIGNED(7 DOWNTO 0);
          
          ...
          end package_x;
          
          package body package_x is
          
            procedure someprocedure (signal sig: in any_type) is
          
            VARIABLE li   : line;
            file output : text open write_mode is "output";
          
            begin
              write(li, std_logic_vector(sig));
              writeline(output, li);
            end;
          end package_x;
          

          【讨论】:

          • OP 要求转换为字符串。另一方面,这是 write/writeline。请参阅 Brian 的帖子了解如何转换为字符串
          • 好吧,line 只是定义为access 类型到string。因此,可以将其转换为函数并返回 li.all
          • @PlayDough 如何在不造成内存泄漏的情况下返回 li.all?您需要在返回之前释放 li - 至少在我们在 VHDL-2019 中进行垃圾收集之前
          • @JimLewis 够公平的。语义要求调用者解除分配。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-19
          • 2020-02-27
          • 1970-01-01
          • 1970-01-01
          • 2017-12-11
          相关资源
          最近更新 更多