Friday, 26 January 2018

`define macro usage in SystemVerilog

It's not possible to use a `define macro within a string literal. According to the SystemVerilog LRM: Macro substitution and argument substitution shall not occur within string literals
Let’s go through below example to understand it in detail,
 ---------------------------------------------------------------------------
module top();
`define HI Hello
`define LO "`HI, world"
`define H(x) "Hello, x"
initial begin
$display("`HI, world");
$display(`LO);
$display(`H(world));
end
endmodule : top
//Output:
// `HI, world
// `HI, world
// Hello, x
 ---------------------------------------------------------------------------

However a string literal can be constructed by using a macro that takes an argument and including the quotes in the macro by using `".
According to SystemVerilog LRM: An `" overrides the usual lexical meaning of " and indicates that the expansion shall include the quotation mark, substitution of actual arguments, and expansions of embedded macros. This allows string literals to be constructed from macro arguments.
 ---------------------------------------------------------------------------
module top();
`define HI Hello
// macro substitution
`define LO `"`HI, world`"
// argument substitution
`define H(x) `"Hello, x`"
initial begin
$display(`LO);
$display(`H(world));
end
endmodule : top
//Output:
// Hello, world
// Hello, world
 ---------------------------------------------------------------------------

Now what if you want to add double quotes in string which is constructed using macro. SystemVerilog provides support for that.
A `\`" indicates that the expansion should include the escape sequence \".
Let’s go through example to see how it works,
 ---------------------------------------------------------------------------
module top();
`define msg(x,y) `"x: `\`"y`\`"`"
initial begin
$display(`msg(left side,right side));
// expands to
// $display("left side: \"right side\"");
end
endmodule : top
//Output:
// left side: "right side"
 ---------------------------------------------------------------------------

 SystemVerilog LRM also provides support to construct identifier from arguments using ``.
There are three places where we can substitute argument to construct identifier
1) Substitute argument in between something (neither at the end nor at the beginning of the identifier)
2) Prepend argument (at the beginning of the identifier)
2) Append argument (at the end of the identifier)
 ---------------------------------------------------------------------------
module top();
int unsigned pkt_tx_cnt;
int unsigned pkt_rx_cnt;
bit clock_master;
bit reset_master;
int unsigned count_a;
int unsigned count_b;
`define increment(dir) \
pkt_``dir``_cnt = pkt_``dir``_cnt + 1;
`define set(sig, value) \
sig``_master = value;
`define update_count(sel, value) \
count_``sel = value;
initial begin
$display("pkt_tx_cnt:%0d, pkt_rx_cnt:%0d", pkt_tx_cnt, pkt_rx_cnt);
$display("clock_master:%b, reset_master:%b", clock_master, reset_master);
$display("count_a:%0d, count_b:%0d", count_a, count_b);
$display();
`increment(tx)
`set(clock, 1)
`update_count(a, 5)
$display("pkt_tx_cnt:%0d, pkt_rx_cnt:%0d", pkt_tx_cnt, pkt_rx_cnt);
$display("clock_master:%b, reset_master:%b", clock_master, reset_master);
$display("count_a:%0d, count_b:%0d", count_a, count_b);
$display();
`increment(rx)
`set(reset, 1)
`update_count(b, 7)
$display("pkt_tx_cnt:%0d, pkt_rx_cnt:%0d", pkt_tx_cnt, pkt_rx_cnt);
$display("clock_master:%b, reset_master:%b", clock_master, reset_master);
$display("count_a:%0d, count_b:%0d", count_a, count_b);
end
endmodule : top
//Output:
// pkt_tx_cnt:0, pkt_rx_cnt:0
// clock_master:0, reset_master:0
// count_a:0, count_b:0
// pkt_tx_cnt:1, pkt_rx_cnt:0
// clock_master:1, reset_master:0
// count_a:5, count_b:0
// pkt_tx_cnt:1, pkt_rx_cnt:1
// clock_master:1, reset_master:1
// count_a:5, count_b:7
 ---------------------------------------------------------------------------

Reference:
1) SystemVerilog 2012 LRM

1 comment:

  1. I have macro, inside one more macro is there. meanwhile I am passing value from top macro to inner macro. I have argument in top macro, then I want to pass the same value into inner macro.is it possible.

    ReplyDelete