Мастерство функций в Verilog для эффективного RTL дизайна
Часто в RTL встречаются повторяющиеся фрагменты кода, вызываемые многократно. Они обычно не потребляют время симуляции и могут содержать сложные вычисления с разными данными. В таких случаях объявляют function, помещают повторяющийся код внутрь и возвращают результат. Это резко сокращает объем RTL: достаточно вызвать функцию и передать данные. Это очень похоже на функции в C.
Назначение функции — вернуть значение для использования в выражении. Определение начинается с ключевого слова function, за которым следуют тип возврата, имя и список портов в скобках. Verilog понимает, что определение окончено, встретив endfunction. Функция должна иметь минимум один вход, а тип возврата будет void, если функция ничего не возвращает.
Синтаксис
function [automatic] [return_type] name ([port_list]);
[statements]
endfunction
Ключевое слово automatic делает функцию реентерабельной (reentrant): элементы внутри динамически выделяются для каждого вызова, а не разделяются между вызовами. Полезно для рекурсивных функций и параллельного выполнения при форке.
Объявление функций
Два способа объявить входы:
// Стиль 1
function [7:0] sum;
input [7:0] a, b;
begin
sum = a + b;
end
endfunction
// Стиль 2 (ANSI)
function [7:0] sum (input [7:0] a, b);
begin
sum = a + b;
end
endfunction
Возврат значения
Определение функции неявно создает внутреннюю переменную с тем же именем, что и функция. Поэтому объявлять другую переменную с тем же именем внутри функции нельзя. Возвращаемое значение устанавливается присваиванием результата этой внутренней переменной.
sum = a + b;
Вызов функции
Function call — это операнд в выражении.
reg [7:0] result;
reg [7:0] a, b;
initial begin
a = 4;
b = 5;
#10 result = sum (a, b);
end
Правила функций
- Не могут содержать операторов управления временем: #, @, wait, posedge, negedge
- Не могут запускать task (потому что это потребляет время), но могут вызывать другие функции
- Должны иметь минимум один вход
- Не могут иметь неблокирующих назначений,
force-releaseилиassign-deassign - Не могут иметь триггеров
- Не могут иметь output или inout портов
Рекурсивные функции
Функции, вызывающие сами себя — рекурсивные. Пример: вычисление факториала.
module tb;
initial begin
integer result = factorial(4);
$display("factorial(4) = %0d", result);
end
function automatic integer factorial(integer i);
integer result = i;
if (i) begin
result = i * factorial(i-1);
$display("i=%0d result=%0d", i, result);
end else
result = 1;
return result;
endfunction
endmodule
Simulation Log
xcelium> run i=1 result=1 i=2 result=2 i=3 result=6 i=4 result=24 factorial(4) = 24 xmsim: *W,RNQUIE: Simulation is complete
Verilog
- 10 ключевых функций Insight для оптимизации FDM-печати на Stratasys
- Функции в C++: подробное объяснение с практическими примерами кода
- Освоение лямбда-функций Python: практические примеры и лучшие практики
- Освоение Verilog: полное руководство по проектированию цифровых схем
- Освоение конкатенации в Verilog: практическое руководство
- Понимание назначений в Verilog: типы, синтаксис и лучшие практики
- Блокирующие и неблокирующие назначения в Verilog: ключевые различия
- Мастерство математических функций Verilog для эффективного аппаратного дизайна
- Функции в C: объявление, определение, вызов, аргументы (по значению и по ссылке), рекурсия
- Функции в MATLAB: определение, рабочая область, входные и выходные аргументы