Verilog

Иерархические идентификаторы.

Иерархические идентификаторы

Иерархические имена путей основаны на идентификаторе модуля верхнего уровня и записываются последовательно, разделяясь запятыми. Это полезно тогда, когда хотят показать сигнал внутри нижнего модуля или передать значение во внутренний модуль. Ниже показан пример наблюдения сигнала во внутреннем модуле:

 

Verilog Code:
  1. //-----------------------------------------------------
  2. // Это пример простого сумматора
  3. // Имя проекта : adder_hier
  4. // Имя файла : adder_hier.v
  5. // Функция : Эта программа показывает работу с иерархическими идентификаторами
  6. // Автор : Deepak
  7. //-----------------------------------------------------
  8. `include "addbit.v"
  9. module adder_hier (
  10. result , // Выход результата сумматора
  11. carry , // Выход переноса сумматора
  12. r1 , // первый вход
  13. r2 , // второй вход
  14. ci // вход переноса
  15. );
  16.  
  17. // Объявление входных портов
  18. input [3:0] r1 ;
  19. input [3:0] r2 ;
  20. input ci ;
  21.  
  22. // Объявление выходных портов
  23. output [3:0] result ;
  24. output carry ;
  25.  
  26. // Соединения портов
  27. wire [3:0] r1 ;
  28. wire [3:0] r2 ;
  29. wire ci ;
  30. wire [3:0] result ;
  31. wire carry ;
  32.  
  33. // Внутренние переменные
  34. wire c1 ;
  35. wire c2 ;
  36. wire c3 ;
  37.  
  38. // Code Starts Here
  39. addbit u0 (r1[0],r2[0],ci,result[0],c1);
  40. addbit u1 (r1[1],r2[1],c1,result[1],c2);
  41. addbit u2 (r1[2],r2[2],c2,result[2],c3);
  42. addbit u3 (r1[3],r2[3],c3,result[3],carry);
  43.  
  44. endmodule // Конец модуля adder
  45.  
  46. module tb();
  47.  
  48. reg [3:0] r1,r2;
  49. reg ci;
  50. wire [3:0] result;
  51. wire carry;
  52.  
  53. // Входные значения
  54. initial begin
  55. r1 = 0;
  56. r2 = 0;
  57. ci = 0;
  58. #10 r1 = 10;
  59. #10 r2 = 2;
  60. #10 ci = 1;
  61. #10 $display("+--------------------------------------------------------+");
  62. $finish;
  63. end
  64.  
  65. // Подсоединяемся к модулю нижнего уровня
  66. adder_hier U (result,carry,r1,r2,ci);
  67.  
  68. // Вывод результатов
  69. initial begin
  70. $display("+--------------------------------------------------------+");
  71. $display("| r1 | r2 | ci | u0.sum | u1.sum | u2.sum | u3.sum |");
  72. $display("+--------------------------------------------------------+");
  73. $monitor("| %h | %h | %h | %h | %h | %h | %h |",
  74. r1,r2,ci, tb.U.u0.sum, tb.U.u1.sum, tb.U.u2.sum, tb.U.u3.sum);
  75. end
  76.  
  77. 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:
  1. module test_wor();
  2.  
  3. wor a;
  4. reg b, c;
  5.  
  6. assign a = b;
  7. assign a = c;
  8.  
  9. initial begin
  10. $monitor("%g a = %b b = %b c = %b", $time, a, b, c);
  11. #1 b = 0;
  12. #1 c = 0;
  13. #1 b = 1;
  14. #1 b = 0;
  15. #1 c = 1;
  16. #1 b = 1;
  17. #1 b = 0;
  18. #1 $finish;
  19. end
  20.  
  21. endmodule

Вывод симулятора

 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

Пример - WAND

Verilog Code:
  1. module test_wand();
  2.  
  3. wand a;
  4. reg b, c;
  5.  
  6. assign a = b;
  7. assign a = c;
  8.  
  9. initial begin
  10. $monitor("%g a = %b b = %b c = %b", $time, a, b, c);
  11. #1 b = 0;
  12. #1 c = 0;
  13. #1 b = 1;
  14. #1 b = 0;
  15. #1 c = 1;
  16. #1 b = 1;
  17. #1 b = 0;
  18. #1 $finish;
  19. end
  20.  
  21. endmodule

Вывод симулятора

 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

Пример - TRIREG

Verilog Code:
  1. module test_trireg();
  2.  
  3. trireg a;
  4. reg b, c;
  5.  
  6. assign a = (b) ? c : 1'bz;
  7.  
  8. initial begin
  9. $monitor("%g a = %b b = %b c = %b", $time, a, b, c);
  10. b = 0;
  11. c = 0;
  12. #1 b = 1;
  13. #1 b = 0;
  14. #1 c = 1;
  15. #1 b = 1;
  16. #1 b = 0;
  17. #1 $finish;
  18. end
  19. endmodule

Вывод симулятора

 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 

Регистровые типы данных

  • Регистры сохраняют данные после записи до тех пор, пока они не будут изменены при очередной записи.
  • Регистры представляют устройства хранения данных.
  • Можно создавать массивы памяти регистрового типа (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:
  1. //-----------------------------------------------------
  2. // Имя проекта : strings
  3. // Имя файла : strings.v
  4. // Функция : Пример возможности сохранения
  5. // строки в регистре
  6. // Автор : Deepak Kumar Tala
  7. //-----------------------------------------------------
  8. module strings();
  9. // Объявляем регистровую переменную длиной 18 байт
  10. reg [8*18:0] string ;
  11.  
  12. initial begin
  13. string = "Это простая строка";
  14. $display ("%s \n", string);
  15. end
  16.  
  17. endmodule