Цикл for в макросе `define

Я искал на SO и в Интернете, нигде не нашел ответов. У меня есть следующий код, где он успешно полностью проанализировал определение и сгенерировал ожидаемые результаты, но если количество вызовов макроса велико, можем ли мы использовать циклическую конструкцию?.

`define myreg(name) \
   addr_``name    

`define para(i) \
  parameter `myreg(i) = i  

module register;

`para(1);
`para(2);
`para(3);
`para(4);

initial
begin
  $display("ADDR1 = %d, ADDR2 = %d", addr_1, addr_2);
  $display("ADDR3 = %d, ADDR4 = %d", addr_3, addr_4);
  #100 $finish;
end
endmodule

Результат моделирования:

// # Loading work.register(fast)
// # run -all
// # ADDR1 =           1, ADDR2 =           2
// # ADDR3 =           3, ADDR4 =           4
// # ** Note: $finish    : reg.v(18)

Теперь, когда я использую цикл for, как в приведенном ниже коде,

`define myreg(name) \
   addr_``name    

`define para(i) \
  parameter `myreg(i) = i  

module register;

genvar i;
generate 
  for (i = 1; i<=4; i=i+1)
  begin
    `para(i);
  end
endgenerate

initial
begin
  $display("ADDR1 = %d, ADDR2 = %d", addr_1, addr_2);
  $display("ADDR3 = %d, ADDR4 = %d", addr_3, addr_4);
  #100 $finish;
end
endmodule

В этом случае при отображении или использовании отображается ошибка, Результат моделирования:

// # vsim -lib work register -c -do "run -all; quit -f" -appendlog -l qverilog.log -vopt 
// # ** Note: (vsim-3813) Design is being optimized due to module recompilation...
// # ** Error (suppressible): (vopt-7063) reg.v(24): Failed to find 'addr_1' in hierarchical name '/addr_1'.
// # ** Error (suppressible): (vopt-7063) reg.v(24): Failed to find 'addr_2' in hierarchical name '/addr_2'.
// # ** Error (suppressible): (vopt-7063) reg.v(25): Failed to find 'addr_3' in hierarchical name '/addr_3'.
// # ** Error (suppressible): (vopt-7063) reg.v(25): Failed to find 'addr_4' in hierarchical name '/addr_4'.
// # Optimization failed
// # Error loading design

Его спрашивают больше раз, но никто не дает правильного решения, любая помощь очень ценится.


person Prakash Darji    schedule 15.04.2016    source источник


Ответы (2)


Проблема на самом деле гораздо проще, чем объясняет sharvil111.

Директивы `defines, `ifdefs и `includes обрабатываются препроцессором, который создает поток текста и передает его компилятору. Препроцессор ничего не знает о синтаксисе Verilog, а компилятор не видит ни одной из этих директив, потому что они были обработаны.

Вы действительно можете увидеть этот промежуточный поток текста, добавив опцию vlog -E <filename>, которая записывает вывод препроцессора в

В Verilog/SystemVerilog нет директивы зацикливания. Некоторые варианты для вас:

  • написать макросы вручную. Возможно, вы найдете в своем текстовом редакторе какую-нибудь функцию, которая поможет вам в этом.
  • используйте другой препроцессор макросов для генерации кода. Это может затруднить отладку, поскольку вам придется управлять двумя наборами файлов исходного кода.
  • Реструктурируйте свой код, чтобы использовать массив вместо параметров с отдельными именами.
person dave_59    schedule 15.04.2016
comment
используйте другой препроцессор макросов для генерации кода. Это может затруднить отладку, поскольку вам придется управлять двумя наборами файлов исходного кода. Можете ли вы привести какой-либо пример или код? - person Prakash Darji; 16.04.2016
comment
Подскажите, пожалуйста, как мне использовать этот vlog -E ‹filename›? - person Prakash Darji; 18.04.2016
comment
Он указан в справочном руководстве Questa/ModelSim. - person dave_59; 18.04.2016
comment
Я не могу найти это, не могли бы вы поделиться ссылкой на этот документ и номером страницы? - person Prakash Darji; 19.04.2016
comment
Просто введите vlog -help или загляните в меню справки, когда откроете графический интерфейс. - person dave_59; 19.04.2016
comment
Я запускаю команду vlog -E reg.v, но она снова показывает справку. - person Prakash Darji; 19.04.2016
comment
Большое спасибо, я использовал это, vlog filename.v - E output.v, где output.v содержит определение проанализированного файла. - person Prakash Darji; 19.04.2016

Для любого моделирования имеет место следующая последовательность событий:

Фаза компиляции ==> Фаза проработки ==> Фаза запуска (Этап моделирования)

Во время компиляции выполняется проверка синтаксических ошибок и подстановка текста макросов. Вычисляется память для всех переменных и создается исполняемый файл. Во время компиляции исходный код программы транслируется в исполняемый код.

Во время разработки формируются экземпляры и соединение между экземплярами. Под подключением я подразумеваю проверку ширины портов и наличия портов и т. д. Поскольку фактические экземпляры создаются, параметры также оцениваются< /strong> во время разработки.

Во время времени выполнения, конечно, фактическая симуляция начинается с нулевого времени на вардах.

Макросы оцениваются в во время компиляции (отсюда называемые директивами компилятора), а блок generate оценивается в время разработки.

Ссылаясь на IEEE 1800-2012, раздел 27.3:

Генерируемые схемы оцениваются во время разработки дизайна. ... Они оцениваются во время разработки, и результат определяется до начала моделирования. Следовательно, все выражения в схемах генерации должны быть константными выражениями, детерминированными во время разработки.

Первый пример запускается, потому что все делается во время компиляции. Все переменные объявляются во время компиляции. Следовательно, код работает нормально.

Во втором примере вы пытаетесь объявить переменные во время уточнения, что недопустимо. Во время обработки больше не выделяется память для переменных.

Дополнительную информацию о компиляции и время проработки.

person sharvil111    schedule 15.04.2016
comment
Ваше объяснение идеально! Я понял концепцию, теперь что мне делать со вторым кодом? Возможно ли повторение или зацикливание во время компиляции? Или это не возможно? - person Prakash Darji; 15.04.2016
comment
У вас есть только ограниченный набор директив компилятора, использование цикла generate никоим образом не является решением. Я бы предпочел использовать массив переменных, управляемых параметром, например parameter SIZE=5; reg [7:0] ADDR[SIZE];. Или вы можете использовать массив, управляемый макросами, например ifdef SIZE reg [7:0] ADDR[SIZE]; else define SIZE 5 ADDR[SIZE]; endif. И укажите SIZE в качестве переключателя симуляции, например +define+SIZE=5. Это переопределит SIZE в соответствии с переключателем симуляции. - person sharvil111; 15.04.2016
comment
Скорее в комментариях, не могли бы вы добавить его в ответ? - person Prakash Darji; 16.04.2016