vhdl
Защищенные типы
Поиск…
замечания
Ранее VHDL 1993, два параллельных процесса могли связываться только с сигналами. Благодаря семантике моделирования языка, который обновляет сигналы только между этапами моделирования, результат моделирования был детерминированным: он не зависел от порядка, выбранного планировщиком моделирования для выполнения процессов.
[На самом деле, это не на 100% верно. Процессы также могут взаимодействовать с использованием ввода / вывода файлов. Но если дизайнер скомпрометировал детерминизм с помощью файлов, это не могло быть ошибкой.]
Таким образом, язык был безопасным. Кроме того, было практически невозможно разработать недетерминированные модели VHDL.
VHDL 1993 представила общие переменные, и разработка недетерминированных моделей VHDL стала очень простой.
В VHDL 2000 были введены защищенные типы и ограничение, что общие переменные должны быть защищенного типа.
В VHDL защищенные типы похожи на концепцию объектов на объектно-ориентированных (OO) языках. Они реализуют инкапсуляцию структур данных и их методов. Они также гарантируют эксклюзивный и атомный доступ к своим членам данных. Это не полностью предотвращает детерминизм, но, по крайней мере, добавляет исключительность и атомарность к общим переменным.
Защищенные типы очень полезны при разработке моделей VHDL высокого уровня, предназначенных только для моделирования. У них есть несколько очень хороших свойств языков OO. Использование их часто делает код более читаемым, поддерживаемым и многоразовым.
Заметки:
- Некоторые цепочки инструментов моделирования по умолчанию выдают предупреждения только тогда, когда общая переменная не относится к защищенному типу.
- Некоторые инструменты синтеза не поддерживают защищенные типы.
- Некоторые инструменты синтеза имеют ограниченную поддержку общих переменных.
- Можно подумать, что общие переменные не пригодны для моделирования модели и должны быть зарезервированы для инструментария кода без побочных эффектов. Но шаблоны VHDL, рекомендованные несколькими поставщиками EDA для моделирования плоскости памяти многопортовых запоминающих устройств произвольного доступа (ОЗУ), используют общие переменные. Итак, да, общие переменные могут быть синтезированы при определенных обстоятельствах.
Псевдослучайный генератор
Педо-случайные генераторы часто полезны при проектировании имитационных сред. Следующий пакет VHDL показывает, как использовать защищенные типы для создания псевдослучайного генератора boolean
, bit
и bit_vector
. Его можно легко расширить, чтобы также генерировать случайный std_ulogic_vector
, signed
, unsigned
. Расширение его для генерации случайных целых чисел с произвольными границами и равномерное распределение является немного более сложным, но выполнимым.
Объявление пакета
Защищенный тип имеет объявление, в котором объявляются все общедоступные подпрограммы. Для нашего случайного генератора мы опубликуем одну процедуру инициализации семян и три нечистые функции, возвращающие случайный boolean
bit
или bit_vector
. Обратите внимание, что функции не могут быть чистыми, поскольку разные вызовы любого из них с одинаковыми параметрами могут возвращать разные значения.
-- file rnd_pkg.vhd
package rnd_pkg is
type rnd_generator is protected
procedure init(seed: bit_vector);
impure function get_boolean return boolean;
impure function get_bit return bit;
impure function get_bit_vector(size: positive) return bit_vector;
end protected rnd_generator;
end package rnd_pkg;
Корпус упаковки
Тело защищенного типа определяет внутренние структуры данных (элементы) и тела подпрограммы. Наш случайный генератор основан на 128-битном линейном регистре сдвига обратной связи (LFSR) с четырьмя кранами. Переменная state
хранит текущее состояние LFSR. Процедура частного throw
сдвигает LFSR каждый раз, когда используется генератор.
-- file rnd_pkg.vhd
package body rnd_pkg is
type rnd_generator is protected body
constant len: positive := 128;
constant default_seed: bit_vector(1 to len) := X"8bf052e898d987c7c31fc71c1fc063bc";
type tap_array is array(natural range <>) of positive range 1 to len;
constant taps: tap_array(0 to 3) := (128, 126, 101, 99);
variable state: bit_vector(1 to len) := default_seed;
procedure throw(n: positive := 1) is
variable tmp: bit;
begin
for i in 1 to n loop
tmp := '1';
for j in taps'range loop
tmp := tmp xnor state(taps(j));
end loop;
state := tmp & state(1 to len - 1);
end loop;
end procedure throw;
procedure init(seed: bit_vector) is
constant n: natural := seed'length;
constant tmp: bit_vector(1 to n) := seed;
constant m: natural := minimum(n, len);
begin
state := (others => '0');
state(1 to m) := tmp(1 to m);
end procedure init;
impure function get_boolean return boolean is
constant res: boolean := state(len) = '1';
begin
throw;
return res;
end function get_boolean;
impure function get_bit return bit is
constant res: bit := state(len);
begin
throw;
return res;
end function get_bit;
impure function get_bit_vector(size: positive) return bit_vector is
variable res: bit_vector(1 to size);
begin
if size <= len then
res := state(len + 1 - size to len);
throw(size);
else
res(1 to len) := state;
throw(len);
res(len + 1 to size) := get_bit_vector(size - len);
end if;
return res;
end function get_bit_vector;
end protected body rnd_generator;
end package body rnd_pkg;
Затем случайный генератор можно использовать в стиле OO, как в:
-- file rnd_sim.vhd
use std.env.all;
use std.textio.all;
use work.rnd_pkg.all;
entity rnd_sim is
end entity rnd_sim;
architecture sim of rnd_sim is
shared variable rnd: rnd_generator;
begin
process
variable l: line;
begin
rnd.init(X"fe39_3d9f_24bb_5bdc_a7d0_2572_cbff_0117");
for i in 1 to 10 loop
write(l, rnd.get_boolean);
write(l, HT);
write(l, rnd.get_bit);
write(l, HT);
write(l, rnd.get_bit_vector(10));
writeline(output, l);
end loop;
finish;
end process;
end architecture sim;
$ mkdir gh_work
$ ghdl -a --std=08 --workdir=gh_work rnd_pkg.vhd rnd_sim.vhd
$ ghdl -r --std=08 --workdir=gh_work rnd_sim
TRUE 1 0001000101
FALSE 0 1111111100
TRUE 1 0010110010
TRUE 1 0010010101
FALSE 0 0111110100
FALSE 1 1101110010
TRUE 1 1011010110
TRUE 1 0010010010
TRUE 1 1101100111
TRUE 1 0011100100
simulation finished @0ms