Порты Verilog в Generate Loop
По причинам, которых нельзя избежать (требования Qsys), у меня есть несколько модулей Verilog, которые имеют много портов, с которыми было бы намного проще работать, если бы они были упакованы. Чтобы попытаться объяснить, что я имею в виду, вот пример:
module foo #(
COUNT = 4
) (
//Interface 0
input bar_0,
output deadbeef_0,
//Interface 1
input bar_1,
output deadbeef_1,
//Interface 2
input bar_2,
output deadbeef_2,
//Interface 3
input bar_3,
output deadbeef_3,
);
...
endmodule
Теперь обычно можно сделать два векторизованных порта (например, input [COUNT-1:0] bar,
), однако Qsys не может справиться с этим, если сигналы нужно подавать на разные интерфейсы - вы можете выбрать только целый порт, а не только один бит.
Как вы можете себе представить, это становится очень раздражающим, если внутренне вам нужно получить доступ к портам в чем-то вроде generate
цикл, и это особенно проблематично, если у вас есть модуль с интерфейсами, которые имеют 10 портов, которые должны быть записаны 16 раз!
До этого момента я делал ручное добавление отображения в модуль. Снова и пример, чтобы объяснить - продолжая пример выше, у меня было бы что-то вроде этого в теле модуля:
wire [COUNT-1:0] bar;
wire [COUNT-1:0] deadbeef;
generate
if (COUNT > 0) begin
assign bar[0] = bar_0;
assign deadbeef_0 = deafbeef[0];
end else begin
assign deadbeef_0 = 1'b0; //Terminate!
end
if (COUNT > 1) begin
assign bar[1] = bar_1;
assign deadbeef_1 = deafbeef[1];
end else begin
assign deadbeef_1 = 1'b0; //Terminate!
end
...
endgenerate
// deadbeef[] and bar[] can now be used as arrays, woop.
Даже написать пару интерфейсов для двух сигналов в этом примере было невероятно утомительно!
Каждая часть программиста во мне кричит прекратить делать это, и что должен быть лучший путь. И это подводит меня к моему вопросу:
Есть ли простой способ сделать это?
В идеале у меня была бы какая-то форма цикла, которая генерирует эти отображения для меня, генерируя имена сигналов из переменной цикла. Но я не уверен, возможно ли это даже в Verilog.
Кроме того, просто для того, чтобы сделать вещи интересными, я использовал шестнадцатеричное значение для портов, чтобы упростить процесс записи, например:
input bar_0,
input bar_1,
...
input bar_9,
input bar_a,
input bar_b,
...
В идеале решение этой проблемы также могло бы справиться с такими именами, но, если честно, я мог бы легко преобразовать имена в десятичные (bar_10
) если это упрощает вещи.
Если вам интересно, в Qsys это очень просто связать интерфейсы с портами, потому что Qsys использует файлы TCL для отображения. В TCL я могу просто использовать цикл for и объединить переменную цикла для создания имен.
1 ответ
Я думаю, в вашем случае, макрос может быть использован для решения вашей проблемы. Таким образом, везде, в вашем коде, вы можете использовать bar
как вектор, хотя это не так.
Определите макрос как это:
`define bar(n) bar_``n``
`define deadbeef(n) deadbeef_``n``
Вы можете использовать бар в качестве вектора, как показано ниже:
`bar(0)
`deadbeef(0)