如何在 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