简体   繁体   中英

How to pass a variable value to a macro in SystemVerilog?

I think the question sums it up pretty well as to what I want: passing the value of a variable to a macro in SystemVerilog.

For example, what I want: Say, there are 4 signals by the name of abc_X_def and I want to initialize all of them to 0. So, without macros:

abc_0_def = 4'b0000;
abc_1_def = 4'b0000;
abc_2_def = 4'b0000;
abc_3_def = 4'b0000;

Now, the code that I have written is having a problem:

`define set_value(bit) abc_``bit``_def = 4'b0000

for (int i = 0; i < 4; i++) begin
  `set_value(i);
end

The error is that it's trying to find the signal abc_i_def which is obviously wrong. Just wondering if it's possible to pass the actual value of the variable 'i' to the macro.

The preprocessor directives are evaluated by the preprocessor and modify the code that is presented to the compiler.

The for loop is a verilog construct that is evaluated by the compiler.

So your preprocessor is not evaluating the for loop. It sees:

`define `set_value(bit) abc_``bit``_def = 4'b0000

[some verilog]
   `set_value(i);
[some verilog]

So 'i' is just i. It doesn't become a number until compilation.

Why don't you use local params with generate, so the local params are created in a loop at elaboration as the for loop is unrolled?

This is one of the many places that macros are a problem. Generate is a problem in other places (like when you want to control port lists).


I dug into this a bit more. Parameters and local parameters inside a generate are created a localparams in the scope of the generate. See here: System Verilog parameters in generate block . I had to get back to work before I could test it.

I would just use code and populate an array. This compiles in VCS:

module veritest  
    #(  
    parameter   MAX_X = 5,  
                MAX_Y = 3,  
                MAX_Z = 2  
    )  
    (); // empty port list  

logic [4:0] abc_def[1:MAX_X][1:MAX_Y][1:MAX_Z];  

always @*  
begin  
for (integer z=1; z<(MAX_X+1);z=z+1)  
   for (integer y=1; y<(MAX_Y+1);y=y+1)  
       for (integer x=1; x<(MAX_X+1);x=x+1)  
       begin  
            abc_def[x][y][z] = 4'b0000;  
       end  
end  
endmodule  

Since you said the naming conventions is out of your control, you should consider using another tool to generate the verilog for you.

You can have the code generated by your preferred programming then use an `include statement in your verilog file. Or you can go with an embedded route.

Concept is the same, just a difference in embedded language and tool used for conversion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM