how to define a multi line macro in verilog?

2019-08-31 01:45发布

问题:

I am relatively new to verilog (a VHDL user), and in order to improve my skills i built my test environment using verilog (my QC use their own env).

In my env, I emulate a master that force random stimuli on the lines (i2c master).

since i didn't really want to use a real master and wanted only a 'well behaved' master, i created the following macros to provide me with the i2c communications:

`define writeChipId(addr)\
sda = 1\
#7500 sda = addr[3];\
#2500 sda = addr[2];\
#2500 sda = addr[1];\
#2500 sda = addr[0];\
#2500;

`define writeData(data)\
sda = data[7]\
#2500 sda = data[6];\
#2500 sda = data[5];\
#2500 sda = data[4];\
#2500 sda = data[3];\
#2500 sda = data[2];\
#2500 sda = data[1];\
#2500 sda = data[0];\
#2500 sda = 1;\
#2500; // time for the slave to answer

`define readData\
#sda = 1\
#20000 sda = 0;\
#2500; // master always answer ACK

my problem is that, when i try to use these macros i get a compilation errors (using modelsim) saying i have a syntax error and i have unexpected '[' that should be ';' for using the chipID macro and having unexpected '#' that should be ';' when using the read\ write macros.

the usages i try (and fail) are

`writeChipId(`chipID)  

and

`writeData(rndData)   

and

 `readData

last, but not least: if i write the same lines without the macro in my code, it compiles perfectly (only tried in one place, don't want to do it for the 12 other places i'll need these macros...)

anyone have a clue what is the problem? i've been trying to play with the macros with no luck and also verified they have no white spaces stuck in the middle.
also looked for multi-line macro examples and found similar things to what I did that didn't give an answer.

thanks in advance to all repliers

edit
something i forgot saying: when i take the macro and remove the input and use const values instead of the input, it works fine.

回答1:

The syntax for a `define requires a space after the macro identifier/arguments.

`define writeChipId(addr) \
sda = 1;\
#7500 sda = addr[3];\
#2500 sda = addr[2];\
#2500 sda = addr[1];\
#2500 sda = addr[0];\
#2500;

As Greg pointed out, this really calls for using a task.

task writeChipId(input [3:0] addr);
sda = 1;
#7500 sda = addr[3];
#2500 sda = addr[2];
#2500 sda = addr[1];
#2500 sda = addr[0];
#2500;
endtask


回答2:

ok, solution found: the first line of each macro should also have semicolon (;), also - the use of parameter for the chipID is hard on the verilog, this was solved by putting the input into a reg and using the reg's bits.

i didn't come across this problem the previous time I used macros because of another mistake I made - I defined the macro of the constant to have semicolon (meaning `define ADD 32'h0;) and when I used it it inserted the ; to the line and seemed OK.