亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> VHDL

使用 TEXTIO 在测试台中读取的刺激文件

从文件中读取信号值是为被测设备 (DUT) 生成刺激的另一种方法。测试台序列和时序硬编码在 VHDL 测试台逐行读取的激励文件中。这使您可以轻松更改要馈送到测试对象的波形模式。

有时,您有一个非常具体的测试模式或事件序列,您希望您的 DUT 通过。您可以通过在 ASCII 文件中指定每个信号应具有的信号值以及它们应更改的相对仿真时间来实现此目的。 VHDL 测试平台在这种策略中的作用是从激励文件中读取数据,并在正确的时间将这些值应用于 DUT 输入。

本文是 VHDL 文件访问系列文章的第二篇。我们在上一篇博文中了解了如何从文件中读取十六进制、八进制和二进制值,如果您想了解有关使用 TEXTIO 从文件读取的更多信息,请返回阅读它 VHDL 中的库。

这篇博文是关于在 VHDL 中使用 TEXTIO 库的系列文章的一部分。在此处阅读其他文章:

如何使用 TEXTIO 从文件初始化 RAM

使用 TEXTIO 读取 BMP 文件位图图像

测试用例

示例 DUT 将是一个 4 输入多路复用器 (MUX),取自我之前的一篇博客文章。它是一个标准的异步 4 对 1 MUX,数据宽度为一个字节。它的工作原理对于本文并不重要,因为我们不会对输出进行任何检查,这只是为了演示目的。

MUX的实体如下图。

entity mux_4 is
  port(
    -- Data in
    din_0 : in unsigned(7 downto 0);
    din_1 : in unsigned(7 downto 0);
    din_2 : in unsigned(7 downto 0);
    din_3 : in unsigned(7 downto 0);

    -- Selector
    sel  : in unsigned(1 downto 0);

    -- Data out
    dout : out unsigned(7 downto 0));
end entity;

在 VHDL 文件顶部导入必要的包后,我们继续声明我们将要连接到 DUT 的输入信号。从下面的清单可以看出,它们是 MUX 实体声明的蓝图。

signal din_0 : unsigned(7 downto 0);
signal din_1 : unsigned(7 downto 0);
signal din_2 : unsigned(7 downto 0);
signal din_3 : unsigned(7 downto 0);
signal sel  : unsigned(1 downto 0);
signal dout : unsigned(7 downto 0);

我们使用实体实例化方法在测试平台的架构区域顶部创建带有标签“DUT”的 MUX 实例。实体信号连接到本地同名的testbench信号,如下代码所示。

DUT: entity work.mux_4(rtl)
port map (
    din_0 => din_0,
    din_1 => din_1,
    din_2 => din_2,
    din_3 => din_3,
    sel  => sel,
    dout => dout
);

刺激文件

刺激文件可以有很多不同的格式,这里介绍的只是我在写这篇文章时想到的一个例子。不过,当您了解我是如何创建它时,您应该能够对其进行修改以满足您的需求。

下面的清单显示了本示例中使用的完整激励文件。

# Column description:
# wait_time | sel | din_0 | din_1 | din_2 | din3 # Optional console printout

0 ns 0 AA BB CC DD # Setting initial values
10 ns 1 AA BB CC DD # Testing by changing the selector signal
10 ns 2 AA BB CC DD
10 ns 3 AA BB CC DD
10 ns 3 A1 B1 C1 D1 # Testing by changing all data inputs
10 ns 3 A2 B2 C2 D2
10 ns 3 A3 B3 C3 D3
10 ns 3 00 00 00 D2 # Changing all unselected inputs
10 ns 3 01 02 03 D2
10 ns 3 11 22 33 D2
1 ns 0 CC DD EE FF # Changing all inputs fast
1 ns 1 DD EE FF CC
1 ns 2 EE FF CC DD
1 ns 3 FF CC DD EE
10 ns 0 00 00 00 00 # Simulation stop

让我们暂时忽略评论,那些是用绿色标记的,总是以“#”字符开头。每条线代表模拟中的一个时间步长。每行有六列命令,实际上是七列文本,但前两列属于同一个数据项。

文本列一和二描述了一个时间值,即模拟器在应用其他列中列出的值之前应该在该行暂停多长时间。因此,执行命令时的绝对仿真时间是相对于上一行描述的事件而言的。我们只使用 0、1 或 10 纳秒,但它可以是任何值,1000 纳秒或 1000 小时(1000 hr ) 就此而言。

其余五个文本列描述了应用于 DUT 输入的信号值。它们以十六进制文字形式给出,信号顺序为 sel , din_0 , din_1 , din_2 ,最后是 din_3 .

现在,转到评论。有两种类型的评论;单行注释和尾随注释。我们的测试平台将区别对待它们。单行注释,如文件顶部的注释,将被忽略。另一方面,尾随注释应打印到模拟器控制台。我们可以使用它们为我们提供有关模拟运行时发生的情况的线索。

在 VHDL 中读取激励文件

VHDL 不是最适合文本处理的语言,但它可以胜任。对动态字符串的支持是有限的,并且它缺乏方便的例程,例如用于剥离或跳过空格。为了让我们自己更容易,我们将假设刺激文件写得很好。让我们非常小心地确保文本元素之间总是有一个空格,而“#”字符和注释文本之间总是有一个空格。此外,刺激文件中的任何位置都没有额外的前导或尾随空格。

