SystemVerilog — multiplication in indexed-part select is usually poor style — v[W*idx+:W]

In old Verilog, there were no multidimensional module ports, so to index into a vector of words you were forced to write obfuscated code like the assignment in the following SystemVerilog example

  module test#(N=64,W=16)
  (  output [W-1:0] out
  ,  input [N*W-1:0] in
  ,  input [$clog2(N)-1:0] idx
  );
    assign out = in[W*idx+:W];
  endmodule

But in SystemVerilog you can simply write

  module test#(N=64,W=16)
  (  output [W-1:0] out
  ,  input [N-1:0][W-1:0] in
  ,  input [$clog2(N)-1:0] idx
  );
    assign out = in[idx];
  endmodule

If the port connection uses a legacy vector not declared in the multidimensional style, it doesn’t matter, because the two styles are interassignable. You can use that fact if your coding rules prohibit multidimensional ports (to guarantee the port naming) by adding just one more line of code.

  module test#(N=64,W=16)
  (  output [W-1:0] out
  ,  input [N*W-1:0] in
  ,  input [$clog2(N)-1:0] idx
  );
    wire [N-1:0][W-1:0] in_array = in;
    assign out = in_array[idx];
  endmodule

In SystemVerilog a multiplication in an indexed-part select is almost never needed. If you see it in a code review, please don’t accept “because that’s the way I’ve always done it” as a justification for code that’s harder to read, easier to get wrong, and often less efficient.

Advertisements

2 Comments

  1. It’s important to mention, what you describe here assumes declarations as packed arrays. Does this scheme work if you have arrays of interfaces or structures? I am asking.

    Like

    • Good point about vectors where the embedded words are structs. (Interfaces couldn’t be embedded that way. Also, arrays of interfaces are not dynamically addressable.)

      If you’re forced to use such vector ports, declare an internal wire or variable as in the final example above and use the bit-stream operator.

      For example, if ST is the struct type, then

         ST in_array[N];
         assign in_array = {>>{in}};
      

      or

         ST out_array[N];
         assign {>>{out}} = out_array;  
      

      and work internally with in_array or out_array.

      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