David Belohrad
David Belohrad

Reputation: 468

How do I randomize a signed multidimensional array?

I have declared a signed multidimensional array as follows:

typedef logic signed [3:0][31:0] hires_frame_t;
typedef hires_frame_t [3:0] hires_capture_t;
hires_capture_t rndpacket;

I want to randomize this array such that each element has a value between -32768 to 32767, in 32-bit two's-complement.

I've tried the following:

assert(std::randomize(rndpacket) with
     {foreach (rndpacket[channel])
       foreach (rndpacket[channel][subsample])
          {rndpacket[channel][subsample] < signed'(32768);
           rndpacket[channel][subsample] >= signed'(-32768);}});

This compiles well, but (mentor graphics) modelsim fails in simulation claiming

randomize() failed due to conflicts between the following constraints:
#   clscummulativedata.sv(56): (rndpacket[3][3] < 32768);
#   cummulativedata.sv(57): (rndpacket[3][3] >= 32'hffff8000);

This is clearly something linked to usage of signed vectors. I had a feeling that everything should be fine as array is declared as signed as well as thresholds in the randomize call, but apparently not. If I replace the range by 0-65535, everything works as expected.

What is the correct way to randomize such a signed array?

Upvotes: 1

Views: 271

Answers (1)

dave_59
dave_59

Reputation: 42698

Your problem is hires_frame_t is a signed 128-bit 2-dimensional packed array, and selecting a part of a packed array is unsigned. A way of keeping the part-select of a packed dimension signed is using a separate typedef for the dimension you want signed:

typedef bit signed [31:0] int32_t;
typedef int32_t [3:0] hires_frame_t;
typedef hires_frame_t [3:0] hires_capture_t;

Another option is putting the signed cast on the LHS of the comparisons. Your signed cast on the RHS is not doing anything because bare decimal numbers are already treated as signed. A comparison is unsigned if one or both sides are unsigned.

 assert(std::randomize(rndpacket) with {
       foreach (rndpacket[channel,subsample])
          {signed'(rndpacket[channel][subsample]) < 32768;
           signed'(rndpacket[channel][subsample]) >= -32768;}});

BTW, I'm showing the LRM compliant way of using a 2-d foreach loop.

Upvotes: 3

Related Questions