PROC_SEQUENCER : process
  file text_file : text open read_mode is "stimulus.txt";
  variable text_line : line;
  variable ok : boolean;
  variable char : character;
  variable wait_time : time;
  variable selector : sel'subtype;
  variable data : dout'subtype;
begin

PROC_SEQUENCER 的声明区域 程序如上所示。首先,我们声明特殊的 file 对象,VHDL 文件处理程序类型。然后,我们声明一个 line 类型的变量 .这只是一个对字符串的访问类型,一个指向动态分配的字符串对象的指针。 ok Boolean 类型的变量用于检查读取操作是否成功。最后,我们声明四个变量char , wait_time , selector , 和 data .这些变量用于从每一行文本中提取每一列的数据。

  while not endfile(text_file) loop

    readline(text_file, text_line);

    -- Skip empty lines and single-line comments
    if text_line.all'length = 0 or text_line.all(1) = '#' then
      next;
    end if;

在流程主体中,我们直接进入一个 while 循环,该循环将遍历激励文件中的每一行文本。 readline 过程将新的文本行分配给 text_line 此循环的每次迭代中的变量。读取该行后,我们检查该行是否为空或第一个字符是否为“#”,在这种情况下,我们立即使用 next 转到下一行 关键字跳过循环的迭代。请注意,我们使用的是 text_line.all 访问 line 中的字符串 对象。

    read(text_line, wait_time, ok);
    assert ok
      report "Read 'wait_time' failed for line: " & text_line.all
      severity failure;

    hread(text_line, selector, ok);
    assert ok
      report "Read 'sel' failed for line: " & text_line.all
      severity failure;
    sel <= selector;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_0' failed for line: " & text_line.all
      severity failure;
    din_0 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_1' failed for line: " & text_line.all
      severity failure;
    din_1 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_2' failed for line: " & text_line.all
      severity failure;
    din_2 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_3' failed for line: " & text_line.all
      severity failure;
    din_3 <= data;

接下来是来自 text_line 的一些读取 目的。 readhread 过程调用跳过前导空格,这样我们就不必执行任何虚拟读取来移动 text_line 内的内部读取起始位置 目的。我们可以省略断言语句,但我希望在读取失败时停止模拟。至少在 ModelSim 中,发生这种情况时模拟不会自动停止。我们将每个成功读取的变量分配给相关的 DUT 信号,除了 wait_time 没有对应 DUT 输入的变量。

    wait for wait_time;

分配信号值后,我们等待指定的时间。命中等待语句会导致预定的信号值在相同的增量周期内生效。

    -- Print trailing comment to console, if any
    read(text_line, char, ok); -- Skip expected newline
    read(text_line, char, ok);
    if char = '#' then
      read(text_line, char, ok); -- Skip expected newline
      report text_line.all;
    end if;

  end loop;

  finish;

end process;

最后,当程序从等待语句中唤醒时,我们在 text_line 上寻找附加的尾随注释 目的。在我们使用虚拟读取去除“#”字符和以下空格后,使用报告语句将任何注释打印到控制台。

在处理完刺激文件的最后一行文本后,while 循环终止。有一个 VHDL-2008 finish 负责停止测试平台的进程结束时的关键字。

输出

示例测试台在 ModelSim 中运行时将下面显示的文本打印到模拟器控制台。我们可以看到评论是来自刺激文件的评论。打印的时间值是基于刺激文件中指定的纳秒延迟的累积模拟时间。


# ** Note: Setting initial values
#    Time: 0 ns  Iteration: 1  Instance: /file_stim_tb
# ** Note: Testing by changing the selector signal
#    Time: 10 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Testing by changing all data inputs
#    Time: 40 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Changing all unselected inputs
#    Time: 70 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Changing all inputs fast
#    Time: 91 ns  Iteration: 0  Instance: /file_stim_tbf
# ** Note: Simulation stop
#    Time: 104 ns  Iteration: 0  Instance: /file_stim_tb
# Break in Process PROC_SEQUENCER at file_stim_tb.vhd line 98

仿真波形如下所示。它直观地展示了我们的激励文件中的值如何在指定的仿真时间应用于信号。

最后的想法

如果您有需要应用的非常具体的测试模式,则从文件中读取测试台刺激可能会很有优势。整个测试台不必由文本文件控制,这个例子只是为了展示VHDL文件访问的可能性。

但是,我们尚未讨论的一件事是检查 DUT 输出。我们的示例测试平台根本不检查输出。您可以像在完整的 VHDL 测试平台中一样验证 DUT 行为,例如通过使用行为模型进行比较。或者您可以修改代码和激励文件以包含预期的输出值。无论您选择哪种策略,请确保您创建了一个自检测试平台,而不是依赖手动检查波形。


VHDL

  1. C# 使用
  2. C 文件处理
  3. Java 文件类
  4. 在 Linux 中使用数字签名进行数据完整性检查
  5. 使用 PSL 在 VHDL 中进行形式化验证
  6. 如何使用 TEXTIO 从文件初始化 RAM
  7. 如何创建自检测试平台
  8. Java BufferedReader:如何通过示例在 Java 中读取文件
  9. Python JSON:编码(转储)、解码(加载)和读取 JSON 文件
  10. Verilog 文件 IO 操作
  11. C - 头文件
  12. 什么是三角文件?