DocsTech
/
NONEDISPLAY
/

~ cd модули в verilog

Сводка

Модуль — это иерархическая единица Verilog описания аппаратного обеспечения. Модуль объявляется в глобальном пространстве через ключевое слово «module» и заканчивается ключевым словом «endmodule«. В объявления модуля входит идентификатор, порты(необязательно) и параметры(необязательно). Объявление портов может содержать входные, выходные и двунаправленные порты. Объявление параметров может содержать параметры любого типа. Модуль может входить в другой модуль, но объявляется в качестве экземпляра. Различают 2 вида модулей:

  1. Модуль верхнего уровня — это модуль, который не входит в состав другого модуля проекта в качестве экземпляра. Т.е. имеет одно объявление в глобальной области и содержит в себе экземпляры других модулей, если таковы есть.
  2. Модуль низкого уровня — это модуль объявляемый в глобальном пространстве и в качестве экземпляра в другом модуле.

Объявления в глобальном пространстве модуля верхнего и низкого уровня ничем не отличаются.

Синтаксис

Объявления модуля в глобальном пространстве

Существует 4 вида объявления модуля Verilog(см. 12) в глобальном пространстве. Поэтому объявление параметров модуля может происходить в строке модуля, так и внутри блока модуля. Такая же ситуация обстоит и с портами. Если объявление портов происходит внутри блока, то строке модуля прописывается список портов.

Синтаксис объявления модуля outside в глобальном пространстве приведен в синтаксисе 1.

...
Копировать
module #(/* объявление параметров */) identifier (/* объявление портов */);

    // другие объявления внутри блока

endmodule
Синтаксис 1 — Объявление модуля outside в глобальном пространстве.

Синтаксис объявления модуля inside в глобальном пространстве приведен в синтаксисе 2.

...
Копировать
module identifier(/* список портов */);
    /* объявление параметров */
    /* объявление портов*/

    // другие объявления внутри блока

endmodule
Синтаксис 2 — Объявление модуля в глобальном пространстве.

Объявления экземпляра модуля

Экземпляр модуля — это объявление модуля внутри блока другого модуля. Объявление портов и параметров имеет два вида: простая и точечная нотация. Если используется простая нотация, необходимо присваивать цепи и регистры в той последовательности, в какой объявлены порты или параметры. Если используется точечная нотация, то присваивание можно объявлять в любом порядке.

Синтаксис экземпляра модуля с простой нотацией приведен в синтаксисе 3.

...
Копировать
identifier_module #(/* значения параметра через запятую */)
    identifier_module_local(/* список портов через запятую */);
Синтаксис 3 — Объявление экземпляра модуля.

identifier_module — это идентификатор модуля в глобальном пространстве, а identifier_module_local — это новый идентификатор модуля в локальном пространстве объявления.

Синтаксис экземпляра модуля с точечной нотацией приведен в синтаксисе 4.

...
Копировать
identifier_module #(.PARAM_NAME(VALUE_PARAM), .PARAM_NAME(VALUE_PARAM), /* и тд */)
    identifier_module_local (.PORT_NAME(WIRE_NAME), .PORT_NAME(WIRE_NAME), /* и тд */);
Синтаксис 4 — Объявление экземпляра модуля.

Примеры объявления модуля

Примеры модуля в глобальном пространстве

Пример 1 — Объявления модуля памяти, использующий примитив FPGA для хранения данных. Данный модуль не использует регистры, а примитив. В данном случае имеется виду ресурс заложенный в микрочип, отдельный от логических клеток.
...
Копировать
module TWISE_PORTS_RAM 
#(
    parameter BITS_DATA = 8, // кол-во битов в линии данных
    parameter BITS_ADDR = 6 // кол-во битов в линии адреса
)
(
    input wire [(BITS_DATA - 1): 0] data,  // линия данных
    input wire [(BITS_ADDR - 1): 0] addr_we,  // линия адреса для записи
    input wire [(BITS_ADDR - 1): 0] addr_re,  // линия адреса для чтения
    input wire we,  // линия включения записи
    input wire clk, // тактовый сигнал
    output reg [(BITS_DATA - 1): 0] q  // линия выхода
);
    // регистр, использующий примитив FPGA
    reg [(BITS_DATA - 1): 0] ram [((2**BITS_ADDR) - 1): 0]; 

    always @(posedge clk) begin
        // запись
        if (we)
            ram[addr_we] <= data;

        // чтение
        q <= ram[addr_re];
    end
endmodule

В этом модуле реализован механизм простой двухпортовой однотактовой памяти(см. 4.9.3 Память). При приходе восходящего фронта в тактовом сигнале clk и высоком сигнале записи write, происходит запись в память по адресу addr_we. При такой же ситуации тактовым сигналом, то происходит чтение с памяти по адресу addr_re. RTL модель показана на рисунке 1.

