Append logic vector to vector

I created a function for appending in_data (with in_data_offset) to out_data (at position out_data_pos)

// expected out data : xxxx1234abcdxxxx000000000000000000000000000000000000000000000000
// actual out data___: xxxxabcdxxxx0000000000000000000000000000000000000000000000000000

Please kindly advise.


module testbench();
  
  logic[255:0] in_data;
  logic[255:0] out_data;
  shortint in_data_offset;
  shortint out_data_pos;
 
  function void slice(ref logic[255:0] in_data, ref logic[255:0] out_data, shortint in_data_offset, shortint out_data_pos);
    out_data[255-out_data_pos-:256] = in_data<<in_data_offset;
  endfunction
  
  initial begin
    $display("start...");
    
    in_data = {24'h0, 32'h1234abcd, 16'hxxxx, 184'h0};
    in_data_offset = 24;
    out_data_pos = 16;
    $display("in_data = %h", in_data);
    
    slice(in_data, out_data, in_data_offset, out_data_pos);    
    $display("out_data = %h", out_data);
    
  end
  
endmodule

In reply to Ken Tsang:

x +: N, The start position of the vector is given by x and you count up from x by N
x -: N, in this case, the start position is x and you count down from x by N
N is a constant and x is an expression that can contain iterators

this is an example from LRM, I think your mess up this syntax


logic [31: 0] a_vect;
logic [0 :31] b_vect;
logic [63: 0] dword;
integer sel;
a_vect[ 0 +: 8] // == a_vect[ 7 : 0]
a_vect[15 -: 8] // == a_vect[15 : 8]
b_vect[ 0 +: 8] // == b_vect[0 : 7]
b_vect[15 -: 8] // == b_vect[8 :15]
dword[8*sel +: 8] // variable part-select with fixed width

if you want to append in_data (with in_data_offset) to out_data (at position out_data_pos)
it should be like this


function void slice(ref logic[255:0] data, ref logic[255:0] out_data, input shortint in_data_offset, input shortint out_data_pos);
    out_data = in_data<<in_data_offset; // shift in_data
    out_data <<= out_data_pos; // start from this position
endfunction

In reply to javatea:

Thanks to your hints.

  function automatic void slice(ref logic[255:0] in_data, ref logic[255:0] out_data, input shortint in_data_offset, input shortint out_data_pos);
    
    out_data = in_data<<in_data_offset; // shift in_data
    out_data >>= out_data_pos; // start from this position
  endfunction

It works but it will loss the original first n bits (up to out_data_pos):

before in_data  = 2222221234abcdxxxx0000000000000000000000000000000000000000000000
before out_data = eeeexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
after  out_data = 00001234abcdxxxx000000000000000000000000000000000000000000000000
expected        = eeee1234abcdxxxx000000000000000000000000000000000000000000000000

Finally I use for-loop. It works but I want to learn a bit-shifting way. Please advise.

  function automatic void slice(ref logic[255:0] in_data, ref logic[255:0] out_data, input shortint in_data_offset, input shortint out_data_pos);
    /*
    out_data = in_data<<in_data_offset; // shift in_data
    out_data >>= out_data_pos; // start from this position
    */

    // filling out_data_pos up to last bit with in_data with offset
    for (int i = 255 - out_data_pos ; i >= 0 ; i--) begin
      int t = i + out_data_pos - in_data_offset;
      if (t >= 0 || t <= 255) begin
        out_data[i] = in_data[t];
      end
    end
    
  endfunction

In reply to Ken Tsang:

your code has some issue, you need to handle out_data_pos greater or less than in_data_offset.

the out_data has 'hx in tail.
before in_data = 2222221234abcdxxxx0000000000000000000000000000000000000000000000
before out_data = eeeexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
after out_data = eeee1234abcdxxxx0000000000000000000000000000000000000000000000xx (unknown)

As I mentioned, N has to be a CONSTANT, x allows variable.
i.g. fixed value or parameter size 10 for N … etc. this is LRM
x +: N, The start position of the vector is given by x and you count up from x by N
x -: N, in this case, the start position is x and you count down from x by N

Unless some compiler supports this new feature/request.

To meet your requirements, try this:


function automatic void slice( 
  ref logic[255:0] in_data, 
  ref logic[255:0] out_data, 
  input shortint in_data_offset,
  input shortint out_data_pos);
    
    // support out_data_pos from 0 ~ 254 and 255
    bit [255:0] mask = ((1 << out_data_pos) - 1) << (255 - out_data_pos + 1);    
    if (out_data_pos == 255) return; 
    out_data = (out_data & mask) | 
               ((in_data << in_data_offset) >> out_data_pos);  
              
endfunction