Verilog

Модули Verilog.

Модули

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

module.gif

Порты

  • С помощью портов осуществляется связь между модулями и их окружением.
  • Почти все модули верхнего уровня в иерархии имеют порты.
  • Порты могут быть связаны перечислением или по имени.

Порты объявляются как input, output или inout. Синтаксис объявления портов следующий:

input [мин:макс] список_идентификаторов;

output [мин:макс] список_идентификаторов;

inout [мин:макс] список_идентификаторов;

Примечание : Хорошей практикой является использование по одному идентификатору на строку, как показано ниже:

Пример: объявление портов

Verilog Code:
  1. input clk ; // вход тактирования
  2. input [15:0] data_in ; // 16 битная входящая шина
  3. output [7:0] count ; // 8 битный выход счетчика
  4. inout data_bi ; // двунаправленная шина данных

Примеры : Сумматор на verilog

Verilog Code:
  1. module addbit (
  2. a , // первый бит
  3. b , // второй бит
  4. ci , // вход переноса
  5. sum , // выход суммы
  6. co // выход переноса
  7. );
  8. //Объявление входов
  9. input a;
  10. input b;
  11. input ci;
  12. //Объявление выходов
  13. output sum;
  14. output co;
  15. //Провода
  16. wire a;
  17. wire b;
  18. wire ci;
  19. wire sum;
  20. wire co;
  21. //Начало кода
  22. assign {co,sum} = a + b + ci;
  23.  
  24. endmodule // Конец модуля addbit

Модули с подключением путем перечисления (неявно)

Здесь должен соблюдаться порядок. Обычно такое подключение нежелательно. При отладке могут возникнуть трудности при поиске порта в случае ошибок компиляции), при добавлении нового порта или удалении.

