Wednesday 2 August 2017

Packed Array index selection in system verilog

Array part selection syntax is bit confusing in system verilog and sometimes it requires to make an example to recall it. To avoid it, an example is shown below which helps to understand the address part selection of packed array.
Let's understand it from an example:

Example:
module top();
  bit [15:0] a_msb;
  bit [0:15] a_lsb;

  initial begin
    a_msb = 'h8465;
    a_lsb = 'h8465;
    $display("O0: *******************");
    $display("a_msb=%0h(%0b), \na_lsb=%0h(%0b)",a_msb,a_msb,a_lsb,a_lsb);

    $display("O1: *******************");
    $display("a_msb[7:0]=%08b, a_lsb[0:7]=%08b",a_msb[7:0], a_lsb[0:7]);
    $display("a_msb[15:8]=%08b, a_lsb[8:15]=%08b",a_msb[15:8], a_lsb[8:15]);

    $display("O2: *******************");
    for(int i = 0; i < 16; ++i) begin
      $display("a_msb[%0d]=%0b, a_lsb[%0d]=%0b",i,a_msb[i],i,a_lsb[i]);
    end

    $display("O3: *******************");
    for(int sel = 0; sel < 2; ++sel) begin
      $display("a_msb[%0d +: 8]=%08b",8*sel,a_msb[8*sel +: 8]);
      $display("a_lsb[%0d +: 8]=%08b",8*sel,a_lsb[8*sel +: 8]);
    end

    $display("O4: *******************");
    for(int sel = 2; sel > 0; --sel) begin
      $display("a_msb[%0d -: 8]=%08b",(8*sel - 1),a_msb[(8*sel - 1) -: 8]);
      $display("a_lsb[%0d -: 8]=%08b",(8*sel - 1),a_lsb[(8*sel - 1) -: 8]);
    end
  end
endmodule

As shown in the above example, 2 fields (a_msb and a_lsb) of 16 bits width are declared. In a_msb, the MSB is 15 and in a_lsb, MSB is 0. In both fields, 'h8465 value is stored. While printing both variables without indexing, it prints same (Ref Output: O0). 

But the indexing of both fields are different to each other. It means while accessing the index value of both variables, output will be different (Ref Output: O1). The reason behind it is the MSB and LSB are different for both variables. As a_msb's lsb bit is 0, 'h5 is stored on location [3:0]. On other hand, a_lsb's lsb bit is 15, so 'h5 is stored on location [12:15]. Similarly, other values are stored on different index and same is reflected in Output O1 and O2.

As shown in Output O3, index part selection is taken care automatically by system verilog. By comparing Output O2 with Output O3 and O4, we can say that
a_msb[7:0] = a_msb[0 +: 8] = a_msb[7 -: 8] and
a_lsb[0:7]   = a_lsb[0 +:8]    = a_lsb[7 -: 8]

Output:
O0: *******************
a_msb=8465(1000010001100101), 
a_lsb=8465(1000010001100101)

O1: *******************
a_msb[7:0]=01100101, a_lsb[0:7]=10000100
a_msb[15:8]=10000100, a_lsb[8:15]=01100101

O2: *******************
a_msb[0]=1, a_lsb[0]=1
a_msb[1]=0, a_lsb[1]=0
a_msb[2]=1, a_lsb[2]=0
a_msb[3]=0, a_lsb[3]=0
a_msb[4]=0, a_lsb[4]=0
a_msb[5]=1, a_lsb[5]=1
a_msb[6]=1, a_lsb[6]=0
a_msb[7]=0, a_lsb[7]=0
a_msb[8]=0, a_lsb[8]=0
a_msb[9]=0, a_lsb[9]=1
a_msb[10]=1, a_lsb[10]=1
a_msb[11]=0, a_lsb[11]=0
a_msb[12]=0, a_lsb[12]=0
a_msb[13]=0, a_lsb[13]=1
a_msb[14]=0, a_lsb[14]=0
a_msb[15]=1, a_lsb[15]=1

O3: *******************
a_msb[0 +: 8]=01100101
a_lsb[0 +: 8]=10000100
a_msb[8 +: 8]=10000100
a_lsb[8 +: 8]=01100101

O4: *******************
a_msb[15 -: 8]=10000100
a_lsb[15 -: 8]=01100101
a_msb[7 -: 8]=01100101
a_lsb[7 -: 8]=10000100