"header" 文件的 VHDL 标准布局和语法
VHDL standard layout & syntax for "header" file
IDE:Quartus 15
我是 VHDL 编程的新手,所以有一些我不习惯的细微差别(从 C++ 翻译而来)。虽然我已经找到了对 "source" 文件进行编程的资源,但我一直在努力寻找 "header" 文件的资源。
简而言之,VHDL "header" 文件的标准布局/语法是什么?
为简单起见,我感兴趣的用例是声明 subtype
和 "source" 文件之间使用的函数引用。
我找到了以下代码片段 here,它有点帮助,但我仍然不确定 package
和 package body
之间的区别。我也不确定 "work" 来自哪里。
"Header":
package DEFS is
CONSTANT MAJOR_VERSION: INTEGER := 0;
CONSTANT MINOR_VERSION: INTEGER := 22;
CONSTANT MAXREG: integer := 52;
TYPE REGS_TYPE is array (0 to MAXREG) of STD_LOGIC_VECTOR(15 downto 0);
FUNCTION opndrn(inp: std_logic) return std_logic;
end package DEFS;
package body DEFS is
FUNCTION opndrn(inp: std_logic) return std_logic IS
begin
CASE INP is
WHEN '0' => return '0';
WHEN OTHERS => return 'Z';
END CASE;
end;
end package body DEFS;
"Source":
LIBRARY work;
USE work.defs.all;
感谢任何帮助。
幸运的是,VHDL 中没有头文件。
你所拥有的是一个包裹,从来没有 "include"d 在任何地方。
与头文件不同,包被单独编译为一个库,然后您可以 "use" 正如您所做的那样。
与头文件不同,包创建自己的命名空间。 USE work.defs.all;
导入整个命名空间,就像 C++ 中的 using namespace defs
一样。有时更好的做法是编写 USE work.defs;
,这样您就可以有选择地使用该名称空间,并在源代码中引用 defs.Major_Version
,从而 (a) 保持全局名称空间整洁,以及 (b) 记录 Major_Version
已定义。
与头文件不同,包鼓励将接口和实现适当分离。您的来源只能访问包导出的内容,即在包中而不是包体中声明的内容。这允许信息隐藏、不透明类型和通常更好的抽象。
例如,您可以在包中声明 Major_Version
,但在正文中隐藏其实际值(参见 "deferred constants")
包和包体(接口和实现)在同一个文件中是合法的,但如果你想强制分离接口和实现,包体将是一个单独的文件。
然后您可以修改包体(实现)并重新编译它:使用该包的任何东西都不需要重新编译(除非您还更改了接口。
包的任何客户只需要看包文件,而不是包体。
简而言之,您所做的看起来还不错。
但是你可以在信息隐藏方面走得更远。
要注意的一件事是创建一个通用的 God 包:将总线常量、函数等分离到一个 "bus" 包、寄存器类型(可能还有它们所有名称的枚举)中要好得多在 "registers" 包中,在 "instructions" 包中的说明等
IDE:Quartus 15
我是 VHDL 编程的新手,所以有一些我不习惯的细微差别(从 C++ 翻译而来)。虽然我已经找到了对 "source" 文件进行编程的资源,但我一直在努力寻找 "header" 文件的资源。
简而言之,VHDL "header" 文件的标准布局/语法是什么?
为简单起见,我感兴趣的用例是声明 subtype
和 "source" 文件之间使用的函数引用。
我找到了以下代码片段 here,它有点帮助,但我仍然不确定 package
和 package body
之间的区别。我也不确定 "work" 来自哪里。
"Header":
package DEFS is
CONSTANT MAJOR_VERSION: INTEGER := 0;
CONSTANT MINOR_VERSION: INTEGER := 22;
CONSTANT MAXREG: integer := 52;
TYPE REGS_TYPE is array (0 to MAXREG) of STD_LOGIC_VECTOR(15 downto 0);
FUNCTION opndrn(inp: std_logic) return std_logic;
end package DEFS;
package body DEFS is
FUNCTION opndrn(inp: std_logic) return std_logic IS
begin
CASE INP is
WHEN '0' => return '0';
WHEN OTHERS => return 'Z';
END CASE;
end;
end package body DEFS;
"Source":
LIBRARY work;
USE work.defs.all;
感谢任何帮助。
幸运的是,VHDL 中没有头文件。
你所拥有的是一个包裹,从来没有 "include"d 在任何地方。
与头文件不同,包被单独编译为一个库,然后您可以 "use" 正如您所做的那样。
与头文件不同,包创建自己的命名空间。 USE work.defs.all;
导入整个命名空间,就像 C++ 中的 using namespace defs
一样。有时更好的做法是编写 USE work.defs;
,这样您就可以有选择地使用该名称空间,并在源代码中引用 defs.Major_Version
,从而 (a) 保持全局名称空间整洁,以及 (b) 记录 Major_Version
已定义。
与头文件不同,包鼓励将接口和实现适当分离。您的来源只能访问包导出的内容,即在包中而不是包体中声明的内容。这允许信息隐藏、不透明类型和通常更好的抽象。
例如,您可以在包中声明 Major_Version
,但在正文中隐藏其实际值(参见 "deferred constants")
包和包体(接口和实现)在同一个文件中是合法的,但如果你想强制分离接口和实现,包体将是一个单独的文件。
然后您可以修改包体(实现)并重新编译它:使用该包的任何东西都不需要重新编译(除非您还更改了接口。
包的任何客户只需要看包文件,而不是包体。
简而言之,您所做的看起来还不错。
但是你可以在信息隐藏方面走得更远。
要注意的一件事是创建一个通用的 God 包:将总线常量、函数等分离到一个 "bus" 包、寄存器类型(可能还有它们所有名称的枚举)中要好得多在 "registers" 包中,在 "instructions" 包中的说明等