Иерархические идентификаторы
Иерархические имена путей основаны на идентификаторе модуля верхнего уровня и записываются последовательно, разделяясь запятыми. Это полезно тогда, когда хотят показать сигнал внутри нижнего модуля или передать значение во внутренний модуль. Ниже показан пример наблюдения сигнала во внутреннем модуле:
Verilog Code:
//----------------------------------------------------- // Это пример простого сумматора // Имя проекта : adder_hier // Имя файла : adder_hier.v // Функция : Эта программа показывает работу с иерархическими идентификаторами // Автор : Deepak //----------------------------------------------------- `include "addbit.v" module adder_hier ( 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 ; // Code Starts Here 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 module tb(); reg [3:0] r1,r2; reg ci; wire [3:0] result; wire carry; // Входные значения initial begin r1 = 0; r2 = 0; ci = 0; #10 r1 = 10; #10 r2 = 2; #10 ci = 1; #10 $display("+--------------------------------------------------------+"); $finish; end // Подсоединяемся к модулю нижнего уровня adder_hier U (result,carry,r1,r2,ci); // Вывод результатов initial begin $display("+--------------------------------------------------------+"); $display("| r1 | r2 | ci | u0.sum | u1.sum | u2.sum | u3.sum |"); $display("+--------------------------------------------------------+"); $monitor("| %h | %h | %h | %h | %h | %h | %h |", r1,r2,ci, tb.U.u0.sum, tb.U.u1.sum, tb.U.u2.sum, tb.U.u3.sum); end endmodule
r1 |
r2 | ci | u0.sum | u1.sum | u2.sum | u3.sum |
0 | 0 | 0 | 0 | 0 | 0 | 0 |
0x0A | 0 | 0 | 0 | 1 | 0 | 1 |
0x0A | 2 | 0 | 0 | 0 | 1 | 1 |
0x0A | 2 | 1 | 1 | 0 | 1 | 1 |
Типы данных
Язык verilog имеет два основных типа данных:
- Сеть (net) − соответствует структуре соединения компонентов.
- Регистры (reg) − представляют переменные, используемые для хранения данных.
Каждый сигнал имеет собственный тип данных:
- Явно объявленный в коде Verilog.
- Неявно объявленный но используемый для соединения структурных элементов в коде. Неявно объявленный всегда имеет тип wire шириной 1 бит.
Тип шина (nets)
Каждая сеть имеет функцию, которая используется для моделирования различных типов аппаратуры (таких как PMOS, NMOS, CMOS, и т.д.)
Тип шины |
Функциональность |
wire, tri |
Соединительные провода - без специальной функции разрешения |
wor, trior |
Проводники объединенные по ИЛИ (модель ЭСЛ) |
wand, triand |
Проводники объединенные по И (модель выходы с открытым коллектором) |
tri0, tri1 |
Шины подтянутые к питанию или земле, когда не подключены |
supply0, supply1 |
Шины постоянно находящиеся в уровне логического 0 или 1 (источники питающих напряжений) |
trireg |
Сохраняющие последнее значение, когда подключены к проводнику с z состоянием (тристабильные выходы) |
Примечание: из всех типов сетей, провод (wire) используется наиболее часто.
Пример - WOR
Verilog Code:
module test_wor(); wor a; reg b, c; assign a = b; assign a = c; initial begin $monitor("%g a = %b b = %b c = %b", $time, a, b, c); #1 b = 0; #1 c = 0; #1 b = 1; #1 b = 0; #1 c = 1; #1 b = 1; #1 b = 0; #1 $finish; end endmodule
Вывод симулятора
Code:
<span style="color: black; font-size: small;"> 0 a = x b = x c = x 1 a = x b = 0 c = x 2 a = 0 b = 0 c = 0 3 a = 1 b = 1 c = 0 4 a = 0 b = 0 c = 0 5 a = 1 b = 0 c = 1 6 a = 1 b = 1 c = 1 7 a = 1 b = 0 c = 1 </span>
Пример - WAND
Verilog Code:
module test_wand(); wand a; reg b, c; assign a = b; assign a = c; initial begin $monitor("%g a = %b b = %b c = %b", $time, a, b, c); #1 b = 0; #1 c = 0; #1 b = 1; #1 b = 0; #1 c = 1; #1 b = 1; #1 b = 0; #1 $finish; end endmodule
Вывод симулятора
Code:
<span style="color: black; font-size: small;"> 0 a = x b = x c = x 1 a = 0 b = 0 c = x 2 a = 0 b = 0 c = 0 3 a = 0 b = 1 c = 0 4 a = 0 b = 0 c = 0 5 a = 0 b = 0 c = 1 6 a = 1 b = 1 c = 1 7 a = 0 b = 0 c = 1 </span>
Пример - TRIREG
Verilog Code:
module test_trireg(); trireg a; reg b, c; assign a = (b) ? c : 1'bz; initial begin $monitor("%g a = %b b = %b c = %b", $time, a, b, c); b = 0; c = 0; #1 b = 1; #1 b = 0; #1 c = 1; #1 b = 1; #1 b = 0; #1 $finish; end endmodule
Вывод симулятора
Code:
<span style="color: black; font-size: small;"> 0 a = z b = 0 c = 0 1 a = 0 b = 1 c = 0 2 a = z b = 0 c = 0 3 a = z b = 0 c = 1 4 a = 1 b = 1 c = 1 5 a = z b = 0 c = 1 </span>
Регистровые типы данных
- Регистры сохраняют данные после записи до тех пор, пока они не будут изменены при очередной записи.
- Регистры представляют устройства хранения данных.
- Можно создавать массивы памяти регистрового типа (reg).
- Регистровый тип данных используется как переменная в структурных блоках.
- Регистровые типы данных требуются, если сигнал получает значение внутри процедурного блока.
- Процедурные блоки начинаются с ключевых слов initial и always.
Тип данных |
Использование |
reg |
Без знаковая переменная |
integer |
Знаковая переменная - 32 бита |
time |
Без знаковое целое - 64 бита |
real |
Число с плавающей точкой двойной точности |
Примечание: Из всех регистровых типов, наиболее часто используется reg.
Строки
Строка является последовательностью символов, которые взяты в двойные кавычки и не содержит символов перевода строки. Строки используемые как операнды в выражениях и присваиваниях рассматриваются как последовательности восьмибитных значений ASNII, где одиночный восьмибитный ASNII-символ соответствует знаку. Для объявления переменной для хранения строки, объявите достаточно большой регистр, чтобы в нем поместилась строка. Заметьте, что нет необходимости хранить в строке завершающий символ, Verilog этого не предусматривает. Строками можно манипулировать используя стандартные операторы.
Если переменная для строки оказывается больше, чем требуется, Verilog заполняет оставшееся место нулями. Это целесообразно для последующих присваиваний нестроковых переменных.
Некоторые символы могут быть использованы в строках только для записи escape-последовательностей [метасимволы]. В таблице ниже эти символы показаны в левой колонке, вместе с их описаниями справа.
Специальные символы в строке
Символ |
Описание |
\n |
Начало новой строки |
\t |
Символ табуляции |
\\ |
Обратный слэш (\) |
\" |
Двойные кавычки (") |
\ddd |
Символ описанный 1-3 восьмеричными числами (0 <= d <= 7) |
%% |
Знак процента (%) character |
Пример- строки
Verilog Code:
//----------------------------------------------------- // Имя проекта : strings // Имя файла : strings.v // Функция : Пример возможности сохранения // строки в регистре // Автор : Deepak Kumar Tala //----------------------------------------------------- module strings(); // Объявляем регистровую переменную длиной 18 байт reg [8*18:0] string ; initial begin string = "Это простая строка"; $display ("%s \n", string); end endmodule