Генерация случайных чисел в VHDL: от Uniform к OSVVM
VHDL включает встроенный псевдослучайный генератор, выдающий вещественные значения в интервале [0, 1]. Масштабируя и смещая эти значения, можно создавать случайные данные любого типа — real, integer, std_logic_vector или time — подходящие для тестбенчей. Следующее руководство показывает, как строить эти генераторы с процедурой uniform пакета IEEE MATH_REAL и как использовать пакет Random библиотеки OSVVM для еще большей гибкости.
Процедура uniform, определенная в пакете IEEE MATH_REAL, является основой примеров ниже:
procedure UNIFORM(variable SEED1, SEED2 : inout POSITIVE; variable X : out REAL);
Она требует двух переменных-семян, обновляемых при каждом вызове. Выход X — псевдослучайное вещественное число между 0 и 1. Поскольку алгоритм детерминирован, одна и та же начальная пара семян даст точно такую же последовательность чисел — важное свойство для воспроизводимых тестбенчей.
Для глубокого понимания базового алгоритма обратитесь к статье Пьера Л'Экуайера Efficient and Portable Combined Random Number Generators или изучите реализацию, поставляемую с симулятором GHDL.
Тестовый случай
Все примеры ниже используют 999 как оба значения семени. Объявите семена в декларативной области процесса и реализуйте функции рандомизации как нечистые функции внутри того же процесса:
variable seed1, seed2 : integer := 999;
Вы можете скачать полный тестбенч, содержащий все примеры этой статьи, как ZIP-файл. Архив также включает проект ModelSim со скриптом, компилирующим и запускающим симуляцию.
Случайное вещественное значение
Процедура uniform возвращает вещественное число в диапазоне [0.0, 1.0]. Для отображения на произвольный интервал [min_val, max_val] умножьте на ширину и добавьте смещение:
impure function rand_real(min_val, max_val : real) return real is variable r : real; begin uniform(seed1, seed2, r); return r * (max_val - min_val) + min_val; end function;
Случайное целое значение
Генерация случайного целого из вещественного значения хитро, потому что простое округление искажает вероятность крайних значений. Следующая функция исправляет это смещение, добавляя 0.5 перед округлением:

impure function rand_int(min_val, max_val : integer) return integer is variable r : real; begin uniform(seed1, seed2, r); return integer( round(r * real(max_val - min_val + 1) + real(min_val) - 0.5)); end function;
Корректировка гарантирует, что каждое целое в интервале [min_val, max_val] имеет равный шанс быть выбранным.
Случайный std_logic_vector
Для заполнения std_logic_vector произвольной длины случайными битами, итерируйте по каждой позиции и присваивайте '1', когда случайное вещественное превышает 0.5, иначе '0':
impure function rand_slv(len : integer) return std_logic_vector is variable r : real; variable slv : std_logic_vector(len - 1 downto 0); begin for i in slv'range loop uniform(seed1, seed2, r); slv(i) := '1' when r > 0.5 else '0'; end loop; return slv; end function;
Случайное значение времени
Когда нужно случайное временное значение — например, для симуляции пульсирующего трафика — можно масштабировать случайное вещественное к желаемому интервалу и преобразовать обратно в VHDL-тип time:
impure function rand_time(min_val, max_val : time; unit : time := ns) return time is variable r, r_scaled, min_real, max_real : real; begin uniform(seed1, seed2, r); min_real := real(min_val / unit); max_real := real(max_val / unit); r_scaled := r * (max_real - min_real) + min_real; return real(r_scaled) * unit; end function;
Обратите внимание, что нужно передать единицу времени симулятора (например, ns) в функцию.
Пакет Random библиотеки OSVVM
Для тех, кто предпочитает готовое решение, пакет Random библиотеки OSVVM предлагает богатый набор перегруженных функций, генерирующих случайные значения для всех стандартных типов VHDL. Импортируйте пакет так:
library osvvm; use osvvm.RandomPkg.all;
ModelSim поставляется с предустановленным OSVVM, поэтому на этой платформе дополнительная загрузка не требуется. Для других симуляторов обратитесь к файлу RandomPck.vhd в репозитории OSVVM на GitHub.
VHDL
- Создание списков строк в VHDL: лучшие практики и пример
- Корректное завершение симуляции VHDL-тестбенча
- Реализация PWM-контроллера в VHDL: проектирование, симуляция и FPGA-демо
- Реализация динамического связного списка в VHDL с защищенными типами и указателями доступа
- Использование внутрипроцессных процедур для более чистого проектирования FSM на VHDL
- Использование нечистых функций в VHDL: повышение читаемости и поддерживаемости FSM
- Освоение функций VHDL: практическое руководство по эффективному дизайну
- Проектирование конечного автомата в VHDL: практический пример светофора
- Использование процедур в VHDL: упростите свой дизайн с повторно используемым кодом
- Генерация случайных чисел в Java: Практическое руководство с Random и Math.random