2

How can I format a dynamic array of bits (or more correctly, logics) as a string, e.g., for UVM's convert2string? For example, I would like to convert

logic        vdyn[];  
...  
vdyn = new [16] ('{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1});  

to the string 0097.

I thought the following would work (the # are just to delimit the string for readability):

  fmt = $sformatf("#%%%0dh#", (vdyn.size-1)/4 + 1); // "#%4h#"
  vstr = $sformatf(fmt, { >> {vdyn}});

but it returns # x#, at least in Questa 10.3d (I suspect this is a bug - I'd be interested if it works on other simulators).

I tried converting it to a packed array first, but that runs into other problems. Without a size constraint on the result, the source value always gets left-justified in the destination variable, e.g.:

logic [63:0] v64;
...
v64 = {>> {vdyn}}; // 64'h0097000000000000

There's no way to print out just the part I want without using variable-size slices. The following works, but it requires that I know the size of the array at compile time:

v64 = 16'({>> {vdyn}});  // 64'h0000000000000097

The best thing I've found is the following "double-reverse" (note that I'm using << here, not >>):

     v64 = {<< {vdyn}};    // 64'he900000000000000 
     v64 = {<< {v64}};     // 64'h0000000000000097
     vstr = $sformatf(fmt, v64); // #0097#

It seems kind of hokey to have to do this, though. By the way, combining the first two statements into one doesn't work:

     v64 = {<< {{<< {vdyn}}}};     // 64'hZ900000000000000

(v64[63] is z for some reason). Again, I suspect this is a bug in Questa 10.3d.

2 Answers 2

1

Try casting a slice of the array and loop through. For example an 4 entry slice that is cast to a 4-bits value. A slize can be done with the -: or +: operator (See IEEE Std 1800-2012 § 7.4.3 Operations on arrays and § 7.4.6 Indexing and slicing of arrays)

vstr = "";
for(int i=vdyn.size()-1; i>=0; i-=4) begin
  vstr = $sformatf("%h%s", 4'({>>{vdyn[i -: 4]}}), vstr);
end
vstr = $sformatf("#%s#", vstr); // user formatting

The 4s in the code can be changed to something else depending how much leading 0 or a non-power-of-two formatting is desired, but it must be a numeric constant


I tried your code on some other simulators. vstr = $sformatf(fmt, { >> {vdyn}}); sometimes gave me compiling errors. Casting the array to something bigger than its expected max size seems to work

fmt = $sformatf("#%%%0dh#", (vdyn.size-1)/4 + 1); // "#%4h#"
vstr = $sformatf(fmt, 128'({ >> {vdyn}})); // works iff 128>=vdyn.size
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I had thought about doing it with a loop (I generally write VHDL, so I'm used to doing things the brute-force way). I think it would need a little enhancement to support sizes that aren't a multiple of 4, but otherwise it should work for virtually any size array. Streaming to a packed array (like I did) still puts an upper limit on the size. Thanks for trying the code on another simulator. Casting it to a fixed size "works" on Questa 10.3d, but it has the same left-justification problem I mentioned.
I played with it non-multiples of 4 and it still casts correctly with the simulators on edaplayground after changing i>0 to i>=0. Example: vdyn = new [17]
1

I think the problem may be that the width of the streaming operator using dynamic types is not defined in a self-determined context (e.g. an argument to a system task). I think the LRM should have treated this an error.

A work-around is to shift the left-justified result to the right by

v64 = {>> {vdyn}}; 
v64 >>= 64-vdyn.size;

2 Comments

(a) The width should be unambiguous, although obviously not static (if that's what you meant by "self-determined"). (b) That's a little bit saner way to change the justification, but is there really no way to directly convert a dynamic array of bits to the equivalent (right-justified) packed array? Seems to me like that would be an obvious language feature. (c) Is there any way to add line breaks in a comment on here? I just noticed that everything runs together into one paragraph.
Yes. I should have said not statically defined. Verilog requires the width of all integral types to be statically determined.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.