Verilog Code:
  1. //-----------------------------------------------------
  2. // Пример простого сумматора
  3. // Имя проекта : adder_implicit
  4. // Имя файла : adder_implicit.v
  5. // Функция : Эта программа показывает
  6. // неявное соединение портов
  7. // Автор : Deepak Kumar Tala
  8. //-----------------------------------------------------
  9. module adder_implicit (
  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. // Начало кода
  39. addbit u0 (
  40. r1[0] ,
  41. r2[0] ,
  42. ci ,
  43. result[0] ,
  44. c1
  45. );
  46.  
  47. addbit u1 (
  48. r1[1] ,
  49. r2[1] ,
  50. c1 ,
  51. result[1] ,
  52. c2
  53. );
  54.  
  55. addbit u2 (
  56. r1[2] ,
  57. r2[2] ,
  58. c2 ,
  59. result[2] ,
  60. c3
  61. );
  62.  
  63. addbit u3 (
  64. r1[3] ,
  65. r2[3] ,
  66. c3 ,
  67. result[3] ,
  68. carry
  69. );
  70.  
  71. endmodule // Конец модуля adder

Подключение модулей по имени (явно)

В этом случае достаточно соблюдения имен портов, как у вложенного модуля, порядок не имеет значения.

Verilog Code:
  1. //-----------------------------------------------------
  2. // Пример простого сумматора
  3. // Имя проекта : adder_explicit
  4. // Имя файла : adder_explicit.v
  5. // Функция : Здесь имена должны совпадать
  6. // с именем при описании модуля,
  7. // порядок не важен.
  8. // Автор : Deepak Kumar Tala
  9. //-----------------------------------------------------
  10. module adder_explicit (
  11. result , // Выход сумматора
  12. carry , // Выход переноса сумматора
  13. r1 , // первый вход
  14. r2 , // второй вход
  15. ci // вход переноса
  16. );
  17.  
  18. // Объявление входных портов
  19. input [3:0] r1 ;
  20. input [3:0] r2 ;
  21. input ci ;
  22.  
  23. // Объявление выходных портов
  24. output [3:0] result ;
  25. output carry ;
  26.  
  27. // Соединения
  28. wire [3:0] r1 ;
  29. wire [3:0] r2 ;
  30. wire ci ;
  31. wire [3:0] result ;
  32. wire carry ;
  33.  
  34. // Внутренние соединения
  35. wire c1 ;
  36. wire c2 ;
  37. wire c3 ;
  38.  
  39. // Начало кода
  40. addbit u0 (
  41. .a (r1[0]) ,
  42. .b (r2[0]) ,
  43. .ci (ci) ,
  44. .sum (result[0]) ,
  45. .co (c1)
  46. );
  47.  
  48. addbit u1 (
  49. .a (r1[1]) ,
  50. .b (r2[1]) ,
  51. .ci (c1) ,
  52. .sum (result[1]) ,
  53. .co (c2)
  54. );
  55.  
  56. addbit u2 (
  57. .a (r1[2]) ,
  58. .b (r2[2]) ,
  59. .ci (c2) ,
  60. .sum (result[2]) ,
  61. .co (c3)
  62. );
  63.  
  64. addbit u3 (
  65. .a (r1[3]) ,
  66. .b (r2[3]) ,
  67. .ci (c3) ,
  68. .sum (result[3]) ,
  69. .co (carry)
  70. );
  71.  
  72. endmodule // Конец модуля adder

Пример реализации модуля

Verilog Code:
  1. //-----------------------------------------------------
  2. // Пример простого модуля подсчета четности
  3. // Имя проекта : parity
  4. // Имя файла : parity.v
  5. // Функция : Пример показывающий как на verilog
  6. // можно объединять модули
  7. // Автор : Deepak
  8. //-----------------------------------------------------
  9. module parity (
  10. a , // Первый вход
  11. b , // Второй вход
  12. c , // Третий вход
  13. d , // Четвертый вход
  14. y // Выход четности
  15. );
  16.  
  17. // Объявление входных портов
  18. input a ;
  19. input b ;
  20. input c ;
  21. input d ;
  22. // Объявление выходных портов
  23. output y ;
  24. // Соединения
  25. wire a ;
  26. wire b ;
  27. wire c ;
  28. wire d ;
  29. wire y ;
  30. // Внутренние соединения
  31. wire out_0 ;
  32. wire out_1 ;
  33.  
  34. // Начало кода
  35. xor u0 (out_0,a,b);
  36.  
  37. xor u1 (out_1,c,d);
  38.  
  39. xor u2 (y,out_0,out_1);
  40.  
  41. endmodule // Конец модуля parity

Вопрос : В чем разница между u0 в модуле adder и модуле parity?

Схема

module_inst.gif

Правила подключения портов

  • Входы: внутри указывается шина(net: wire, wor, wand, tri и так далее), снаружи входы могут быть подключены к переменным типа reg или net.
  • Выходы: внутри могут использоваться типы reg или net, снаружи выходы подключаются к переменным типа net.
  • Двунаправленные: внутри или снаружи всегда используется тип net, подключение допускается только к типу net.

ports.gif

  • Совпадение размеров: допускается подключать внутренние и внешние порты с разной шириной. Но имейте в виду, что утилиты синтеза выведут предупреждения.
  • Неподключенные порты: допускаются с использованием ",".
  • Для подключения к структуре используется тип данных net.
  • Если сигнал может быть приведен к структурному типу, требуется тип данных net.

Пример - неявное подключение портов

Verilog Code:
  1. module implicit();
  2. reg clk,d,rst,pre;
  3. wire q;
  4.  
  5. // Здесь второй порт не подключен
  6. dff u0 ( q,,clk,d,rst,pre);
  7.  
  8. endmodule
  9.  
  10. // D триггер
  11. module dff (q, q_bar, clk, d, rst, pre);
  12. input clk, d, rst, pre;
  13. output q, q_bar;
  14. reg q;
  15.  
  16. assign q_bar = ~q;
  17.  
  18. always @ (posedge clk)
  19. if (rst == 1'b1) begin
  20. q <= 0;
  21. end else if (pre == 1'b1) begin
  22. q <= 1;
  23. end else begin
  24. q <= d;
  25. end
  26.  
  27. endmodule

Пример - явное подключение портов

Verilog Code:
  1. module explicit();
  2. reg clk,d,rst,pre;
  3. wire q;
  4.  
  5. // Здесь q_bar не подключен
  6. // Мы можем соединять порты в любом порядке
  7. dff u0 (
  8. .q (q),
  9. .d (d),
  10. .clk (clk),
  11. .q_bar (),
  12. .rst (rst),
  13. .pre (pre)
  14. );
  15.  
  16. endmodule
  17.  
  18. // D fli-flop
  19. module dff (q, q_bar, clk, d, rst, pre);
  20. input clk, d, rst, pre;
  21. output q, q_bar;
  22. reg q;
  23.  
  24. assign q_bar = ~q;
  25.  
  26. always @ (posedge clk)
  27. if (rst == 1'b1) begin
  28. q <= 0;
  29. end else if (pre == 1'b1) begin
  30. q <= 1;
  31. end else begin
  32. q <= d;
  33. end
  34.  
  35. endmodule