在 VHDL 中初始化数组:它究竟是如何工作的?
Initializing arrays in VHDL: How exactly does it work?
考虑以下 VHDL 代码:
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1', others => '0');
这里,索引 7 和 6 很重要:它们指示哪些元素应该为 1,编译器可以从中得出哪些元素应该为 0。
问题 1
如果我没理解错的话,这也可以写成
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1') & (5 downto 0 => '0');
现在我想知道这究竟是如何工作的,以及索引是否仍然重要或只是它们之间的区别。按照我的理解,表达式 (x downto y => z)
创建一个索引为 x downto y
的数组,其元素都等于 z
(并且具有相同的类型)。但是当数组连接时这些索引重要吗?即,我还可以写以下任何内容吗:
constant c : std_logic_vector(7 downto 0) := (1 downto 0 => '1') & (5 downto 0 => '0');
constant c : std_logic_vector(7 downto 0) := (99 downto 98 => '1') & (4 downto -1 => '0');
当然可以说那些陈述,尤其是。最后一个,不是很清楚,但我的问题是:他们会有相同的结果吗?或者它们会导致某种错误吗?
我想知道的原因是你也可以写
constant c : std_logic_vector(7 downto 0) := "11" & "000000";
和文字 "11"
没有指定任何范围,所以我不确定这个文字的确切类型是什么,但肯定不是 std_logic_vector(7 downto 6)
.
问题二
最后,我想知道两者有什么区别
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1') & (5 downto 0 => '0');
和
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1', 5 downto 0 => '0');
我的意思是:你有什么理由 want/need 写前者(这似乎更容易出错,因为如果你交换 2 个聚合,它会产生意想不到的结果)而不是后者?还是只是品味问题?
- 让我们从文字开始。当您指定文字时,默认范围是 (type_index'low to type_index'low + len-1)。最简单的方法是在指定常量时,子类型中不需要范围:
constant SOME_CONSTANT : std_logic_vector := x"00";
在这里,如果您检查 SOME_CONSTANT 的范围,您会看到它的(0 到 7)。这是因为 std_logic_vector 声明为:
type std_ulogic_vector is array(natural range <>) of std_logic;
'自然的低值为0,即起点。
假设你有点疯狂,这:
type my_crazy_array_t is array(std_logic range <>) of integer;
并且你声明了一个常量:
constant CRAZY : my_crazy_array_t := (0, 22);
结果是:
CRAZY('U') = 0
CRAZY('X') = 22
CRAZY'left = 'U'
CRAZY'right = 'X'
CRAZY'low = 'U'
CRAZY'high = 'X'
因为'U'
是std_logic
的低值,后面是'X'.
在其他问题上,这一切都有效,因为 VHDL 始终是上下文驱动的,并且对于长度匹配的数组,生成的数组始终可以从“左”映射到“右”。在您的示例中,长度是正确的,并且从声明中知道子类型,因此可以按照您指定的方式进行映射。
注意:(4 downto -1 => '0');
是非法的,因为 -1 不是 std_logic_vector 的有效索引值,所以你会得到一个错误(可能来自 &
函数,因为它无法计算出你指的是什么类型,因为它不能是 std_logic_vector).
- 不同的是,第一个是2位和6位的位串拼接而成,第二个是完整的8位位串。您使用的可能是风格问题。但通常,为此,我会使用文字,例如:
constant c : std_logic_vector(7 downto 0) := x"C0";
你使用什么以及何时使用可能取决于用户最清楚的内容。
考虑以下 VHDL 代码:
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1', others => '0');
这里,索引 7 和 6 很重要:它们指示哪些元素应该为 1,编译器可以从中得出哪些元素应该为 0。
问题 1
如果我没理解错的话,这也可以写成
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1') & (5 downto 0 => '0');
现在我想知道这究竟是如何工作的,以及索引是否仍然重要或只是它们之间的区别。按照我的理解,表达式 (x downto y => z)
创建一个索引为 x downto y
的数组,其元素都等于 z
(并且具有相同的类型)。但是当数组连接时这些索引重要吗?即,我还可以写以下任何内容吗:
constant c : std_logic_vector(7 downto 0) := (1 downto 0 => '1') & (5 downto 0 => '0');
constant c : std_logic_vector(7 downto 0) := (99 downto 98 => '1') & (4 downto -1 => '0');
当然可以说那些陈述,尤其是。最后一个,不是很清楚,但我的问题是:他们会有相同的结果吗?或者它们会导致某种错误吗?
我想知道的原因是你也可以写
constant c : std_logic_vector(7 downto 0) := "11" & "000000";
和文字 "11"
没有指定任何范围,所以我不确定这个文字的确切类型是什么,但肯定不是 std_logic_vector(7 downto 6)
.
问题二
最后,我想知道两者有什么区别
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1') & (5 downto 0 => '0');
和
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1', 5 downto 0 => '0');
我的意思是:你有什么理由 want/need 写前者(这似乎更容易出错,因为如果你交换 2 个聚合,它会产生意想不到的结果)而不是后者?还是只是品味问题?
- 让我们从文字开始。当您指定文字时,默认范围是 (type_index'low to type_index'low + len-1)。最简单的方法是在指定常量时,子类型中不需要范围:
constant SOME_CONSTANT : std_logic_vector := x"00";
在这里,如果您检查 SOME_CONSTANT 的范围,您会看到它的(0 到 7)。这是因为 std_logic_vector 声明为:
type std_ulogic_vector is array(natural range <>) of std_logic;
'自然的低值为0,即起点。
假设你有点疯狂,这:
type my_crazy_array_t is array(std_logic range <>) of integer;
并且你声明了一个常量:
constant CRAZY : my_crazy_array_t := (0, 22);
结果是:
CRAZY('U') = 0
CRAZY('X') = 22
CRAZY'left = 'U'
CRAZY'right = 'X'
CRAZY'low = 'U'
CRAZY'high = 'X'
因为'U'
是std_logic
的低值,后面是'X'.
在其他问题上,这一切都有效,因为 VHDL 始终是上下文驱动的,并且对于长度匹配的数组,生成的数组始终可以从“左”映射到“右”。在您的示例中,长度是正确的,并且从声明中知道子类型,因此可以按照您指定的方式进行映射。
注意:(4 downto -1 => '0');
是非法的,因为 -1 不是 std_logic_vector 的有效索引值,所以你会得到一个错误(可能来自 &
函数,因为它无法计算出你指的是什么类型,因为它不能是 std_logic_vector).
- 不同的是,第一个是2位和6位的位串拼接而成,第二个是完整的8位位串。您使用的可能是风格问题。但通常,为此,我会使用文字,例如:
constant c : std_logic_vector(7 downto 0) := x"C0";
你使用什么以及何时使用可能取决于用户最清楚的内容。