std_logic_vector 到整数转换 vhdl

std_logic_vector to integer conversion vhdl

我面临转换 problem/I 阅读了很多类似的主题,但我的代码仍然不是 working.Could 请您给我一些提示。 Quartus 给我错误:

Error (10476): VHDL error at true_dual_port_ram_single_clock.vhd(44): type of identifier "random_num_i" does not agree with its usage as "std_logic_vector" type

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;

首先,删除非标准库。

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 =>random_num_i这样的简单端口映射要求双方具有相同的类型。如果双方实际上是同一类型,这将起作用:例如,如果您添加了信号声明

random_num_slv : std_logic_vector (width-1 downto 0);

那么端口映射 random_num =>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) <=是信号赋值,需要=>一个n关联运算符 (b) 您正在将整数转换为整数,并用它驱动 std_logic_vector。那真的不行... (c) 组件端口是一个输出端口,所以你不应该首先驱动它。

你的意思可能是

   to_integer(unsigned(random_num)) => random_num_i

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

  • 再次出现溢出问题,32 位向量放不下 5 位整数。
  • 您可以通过转换 unsigned 而不是转换函数 to_signed 将 std_logic_vector 转换为有符号或无符号,因为它们是密切相关的类型。整数不是 "closely related" 这些,所以需要一个转换函数 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 => 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;

等等...

您的问题不是 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?