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*/
. Проверьте ссылку для дальнейшего информация.