如何在 VHDL 中使用常量和通用映射
创建模块是重用代码的好方法,但您通常需要在整个设计中具有较小变化的相同模块。这就是泛型和泛型映射的用途。它允许您在编译时使模块的某些部分可配置。
当我们想避免一遍又一遍地输入相同的值时,就会使用常量。它们可用于在编译时定义信号向量的位宽,甚至还可以映射到通用常量。常量可以在代码中的任何地方代替信号和变量,但是它们的值在编译后不能改变。
这篇博文是基本 VHDL 教程系列的一部分。
在上一教程中,我们创建了一个总线宽度为 8 位的 4 输入多路复用器模块。但是,如果我们还需要具有不同总线宽度的类似 MUX 怎么办?将代码复制粘贴到新模块中并更改数字的唯一解决方案是吗?
幸好没有。
可以使用以下语法在 VHDL 中创建常量:constant <constant_name> : <type> := <value>;
常量可以在VHDL文件的声明部分与信号一起声明,也可以在进程中与变量一起声明。
常量可以通过实体通过generic传入模块 关键词。为接受通用常量的模块创建实体的语法是:entity <entity_name> is
generic(
<entity_constant_name> : <type> [:= default_value];
...
);
port(
<entity_signal_name> : in|out|inout <type>;
...
);
end entity;
在另一个 VHDL 文件中实例化通用模块的语法是:<label> : entity <library_name>.<entity_name>(<architecture_name>)
generic map(
<entity_constant_name> => <value_or_constant>,
...
)
port map(
<entity_signal_name> => <local_signal_name>,
...
);
运动
在本视频教程中,我们将学习如何在 VHDL 中使用通用常量创建和实例化模块:
通用 MUX testbench 的最终代码 :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity T16_GenericMapTb is
end entity;
architecture sim of T16_GenericMapTb is
constant DataWidth : integer := 8;
signal Sig1 : signed(DataWidth-1 downto 0) := x"AA";
signal Sig2 : signed(DataWidth-1 downto 0) := x"BB";
signal Sig3 : signed(DataWidth-1 downto 0) := x"CC";
signal Sig4 : signed(DataWidth-1 downto 0) := x"DD";
signal Sel : signed(1 downto 0) := (others => '0');
signal Output : signed(DataWidth-1 downto 0);
begin
-- An Instance of T16_GenericMux with architecture rtl
i_Mux1 : entity work.T16_GenericMux(rtl)
generic map(DataWidth => DataWidth)
port map(
Sel => Sel,
Sig1 => Sig1,
Sig2 => Sig2,
Sig3 => Sig3,
Sig4 => Sig4,
Output => Output);
-- Testbench process
process is
begin
wait for 10 ns;
Sel <= Sel + 1;
wait for 10 ns;
Sel <= Sel + 1;
wait for 10 ns;
Sel <= Sel + 1;
wait for 10 ns;
Sel <= Sel + 1;
wait for 10 ns;
Sel <= "UU";
wait;
end process;
end architecture;
通用 MUX 模块 的最终代码 :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity T16_GenericMux is
generic(DataWidth : integer);
port(
-- Inputs
Sig1 : in signed(DataWidth-1 downto 0);
Sig2 : in signed(DataWidth-1 downto 0);
Sig3 : in signed(DataWidth-1 downto 0);
Sig4 : in signed(DataWidth-1 downto 0);
Sel : in signed(1 downto 0);
-- Outputs
Output : out signed(DataWidth-1 downto 0));
end entity;
architecture rtl of T16_GenericMux is
begin
process(Sel, Sig1, Sig2, Sig3, Sig4) is
begin
case Sel is
when "00" =>
Output <= Sig1;
when "01" =>
Output <= Sig2;
when "10" =>
Output <= Sig3;
when "11" =>
Output <= Sig4;
when others => -- 'U', 'X', '-', etc.
Output <= (others => 'X');
end case;
end process;
end architecture;
我们按下运行后 ModelSim 中的波形窗口,并在时间轴上放大:
分析
我们创建了一个具有可配置总线宽度的 MUX 模块。现在,总线宽度只在一个地方指定,在测试台文件中。我们可以轻松更改它以创建具有不同总线宽度的 MUX。
如果我们将波形与上一教程中的波形进行比较,我们可以看到行为是相同的。这是因为我们根本没有改变代码的行为。
外卖
- 可以使用常量来避免在多个位置硬编码值
- 泛型可用于使模块更具适应性
转到下一个教程 »
VHDL