Когда я пишу универсальный модуль, я часто сталкиваюсь с регистром 0-битной ширины.
module test #(
parameter WIDTH
) (
input logic [31 : 0] x,
output logic [31 : 0] y
);
always_comb begin
y = x[WIDTH - 1 : 0];
end
endmodule
Например, приведенный выше модуль извлекает младшие биты WIDTH из x. Когда WIDTH равен 0, вывод не имеет значения. Однако, когда модуль создается с WIDTH 0, я получаю следующую ошибку в Modelsim:
# ** Fatal: (vsim-3373) test.sv(8): Range of part-select [-1:0] into 'x' [31:0] is reversed.
Я попробовал следующий код, надеясь, что плохая часть будет оптимизирована во время компиляции, но ошибка остается.
if (WIDTH == 0) y = 0;
else y = x[WIDTH - 1 : 0];
Есть ли выход из этой ситуации?
Ваш процедурный код должен компилироваться, даже если ветвь с неправильным диапазоном никогда не будет выбрана.
module test #(
parameter WIDTH
) (
input logic [31 : 0] x,
output logic [31 : 0] y
);
always_comb
if (WIDTH == 0) y = 'x;
else y = x[WIDTH - 1 + (WIDTH==0): 0];
endmodule
Вы также можете сделать
module test #(
parameter WIDTH
) (
input logic [31 : 0] x,
output logic [31 : 0] y
);
if (WIDTH==0)
assign y = 'x;
else
assign y = x[WIDTH - 1: 0];
endmodule
О, я ошибся, x[0] не переходит в y. Хотя он не кажется "чистым", он работает. Спасибо.
Вы можете заменить assign
на always_comb
во втором примере. Пока if
остается вне процедурного кода, он становится конструкцией generate-if
.
Я предпочитаю обрабатывать его внутри always_comb (без назначения), но первый метод не будет работать, когда y не все равно. (x[0] переходит в y) Хотя я представил пример безразличия, мой фактический модуль должен выводить 0, когда WIDTH равен 0. Есть ли другой способ в этой ситуации?