Search code examples
verilogsystem-verilog

Order of bits in reg declaration


If I need to use 4 8-bit numbers, I would declare the following reg:

reg [7:0] numbers [3:0]

I'm quite confused about the difference between the first and second declaration ([7:0] and [3:0]). In what order should they come? Does first one stay for the size of a number while the second is for the number of numbers, or vice versa? And, does [7:0] or [0:7] give the right order?

Ordinary arrays of numbers look like this, for example:

0000
0110
0001

There are three 4-bit numbers (0000, 0110, 0001). We can access them by using array indices. So, accessing the first digit of the second number is done by something like this

a[0][1]

assuming that this array is stored in a variable a.

Returning to Verilog, how would accessing elements change if I would swap values in reg or declare them in reverse order ([0:7]), for example?


Solution

    1. reg[7:0] is an 8-bit "register", or variable
    2. reg[7:0] numbers[3:0] is a 1-D array with 4 elements, named numbers, each of which is an 8-bit register
    3. An element of numbers is accessed as numbers[index]
    4. numbers[i][j] is a bit-select of numbers[i]. It accesses bit j in the ith element of numbers
    5. As toolic says, it's more conventional for array indices to be numbered [lsb:msb], but there's no good reason for this.

    When assigning two objects, bits are copied left-to-right, as for VHDL.

    Verilog has (very) poor checking of bit and part selects and array indexes. See the code below.

    module top;
       initial
         test;
       task test;
          reg[3:0] a[0:1];
          reg[0:3] b[0:1];
          reg[2:5] c[0:1];
          begin
           a[0] = 4'b1101;
           a[1] = 4'b0110;
           a[2] = 4'b0001;                      // error, but not caught by Verilog
    
           $display("a[2] is %d", a[2]);        // modelsim produces no warning, prints 'a[2] is x'
           $display("a[0][4] is %b", a[0][4]);  // modelsim warns, and prints 'a[0][4] is x'
    
           $display(                            // produces '1.1.0.1'
             "a[0][3:0] is %b.%b.%b.%b", a[0][3], a[0][2], a[0][1], a[0][0]);
    
           b[0] = a[0];                         
           $display("b[0] is %d", b[0]);        // produces '13'
           $display(                            // produces '1.1.0.1'
             "b[0][0:3] is %b.%b.%b.%b", b[0][0], b[0][1], b[0][2], b[0][3]);
    
           c[0] = a[0];                         
           $display("c[0] is %d", c[0]);        // produces '13'
           $display(                            // produces '1.1.0.1'
             "c[0][2:5] is %b.%b.%b.%b", c[0][2], c[0][3], c[0][4], c[0][5]);
         end
       endtask
    endmodule