【问题标题】:std_logic_vector to integer conversion vhdlstd_logic_vector 到整数转换 vhdl
【发布时间】:2016-07-15 15:44:46
【问题描述】:

我遇到了转换问题/我阅读了很多类似的主题,但我的代码仍然无法正常工作。请给我一些提示。 Quartus 给我报错:

错误 (10476):true_dual_port_ram_single_clock.vhd(44) 处的 VHDL 错误:标识符类型“random_num_i”不同意其用作“std_logic_vector”类型

LIBRARY ieee;
USE ieee.std_logic_1164.all;
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;

entity write_ram is
  generic(width : integer := 32);
  port(clock_i  : IN  STD_LOGIC;
       we_w     : IN  STD_LOGIC;
       wr_addr  : IN  INTEGER RANGE 0 to 31;
       read_add : IN  INTEGER RANGE 0 to 31;
       q_out    : out STD_LOGIC_VECTOR(2 DOWNTO 0)
  );
end write_ram;

architecture rtl of write_ram is
  --- Component decalarartion
  component random is
    port(clk        : in  std_logic;
         random_num : out std_logic_vector(width - 1 downto 0) --output vector 
    );
  end component;

  component single_clock_ram is
    port(clock         : IN  STD_LOGIC;
         data          : IN  INTEGER RANGE 0 to 31;
         write_address : IN  INTEGER RANGE 0 to 31;
         read_address  : IN  INTEGER RANGE 0 to 31;
         we            : IN  STD_LOGIC;
         q             : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
    );
  end component;
  for all : random use entity work.random(rtl);
  for all : single_clock_ram use entity work.single_clock_ram(rtl);
  Signal random_num_i : INTEGER RANGE 0 to 31; --interanal signals
begin
  -- Component Instantiation

  C1 : random Port map(
      clk        => clock_i,
      --random_num <=to_integer(to_signed(random_num_i))
      random_num => random_num_i
    );
  random_num <= to_integer(to_signed(random_num_i)); -- error

  C2 : single_clock_ram
    Port map(
      clock         => clock_i,
      we            => we_w,
      read_address  => read_add,
      write_address => wr_addr,
      data          => random_num_i,
      q             => q_out
    );

end rtl;

