Все это обычно рассматривается в разделе 23.3.2 документа SystemVerilog IEEE Std 1800-2012 а>.
Самый простой способ - создать экземпляр в основном разделе вверху, создав именованный экземпляр и подключив порты по порядку:
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]
);
До сих пор во всех выполненных подключениях повторно использовались входы и выходы для субмодуля, и никакие соединительные провода не были созданы. Что произойдет, если мы перенесем выходные данные от одного компонента к другому:
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
без скобок для подключения к проводу / регистру с тем же именем. Это может выглядеть аккуратно, особенно с большим количеством 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. .
Другой трюк, который, на мой взгляд, даже хуже, чем описанный выше, - это .*
, который соединяет неупомянутые порты с сигналами того же провода. Я считаю это довольно опасным в производственном коде. Не очевидно, когда новые порты были добавлены и отсутствуют, или что они могут случайно подключиться, если новое имя порта имело противоположную часть на уровне экземпляра, они подключаются автоматически, и никаких предупреждений генерироваться не будет.
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. .
person
Morgan
schedule
19.11.2013
subcomponent subcomponent_instance_name ();
, или опущены, как вsubcomponent subcomponent_instance_name;
? Или это должен быть отдельный вопрос? - person FriendFX   schedule 12.04.2017();
, но современные инструменты, скорее всего, могут обрабатывать только;
- person Morgan   schedule 17.04.2017;
и требуют();
. Тем не менее, я ищу исчерпывающий справочник по этому делу. - person FriendFX   schedule 18.04.2017