Verilog сгенерирует /genvar в всегда блоке
Я пытаюсь получить модуль для проверки синтаксиса в ISE 12.4, и это дает мне ошибку, которую я не понимаю. Сначала фрагмент кода:
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
generate
always @(posedge sysclk) begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0;
end
end
endgenerate
Когда я пытаюсь проверить синтаксис, я получаю следующее сообщение об ошибке:
ОШИБКА: HDLCompiler: 731 - "test.v" Строка 46: Процедурное присвоение не-регистр <c> не разрешено.
Я действительно не понимаю, почему он жалуется. "c" - это не провод, это жанр. Это должно быть эквивалентно полностью законному синтаксису:
reg [3:0] temp;
always @(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
Пожалуйста, никаких комментариев о том, как было бы проще написать это без генерации. Это приведенный пример более сложного фрагмента кода, включающего множественные и неблокирующие назначения для "temp". Кроме того, не просто скажите мне, что есть более новые версии ISE, я уже это знаю. OTOH, если вы знаете, что это исправлено в более поздней версии ISE, сообщите мне, какая версия, которую вы знаете, работает.
Ответы
Ответ 1
Вам нужно отменить вложенность внутри блока генерации:
genvar c;
generate
for (c = 0; c < ROWBITS; c = c + 1) begin: test
always @(posedge sysclk) begin
temp[c] <= 1'b0;
end
end
endgenerate
Технически это генерирует четыре всегда блока:
always @(posedge sysclk) temp[0] <= 1'b0;
always @(posedge sysclk) temp[1] <= 1'b0;
always @(posedge sysclk) temp[2] <= 1'b0;
always @(posedge sysclk) temp[3] <= 1'b0;
В этом простом примере нет разницы в поведении между четырьмя всегда блоками и единственным всегда блоком, содержащим четыре присвоения, но в других случаях может быть.
Операция, зависящая от genvar, должна быть разрешена при построении представления в конструкции в памяти (в случае симулятора) или при сопоставлении с логическими затворами (в случае инструмента синтеза). always @posedge
не имеет значения до тех пор, пока дизайн не будет работать.
При определенных ограничениях вы можете поместить цикл for внутри всегда блока, даже для синтезируемого кода. Для синтеза петля будет развернута. Однако в этом случае цикл for должен работать с reg
, integer
или аналогичным. Он не может использовать genvar
, поскольку наличие цикла for внутри всегда блока описывает операцию, которая происходит на каждом краю часов, а не операцию, которая может быть развернута статически во время разработки дизайна.
Ответ 2
Вам не нужно генерировать bock, если вы хотите, чтобы все биты temp
были назначены в одном и том же блоке всегда.
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
for (integer c=0; c<ROWBITS; c=c+1) begin: test
temp[c] <= 1'b0;
end
end
В качестве альтернативы, если ваш симулятор поддерживает IEEE 1800 (SytemVerilog), то
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
temp <= '0; // fill with 0
end
end
Ответ 3
Внутри модуля Verilog содержит по существу две конструкции: элементы и операторы. Выражения всегда обнаруживаются в процедурных контекстах, которые включают в себя все, что происходит между begin..end, функциями, задачами, всегда блоками и начальными блоками. Элементы, такие как генерация конструкций, перечислены непосредственно в модуле. Для циклов и большинства переменных/констант могут существовать в обоих контекстах.
В вашем коде кажется, что вы хотите, чтобы цикл for оценивался как генерируемый элемент, но цикл фактически является частью процедурного контекста всегда блока. Чтобы цикл for обрабатывался как цикл генерации, он должен быть в контексте модуля. Генерируемые..endgenerate ключевые слова являются полностью необязательными (некоторые инструменты требуют их) и не имеют никакого эффекта. См. этот ответ для примера того, как оцениваются генерации циклов.
//Compiler sees this
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
always @(posedge sysclk) //Procedural context starts here
begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0; //Still a genvar
end
end
Ответ 4
Если вы не против компилировать/генерировать файл, тогда вы можете использовать технику предварительной обработки. Это дает вам силу генерации, но приводит к чистому файлу Verilog, который часто легче отлаживать и приводит к меньшему количеству проблем с имитатором.
Я использую RubyIt для создания файлов verilog из шаблонов с использованием ERB (Embedded Ruby).
parameter ROWBITS = <%= ROWBITS %> ;
always @(posedge sysclk) begin
<% (0...ROWBITS).each do |addr| -%>
temp[<%= addr %>] <= 1'b0;
<% end -%>
end
Создание файла module_name.v с помощью
$ ruby_it --parameter ROWBITS=4 --outpath ./ --file ./module_name.rv
Сгенерированный module_name.v
parameter ROWBITS = 4 ;
always @(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
Ответ 5
для verilog просто do
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
temp <= {ROWBITS{1'b0}}; // fill with 0
end
Ответ 6
Проще говоря, вы не используете generate
внутри всегда процесса, вы используете генерацию для создания параметризованного процесса или создания отдельных модулей, где вы можете комбинировать if-else
или case
. Таким образом, вы можете переместить это генерировать и создать конкретный процесс или экземпляр, например,
module #(
parameter USEIP = 0;
)
(
);