Streaming into dynamic arrays

Hi

I have a 32bit dynamic array that i want to stream into a dynamic array of bytes.

bit [7:0] byte_array[];
bit [31:0] reg_array[];

i want to make sure that LSB element reg_array[0] is assigned to byte_array[4:0]


 reg_array[0] = 01020304;
 reg_array[1] = 05060708;

when i do this :

byte_array = {>>byte{reg_array}};

the order of the values internally is preserved but
byte_array = 01020304 05060708

and

byte_array = {<<byte{reg_array}};

results in
byte_array = 08070605 04030201

i want byte_array to be : 05060708 01020304

Please help me achieve this.

Thanks

In reply to theketi:
Try

    byte_array = {<<32{reg_array}};

Thanks a lot! It worked.

I am not clear how this works though , as we are parsing in blocks of 32 bits at a time and the LHS side needs a byte

*In reply to theketi:*Think of three separate operations with 2 intermediate streams of bits

  1. The individual reg_array elements get concatenated into a single stream
  2. Apply the transformation based on the streaming operator arguments from the first intermediate stream to the second.
  3. Assign the second stream to a concatenation of byte_array elements.

In pseudo code

stream1 = {reg_array[0], reg_array[1]};

stream2 = sreamop(stream1); // skip this step for left >> right streaming

{byte[0], byte[1], ...} = stream2;

In reply to sharvil111:

I do not think you got my point about the intermediate streams. Think of each stream as an dynamic array of bits sized to the number of bits in the RHS expression; 64 in this case.

Regardless of the specific streaming operator, we create stream1 the same way; as a concatenation of the RHS.

{stream1[0], stream1[1], ... stream1[62], stream1[63]} = {reg_array[0], reg_array[1]};

For any kind of left-to-right streaming operator (as well as a bit-stream cast), the resulting stream2 is identical to stream1.

for(int i=0;b<$bits(stream1);i++) stream2*= stream1[i];

Let me hold of on what happens on a right-to-left streaming operator and explain what happens after any resulting stream2. That gets concatenated into the variables on the LHS.

{byte_array[0], byte_array[1],... byte_array[7]} = {stream2[0], stream2[1], ... stream2[62], stream2[63]}

So you should understand by now that the first and last steps happen the same way for any kind of streaming operator.

Let us go back to the right-to-left streaming operator, where stream2 = {<<{stream1}}. With no [I]slice_size* specified, bits from stream1 are taken one at a time from right to left into stream2 left-to-right. In another word - reversed.

for(int i=0,j=$bits(stream1)-1;i<$bits(stream1);i++,j--)
     stream2*= stream1[j];

With a [I]slice_size* greater than one, bits are still taken from right–to-left, but in left-to-right(or un-reversed) blocks. So the pseudo-code for stream2 = {<<slice_size{stream1}} would look something like

for(int I=0,j=$bits(stream1)-1;i<$bits(stream1);I+=slize_size,j-=slice_sice) 
       stream2[i+:slice_size] = stream1[j-:slice_size];

In reply to dave_59:
Thanks Dave for the clear explanation. Now I got it in the correct way. It’s about the way how the bits/slices gets arranged in stream2 that is making all the difference.

With a slice_size greater than one, bits are still taken from right–to-left, but in left-to-right(or un-reversed) blocks. So the pseudo-code for stream2 = {>>slice_size{stream1}} would look something like

Just to be on the same page, I believe that here right to left operator {<< slice_size{stream1}} will be there. Please correct me if I am wrong.

Thanks again!!

In reply to sharvil111:

You might want to take a look at these 2 tutorials about packing and unpacking using streaming operators. They will answer your questions:

https://www.amiq.com/consulting/2017/06/23/how-to-unpack-data-using-the-systemverilog-streaming-operators/

https://www.amiq.com/consulting/2017/05/29/how-to-pack-data-using-systemverilog-streaming-operators/