3

在多年没有接触过 VHDL 之后,我最近才重新开始学习 VHDL。希望用它来开发具有各种传感器接口等的控制系统。我在嵌入式 C 方面相当胜任,在此之前,这一直是我所从事的任何嵌入式项目的首选语言,这使得学习VHDL更加令人沮丧。

基本上,我现在的问题(我认为这是我能够推进我的预期项目的最大障碍)是我不知道如何开发和合并一个我可以将变量传递给并调用的模块(比如C) 中的函数来执行某些任务,即在 4 位 7 段显示器上显示整数 0-9999。我知道 VHDL 中有组件,但这似乎是一种执行一项任务的冗长方式。有没有更好的方法来做到这一点?

在我看来,在您完成所有数字教程之后,关于如何在 VHDL 中实际开发完整系统的信息存在巨大差距。

4

3 回答 3

5

编辑:进一步解释:底部的第三条评论。为这篇文章的长度道歉!

VHDL 也有函数和过程,就像 C if 语句、与 C 的 switch 有一些相似之处的 case 语句)等等。

到目前为止,这一切都是可以综合的;其他一些 VHDL 功能仅用于仿真(让您测试可综合代码)。因此,在模拟中,您可以像 C 一样打开、读取和写入文件,并使用指针(访问类型)来处理内存。我希望你能明白为什么 VHDL 的这些部分是不可综合的!)

但是 VHDL 的不同之处在于您需要一些额外的行来将这个顺序代码包装在一个进程中。在 C 中,这发生在你身上;一个典型的 C 程序只是一个进程(如果你想要多个进程,你必须求助于库或操作系统功能,如 fork 或 pthreads)

但是 VHDL 可以做得更多。您可以非常轻松地创建多个进程,将它们与信号互连,将它们包装为可重用的组件,使用“for ... generate”来创建多个进程,等等。同样,所有可综合:这施加了一些限制,例如,在系统运行时不能更改硬件的大小(进程数)!

关键:了解信号分配的规则,而不是变量分配。变量在 C 中的工作方式非常相似;信号不!相反,他们所做的是提供安全、同步的进程间通信,而不会大惊小怪。要了解如何,您需要了解“延迟分配”、增量周期、等待语句以及进程如何挂起自身并再次唤醒。

您似乎在这里问了两个问题:

(1) - 我可以使用 C 中的函数吗?非常如此;通过将有用的类型和相关函数、过程包装在一个包中并在多个设计中重用该包,您可以做得比 C 更好。它有点像 C++ 可重用类,有一些强点,也有一些弱点。

(2) 我可以在 VHDL 中完全避免实体、架构和组件吗?您可以避免使用组件(搜索“VHDL 直接实体实例化”),但在某些时候您将需要实体和架构。

您至少可以编写一个完成您的工作的进程,接收信号的输入(clk、count)并在其他信号上传输到 LED。

创建一个将所有这些信号作为端口的实体,以及一个包含您的进程的架构,将其信号连接到端口。这很容易——它只是样板文件。在 FPGA 上,您还需要定义这些端口与 LED 连接到的实际引脚之间的映射。合成它,你就完成了,对吧?.. 不完全的。

创建另一个没有外部端口的“测试台”实体。这将包含您的实体(直接实例化)、一组连接到其端口的信号,以及一个驱动实体输入端口并监视其输出端口的新进程。(最佳实践是让测试台自检,并在出现问题时断言!)通常“clk”来自它自己的单行进程,并为测试台和实体提供时钟。

现在,您可以模拟测试台并以您想要的任何详细程度观察您的设计是否正常工作(或不工作!)。当它起作用时 - 合成。

编辑以获取更多信息:re:组件、过程、功能。

实体/组件是主要工具(如果您愿意,您可以忽略组件,稍后我将处理实体)。

过程和函数通常在一个进程中协同工作。如果将它们重构为一个包,它们可以在其他志同道合的过程中重用(例如,对相同的数据类型进行操作)。一个常见的抽象是一个数据类型,加上在它上面操作的所有函数和过程,包装在一个包中——这有点类似于 C++ 类。函数在任何声明区域也有用途,作为初始化器(在软件术语中也称为“工厂”模式)

但主要工具是实体。

这是一个嵌入式 C 程序员可能不熟悉的级别,因为 C 基本上停留在进程级别。

如果您编写了一个像 SPI 主机这样的物理块,作为一个进程,您将把该进程包装在一个实体中。这将通过端口与世界其他地方进行通信(在实体内部,端口的行为类似于信号)。它可以通过泛型进行参数化(例如,对于内存大小,如果它是内存)。实体可以包装多个进程、其他实体和其他不完全适合进程的逻辑(例如,非时钟逻辑,进程被计时的地方)

要创建一个系统,您将在“结构 HDL 代码”(有用的搜索词!)中互连实体 - 可能是它们的整个层次结构 - 在顶级实体中。您通常会将其综合到 FPGA 中。

要通过仿真测试系统,您将把顶层实体 (=FPGA) 嵌入到另一个没有外部端口的实体 - 测试平台中。相反,FPGA 的端口连接到测试台内的信号。这些信号连接到......其中一些连接到其他实体 - 可能是存储器模型或 SPI 从外设,因此您可以模拟 SPI 事务......其中一些由测试台中的进程驱动,该进程为您的 FPGA 刺激提供信号并检查其响应、检测和报告错误。

最佳实践涉及您创建的每个实体的测试台 - 换句话说,单元测试。SPI 主机可能会连接到其他人的 SPI 从机和测试进程,以启动 SPI 事务并检查正确的响应。这样,您可以在实体级别定位和纠正问题,而不是尝试从顶级测试平台诊断它们。

此处显示了一个基本示例:

请注意,他通过位置关联和(稍后)命名关联来显示端口映射 - 您也可以将这两种形式用于函数参数,如在 Ada 中,但不能使用仅允许位置关联的 C。

“vhdlguru”没有说命名关联是首选,因为位置关联是混乱和错误的丰富来源。

这开始有帮助了吗?

于 2012-12-04T15:18:51.400 回答
0

基本上有两种将信息传递给实体的可能性:

在运行时

实体使用端口语句中定义的信号相互通信。为了更好的可读性,我建议在适当的情况下使用 std_logic_vector、numeric_std 甚至更好的记录类型。请参阅下面的链接。

在合成时

如果您想在综合时将实体的参数设置为固定值(例如 fifo 的大小),您可能需要使用通用语句。另请参阅下面的链接。

我也可以推荐阅读这篇论文。在处理超过一定复杂性的系统时,它对我有很大帮助: 一种结构化的 VHDL 设计方法

于 2014-06-19T08:10:11.717 回答
0

实体/组件与子程序(函数/过程)的一些简单概括。

当可重用代码块包含触发器(寄存器)时,使用实体。

使用函数做计算。对于 RTL 代码,我将函数用于小型、可重用的组合逻辑。

我主要使用测试平台的程序。我使用程序将单个事务(波形或接口操作)应用于我正在测试的设计。对于测试平台,我进一步使用过程来封装经常使用的事务序列。

于 2014-06-19T17:19:57.460 回答