【问题讨论】:

    标签: vhdl


    【解决方案1】:

    您的问题不是 MCVE 存在随机和 single_clock_ram 的配置规范。您没有为它们提供实体声明和架构主体 (rtl)。

    与他们一起评论了这个分析:

    library ieee;
    use ieee.std_logic_1164.all;
    -- use ieee.std_logic_signed.all;  -- NOT USED
    -- use ieee.std_logic_unsigned.all;  -- NOT USED
    use ieee.numeric_std.all;
    -- use ieee.std_logic_arith.all;  -- NOT USED
    
    entity write_ram is
      generic (width:  integer := 32);
      port (clock_i:   in  std_logic;
            we_w:      in  std_logic;
            wr_addr:   in  integer range 0 to 31;
            read_add:  in  integer range 0 to 31;
            q_out:     out std_logic_vector(2 downto 0)
      );
    end entity write_ram;
    
    architecture rtl of write_ram is
      --- component declaration
      component random is
        port (clk:         in  std_logic;
             random_num:   out std_logic_vector(width - 1 downto 0) --output vector 
        );
      end component;
    
      component single_clock_ram is
        port (clock:          in  std_logic;
              data:           in  integer range 0 to 31;
              write_address:  in  integer range 0 to 31;
              read_address:   in  integer range 0 to 31;
              we:             in  std_logic;
              q:              out std_logic_vector(2 downto 0)
        );
      end component;
      -- for all:  random use entity work.random(rtl);
      -- for all:  single_clock_ram use entity work.single_clock_ram(rtl);
      signal random_num_i:  integer range 0 to 31; -- internal signals 
      signal random_num:   std_logic_vector(width - 1 downto 0); -- added
    begin
      -- component instantiation
    
      c1:  random port map (
          clk        => clock_i,
          -- random_num <=to_integer(to_signed(random_num_i))
          -- random_num => random_num_i  -- DELETED
          random_num => random_num   -- ADDED
        );
      -- random_num <= to_integer(to_signed(random_num_i)); -- error DELETED
      random_num_i <= to_integer(signed(random_num));   -- ADDED
    
      c2:  single_clock_ram
        port map (
          clock         => clock_i,
          we            => we_w,
          read_address  => read_add,
          write_address => wr_addr,
          data          => random_num_i,
          q             => q_out
        );
    
    end architecture rtl;
    

    请注意,有一个 random_num std_logic_vector 声明连接到 random 的输出,它被转换为一个整数 random_num_i,用作 single_clock_ram 数据的输入。 single_clock_ram 的输出 q 看起来有点可疑,应该是整数还是更宽的 std_logic_vector?

    【讨论】:

    • 感谢大家的帮助,@user1155120。我的目的是为两个实体 random 和 single_clock_ram 创建顶级。所以我试图将随机的输出连接到 ram 块。根据你的 cmets,我改变了我的代码,但我仍然有同样的错误。
    • 还有一个问题如何做std_vector和整数等长?
    【解决方案2】:

    首先,删除非标准库。

    use IEEE.std_logic_signed.all;
    use IEEE.std_logic_unsigned.all;
    use IEEE.STD_LOGIC_ARITH.ALL;
    

    只留下std_logic_1164numeric_std

    其他的引入了一堆重叠的声明,这使得很难确定发生了什么 - 如果同一个运算符有多个声明具有相同的参数和结果类型,编译器会使它们全部不可见,而不是选择一个任意一个。


    然后,决定你要做什么。这是目前模棱两可和矛盾的。

    (1)你有一个generic (width : integer :=32); 和一个端口声明

    random_num : out std_logic_vector (width-1 downto 0)
    

    这表明您正在处理 32 位字。

    (2) 你有一个范围整数:Signal random_num_i: INTEGER RANGE 0 to 31; 其中 (a) 应该是一个范围 NATURAL 以便更清楚地表明负值是错误,并且 (b) 表明你正在处理 5 位字。

    它是什么?你到底想做什么?

    在这里,您显然试图在端口映射中将它们连接在一起......

     C1: random Port map ( 
         clk => clock_i,
         --random_num <=to_integer(to_signed(random_num_i))
         random_num =>random_num_i
     );
     random_num <=to_integer(to_signed(random_num_i)); -- error
    

    这里有很多问题。

    1) 像random_num =&gt;random_num_i 这样的简单端口映射要求双方具有相同的类型。如果双方实际上是相同的类型,这将起作用:例如,如果您添加了信号声明

    random_num_slv : std_logic_vector (width-1 downto 0);
    

    然后端口映射random_num =&gt;random_num_slv 将起作用。现在您可以在信号分配中转换为所需的类型random_num_i

    random_num_i <= to_integer (unsigned(random_num_slv));
    

    这仍然存在问题:32 位输出可能会溢出 5 位整数。

    虽然添加中间信号random_num_slv 可能看起来效率低下且多余,但它使设计保持简洁,这在处理不了解端口类型转换的工具时很重要。

    确保您知道如何使用中间信号,即使有更简洁的方法。当一切都失败时,它可以拯救你。

    (2) 被注释掉的端口映射

     random_num <=to_integer(to_signed(random_num_i))
    

    将是这样做的方式,除了三件事...... (a)&lt;=是信号赋值,需要=&gt;一个n关联运算符 (b) 您正在将整数转换为整数,并用它驱动 std_logic_vector。那真的不行。。。 (c) 组件端口是一个 OUTPUT,所以你不应该首先驱动它。

    你的意思可能是

       to_integer(unsigned(random_num)) => random_num_i
    

    如果您的工具正确支持端口映射中的转换,这将是最简洁的方法。 备注:

    • 同样存在溢出问题,32 位向量不适合 5 位整数。
    • 您可以通过强制转换 unsigned 而不是转换函数 to_signed 从 std_logic_vector 转换为有符号或无符号,因为它们是密切相关的类型。整数与这些没有“密切关系”,因此需要一个转换函数to_integer
    • 由于random_num_i 的声明不允许负数,因此请使用unsigned 而不是signed

    (3)现有信号分配

    random_num <=to_integer(to_signed(random_num_i)); -- error
    

    再次包含几个错误。最大的问题是在组件声明之外没有可见的random_num 端口。只需删除此行,您需要使用其中一个端口映射。


    进一步考虑:

    (1) 一些类型转换是不可避免的。但是,如果你做的太多,这通常表明设计错误,比如在任何地方都使用std_logic_vector,即使对于那些不可避免地是无符号整数的地址也是如此,所以unsignednatural 将是一个更好的选择。使设计尽可能简单易读。我认为您在此处使用 integer 通常很好,但 natural 会更好(除非您需要负地址!)

    (2) 如果您要添加像 width 这样的泛型的灵活性,请正确且一致地使用它 - 或者 - 检查它是否有效。

    在这里,如上所述,如果此实体使用width =&gt; 5 实例化,您的设计只有在没有意外情况下才能正常工作。

    因此,如果不满足此前提条件,请检查该值并中止。

    assert Width = 5 report "Width of " & natural'image(width) & " not supported!" 
       severity FAILURE;
    

    或者使设计适用于泛型的所有合理值,例如通过使其他数量以有效方式依赖于它。例如:

       constant DEPTH : natural := 2**WIDTH - 1;
       signal random_num_i : natural range 0 to DEPTH;
    

    等等……

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 2015-09-15
      相关资源
      最近更新 更多