如何让图书馆工作?

时间:2015-08-12 18:30:46

标签: vhdl

我的同行一直担心使用当前工作库的名称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_designwork的任何设计被分开,设计将被破坏,参考必须更新。

在显式库名称上使用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,所以没有混淆?

脚注:Never name your libraries work

4 个答案:

答案 0 :(得分:4)

哦工作。我怎么讨厌你?让我来计算一下。

  1. 当所有内容都在工作时,代码依赖于编译顺序。编译的最后一件事是坚持。
  2. Code适用于裁员。每个单个常量必须命名为完全不同的东西,这在大型设计中几乎是不可能的。
  3. 允许在多个地方声明components。这些component声明经常发生冲突!
  4. 我已经看到了多个包文件中定义的相同常量和类型,一遍又一遍地再次出现冲突。
  5. 没有杠杆能力
  6. 请,请使用图书馆!他们是有原因的。它允许您的代码更有条理,更灵活,更便携。

    <强>组织

    图书馆应该存在于自己的文件夹中。我喜欢将所有内容放在一个顶级文件夹下,例如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的一部分,即我会对foowork.foo所指的内容感到困惑。我并不是说它不能像我从未经历过那样。

到目前为止,您可能已经猜到我更喜欢使用work。一个原因是我认为模块化是好的设计,这意味着避免依赖。如果我可以避免依赖于我编译成的库的名称,那么如果需要更改库名,我可以降低代码更改的风险。我同意,如果你使用你的库的良好描述性名称,库名称问题并不常见,但它仍然会发生,至少对我而言:

  • 名称与外部库的冲突确实发生,如果你能够在不改变代码的情况下处理这种情况,它们会更好。特别是如果您决定从其代码中删除命名引用。他们可能会制作新版本,以便您必须重新执行此操作。
  • 有时没有真正的碰撞,但外部库以未建立的缩写命名,您需要更具描述性的名称。有时,这个缩写与你自己的缩写相冲突,具有完全不同的含义。
  • 我甚至让我的vunit库被VHDL 2008劫持,当时该标准使vunit成为一个保留字。

还有一些项目,您的策略并不重要。例如,您可以自己完成所有编码并将所有内容编译到单个库中的小项目,因为它很简单。但是,我仍然会使用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。可以通过两种方式实例化实体:

  1. 使用PoC.arith中的arith.pkg.vhdl包。
    myDiv : arith_div

  2. 使用实体关键字
    myDiv : entity PoC.arith_div

  3. 子命名空间层次结构最多可以包含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