Verilog имеет липкую семантику для файлов, которые он компилирует. Это означает, что если у вас есть несколько файлов в командной строке, макросы, определенные в одном файле, остаются также определенными в другом файле.
av
`include "h.vh"
`define A_V 1
bv
`include "h.vh"
...
assign A = `A_V;
Итак, макрос A_V доступен в файле bv, если вы скомпилируете их в следующем порядке: a.v, b.v
.
В результате, если h.vh
использует защитные макросы, он будет проанализирован только как включенный в AV и будет охраняться в BV и не анализируется.
Теперь предположим, что вы содержите определения параметров функций в h.vh:
`ifndef H_VH
`defien H_VH
paremeter I = 10;
`endif
и получите включение в тело модуля:
av
module A;
`include "h.vh"
assign A = I;
endmodule
bv
module B;
`include "h.vh"
assign B = I;
endmodule
Теперь, когда файл сначала включается в модуль A
, параметр теперь определяется внутри модуля A
. Но макрос H_VH также определен. Включаемый файл не будет проанализирован во второй раз в файле 'bv'. Таким образом, включение его в модуль не расширится до определения параметра, и компиляция не удастся, поскольку I
недоступно.
Защитные макросы в verilog полезны, если файл включен в глобальную область за пределами модулей. Они создают много проблем, если включены в области видимости. Правило большого пальца состоит в том, чтобы использовать их для глобально включенных заголовков и никогда не использовать их, если заголовок включен в область действия. Никогда не смешивайте глобальные и объемные включения.
И да, как все уже упоминали, в системном Verilog лучше использовать пакеты для этого. В обычном verilog у вас нет другого выбора для определения общих деклараций.