Veridian
Veridian

Reputation: 3667

Declaring Variable in Verilog with Indexing that doesn't start at zero

I am using this wire declaration in Verilog:

wire [23:15] myvar;

My code works and I have seen this coding style before, but I am not sure what is actually happening, I can only guess that a wire that is 9 bits wide is getting declared. Is that what is happening? I wanted to read more on this online, but i didn't know what this is called, so apologies for the simplistic question.

Upvotes: 1

Views: 4057

Answers (2)

sharvil111
sharvil111

Reputation: 4381

Verilog is a Hardware Descriptive Language(HDL). Whatever you write/declare, ultimately turns out to be a form of hardware.

Lets have a look at the image below:

wire indexing

Here, declaring wire [23:15] myvar; or wire [8:0] myvar; declares the same bunch of wires, nine bits wide. Its just the indexing part that differs. No matter you call it as a[0] (when a is wire [8:0] a) or a[15] (when a is wire [23:15] a). The coding part is different according to the ease for programmer, while synthesis part remains the same.

Also, note that in former case, myvar[15] is the least significant bit while latter has myvar[0] as the LSB. We can swap the declarations part, which shall swap the MSB-LSB too.

reg  [7:0] reg1;    // 8-bit vector with MSB=7 LSB=0
reg  [0:7] reg2;    // 8-bit vector with MSB=0 LSB=7
// ...
// ...
reg1 = 8'hF0; // reg1[7] = 1 and reg1[0] = 0 ultimately, reg1 = F0
reg2 = 8'hF0; // reg2[7] = 0 and reg2[0] = 1 ultimately, reg2 = F0

Lets take an example:

wire [23:15] myvar;
reg [23:15] reg2;
reg [31:0] reg3;
initial begin
    $monitor("myvar = %0h myvar2 = %0h reg3 = %0h",myvar,myvar2,reg3);
    reg3 = 32'h5ABC_FEDC;

// This will correctly assign values to reg2, since it is [23:15]
    for(int i=16;i<20;i++)
      begin
      reg2[i] = myvar[i];
        $display("1: reg2[%0d] = %0h myvar[%0d] = %0h",i,reg2[i],i,myvar[i]);
      end

// While, this will not assign correctly, 
// since reg2 does not have [5:0] indexes,neither does myvar
    for(int i=0;i<5;i++)
      begin
      reg2[i] = myvar[i];
        $display("2: reg2[%0d] = %0h myvar[%0d] = %0h",i,reg2[i],i,myvar[i]);
      end
  end

Another alternative is that your reg is [8:0] while wire is [23:0]. Here is all that matters, but just in the coding part. Note that in the first snippet below, values are assigned to reg1[4:0] and in the second snippet, it is in the range reg1[20:15].

reg [8:0] reg1;
wire [23:15] myvar;
// Correct, since LSB of myvar is at index position 15
    for(int i=0;i<5;i++)
      begin
        reg1[i] = myvar[i+15];
        $display("3 : reg1[%0d] = %0h myvar[%0d] = %0h",i,reg1[i],i,myvar[i+15]);
      end

reg [31:0] reg1;
wire [23:15] myvar;
// reg1[19:15] is assigned here
for(int i=15;i<20;i++)
      begin
        reg1[i] = myvar[i];
        $display("4 : reg1[%0d] = %0h myvar[%0d] = %0h",i,reg1[i],i,myvar[i]);
      end

So, in the end, just some slicing differs while driving from the wire, no effect on the actual hardware. More information can be obtained from Verilog Syntax Details link.

Upvotes: 4

dave_59
dave_59

Reputation: 42658

You are correct that you are declaring a 9-bit wire. Many designs have different ideas about what the LSB and MSB values should be, which direction the index numbering should go in. It really doesn't matter what use for index values until you start referencing individual bit or slices.

Upvotes: 2

Related Questions