Verilog: как создать экземпляр модуля

Если у меня есть модуль Verilog " top "и модуль verilog "subcomponent", как создать экземпляр подкомпонента в top?

верхняя:

module top(
   input        clk,
   input        rst_n,
   input        enable,
   input  [9:0] data_rx_1,
   input  [9:0] data_rx_2,
   output [9:0] data_tx_2
);

подкомпонентов:

module subcomponent(
   input        clk,
   input        rst_n,
   input  [9:0] data_rx,
   output [9:0] data_tx
);

Примечание
Это было написано как общий вопрос, который продолжает появляться время от времени, он следует за self-answer. Рекомендуется добавлять ответы и обновления.

2 ответов


все это, как правило, охватывается разделом 23.3.2 SystemVerilog IEEE Std 1800-2012.

самый простой способ-создать экземпляр в главном разделе top, создав именованный экземпляр и подключив порты по порядку:

module top(
   input        clk,
   input        rst_n,
   input        enable,
   input  [9:0] data_rx_1,
   input  [9:0] data_rx_2,
   output [9:0] data_tx_2
);

subcomponent subcomponent_instance_name (
  clk, rst_n, data_rx_1, data_tx ); 

endmodule

это описано в разделе 23.3.2.1 SystemVerilog IEEE Std 1800-2012.

это имеет несколько недостатков, особенно в отношении порядка портов кода подкомпонента. простой рефакторинг здесь может нарушить связь или изменить поведение. например, если кто-то еще исправляет ошибку и по какой-то причине переупорядочивает порты, переключая clk и порядок сброса. Не будет проблемы с подключением от вашего компилятора, но не будет работать по назначению.

module subcomponent(
  input        rst_n,       
  input        clk,
  ...

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

module top(
   input        clk,
   input        rst_n,
   input        enable,
   input  [9:0] data_rx_1,
   input  [9:0] data_rx_2,
   output [9:0] data_tx_2
);

subcomponent subcomponent_instance_name (
  .clk(clk), .rst_n(rst_n), .data_rx(data_rx_1), .data_tx(data_tx) ); 

endmodule

это описано в разделе 23.3.2.2 SystemVerilog IEEE Std 1800-2012.

предоставление каждому порту своей собственной строки и отступов правильно добавляет к удобочитаемости и качеству кода.

subcomponent subcomponent_instance_name (
  .clk      ( clk       ), // input
  .rst_n    ( rst_n     ), // input
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);

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

clk_gen( 
  .clk      ( clk_sub   ), // output
  .en       ( enable    )  // input

subcomponent subcomponent_instance_name (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);

это номинально работает как провод для clk_sub автоматически созданное, есть опасность полагаться на это. по умолчанию он будет создавать только 1-битный провод. Пример, где это проблема, будет для данных:

обратите внимание, что имя экземпляра для второго компонента было изменено

subcomponent subcomponent_instance_name (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_temp )  // output [9:0]
);
subcomponent subcomponent_instance_name2 (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_temp ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);

проблема с вышеуказанным кодом заключается в том, что data_temp имеет ширину всего 1 бит, будет предупреждение компиляции о несоответствии ширины порта. Необходимо создать провод подключения и указать ширину. Я бы рекомендуется, чтобы все провода подключения были явно выписаны.

wire [9:0] data_temp
subcomponent subcomponent_instance_name (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_temp )  // output [9:0]
);
subcomponent subcomponent_instance_name2 (
  .clk      ( clk_sub   ), // input
  .rst_n    ( rst_n     ), // input 
  .data_rx  ( data_temp ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);

переход к SystemVerilog есть несколько трюков, которые позволяют сэкономить набрав несколько символов. Я считаю, что они препятствуют читаемости кода и могут затруднить поиск ошибок.

использовать .port без кронштейнов для подключения к проводу / reg с тем же именем. Это может выглядеть аккуратно, особенно с большим количеством clk и сбросов, но на некоторых уровнях вы можете генерировать разные часы или сбросы или вы на самом деле не хотите подключаться к сигналу с тем же именем, но модифицированному, и это может привести к ошибкам проводки, которые не очевидны для глаза.

module top(
   input        clk,
   input        rst_n,
   input        enable,
   input  [9:0] data_rx_1,
   input  [9:0] data_rx_2,
   output [9:0] data_tx_2
);

subcomponent subcomponent_instance_name (
  .clk,                    // input **Auto connect**
  .rst_n,                  // input **Auto connect**
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);

endmodule

это описано в разделе 23.3.2.3 SystemVerilog IEEE Std 1800-2012.

еще один трюк, который я думаю, еще хуже, чем тот, что выше .* который соединяет unmentioned порты к сигналам такого же провода. Я считаю, что это довольно опасно в производственном коде. Это не очевидно, когда новые порты были добавлены и отсутствуют или что они могут случайно подключиться, если новое имя порта имело встречную часть на уровне создания экземпляра, они автоматически подключаются, и предупреждение не будет создано.

subcomponent subcomponent_instance_name (
  .*,                      // **Auto connect**
  .data_rx  ( data_rx_1 ), // input  [9:0]
  .data_tx  ( data_tx   )  // output [9:0]
);

это описано в разделе 23.3.2.4 SystemVerilog IEEE Std 1800-2012.


обязательно проверьте verilog-mode и особенно verilog-auto. http://www.veripool.org/wiki/verilog-mode/ это режим verilog для emacs, но Плагины существуют для vi (m?) например.

экземпляр может быть автоматизирован с помощью AUTOINST. Комментарий расширен с помощью M-x verilog-auto и после этого можно вручную редактировать.

subcomponent subcomponent_instance_name(/*AUTOINST*/);

расширен

subcomponent subcomponent_instance_name (/*AUTOINST*/
  //Inputs
  .clk,         (clk)           
  .rst_n,       (rst_n)
  .data_rx      (data_rx_1[9:0]),
  //Outputs
  .data_tx      (data_tx[9:0])
);

неявные провода можно автоматизировать с /*AUTOWIRE*/. Проверьте ссылку для дальнейшего информация.