如何在 VHDL 中创建信号向量:std_logic_vector
std_logic_vector
type 可用于在 VHDL 中创建信号总线。 std_logic
是VHDL中最常用的类型,std_logic_vector
是它的数组版本。
而 std_logic
非常适合对单根导线可以承载的值进行建模,但对于实现进出组件的导线集合并不是很实用。 std_logic_vector
是复合类型,这意味着它是子元素的集合。 std_logic_vector
的信号或变量 type 可以包含任意数量的 std_logic
元素。
这篇博文是基本 VHDL 教程系列的一部分。
声明 std_logic_vector
的语法 信号是:signal <name> : std_logic_vector(<lsb> to <msb>) := <initial_value>;
或signal <name> : std_logic_vector(<msb> downto <lsb>) := <initial_value>;
其中<name>
是信号和 <initial_value>
的任意名称 是一个可选的初始值。 <lsb>
是最低位的索引,<msb>
是最高位的索引。
to
或 downto
指定总线范围的方向,基本上是它的字节序。尽管两者工作得一样好,但 VHDL 设计人员最常见的是使用 downto
声明向量 .因此,我建议您始终使用 downto
当您声明位向量以避免混淆时。
声明一个可以容纳一个字节的向量信号的VHDL代码:signal MySlv : std_logic_vector(7 downto 0);
声明一个可以保存一位的向量信号的VHDL代码:signal MySlv : std_logic_vector(0 downto 0);
用于声明可以保存零位的矢量信号的 VHDL 代码(空范围 ):signal MySlv : std_logic_vector(-1 downto 0);
运动
在本视频教程中,我们将学习如何声明 std_logic_vector
信号并给它们初始值。我们还学习了如何使用 For 循环遍历向量中的位以创建 移位寄存器 :
我们在本教程中创建的最终代码:
library ieee; use ieee.std_logic_1164.all; entity T11_StdLogicVectorTb is end entity; architecture sim of T11_StdLogicVectorTb is signal Slv1 : std_logic_vector(7 downto 0); signal Slv2 : std_logic_vector(7 downto 0) := (others => '0'); signal Slv3 : std_logic_vector(7 downto 0) := (others => '1'); signal Slv4 : std_logic_vector(7 downto 0) := x"AA"; signal Slv5 : std_logic_vector(0 to 7) := "10101010"; signal Slv6 : std_logic_vector(7 downto 0) := "00000001"; begin -- Shift register process is begin wait for 10 ns; for i in Slv6'left downto Slv6'right + 1 loop Slv6(i) <= Slv6(i-1); end loop; Slv6(Slv6'right) <= Slv6(Slv6'left); end process; end architecture;
我们按下运行后 ModelSim 中的波形窗口,并在时间轴上放大:
分析
在本练习中,我们声明了六个 std_logic_vector
总线,每个八位长(一个字节)。
信号 Slv1
声明时没有初始值。在波形截图中可以看到总线的值为 XX。这是因为总线上显示的值是十六进制的,而 XX 表示非十六进制值。但是当我们在波形中展开总线时,我们可以看到各个位确实是 U。
信号 Slv2
使用全 0 的初始值声明。我们没有指定每个位的确切值,而是使用 (other => '0')
代替初始值。这被称为聚合 任务。重要的部分是它将向量中的所有位设置为您指定的任何值,无论它有多长。
信号 Slv3
被声明为使用聚合赋值为所有位赋予初始值 1。我们可以在波形中看到此信号上显示的 FF,即 8 个 1 的十六进制。
信号 Slv4
用十六进制指定的初始值声明,AA。每个十六进制数字都是 4 位长,因此我们必须为 8 位长的向量提供两位(AA)。
信号 Slv5
声明与 Slv4
完全相同的初始值 ,但现在我们指定它为二进制值10101010。从波形中我们可以看出两个信号的十六进制值AA。
信号 Slv6
用全零的初始值声明,除了最右边的位 '1'
.我们使用了一个进程来创建一个移位寄存器 从这个信号。移位寄存器,顾名思义,每10纳秒将向量的内容左移一位。
我们的进程每 10 ns 唤醒一次,For-Loop 将向量中的所有位向左移动一位。最后一位由 Slv6(Slv6'right) <= Slv6(Slv6'left);
移回第一个索引 陈述。在波形中我们可以看到 '1'
穿过向量。
这是 '1'
如何实现的可视化 通过我们的移位寄存器传播:
通过使用 'left'
和 'right
属性,我们使我们的代码更通用。如果我们改变 Sig6
的宽度 ,该过程仍然有效。尽可能使用属性而不是硬编码值是一种很好的设计实践。
您可能想知道是否还有更多可以使用的属性,而且确实有。在本教程系列中我不会更多地讨论它们,因为我认为它们是高级 VHDL 功能。
外卖
- 应使用
std_logic_vector(N-1 downto 0)
声明 N 位向量 - 向量可以作为一个整体分配,也可以单独访问其中的位
- 可以使用聚合赋值
(others => '0')
将向量中的所有位归零 - 使用
'left
等属性可以使代码更通用 和'right
参加基本 VHDL 测验 - 第 2 部分 »
或
转到下一个教程 »
VHDL