«Случай — это псевдоним Бога, когда Он не хочет подписываться своим собственным именем.» А. Франс

Проектирование цифровых систем на языках описания аппаратуры/Лекция 11

Материал из Wiki
Перейти к: навигация, поиск
Лекции ПЦСЯОА

Лекции

Практические

Доп. материалы

Заголовок
Верификация VHDL описаний цифровых систем. Генерация псевдослучайных тестов и функциональное покрытие
Автор
Ланкевич Ю.Ю.
Нижний колонтитул
Проектирование цифровых систем на языках описания аппаратуры/Лекция 11
Дополнительный нижний колонтитул
Ланкевич Ю.Ю., 12:55, 20 октября 2020


Содержание

Слайд:Структура тестирующей программы

Тестирующие программы, реализующие процесс тестирования VHDL модели, не имеют входных и выходных портов. Архитектурное тело тестирующей программы обычно состоит из трех либо четырех частей.
[svg]

  1. Декларативная часть. В декларативной части архитектурного тела указывается тестируемый компонент (интерфейс VHDL модели проектируемого устройства либо системы), а также задаются сигналы, являющиеся входными и выходными портами устройства.
  2. Вызов модели. В исполняемом разделе архитектурного тела, т. е. после ключевого слова Begin, записывается оператор port map для вызова модели устройства.
  3. Задание входных воздействий. В третьей части в исполняемом разделе архитектурного тела записываются входные наборы, подаваемые на вход тестируемого компонента, либо программным образом обеспечивается генерация входных наборов по тем или иным правилам.
  4. Сравнение полученных реакций модели с ожидаемыми реакциями. Если тестирующая программа записала полученные реакции модели в виде файла, то данный файл может быть сравнен с файлом ожидаемых реакций, который обычно считается эталонным.

Заметим, что проектировщик может внести ошибку и в файл ожидаемых реакций, поэтому в результате несовпадений файлов, возможно, придется исправлять как модель, так и файл ожидаемых реакций. Далее будут представлены различные варианты организации тестирующих программ для одной и той же модели двухразрядного умножителя mult_2.

1  library ieee;
2  use ieee.std_logic_1164.all;
3
4  entity mult_2 is
5      port (
6             s1, s0, r1, r0 : in std_logic;
7             t3, t2, t1, t0 : out std_logic);
8  end mult_2;
9  architecture struct of mult_2 is
10     component add1
11         port ( b1, b2 : in std_logic;
12                c1, s1 : out std_logic);
13     end component;
14     signal p1, p2, p3, p4 : std_logic;
15 begin
16     t0 <= r0 and s0;
17     p1 <= r1 and s0;
18     p2 <= r0 and s1;
19     p4 <= r1 and s1;
20     circ1 : add1
21         port map (b1=>p1, b2=>p2, c1=>p3, s1=>t1);
22     circ2 : add1
23         port map (b1=>p3, b2=>p4, c1=>t3, s1=> 2);
24 end struct;

VHDL модель полусумматора add1.

1  library ieee;
2  use ieee.std_logic_1164.all;
3  entity add1 is
4      port( b1, b2 : in std_logic;
5            c1, s1 : out std_logic);
6  end add1;
7  architecture beh of add1 is
8  begin
9      s1 <= (b1 and (not b2)) or ((not b1) and b2);
10     c1 <= b1 and b2;
11 end beh;

Слайд:Задание тестирующих наборов в тестирующей программе

Самая простая тестирующая программа содержит первые три части. На рисунке показаны четыре входных набора, которые должны поочередно подаваться в качестве входных воздействий для функциональной модели двухразрядного умножителя mult_2.

Слайд:Задание тестирующих наборов в тестирующей программе

