Модули
- Модули являются строительными блоками в проектах Verilog.
- Иерархия проектов заключается в использовании вложенных модулей.
- Экземпляры модулей используются в других модулях, уровнем выше.
Порты
- С помощью портов осуществляется связь между модулями и их окружением.
- Почти все модули верхнего уровня в иерархии имеют порты.
- Порты могут быть связаны перечислением или по имени.
Порты объявляются как input, output или inout. Синтаксис объявления портов следующий:
input [мин:макс] список_идентификаторов;
output [мин:макс] список_идентификаторов;
inout [мин:макс] список_идентификаторов;
Примечание : Хорошей практикой является использование по одному идентификатору на строку, как показано ниже:
Пример: объявление портов
Verilog Code:
input clk ; // вход тактирования input [15:0] data_in ; // 16 битная входящая шина output [7:0] count ; // 8 битный выход счетчика inout data_bi ; // двунаправленная шина данных
Примеры : Сумматор на verilog
Verilog Code:
module addbit ( a , // первый бит b , // второй бит ci , // вход переноса sum , // выход суммы co // выход переноса ); //Объявление входов input a; input b; input ci; //Объявление выходов output sum; output co; //Провода wire a; wire b; wire ci; wire sum; wire co; //Начало кода assign {co,sum} = a + b + ci; endmodule // Конец модуля addbit
Модули с подключением путем перечисления (неявно)
Здесь должен соблюдаться порядок. Обычно такое подключение нежелательно. При отладке могут возникнуть трудности при поиске порта в случае ошибок компиляции), при добавлении нового порта или удалении.
Verilog Code:
//----------------------------------------------------- // Пример простого сумматора // Имя проекта : adder_implicit // Имя файла : adder_implicit.v // Функция : Эта программа показывает // неявное соединение портов // Автор : Deepak Kumar Tala //----------------------------------------------------- module adder_implicit ( result , // Выход сумматора carry , // Выход переноса сумматора r1 , // первый вход r2 , // второй вход ci // вход переноса ); // Объявление входных портов input [3:0] r1 ; input [3:0] r2 ; input ci ; // Объявление выходных портов output [3:0] result ; output carry ; // Соединения wire [3:0] r1 ; wire [3:0] r2 ; wire ci ; wire [3:0] result ; wire carry ; // Внутренние соединения wire c1 ; wire c2 ; wire c3 ; // Начало кода addbit u0 ( r1[0] , r2[0] , ci , result[0] , c1 ); addbit u1 ( r1[1] , r2[1] , c1 , result[1] , c2 ); addbit u2 ( r1[2] , r2[2] , c2 , result[2] , c3 ); addbit u3 ( r1[3] , r2[3] , c3 , result[3] , carry ); endmodule // Конец модуля adder
Подключение модулей по имени (явно)
В этом случае достаточно соблюдения имен портов, как у вложенного модуля, порядок не имеет значения.
Verilog Code:
//----------------------------------------------------- // Пример простого сумматора // Имя проекта : adder_explicit // Имя файла : adder_explicit.v // Функция : Здесь имена должны совпадать // с именем при описании модуля, // порядок не важен. // Автор : Deepak Kumar Tala //----------------------------------------------------- module adder_explicit ( result , // Выход сумматора carry , // Выход переноса сумматора r1 , // первый вход r2 , // второй вход ci // вход переноса ); // Объявление входных портов input [3:0] r1 ; input [3:0] r2 ; input ci ; // Объявление выходных портов output [3:0] result ; output carry ; // Соединения wire [3:0] r1 ; wire [3:0] r2 ; wire ci ; wire [3:0] result ; wire carry ; // Внутренние соединения wire c1 ; wire c2 ; wire c3 ; // Начало кода addbit u0 ( .a (r1[0]) , .b (r2[0]) , .ci (ci) , .sum (result[0]) , .co (c1) ); addbit u1 ( .a (r1[1]) , .b (r2[1]) , .ci (c1) , .sum (result[1]) , .co (c2) ); addbit u2 ( .a (r1[2]) , .b (r2[2]) , .ci (c2) , .sum (result[2]) , .co (c3) ); addbit u3 ( .a (r1[3]) , .b (r2[3]) , .ci (c3) , .sum (result[3]) , .co (carry) ); endmodule // Конец модуля adder
Пример реализации модуля
Verilog Code:
//----------------------------------------------------- // Пример простого модуля подсчета четности // Имя проекта : parity // Имя файла : parity.v // Функция : Пример показывающий как на verilog // можно объединять модули // Автор : Deepak //----------------------------------------------------- module parity ( a , // Первый вход b , // Второй вход c , // Третий вход d , // Четвертый вход y // Выход четности ); // Объявление входных портов input a ; input b ; input c ; input d ; // Объявление выходных портов output y ; // Соединения wire a ; wire b ; wire c ; wire d ; wire y ; // Внутренние соединения wire out_0 ; wire out_1 ; // Начало кода xor u0 (out_0,a,b); xor u1 (out_1,c,d); xor u2 (y,out_0,out_1); endmodule // Конец модуля parity
Вопрос : В чем разница между u0 в модуле adder и модуле parity?
Схема
Правила подключения портов
- Входы: внутри указывается шина(net: wire, wor, wand, tri и так далее), снаружи входы могут быть подключены к переменным типа reg или net.
- Выходы: внутри могут использоваться типы reg или net, снаружи выходы подключаются к переменным типа net.
- Двунаправленные: внутри или снаружи всегда используется тип net, подключение допускается только к типу net.
- Совпадение размеров: допускается подключать внутренние и внешние порты с разной шириной. Но имейте в виду, что утилиты синтеза выведут предупреждения.
- Неподключенные порты: допускаются с использованием ",".
- Для подключения к структуре используется тип данных net.
- Если сигнал может быть приведен к структурному типу, требуется тип данных net.
Пример - неявное подключение портов
Verilog Code:
module implicit(); reg clk,d,rst,pre; wire q; // Здесь второй порт не подключен dff u0 ( q,,clk,d,rst,pre); endmodule // D триггер module dff (q, q_bar, clk, d, rst, pre); input clk, d, rst, pre; output q, q_bar; reg q; assign q_bar = ~q; always @ (posedge clk) if (rst == 1'b1) begin q <= 0; end else if (pre == 1'b1) begin q <= 1; end else begin q <= d; end endmodule
Пример - явное подключение портов
Verilog Code:
module explicit(); reg clk,d,rst,pre; wire q; // Здесь q_bar не подключен // Мы можем соединять порты в любом порядке dff u0 ( .q (q), .d (d), .clk (clk), .q_bar (), .rst (rst), .pre (pre) ); endmodule // D fli-flop module dff (q, q_bar, clk, d, rst, pre); input clk, d, rst, pre; output q, q_bar; reg q; assign q_bar = ~q; always @ (posedge clk) if (rst == 1'b1) begin q <= 0; end else if (pre == 1'b1) begin q <= 1; end else begin q <= d; end endmodule