Open Source VHDL Verification Methodology/Описание пакета RandomPkg
- Руководство пользователя (eng)
- Описание пакета CoveragePkg (eng)
- Описание пакета RandomPkg (eng)
Псевдослучайное тестирование (Randomization) и пакет RandomPkg
RandomPkg provides types subprograms and protected type methods to simplify randomization. As such, it is at the heart of SynthWorks' constrained and coverage driven random methodology.
Пакет RandomPkg предоставляет типы подпрограмм и метода защищённого (protected) типа для упрощения псевдослучайной генерации чисел. Как таковой,
This documentation provides details on the STANDARD revision 2.0 of RandomPkg. As such this documentation supercedes the slides presented in the webinar in March of 2009. These packages are updated from time to time and are freely available at http://www.synthworks.com/downloads.
1. Randomization Using IEEE.math_real.uniform = Yuck!
Основная форма генератора псевдослучайных чисел может быть достигнута с помощью процедуры uniform пакета IEEE math_real. Однако, это всегда приводит к тому, что генерация псевдослучайных чисел будет многошаговым процессом: вызов процедуры uniform для получения псевдослучайного числа, масштабирования числа, и затем использования числа.
RandomGenProc : process variable RandomVal : real ; -- Random value variable DataSent : integer ; variable seed1 : positive := 7 ; -- initialize seeds variable seed2 : positive := 1 ; begin for i in 0 to 255*6 loop uniform(seed1, seed2, RandomVal) ; -- randomize 0.0 to 1.0 DataSent := integer(trunc(RandomVal*256.0)) ; -- scale to 0 to 255 do_transaction(…, DataSent, …) ; . . .
Оптимально можно было бы вызвать функцию, которая делала бы это, можно сделать всё за один шаг. Но к сожалению нельзя записать нормальную VHDL функцию, поскольку необходимо прочитать и обновить начальное значение генератора псевдослучайных чисел as well as return a randomized value.
Упрощённая генерация случайных чисел
Пакет RandomPkg использует защищённый тип (protected), именуемый RandomPType, для инкапсуляции начального значения (seed) псевдослучайного генератора. Используя защищённый тип, impure функции могут читать и обновлять seed так же как возвращать псевдослучайное значение. Для генерации псевдослучайных чисел используя защищённый тип, необходимо объявить переменную типа RandomPType, инициализировать начальное значение генератора (seed) и получить псевдослучайное число.
RandomGenProc : process variable RV : RandomPType ; -- protected type from RandomPkg begin RV.InitSeed (RV'instance_name) ; -- Generate initial seeds for i in 0 to 255*6 loop do_transaction(…, RV.RandInt(0, 255), …) ; -- random value between 0 and 255
Следует обратить внимание, что вызовы методов защищённого типа (подпрограммы) включают переменную защищённого типа (RV) с вызовом функции (например, RV.RandInt(0, 255)).
Управление начальными значениями генератора (seed)
Внутренние объекты защищённых типов являются приватными и доступны только через методы. Внутреннее представление начального значения (seed) имеет подходящее начальное значение, однако, чтобы быть уверенным, что каждый процесс псевдослучайной генерации реализован каждый по отдельности, важно дать каждому начальному значению генератора разные начальные значения. В результате для теста, который использует более одной переменной псевдослучайной генерации чисел, инициализировать каждое значение seed единожды — если есть только одна переменная для генерации, то нет необходимости инициализировать seed.
Метод InitSeed преобразует значение аргумента к типу RandomSeedType (внутреннее представление seed) и сохраняет значение внутри защищённого типа. InitSeed перегружена, чтобы принимать значения типа string или integer. Приемлемый путь дать каждому значению seed уникальное значение, это назначить строковое значение RV'instance_name.
RV.InitSeed (RV'instance_name) ;
Методы GetSeed и SetSeed используются для чтения и восстановления значения seed. Объявление для этоко показаны ниже.
impure function GetSeed return RandomSeedType ; procedure SetSeed (RandomSeedIn : RandomSeedType ) ;
Функция to_string и процедуры write и read используются для записи и чтения значения типа RandomSeedType. Декларации для этих подпрограмм показаны ниже. Следует обратить внимание, что это объявлено в файле RandomBasePkg.vhd и отделено от защищённого типа.
function to_string(A : RandomSeedType) return string ; procedure write(L: inout line ; A : RandomSeedType ) ; procedure read (L: inout line ; A : out RandomSeedType ; good : out boolean ) ; procedure read (L: inout line ; A : out RandomSeedType ) ;
Для длинного тест, может быть преимуществом чтение seed периодически и печатать (выводить) его. Если сбой или другой интересное состояние генерируется, seed может быть восстановлено значение, которое было записано перед сбоем с целью генерации ошибки быстро, чтобы помочь с отладкой.
-- Seed Manipulation -- Known ambiguity between InitSeed with string and integer_vector -- Recommendation, use: RV.InitSeed(RV'instance_path) ; -- For integer_vector use either: RV.InitSeed(IV => (1,5)) ; -- or: RV.InitSeed(integer_vector'(1,5)) ; procedure InitSeed (S : string ) ; procedure InitSeed (I : integer ) ; procedure InitSeed (IV : integer_vector ) ; -- SetSeed & GetSeed: Used to save and restore seed values procedure SetSeed (RandomSeedIn : RandomSeedType ) ; impure function GetSeed return RandomSeedType ; -- SeedRandom = SetSeed & GetSeed for SV compatibility -- replace with aliases when they work in popular simulators procedure SeedRandom (RandomSeedIn : RandomSeedType ) ; impure function SeedRandom return RandomSeedType ; -- alias SeedRandom is SetSeed [RandomSeedType] ; -- alias SeedRandom is GetSeed [return RandomSeedType] ;
Задание параметров
-- Setting Randomization Parameters -- Allows RandInt to have distributions other than uniform procedure SetRandomParm (RandomParmIn : RandomParmType) ; procedure SetRandomParm ( Distribution : RandomDistType ; Mean : Real := 0.0 ; Deviation : Real := 0.0 ) ; impure function GetRandomParm return RandomParmType ; impure function GetRandomParm return RandomDistType ; -- For compatibility with previous version - replace with alias procedure SetRandomMode (RandomDistIn : RandomDistType) ; -- alias SetRandomMode is SetRandomParm [RandomDistType, Real, Real] ;
Основы генерации случайных чисел
Базовый генератор псевдослучайных чисел генерирует значение типа integer, которое либо входит в какой-то диапазон или в набор значений. Набор значений и исключенных значений являются все типа integer_vector (определённый в стандарте VHDL-2008). Примеры базовых функций генерации псевдослучайных чисел показаны ниже. Когда задаётся значение типа integer_vector, то дополнительные круглые скобки означают, что это множество (сборное) значений.
RandomGenProc : process variable RV : RandomPType ; -- protected type from RandomPkg variable DataInt : integer ; begin RV.InitSeed (RV'instance_name) ; -- Generate initial seeds -- Generate a value in range 0 to 255 DataInt := RV.RandInt(0, 255) ; . . . -- Generate a value in range 1 to 9 except exclude values 2,4,6,8 DataInt := RV.RandInt(1, 9, (2,4,6,8)) ; . . . -- Generate a value in set 1,3,5,7,9 DataInt := RV.RandInt( (1,3,7,9) ) ; -- note two sets of parens required . . . -- Generate a value in set 1,3,5,7,9 except exclude values 3,7 DataInt := RV.RandInt((1,3,7,9), (3,7) ) ;
Такие же функции доступны для типов std_logic_vector (RandSlv), unsigned (RandUnsigned) и signed (RandSigned). Следует обратить внимание, что значение этого параметра по прежнему задаётся как целое и есть дополнительное значение, которое используется для задания размера (разрядности) генерируемого значения. Например, следующий вызов метода RandSlv задаёт массив размером 8 бит.
. . . variable DataSlv : std_logic_vector(7 downto 0) ; begin . . . -- Generate a value in range 0 to 255 DataSlv := RV.RandSlv(0, 255, 8) ;
Для генерации псевдослучайных чисел из диапазона, существует также функция RandReal. Так же как процедура Uniform, она никогда не генерирует свои конечные значения.
Перегруженные функции RandInt представлены ниже.
impure function RandInt (Min, Max : integer) return integer ; impure function RandInt (Min, Max: integer; Exclude: integer_vector) return integer; impure function RandInt ( A : integer_vector ) return integer ; impure function RandInt ( A : integer_vector; Exclude: integer_vector) return integer;
-- real randomization with a range impure function RandReal(Min, Max: Real) return real ; -- integer randomization with a range impure function RandInt (Min, Max : integer) return integer ; impure function RandSlv (Min, Max, Size : natural ) return std_logic_vector ; impure function RandUnsigned (Min, Max, Size : natural ) return Unsigned ; impure function RandSigned (Min, Max : integer; Size : natural ) return Signed ; -- integer randomization with a range and exclude vector impure function RandInt (Min, Max : integer; Exclude: integer_vector ) return integer ; impure function RandSlv (Min, Max : natural; Exclude: integer_vector ; Size : natural ) return std_logic_vector ; impure function RandUnsigned (Min, Max : natural; Exclude: integer_vector ; Size : natural ) return Unsigned ; impure function RandSigned (Min, Max : integer; Exclude: integer_vector ; Size : natural ) return Signed ; -- Randomly select a value within a set of values impure function RandInt (A : integer_vector ) return integer ; impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector ; impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned ; impure function RandSigned (A : integer_vector ; Size : natural) return Signed ; -- Randomly select a value within a set of values with exclude values (so can skip last or last n) impure function RandInt (A : integer_vector; Exclude: integer_vector ) return integer ; impure function RandSlv (A : integer_vector; Exclude: integer_vector ; Size : natural) return std_logic_vector ; impure function RandUnsigned (A : integer_vector; Exclude: integer_vector ; Size : natural) return Unsigned ; impure function RandSigned (A : integer_vector; Exclude: integer_vector ; Size : natural) return Signed ; . . . -- Convenience Functions impure function RandReal return real ; -- 0.0 to 1.0 impure function RandReal(Max: Real) return real ; -- 0.0 to Max impure function RandInt (Max : integer) return integer ; impure function RandSlv (Size : natural) return std_logic_vector ; impure function RandSlv (Max, Size : natural) return std_logic_vector ; impure function RandUnsigned (Size : natural) return Unsigned ; impure function RandUnsigned (Max, Size : natural) return Unsigned ; impure function RandSigned (Size : natural) return Signed ; impure function RandSigned (Max : integer; Size : natural ) return Signed ;
Имя функции | Входные параметры | Return | Описание | ||||
---|---|---|---|---|---|---|---|
Min | Max | A | Exclude | Size | |||
RandReal | – | – | – | – | – | real | Возвращает псевдослучайное число из диапазона [0.0, 1.0] |
RandSigned | natural | Signed | Возвращает вектор размерности Size из диапазона [0, 2**Size-1] | ||||
RandUnsigned | Unsigned | ||||||
RandSlv | std_logic_vector | ||||||
RandReal | – | real | – | – | – | real | Возвращает псевдослучайное число из диапазона [0.0, Max] |
RandInt | integer | integer | |||||
RandSigned | natural | Signed | Возвращает вектор размерности Size из диапазона [0.0, Max] | ||||
RandUnsigned | natural | Unsigned | |||||
RandSlv | std_logic_vector | ||||||
RandReal | Real | Real | – | – | – | Real | Возвращает псевдослучайное число из диапазона [Min, Max] |
RandInt | integer | integer | integer | ||||
RandSigned | natural | Signed | Генерация вектора размерностью Size в диапазоне значений [Min, Max] | ||||
RandUnsigned | natural | natural | Unsigned | ||||
RandSlv | std_logic_vector | ||||||
RandInt | integer | integer | – | integer_vector | – | integer | Генерация числа в диапазоне [Min, Max] исключая список Exclude |
RandSigned | natural | Signed | Генерация вектора размерностью Size в диапазоне [Min, Max] исключая список Exclude | ||||
RandUnsigned | natural | natural | Unsigned | ||||
RandSlv | std_logic_vector | ||||||
RandInt | – | – | integer_vector | – | – | integer | Генерация случ. числа из списка чисел A |
RandSigned | natural | Signed | Генерация случ. вектора размерностью Size из списка чисел A | ||||
RandUnsigned | Unsigned | ||||||
RandSlv | std_logic_vector | ||||||
RandInt | – | – | integer_vector | integer_vector | – | integer | Генерация случ. числа из списка чисел A исключая список Exclude |
RandSigned | natural | Signed | Генерация случ. вектора размерностью Size из списка чисел A исключая список Exclude | ||||
RandUnsigned | Unsigned | ||||||
RandSlv | std_logic_vector |
Специальные типы данных
Для управления параметрами, представляющими собой набор чисел, в пакете определены два типа:
- DistRecType – запись с двумя полями типа integer Value и Weight;
- DistType – массив (неопределённой длинны) элементов типа DistRecType.
Чтобы обеспечить задание, хранение и восстановление типа случайного распределения, использующийся функциями псевдослучайного генератора, был введён специальный перечислимый тип RandomDistType:
type RandomDistType is (NONE, UNIFORM, FAVOR_SMALL, FAVOR_BIG, NORMAL, POISSON);
На практике значение NONE действует также как и UNIFORM, но позволяет проверить было ли текущее распределение значением по умолчанию (т.е. NONE) или было изменено в коде.
В то время как UNIFORM, NORMAL и POISSON распределения ведут себя как описано в литературе, FAVOR_BIG и FAVOR_SMALL используют внутреннюю функцию квадратного корня, чтобы получить ожидаемые нелинейные (non-uniform) результаты.
Чтобы задать не только тип распределения, но и его числовые параметры, следующая запись RandomParmType объявлена:
type RandomParmType is record Distribution : RandomDistType ; Mean : Real ; StdDeviation : Real ; end record ;
После всех вспомогательных объявлений, в пакет объявляется защищённый типа RandomPType, который управляет операциями генератора псевдослучайных чисел с помощью методов, которые будут описаны далее.
Пожалуйста, обратите внимание, что во избежание снижения качества генерируемых случайных чисел пользователи должны объявлять переменные типа RandomPType как локальные с узкой возможной областью действия. Такие переменные должны быть использованы для создания потока значений для одного конкретного приложения/объекта проекта и не должна быть общими (shared).
constant NULL_INTV : integer_vector (0 downto 1) := (others => 0); -- Supports DistValInt functionality type DistRecType is record Value : integer ; Weight : integer ; end record ; type DistType is array (natural range <>) of DistRecType ; -- Parameters for randomization -- RandomDistType specifies the distribution to use for randomize type RandomDistType is (NONE, UNIFORM, FAVOR_SMALL, FAVOR_BIG, NORMAL, POISSON) ; type RandomParmType is record Distribution : RandomDistType ; Mean : Real ; -- also used as probability of success StdDeviation : Real ; -- also used as number of trials for binomial end record ; -- RandomParm IO function to_string(A : RandomDistType) return string ; procedure write(variable L: inout line ; A : RandomDistType ) ; procedure read(variable L: inout line ; A : out RandomDistType ; good : out boolean ) ; procedure read(variable L: inout line ; A : out RandomDistType ) ; function to_string(A : RandomParmType) return string ; procedure write(variable L: inout line ; A : RandomParmType ) ; procedure read(variable L: inout line ; A : out RandomParmType ; good : out boolean ) ; procedure read(variable L: inout line ; A : out RandomParmType ) ;
Взвешенная генерация псевдослучайных чисел
Взвешенное распределение псевдослучайно генерирует каждый набор значений опоределённый процент раз. RandomPType обеспечивает взвешанное распределение двумя функциями, в одной из которых задаются значение и его вес (DistValInt), а в другой задаётся только вес (DistInt).
DistValInt вызывается с массивом пар значений. Первый элемент в паре это значение, а второй — вес. Частота с которой каждое значение будет возникать равно вес/(сумму всех весов) [weight/(sum of weights)]. В результате в следующем вызове метода DistValInt вероятность возникновения 1 будет 7/10 раз или 70%. Вероятность 3 будет 20%, а 5 — 10%.
variable RV : RandomPType ; . . . DataInt := RV.DistValInt( ((1, 7), (3, 2), (5, 1)) ) ;
DistInt является упрощённой версией DistValInt, в которой задаются только веса. Значения генерируются от 0 до N-1, где N это число заданных весов. Результат следующего вызова DistInt вероятность 0 будет 70%, 1 — 20%, а 2 — 10%.
variable RV : RandomPType ; . . . DataInt := RV.DistValInt((7, 2, 1)) ;
-- Randomly select between 0 and N-1 based on the specified weight. -- where N = number values in weight array impure function DistInt ( Weight : integer_vector ) return integer ; impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector ; impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned ; impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed ; -- Distribution with just weights and with exclude values impure function DistInt ( Weight : integer_vector; Exclude: integer_vector ) return integer ; impure function DistSlv ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return std_logic_vector ; impure function DistUnsigned ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return unsigned ; impure function DistSigned ( Weight : integer_vector; Exclude: integer_vector; Size : natural ) return signed ; -- Distribution with weight and value impure function DistValInt ( A : DistType ) return integer ; impure function DistValSlv ( A : DistType ; Size : natural) return std_logic_vector ; impure function DistValUnsigned ( A : DistType ; Size : natural) return unsigned ; impure function DistValSigned ( A : DistType ; Size : natural) return signed ; -- Distribution with weight and value and with exclude values impure function DistValInt ( A : DistType; Exclude: integer_vector ) return integer ; impure function DistValSlv ( A : DistType; Exclude: integer_vector; Size : natural) return std_logic_vector ; impure function DistValUnsigned ( A : DistType; Exclude: integer_vector; Size : natural) return unsigned ; impure function DistValSigned ( A : DistType; Exclude: integer_vector; Size : natural) return signed ;
Имя функции | Входные параметры | Return | Описание | |||
---|---|---|---|---|---|---|
Weight | A | Exclude | Size | |||
DistInt | integer_vector | – | – | – | integer | Возвращает псевдослучайное число (или вектор размерностью Size) из диапазона [0, N-1] на основе заданного массива весов Weight, где N число элементов в массиве Weight |
DistSlv | natural | std_logic_vector | ||||
DistUnsigned | natural | unsigned | ||||
DistSigned | natural | signed | ||||
DistInt | integer_vector | – | integer_vector | – | integer | Distribution with just weights and with exclude values |
DistSlv | natural | std_logic_vector | ||||
DistUnsigned | unsigned | |||||
DistSigned | signed | |||||
DistValInt | – | DistType | – | – | integer | Distribution with weight and value |
DistValSlv | natural | std_logic_vector | ||||
DistValUnsigned | unsigned | |||||
DistValSigned | signed | |||||
DistValInt | – | DistType | integer_vector | – | integer | Distribution with weight and value and with exclude values |
DistValSlv | natural | std_logic_vector | ||||
DistValUnsigned | unsigned | |||||
DistValSigned | signed |
Использование (Применение)
Каждый результат генератора псевдослучайных чисел производится функцией и результат может быть использован непосредственно в выражении. Таким образом, можно рандомизировать задержку, которая лежит между 3 и 10 периодами синхросигнала.
wait for RV.RandInt(3, 10) * tperiod_Clk - tpd ; wait until Clk = '1' ;
Значения могут также использоватся непосредственно внутри оператора выбора CASE. Следующий пример использует функцию DistInt для генерации выбора первого блока с вероятностью 70%, второго 20 %, и третьего 10%.
variable RV : RandomPType ; . . . StimGen : while TestActive loop -- Repeat until done case RV.DistInt( (7, 2, 1) ) is when 0 => -- Normal Handling -- 70% . . . when 1 => -- Error Case 1 -- 20% . . . when 2 => -- Error Case 2 -- 10% . . . when others => report "DistInt" severity failure ; -- Signal bug in DistInt end case ; end loop ;
Следующий фрагмент кода генерирует транзакции для записи DMA_WORD_COUNT, DMA_ADDR_HI, и DMA_ADDR_LO в случайном порядке, которые запускается каждый раз в различный момент. Последовательность заканчивает с записью в DMA_CTRL. Когда вызывается DistInt с весом 0, соответствующее значение не будет сгенерировано. Следовательно инициализируя все веса в 1 и затем устанавливая их в 0, когда выбираются, каждый блок оператора выбора происходит единожды. Цикл "for loop" проходит три раза чтобы разрешить каждой тракзакции сработаь.
variable RV : RandomPType ; . . . Wt0 := 1; Wt1 := 1; Wt2 := 1; -- Initial Weights for i in 1 to 3 loop -- Loop 1x per transaction case RV.DistInt( (Wt0, Wt1, Wt2) ) is -- Select transaction when 0 => -- Transaction 0 CpuWrite(CpuRec, DMA_WORD_COUNT, DmaWcIn); Wt0 := 0 ; -- remove from randomization when 1 => -- Transaction 1 CpuWrite(CpuRec, DMA_ADDR_HI, DmaAddrHiIn); Wt1 := 0 ; -- remove from randomization when 2 => -- Transaction 2 CpuWrite(CpuRec, DMA_ADDR_LO, DmaAddrLoIn); Wt2 := 0 ; -- remove from randomization when others => report "DistInt" severity failure ; end case ; end loop ; CpuWrite(CpuRec, DMA_CTRL, START_DMA or DmaCycle);
Следующий пример использует список исключений, чтобы не повторить последнего значения. Следует обратить внимание, что когда проходит целое значение integer в параметре integer_vector, множество успользующее поимённое назначени е используется для обозначения одного элемента массива. Обратите внимание, что в течении первого выполнения этого процесса LastDataInt имеет значение integer'left (очень малое значение) которое лежит вне диапазона от 0 до 255, и в результате не имеет влияния на генерацию псевдослучайных чисел.
RandomGenProc : process variable RV : RandomPType ; variable DataInt, LastDataInt : integer ; begin . . . DataInt := RV.RandInt(0, 255, (0 => LastDataInt)) ; LastDataInt := DataInt; . . .
Следующий фрагмент кода использует лист исключений, чтобы избежать четырёх предыдущих значений.
RandProc : process variable RV : RandomPtype ; variable DataInt : integer ; variable Prev4DataInt : integer_vector(3 downto 0) := (others => integer'low) ; begin . . . DataInt := RV.RandInt(0, 100, Prev4DataInt) ; Prev4DataInt := Prev4DataInt(2 downto 0) & DataInt ; . . .
Создание теста
Создание тестов является всё о методологии. SynthWorks методология совмещает подпрограммы псевдослучайной генерации чисел (из пакета RandomPkg) и подпрограммы для функционального покрытия (из CoveragePkg — также свободно доступного по ссылке http://www.synthworks.com/downloads) с конструкциями языка VHDL. Каждая тестовая последовательность получается путём псевдослучайного выбора или ветви кода или значений для операций. Управляемая рандомизация создаётся используя обычную технику последовательное кодирование (например, case, if,
циклы, и операторы присваения). Этот подход прост и до сих пор эффективен. Поскольку весть код последовательный, псевдослучайные последовательности легко смешиваются с прямыми и алгоритмическими последовательностями.
Простая демонстрация превдослучайного тестирования в следующем тесте, который использует эврестики (гаусовый) по длине очередей данных и задержек между очередями данных, чтобы рандомизировать трафик отправленный в FIFO.
variable RV : RandomPType ; . . . TxStimGen : while TestActive loop -- Burst between 1 and 10 values BurstLen := RV.RandInt(Min => 1, Max => 10); for i in 1 to BurstLen loop DataSent := DataSent + 1 ; WriteToFifo(DataSent) ; end loop ; -- Delay between bursts: (BurstLen <=3: 1-6, >3: 3-10) if BurstLen <= 3 then BurstDelay := RV.RandInt(1, 6) ; -- small burst, small delay else BurstDelay := RV.RandInt(3, 10) ; -- bigger burst, bugger delay end if ; wait for BurstDelay * tperiod_Clk - tpd ; wait until Clk = '1' ; end loop TxStimGen ;
Функциональное покрытие считает, какие тестовые состояния сгенерированы и даёт инженерам индикатор того, когда тестирование закончено. Это важно, когда используя псевдослучайное тестирования для создания теста, так как в противном случае нет способа узнать, что тест действительно прошел. Функциональное покрытие может быть выполнено, используя вызовы подпрограмм (собственных или из пакета CoveragePkg) или VHDL-код. Функциональное покрытие сохраняется в сигналах и может использоваться для изменения псевдослучайных тестов (или непосредственно как ограничения или косвенно, как что-либо влияющее на изменение ограничений) для генерации пропущенных элементов (точек) покрытия.
В примере FIFO необходимо увидеть много попыток записи, пока полное и попытки читать, пока пустое. Одно можно сделать для улучшения предыдущего теста то, чтобы увеличить или уменьшить длину пакета и задержку, основанную на числе попыток записи, пока полон, или попыток чтения, пока пусто, мы видели. Чтобы исследовать как генерируется покрытие, необходимо обратиться к документации пакета CoveragePkg.
Для проекта, для которого имеются многочисленные условия необходимо сгенерировать, можно сделать покрытие входных воздействий и затем псевдослучайно выбрать одно из не покрытых условий как следующая транзакция генерируется.
Solutions for the two previous coverage driven randomization problems are provided in SynthWorks' VHDL Testbenches and Verification class.
8. Random Stability
A protected type is always used with a variable object. If the object is declared in a process, it is a regular variable. If the object is declared in an architecture, then it is declared as a shared variable.
All of the examples in this document show RandomPType being defined in a process as a regular variable. This is done to ensure random stability. Random stability is the ability to re-run a test and get exactly the same sequence. Random stability is required for verification since if we find a failure and then fix it, if the same sequence is not generated, we will not know the fix actually worked.
Random stability is lost when a randomization variable is declared as a shared variable in an architecture and shared among multiple processes. When a randomization variable is shared, the seed is shared. Each randomization reads and updates the seed. If the processes accessing the shared variable run during the same delta cycle, then the randomization of the test depends on the order of which RandomPType is accessed. This order can change anytime the design is optimized - which will happen after fixing bugs. As a result, the test is unstable.
To ensure stability, create a separate variable for randomization in each process.
9. Other Distributions
По умолчанию все генераторы случайных чисел используют распределение uniform. В дополнение к этому распределению, в RandomPType есть также другие распределения favor_small, favor_big, normal, и poisson. Далее приведён список этих функций.
-- Generate values, each with an equal probability impure function Uniform (Min, Max : in real) return real ; impure function Uniform (Min, Max : integer) return integer ; impure function Uniform (Min, Max : integer ; Exclude: integer_vector) return integer ; -- Generate more small numbers than big impure function Favor_small (Min, Max : real) return real ; impure function Favor_small (Min, Max : integer) return integer ; impure function Favor_small (Min, Max : integer; Exclude: integer_vector) return integer ; -- Generate more big numbers than small impure function Favor_big (Min, Max : real) return real ; impure function Favor_big (Min, Max : integer) return integer ; impure function Favor_big (Min, Max : integer ; Exclude: integer_vector) return integer ; -- Generate normal = gaussian distribution impure function Normal (Mean, StdDeviation : real) return real ; impure function Normal (Mean, StdDeviation, Min, Max : real) return real ; impure function Normal (Mean : real ; StdDeviation : real ; Min : integer ; Max : integer ; Exclude : integer_vector := NULL_INTV ) return integer ; -- Generate poisson distribution impure function Poisson (Mean : real) return real ; impure function Poisson (Mean, Min, Max : real) return real ; impure function Poisson ( Mean : real ; Min : integer ; Max : integer ; Exclude : integer_vector := NULL_INTV ) return integer ;
Пакет также предоставляет экспериментальные механизмы для изменения распределения использующиеся с функциями RandInt, RandSlv, RandUnsigned, и RandSigned.
10. Compiling RandomPkg and Friends
The core package is RandomPkg. It is supported by the packages RandomBasePkg and SortListPkg_int. We compile all of our packages into a library named SynthWorks. Directions for compiling these packages using either VHDL-2008 or VHDL-2002 are provided in the separate document, README_RandomPkg.pdf. Your programs will need to reference RandomPkg. If your programs need to use IO for the seed (to_string, write, read), then you will also need to include RandomBasePkg.
library SynthWorks ; use SynthWorks.RandomPkg.all ;
11. Future Work
RandomPkg.vhd is a work in progress and will be updated from time to time. In addition to the RandomPkg, we also are freely distributing our coverage package, CoveragePkg. See http://www.SynthWorks.com/downloads. Over time we will also be releasing other packages that we currently distribute with our classes (such as scoreboards and memory modeling) and hope to convince simulation vendors to distribute our libraries with their tools.
12. About SynthWorks
SynthWorks' VHDL training can help you jumpstart your VHDL design and verification tasks. Whether it be introductory, verification or synthesis training, the knowledge you gain will help you finish your next FPGA or ASIC project in a more timely and efficient manner.
We provide training in leading edge VHDL verification techniques, including transactionbased testing, bus functional modeling, self-checking, data structures (linked-lists, scoreboards, memories), directed, algorithmic, constrained random, and coverage driven random testing, and functional coverage. In addition to RandomPkg, our verification class comes with packages for functional coverage, memories, scoreboards, and interfaces.
Help support our open source packages by buying your VHDL training from SynthWorks.
13. About the Author
Jim Lewis, the founder of SynthWorks, has twenty-six years of design, teaching, and problem solving experience. In addition to working as a Principal Trainer for SynthWorks, Mr Lewis has done ASIC and FPGA design, custom model development, and consulting. Mr Lewis is an active member of the VHDL standards effort and is the current IEEE VHDL Study Group chair. I am passionate about the use of VHDL for verification. If you find any innovative usage for the package, let us know. If you find bugs with any of SynthWorks' packages or would like to request enhancements, you can reach me at jim@synthworks.com.