1

I'm trying to create a variable format specifier for use in $display/$write. I've tried a large number of things, but here is what I have at the moment.

What I want to end up with is: $display(format_var,data_1,data_2), where the format string is pre-calculated using $sformatf or other.

Code:

module test;
function void pprint(input int data_1,input int field_1,input int data_2,input int field_2);
string  format;
begin 
    format = $sformatf("%0d'h%%%0dx,%0d'h%%%0dx",field_1,field_1/4,field_2,field_2/4);
    $display("format = %s",format);
    $display(format,data_1,data_2);
end
endfunction

initial 
begin
    pprint(5,8,73737229,128);
    $stop;
end
endmodule

The output I expect is:

format = 8'h%2x,128'h%32x
8'h05,128'h000000000000000000000000465240D

The output I get is:

format = 8'h%2x,128'h%32x
8'h%2x,128'h%32x          5   73737229

What do I need to do? The simulator is Vivado 2020.3

Later:

Trying more things, the following function does do what I want. My conclusion is that $display/$write can't take a variable as the format string, but $sformatf can.

function void pprint(input int data_1,input int field_1,input int data_2,input int field_2);
string  format;
string  outstr;
begin 
    format = $sformatf("%0d'h%%%0dx,%0d'h%%%0dx",field_1,field_1/4,field_2,field_2/4);
    $display("format = %s",format);
    $display("%s",$sformatf(format,data_1,data_2));
end
endfunction
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
MichaelL
  • 11
  • 1
  • 3
  • Try your code on edaplayground on different simulators (like vcs). See also [How can I automatically scale a $display column width?](https://stackoverflow.com/questions/65691848/how-can-i-automatically-scale-a-display-column-width) – toolic May 27 '21 at 17:03

2 Answers2

1

Try:

function void pprint(
    input logic [4095:0] data_1,
    input int field_1,
    input logic [4095:0] data_2,
    input int field_2 );
  string  format; 
  format = $sformatf("%0d'h%%%0dh,%0d'h%%%0dh",
    field_1, (field_1+3)/4,
    field_2, (field_2+3)/4 );
  $display("format = %s",format);
  $display($sformatf(format,data_1,data_2));
endfunction

This should give you the output:

format = 8'h%02h,128'h%032h
8'h05,128'h000000000000000000000000465240D

Adding a zero between the % and digit could tells the simulator to pad the upper bits with zeros.
For some reason $display(format,data_1,data_2) did not use the format on simulators on edaplayground, but it did work with $sformatf so I simply nested it.
I needed to increase the bit width of the input data otherwise it would show leading zeros over 8 digits. Adjust if necessary.
Adding 3 to the field is for handling non multiples of 4. It will always round down after division.

Greg
  • 18,111
  • 5
  • 46
  • 68
  • In my case I do want the zero padding. to the nearest byte. I hadn't considered non-multiples of four for my use case but I like the ability to handle it. Thanks! That $display doesn't work I find interesting and I wonder if it's part of the spec that it doesn't handle a string variable, or it slipped through the cracks. – MichaelL May 27 '21 at 15:45
0

According to section 21.3.3 Formatting data to a string of the SystemVerilog LRM, only $sformat and $sformatf have a specific formatting argument that can be a string literal or string variable. All other output tasks like $display treat any string literal argument as format specifiers and do not interpret the strings inside string variables for formatting.

dave_59
  • 39,096
  • 3
  • 24
  • 63