RTL однотакотовой двухпортовой памяти
Рисунок 1 — RTL однотакотовой двухпортовой памяти.
Пример 2 — Модуль с таким же функционалом, но с другой формой объявления.
...
Копировать
module TWISE_PORTS_RAM(data, addr_we, addr_re, we, clk, q);

    parameter BITS_DATA = 8; // кол-во битов в линии данных
    parameter BITS_ADDR = 6; // кол-во битов в линии адреса

    input wire [(BITS_DATA - 1): 0] data;  // линия данных
    input wire [(BITS_ADDR - 1): 0] addr_we;  // линия адреса для записи
    input wire [(BITS_ADDR - 1): 0] addr_re;  // линия адреса для чтения
    input wire we;  // линия включения записи
    input wire clk; // тактовый сигнал
    output reg [(BITS_DATA - 1): 0] q;  // линия выхода

    // регистр, использующий примитив FPGA
    reg [(BITS_DATA - 1): 0] ram [((2**BITS_ADDR) - 1): 0];

    always @(posedge clk) begin
        // запись
        if (we)
            ram[addr_we] <= data;

        // чтение
        q <= ram[addr_re];
    end
endmodule

Примеры объявления экземпляра модуля

Пример 3 — Объявление экземпляра модуля с двумя видами нотацией.
...
Копировать
module tb2;
    wire [9:0] out_a, out_d;
    wire [4:0] out_b, out_c;
    reg [9:0] in_a, in_d;
    reg [4:0] in_b, in_c;
    reg clk;

    vdff #(.delay(10), .size(15)) mod_a (.out(out_a), .in(in_a), .clk(clk));
    // тоже самое в другом формате
    // vdff #(15, 10) mod_a (out_a, in_a, clk);
endmodule

module vdff (out, in, clk);
    parameter size=5, delay=1;

    // Объявление внутри блока

endmodule
Главная
Курсы
Вебинары
Анализ рынка вакансий в сфере RTL-дизайна в России: тренды, спрос и перспективы
LinuxCNC: Преимущества и применение в станкостроении и автоматизации
Алгоритм Хаффмана: Теория, методология и практическая реализация для эффективного сжатия данных
Chisel vs. SystemVerilog: Новый взгляд на проектирование цифровых схем
Подключение датчика ZMPT101B к Arduino: схема, настройка и пример кода
Подключение MAX6675 к Arduino: схема, библиотеки и примеры кода
Подключение и настройка MPU6050 к Arduino: схема, библиотеки и скетч
Подключение VL53L0X к Arduino: полное руководство по лазерному датчику расстояния
Подключение компас HMC5883L к Arduino: схема, библиотеки и пример кода
Подключение ACS712 к Arduino: схема, библиотеки и скетчи
Подключение ADXL345 к Arduino: схема, библиотеки и код
Подключение датчика INA219 к Arduino: схема, библиотеки и примеры кода
HC-SR04 и Arduino: схема подключения, библиотеки и скетч
Assertion-Based Verification(ABV): основные понятия, принцип работы и примеры
Подключение HX711 к Arduino: схема, библиотеки и код
Подключение DHT22 к Arduino: схема, код и необходимые библиотеки
Как подключить RCWL-0516 к Arduino: схема, библиотеки и скетч
Универсальная Методология Верификации (UVM): Описание, Особенности и Пример Использования
DS18B20: Подключение к Arduino, Библиотеки и Скетч
Методологии верификации HDL-кода: Основы, Преимущества и Популярные Подходы
Роль ПЛИС в Алготрейдинге и Высокочастотной Торговле
Lint, CDC, RDC, LEC, Power Analyzer, STA и DFT для HDL
Пиратство плохо! Мне так сказали…
Применение Icarus Verilog для тестирования с входными данными
Ключевые параметры для выбора цифроаналогового преобразователя (ЦАП)
Все о КНФ и ДНФ: Понятие, Примеры и Применение
Импликация: Что Это, Таблица Истинности и Применение в Информатике
Стрелка Пирса: Что Это за Логическая Операция и Таблица Истинности
Штрих Шеффера: Полное Руководство
STM32F103 с использованием HAL и I2C: Подробная конфигурация и пример кода
Подключение DHT11 к ESP32: Схема, Библиотеки и Пример Кода
ESP8266 I2C: настройка для master и slave
Подключение DHT11 к Arduino и Вывод на LCD 1602 I2C: Схема и Скетч
Подключение DHT11 к Arduino: Схема, Библиотеки и Скетч
ESP32 I2C: Настройка кода под master и slave
TM1637 Подключение к Arduino: Полное Руководство
Подключение часов DS3231 к Arduino и LCD 1602 I2C
Arduino: Часы Реального Времени DS1302 на LCD 1602 I2C
ESP32 SPI: Объявление SPI на ESP32 с Примером Кода
ESP8266 SPI: полная инструкция SPI на ESP8266
Протокол SPI: Регистровая Логика, Передача Данных и Режимы
Демультиплексор: принцип работы, схема и основы
Счетчики с синхронным и асинхронным сбросом на Verilog
Знаковость signed в Verilog: примеры, синтаксис, оптимизация
Директива Define в Verilog: Синтаксис, Примеры и Применение
Таблицы истинности триггеров: JK, RS, D и T
Fork и begin в Verilog: обзор и различия
Posedge и Negedge в Verilog: Синтаксис и Функциональность
Verilog always: Синтаксис, Примеры и Применение
Wire в Verilog: Основы использования, синтаксис и примеры кода
Блокирующие и неблокирующие присваивания в Verilog
Verilog Assign: что делает этот оператор?
Verilog Parameter: Ключевой Инструмент Оптимизации
Многомерные массивы в Verilog
Case Verilog
Дешифратор. Принцип работы и Примеры
Модули в Verilog
Описание FIFO. Примеры на Verilog и С++
Закрыть