我的同行一直担心使用当前工作库的名称work
(指向当前库的别名)而不是显式名称(例如mylib
)。
例如,如果您在同一个库中引用另一个设计单元,则可以执行以下操作:
my_inst : entity work.my_design
或
my_inst : entity mylib.my_design
我觉得使用work
更灵活,因为它不依赖于您为编译设计的库命名的内容。您可以将mylib
重命名为myawesomelib
,它仍可以使用。
我可以想到work
的优点的一个明显例子是,如果您通常将设计单元和测试平台编译到同一个库中。那么,在您的测试平台中,通过work
引用您的UUT(设计)始终是安全的。
一个缺点是如果(如上例所示)my_design
不再位于同一个库中,设计将停止工作;如果my_design
或使用my_design
到work
的任何设计被分开,设计将被破坏,参考必须更新。
在显式库名称上使用work
还有其他明显的缺点吗?在work
的分层使用的情况下,可能存在混淆的原因,哪个库是“当前工作库”?
例如:
mylib1
(top_design.vhd)
...
my_inst1 : entity mylib2.my_design
...
mylib2
(my_design.vhd)
...
my_inst2 : entity work.my_sub_design
...
在编译top_design.vhd时,work
包含的设计中是否存在关于mylib2
引用的混淆?或者,因为my_design.vhd
已经编译成mylib2
,所以没有混淆?
答案 0 :(得分:4)
哦工作。我怎么讨厌你?让我来计算一下。
components
。这些component
声明经常发生冲突!请,请使用图书馆!他们是有原因的。它允许您的代码更有条理,更灵活,更便携。
<强>组织强>
图书馆应该存在于自己的文件夹中。我喜欢将所有内容放在一个顶级文件夹下,例如UART。在那之下,我将有4个目录:build,source,sim,docs。这样,您的模拟和文档都随着库代码一起传播!这有多甜蜜!?你不必担心在哪里找到那个愚蠢的UART sim,你总会知道它在哪里。顺便说一句,这意味着自检Testbenches是强制性的!我坚持不懈。
灵活便携
如果您正在为一个项目编写代码,那么您将做出假设。 “哦,我的时钟是25 MHz,所以我可以让它成为一个常数。”但是如果你为一个库编写代码,你就会意识到你做出了错误的假设。在UART示例中,您需要使波特率为generic
而不是常量。这使您的代码更灵活,更易于其他人使用。
打包文件
每个库应该有一个包文件。您的所有组件都应包含在此包文件中。这样,如果您的实体发生更改,则只需更新包文件中的组件即可。包文件应包含该库中使用的所有常量,函数和过程。这又允许你在一个地方改变一些东西。
<强>结论强>
库是制作周到,可重用,易于移植的代码的方法。当我看到所有代码编译成工作时,我感到畏缩。
答案 1 :(得分:3)
我认为这是有趣的问题之一,因为没有明确的答案。这取决于。对我而言,这取决于项目背景,也取决于个人偏好。
@Josh。我认为,在重组库时,可能必须更改work
引用的风险是反对使用work
的论据。对于命名引用也是如此。
@Russel。使用包而不是直接实例化仍然会让您忘记use x.uart_pkg.all;
中x应该是什么。但是你的参考文献会更少(代价是包中的代码更多)。
@Kevin。我同意mylib.foo
更明确,但我认为我不知道哪个foo
编译成mylib
,但我不知道引用文件也是mylib
的一部分,即我会对foo
中work.foo
所指的内容感到困惑。我并不是说它不能像我从未经历过那样。
到目前为止,您可能已经猜到我更喜欢使用work
。一个原因是我认为模块化是好的设计,这意味着避免依赖。如果我可以避免依赖于我编译成的库的名称,那么如果需要更改库名,我可以降低代码更改的风险。我同意,如果你使用你的库的良好描述性名称,库名称问题并不常见,但它仍然会发生,至少对我而言:
还有一些项目,您的策略并不重要。例如,您可以自己完成所有编码并将所有内容编译到单个库中的小项目,因为它很简单。但是,我仍然会使用work
,因为它会删除一些库语句并使事情变得更加简单。
答案 2 :(得分:2)
我避免使用work
,因为它隐藏了您希望找到标识符的上下文。包含库名称(例如mylib.foo
)会明确说明foo
你所指的是work.foo
,而不是当前库中某处,无论是什么。如果您想从其库外部引用foo
,则无论如何都不能使用work
,因此您最终可能会使用不同名称引用的同一对象,具体取决于您在层次结构中的位置。
随意更改库名称的灵活性在现实世界中并不是特别有用,只会造成不必要的复杂性。使用名为work
的默认库以及工具处理的默认库的做法进一步加剧了这种情况。选择一个好的图书馆名称并坚持下去。我发现work
最终成为那些懒得将可重用代码划分为逻辑分区的人的拐杖。即将其全部转储到work
并希望不会发生冲突。
答案 3 :(得分:0)
我是PoC-Library的作者之一。我们决定使用PoC
作为一个有希望的唯一VHDL库名称。所有实体和包都编译到此单个库中。因为PoC附带了很多文件(~100),所以我们决定将PoC划分为子命名空间(也许有一天VHDL会支持这样的功能......)。
示例:强>
对于算术模块,分隔符组件被分类为子命名空间arith
。在我们的文档中,该实体(实际上)被引用为PoC.arith.div
。该实体名为arith_div
,位于名为arith_div.vhdl
的文件中。每个子命名空间提供一个用于组件,类型,函数和常量的包:例如, arith.pkg.vhdl
。可以通过两种方式实例化实体:
使用PoC.arith
中的arith.pkg.vhdl
包。
myDiv : arith_div
使用实体关键字
myDiv : entity PoC.arith_div
子命名空间层次结构最多可以包含2个级别。一个例子是我们的片上RAM PoC.mem.ocram.*
具有不同的端口变化:sp,sdp,esdp,tdp。为了缩短实体名称,我们仅使用最后一个子命名空间作为名称中的前缀,例如ocram_tdp
。子命名空间名称必须是唯一的。
大多数实例引用都使用实体语法:myInst : entity PoC.xxx_yyy
。
所以是的,我们希望我们的用户将所有来源编译为PoC
:)。
我们如何组织测试平台,文档等?
与@ Russell的架构相比,PoC对每个设施使用相同的目录结构:
o-netlist (precompiled netlists for a specific FPGA device)
| o-<FPGA-NAME>
| o-mem
| o-ocram
o-sim (waveform configuration files: *.wcfg, *.wdo, *.gtkw)
| o-io
| | o-iic
| | o-uart
| o-mem
| | o-ocram
o-src (sources as *.vhdl or *.v files)
| o-io
| | o-iic
| | o-uart
| o-mem
| | o-ocram
o-tb (testbenches as *.vhdl or *.v files)
| o-io
| | o-iic
| | o-uart
| o-mem
| o-ocram
o-xst (synthesis instruction to generate netlists of components)
| o-mem
| o-ocram