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_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) 组件端口是一个输出端口,所以你不应该首先驱动它。
你的意思可能是
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
,即使对于像地址这样的地址,这些地址不可避免地是无符号整数,所以 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;
等等...
您的问题不是 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?
我面临转换 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_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) 组件端口是一个输出端口,所以你不应该首先驱动它。
你的意思可能是
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
,即使对于像地址这样的地址,这些地址不可避免地是无符号整数,所以 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;
等等...
您的问题不是 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?