Add queue inside flip flop

Hi All,

I am new to systemverilog. Before joining fpga world, I mainly work on java server side development.

Now, I have an Avalon-ST output for data streaming. I have to create a data decoder by this Avalon interface.

What I have now is : a list of input and output ports:

  localparam SIZE = 48;
  localparam WIDTH = 256;
	
  // reset & clk
  input logic reset_n,
  input logic clk,
    
  // Avalon ST output
  output logic ready_out,		
    
  // Avalon ST input
  input logic in_vld,
  input logic in_sop,
  input logic in_eop,
  input logic [WIDTH-1:0] in_data, // WIDTH = data width of Avalon ST
  input logic [4:0] in_eop_pos,

and I have to create a output packet:

  // output packet
  // a business message contain max 1500 bytes, so it will be fit into WIDTH * 48 bits
  output logic [WIDTH*SIZE-1:0] msg_packet

I know I have to create a FSM for message decoding.

I created it and I used ModelSim to simulate it and seems everything work fine.

  typedef struct {
    logic[DATA_WIDTH-1:0] data;
    logic[4:0]   eop_pos;
  } in_packet;

  in_packet in_packets[$];
  in_packet the_packet;

  always_ff @(posedge clk or negedge reset_n) begin
    $strobe("%g\tstate=%b, in_packet.size=%2d", $time, state, in_packets.size());
	....
      if (in_vld) begin
        // add in_data to queue
	// I am using blocking assignment here
        the_packet.data = in_data;
        the_packet.eop_pos = in_eop_pos;
        in_packets.push_back(the_packet);
      end
	....
  end

You can checkout it from eda playground:
avalon fsm (va) - EDA Playground

However, there is one thing I am not sure.

All HDL tutorials teach us not to use blocking assignment inside flip flop.

What if I want to add data to queue inside flip flop? I use blocking assignment here.

Am I correct? What’s the appropriate way to push_back queue inside flip flop?

Regards,
Ken

In reply to Ken Tsang:

Is the code with the queue supposed to go into the FPGA(synthesized), or is it being used to test the FPGA? Some synthesis tools do not support queue arrays.

The rule about block assignments in flip-flop (always) blocks is slightly more involved. It’s OK to use a blocking assignment to a variable if the variable is only used within the block. You need to use non-blocking assignments when one block writes and another block reads the same variable, and both blocks are synchronized to the same clock. This prevents simulation races because the block that reads needs a guarantee that it gets the old value.

In reply to dave_59:

Thanks to your reply.

As I said I am new to systemverilog and fpga. It seems that many features of systemverilog (verification) are not synthesized into fpga. (failure when compiling the design).

I am using altera quartus II 16.1. Here is a list of compilation failures I found :

  1. stream operator
shortint msg_size;
{>>msg_size} = {<<8{in_data[pos-:16]}};

How to get first 16 bits data from in_data as shortint in a synthesizable way?

  1. dynamic array
typedef struct {
  byte no_entries;
  int data[];
} mystruct;
function automatic mystruct get_mystruct(ref logic[4095:0] in_data, input int pos) ;
  static mystruct;
  mystruct.no_entries = get_short(in_data, pos);
  mystruct.data = new[mystruct.no_entries]; // set array size at runtime, it is not supported
  for (int i = 0 ; i < mystruct.no_entries ; i++) begin
    mystruct.data[i] = get_int(int_data, pos);
  end
  return mystruct
endfunction


How to create a synthesizable dynamic array? any workaround?

  1. queue
mystruct mystruct_var[$]; // not support in qurtus II

any generic queue module example?

In reply to Ken Tsang:

There is no dynamic memory in hardware. This probably the wrong forum to learn how to write RTL code for synthesis. There are many textbooks and websites on writing RTL.