Debunked: In SystemVerilog unpacked array dimensions, use downto indexing [N-1:0]

Regarding that a declaration of [N] for a SystemVerilog unpacked array dimension implies upto indexing [0:N-1], I noted here that by instead using the hardware-style downto indexing [N-1:0] you can split/merge dimensions more fluidly. For example,

typedef struct {int x, y;} T;

module test#(N=2,M=3)
(   output T A_2D[(2**N)-1:0][(2**M)-1:0]
,   output T A_1D[(2**(N+M))-1:0]
);

logic [N-1:0] idx_N;
logic [M-1:0] idx_M;

always_comb begin
   for (int i = 0; i < 2**N; i++) begin
     for (int j = 0; j < 2**M; j++) begin
       idx_N = i;
       idx_M = j;
       A_2D[idx_N][idx_M] = '{i,j};
       A_1D[{idx_N,idx_M}] = '{i,j};
       assert final (A_2D[idx_N][idx_M] == A_1D[{idx_N,idx_M}]);
     end
   end
end
 
endmodule:test

But with upto indexing [0:N-1] you’d need to flip the order of dimensions in the indexes, as in

typedef struct {int x, y;} T;

module test#(N=2,M=3)
(   output T A_2D[0:(2**N)-1][0:(2**M)-1]
,   output T A_1D[0:(2**(N+M))-1]
);

logic [N-1:0] idx_N;
logic [M-1:0] idx_M;

always_comb begin
   for (int i = 0; i < 2**N; i++) begin
     for (int j = 0; j < 2**M; j++) begin
       idx_N = i;
       idx_M = j;
       A_2D[idx_N][idx_M] = '{i,j};
       A_1D[{idx_M,idx_N}] = '{i,j};
      assert final (A_2D[idx_N][idx_M] == A_1D[{idx_M,idx_N}]);
     end
   end
end

endmodule:test
Advertisements

2 Comments

  1. You have confused transpose with index-position reversal.

    These ‘assert final’ statements are trivially true by construction. But in the second example the bitstreams of A_2D and A_1D are no longer identical to each other, because you’ve transposed A_2D into A_1D, instead of copying it as you did in the first example.

    The algebra of indexing polynomials does not have the kind of mathematical asymmetry you’re suggesting here. There is no a priori reason to prefer positive to negative strides. Only the choice of 0 as either the origin or anti-origin simplifies the polynomials. If you must work in a language that foists ranged bounds onto all arrays, choose them to best suit the loop indices or semantic uses assigned to each dimension. If you have a choice of language, avoid those with user-defined bounds – they convey nothing you want to know. The very need for loops to build these arrays is appalling to my APL sensibilities.
    To illustrate, your first code computes (using []IO←0)
    A_2D ← (⏀⍳2*N)◦.,⏀⍳2*M and A_1D ← ,A_2D
    and your second example computes
    A_2D ← ( ⍳2*N)◦., ⍳2*M and A_1D ← ,⍉A_2D

    Like

Tell me (anonymous OK)

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s