我遇到了转换问题/我读了很多类似的主题,但我的代码仍然没有工作。请你给我一些提示。 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;
答案 0 :(得分:1)
首先,删除非标准库。
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.STD_LOGIC_ARITH.ALL;
仅保留std_logic_1164
和numeric_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)组件端口是OUTPUT,因此您不应该首先驱动它。
你可能意味着什么
to_integer(unsigned(random_num)) => random_num_i
如果您的工具正确支持端口映射中的转换,这将是最干净的方法。 注意:
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
,即使对于像地址这样的地址来说也是不可避免的无符号整数,所以unsigned
或natural
会是一个更好的选择。保持设计尽可能简单易读。我认为您在这里使用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;
依旧......
答案 1 :(得分:1)
您的问题不是MCVE,其中包含random和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_num_i,用作single_clock_ram数据的输入。 single_clock_ram的输出q看起来有点可疑,应该是整数还是更宽的std_logic_vector?