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;
)
(

);