1  library ieee;
2  use ieee.std_logic_1164.all;
3  entity mult_2_tb1 is
4  end;
5  architecture tb of mult_2_tb1 is
6      component mult_2 is
7          port(
8               s1, s0, r1, r0 : in std_logic;
9               t3, t2, t1, t0 : out std_logic);
10     end component;
11     signal s1, s0, r1, r0 : std_logic;
12     signal t3, t2, t1, t0 : std_logic;
13 begin
14     DUT : mult_2 port map (s1, s0, r1, r0, t3, t2, t1, t0);
15     s1 <= '0',
16           '1' after 20 ns,
17           '1' after 40 ns,
18           '0' after 60 ns;
19     s0 <= '1',
20           '0' after 20 ns,
21           '1' after 40 ns,
22           '0' after 60 ns;
23     r1 <= '0',
23           '0' after 20 ns,
24           '1' after 40 ns,
25           '0' after 60 ns;
26     r0 <= '1',
27           '1' after 20 ns,
28           '1' after 40 ns,
29           '1' after 60 ns;
30 end tb;

Слайд:Генерация тестирующих наборов

Достаточно часто, особенно при тестировании блоков комбинационной логики, возникает потребность в генерации всевозможных тестовых наборов – n-разрядных двоичных векторов. Число всех различных n-разрядных двоичных векторов равно 2n , поэтому такая генерация возможна дляограниченного числа n, например, для n≤30.


В тестирующей программе генерация наборов осуществляется согласно возрастанию их десятичного эквивалента, проще говоря, наборы перечисляются, как в левой части таблицы истинности, задающей булеву функцию либо систему булевых функций. Генерация всевозможных 2n наборов (в двоичном коде) согласно возрастанию десятичного эквивалента осуществляется в бесконечном цикле, т. е. после набора 1111 генерируется набор 0000, затем 0001, и т. д. Поэтому для такой программы не рекомендуется выполнять в системе моделирования команду RUN ALL.

 1  library ieee;
2  use ieee.std_logic_1164.all;
3  entity mult_2_tb3 is
4  end;
5  architecture tb of mult_2_tb3 is
6      component mult_2 is
7          port (s1, s0, r1, r0 : in std_logic;
8                t3, t2, t1, t0 : out std_logic);
9      end component;
10     signal s1, s0, r1, r0 : std_logic := '0';
11     signal t3, t2, t1, t0 : std_logic;
12 begin
13     DUT : mult_2 port map (s1, s0, r1, r0, t3, t2, t1,t0);
14     -- не выполнять RUN ALL
15     s1 <= not s1 after 160 ns;
16     s0 <= not s0 after 80 ns;
17     r1 <= not r1 after 40 ns;
18     r0 <= not r0 after 20 ns;
19 end tb;

Слайд:Моделирование с проверкой ожидаемых реакций

Тестирующая программа реализует процесс тестирования, представленный на рисунке ниже. Файл IN.TST представляет собой тест, т. е. наборы входных сигналов, подаваемых на входы тестируемой системы. Файл AWAIT_OUT.TST представляет собой выходные реакции. Каждой строке (входному набору) соответствует строка с тем же номером в файле ожидаемых реакций. Файл OUT.TST представляет собой реакции системы. Данный файл формируется при моделировании.
Алгоритм тестирования следующий:

* из файла IN.TST в цикле считывается строка за строкой;
* считывание строки текстового файла осуществляется функцией readline;
* Затем функция read превращает символы в тип std_logic_vector.
* считанная строка “помещается” в переменную data, потом данные входные воздействия передаются в вектор din, который командой
(s1, s0, r1, r0) <= din;

распределяет разряды на вход модели mult_2.


В каждой итерации цикла считывается также строка из файла AWAIT_OUT.TST. Каждая строка – это вектор (ожидаемая реакция системы). Потом идет ожидание 20 ns – это важно, чтобы подождать и записать затем модельную реакцию схемы в файл OUT.TST. Функция write преобразует std_logic_vector в строку символов, функция writeline записывает строку в файл. Затем идет сравнение строк ожидаемой и действительной реакций. Если есть ошибка, то наращивается значение сигнала errors, подсчитывающего число несовпадающих модельных и ожидаемых реакций. Если ошибок нет, то выдается сообщение "Done!". Если ожидаемая реакция не совпадает с модельной, то выдается номер ошибки и время моделирования (такт), в которое ошибка произошла. Рекомендуется выполнить моделирование с правильным и неправильным файлом ожидаемых реакций. Заметим, что ошибки могут быть и в файле ожидаемых реакций.

