Stream packed struct to bit queue

I have a function that writes 132 bit packed struct into a queue of bits, while another function read from the queue 128 bits. As soon as in the queue there’s enough to serve a read access, the write access pauses.

Unfortunately dealing with pushing bits into the queue is rather cumbersome to code, msb first, save temporary valuas and bits manipulation on the way out of the queue which is essentially a fifo. I was wondering if “streaming operators” could be used here, something on the line of the following code:

module example; typedef struct { bit [3:0] high_nibble; bit [3:0] low_nibble; bit [4:0] id; } data_t;

initial begin
static data_t [3] data = '{ 13’b1_0011_1010_1100, 13’b1_0100_1110_0111, 13’b1_0011_1100_1101 };
bit queue [$];

{>>{queue}} = data; // <-- does this work?

foreach (queue[i])
  $display("queue[%0d] = 0x%h", i, queue[i]);

end
endmodule

To clarify, I’d like to use the queue as a fifo, writing 132bit at a time and reading 128 bit at a time. I’m assuming bit order can be handled by streaming from left to right or from right to left. The stream representation would “look” like this:

// ±> pop
// |
// data132 >> queue >> data128
// |
// ±> push

EDIT: typos and clarification

In reply to abasili:

You need to tell us what kind of bit manipulation you want. Otherwise we have no ides what “works” is supposed to mean. What are you expecting your code to display versus what it actually does?

In reply to dave_59:

Sorry for my lack of details, I’ve edited my post, hoping my clarification helps understand the intent.

In reply to abasili:

Did you mean to declare data_t as struct packed?

And did you mean to say you have a function that writes a 13-bit packed struct, not 132? If that the case, you would have to write 10 data_t elements to get to 130 bits before you can do the first read of 128 bits. Why did you declare data as a fixed array of 3 data_t (which is 39-bits) ?

To answer your direct question "does this line of code work? Yes it does, but we still cannot answer if it does what you want it to do.

In reply to dave_59:

I messed up between my real case and the made up example. Let’s stick to the example since it’s the only shared code so far.

Did you mean to declare data_t as struct packed?

Yes indeed, the data_t should be packed

And did you mean to say you have a function that writes a 13-bit packed struct, not 132?

Correct, let’s assume I have a struct of 13 bits that I want to push on a bit queue for later retrieval.

To answer your direct question "does this line of code work? Yes it does, but we still cannot answer if it does what you want it to do.

I’m trying to push data on the queue data_t bits at a time, while I want to pop it out one byte at a time. Since I want to preserve the ordering of the input vs output (so the msb on the data_t should be the same as the msb of the output byte), I’m currently doing this:


// Writing to the queue
bit [12:0] data13;
{>>{data13}} = data;
for (integer i = $size(data13); i > 0; i--) queue.push_back(data13[i-1]);

// Reading from the queue
byte data8;
for (integer i = $size(data8); i > 0; i--) data8[i-1] = queue.pop_front()

I was wondering if I could simply do instead:


// Writing to the queue
{>>{queue}} = data; // Should store data msb first

// Reading from the queue
{>>{data8}} = queue; // I doubt this will work!

In reply to abasili:

The write needs to do an array concatenation, which is very similar to a push_back

data_t data;
bit queue[$];

queue = {>>{queue, data}};

The you can use the streaming pack operator to pack the queue into bytes

bit [7:0] dataq[$];

// some loop
wait(queue.size >= 128)
dataq = {>>dataq, queue with [0+:128]}}; // pack 16 bytes
queue = queue[127:$]; // pop 16 bytes