1  library ieee;
2  use ieee.std_logic_1164.all;
3  use ieee.numeric_std.all;
4  use std.textio.all;
5  use ieee.std_logic_textio.all;
6  architecture tb2 of mult_2_tb7 is
7      component mult_2 is
8          port (
9                s1, s0, r1, r0 : in std_logic;
10               t3, t2, t1, t0 : out std_logic);
11         end component;
12     signal s1, s0, r1, r0 : std_logic;
13     signal t3, t2, t1, t0 : std_logic;
14     signal din, dout : std_logic_vector (3 downto 0);
15     signal errors : natural := 0;
16 begin
17     DUT : mult_2 port map (s1, s0, r1, r0, t3, t2, t1, t0);
18
19     (s1, s0, r1, r0) <= din;
20     dout <= (t3, t2, t1, t0);
21     p1 : process
22     file fin, fout, fexpected : text;
23     variable l : line;
24     variable data, data_expected : std_logic_vector (3 downto 0);
25     begin
26         file_open(fin, "IN.TST", read_mode);
27         file_open(fexpected, "AWAIT_OUT.TST", read_mode);
28         file_open(fout, "OUT.TST", write_mode);
29         while not (endfile(fin)) loop
30             readline(fin, l);
31             read(l, data);
32             din <= data;
33             readline(fexpected, l);
34             read(l, data_expected);
35             wait for 20 ns;
36             data := dout;
37             write(l, data);
38             writeline(fout, l);
39             if (data /= data_expected) then
40                 assert (false) report "ERRORS =" & to_string(errors) & " !" severity failure;
41                 errors <= errors + 1;
42             end if;
43         end loop;
44         file_close(fout);
45         file_close(fin);
46         file_close(fexpected);
47         err : assert (errors = 0) report "ERRORS =" & to_string(errors) & " !" severity failure;
48         finish: assert (errors /= 0) report "Done!" severity warning;
49         wait;
50     end process p1;
51 end architecture tb2;

Слайд:Генерация псевдослучайных тестов и функциональное покрытие

В данном разделе рассматривается настраиваемая генерация псевдослучайных тестов и функциональное покрытие. Настраиваемая генерация псевдослучайных тестов позволяет обнаруживать случайные ошибки в проектах в отличие от проблемно-ориентированных или прямых тестов. Функциональное покрытие (functional coverage) предназначено для измерения того, какая часть функций проекта была проверена во время выполнения моделирования. В методологии OS-VVM функциональное покрытие осуществляется сбором значений переменных и сигналов VHDL проекта при выполнении моделирования. Методология OS-VVM базируется на VHDL пакетах CoveragePkg и RandomPkg стандарта VHDL’2008.

Рассмотрим подход к генерации псевдослучайных тестовых векторов на примере тестирования простейшего VHDL проекта цифровой системы – умножителя mult, предназначенного для перемножения целых положительных чисел a, b, заданных в двоичном коде. Точнее говоря, каждое из этих чисел задается в виде

a, b : in std_logic_vector (4 downto 1);

Умножитель описан на алгоритмическом уровне: с помощью функции to_integer, находящейся в пакете numeric_std, входящем в стандартную библиотеку ieee, осуществляется переход к численным значениям входных векторов, затем полученные числа перемножаются, после чего осуществляется преобразование произведения e в выходной вектор d.

1  library ieee;
2  use ieee.std_logic_1164.all;
3  use ieee.numeric_std.all;
4  entity mult is
5      port ( a, b : in std_logic_vector (4 downto 1);
6             d : out std_logic_vector (8 downto 1));
7  end mult;
8  architecture functional of mult is
9      signal e : integer range 0 to 225;
10 begin
11     p0 : process(a, b)
12         variable a_int, b_int : integer range 0 to 15;
13     begin
14         a_int := to_integer(unsigned(a));
15         b_int := to_integer(unsigned(b));
16         e <= a_int * b_int;
17     end process;
18     d <= std_logic_vector(to_unsigned(e, 8));
19 end functional;