Arrays are the vector representation of the fundamental datatypes. Arrays can be homogeneous or non-homogeneous . They can also be packed or unpacked . The fundamental difference between packed and unpacked is; that they occupy space in computer differently. Packed is treated as a single continous space of memory, accessed all at the same time, while unpacked is treated as a group of continous segments of memory.
Some common examples of array declarations are given below:-
reg [1:0] A
reg [4] A
reg [0:1] A
wire [3:0] B
reg [1:0][3:0] B
reg C [1:0]
reg [3:0] C [1:0]
wire [3:0][7:0] C [2][2]
reg [3:0] D [1:0][1:0][1:0]
integer E [1:0]
real F [16]
Packed arrays refer to the array declaration where the entirity of the array is treated as a single variable. Indices can still be access individually, but the entire array can also be directly used. Examples of the usage are given below :-
reg [31:0] A
A[1] = 1'b0
A = 32'd100
A[3:2] = 2'd3
$display( "A : %d", A )
Unpacked arrays refer to the array declaration where the array consists of homogenous elements, ie elements of the same datatype. Elements can be accessed using indices, but the entire array cannot be directly used unlike packed arrays. Examples of the usage are given below :-
integer A [3:0]
A[0] = 32'b0
A[1] = 32'd100
A[3:2] = '{ 32'd100, 32'd200 }
$display( "A : %p", A )
$display( "A[1] : %d", A[1] )
Bit-wise part selection is a feature in Verilog that lets you select between a range of bits from an even larger vector. It's an inherited feature in SystemVerilog, so all the rules are the same. It is sometimes also just referred to as " part select ".
To explain it simply; you can use an expression to periodically select a range of bits from a given vector. An expression could mean that you might want to pick 4 bits at a time in an incrementing order from a vector. Or you might want to pick 1 byte at a time in a decrementing order. Either way, this operator is extremely useful in reducing your code length and in some cases, it also improves the readability of your code. There are two kinds of part selects; namely constant and indexed.
Constant Part Select: Here, the expressions inside the address range used in the vector are expressions that ultimately evaluate constants. One additional point is that, if the index is out of bounds, then the output is 'x .
reg [31:0] X; initial begin // vector[ msb_expr : lsb_expr ] X[2**3+1-2:(2**0)+1] = 1; end
Indexed Part Select: In indexed part select, the final range is decided concerning a variable expression for the index and the constant range following it.
reg [31:0] BIG; reg [0:31] LITTLE; integer i; // Used as Index initial begin BIG = $urandom; LITTLE = $urandom; $display( "BIG : %h", BIG ); $display( "LITTLE : %h", LITTLE ); for( i = 0; i < 32/8; i = i + 1 ) begin // big_endian_vector[ lsb_expr +: constant_width ] // The ranges selected will be [7:0], [15:8], [23:16], [31:24] // based on the value of i ( 0 to 3 ) // BIG[ 8*i +: 8 ]; $display( "BIG[ 8*%0d +: 8 ] : %h", BIG[ 8*i +: 8 ] ); // little_endian_vector[ msb_expr +: constant_width ] // The ranges selected will be [0:7], [8:15], [16:23], [24:31] // based on the value of i ( 0 to 3 ) // LITTLE[ 8*i +: 8 ]; $display( "LITTLE[ 8*%0d +: 8 ] : %h", LITTLE[ 8*i +: 8 ] ); // big_endian_vector[ msb_expr -: constant_width ] // The ranges selected will be [31:24], [23:16], [15:8], [7:0] // based on the value of i ( 3 to 0 ) // BIG[ 8*i -: 8 ]; $display( "BIG[ 8*%0d -: 8 ] : %h", BIG[ 8*i -: 8 ] ); // little_endian_vector[ lsb_expr -: constant_width ] // The ranges selected will be [24:31], [16:23], [8:15], [0:7] // based on the value of i ( 3 to 0 ) // LITTLE[ 8*i -: 8 ]; $display( "LITTLE[ 8*%0d -: 8 ] : %h", LITTLE[ 8*i -: 8 ] ); end end
Working Examples: ( You may simulate the following code to cross check the results )
reg [31:0] BIG; reg [0:31] LITTLE; integer i; // Used as Index function get_index_in_8( input integer num ); get_index_in_8 = num*8; endfunction initial begin for( i = 2; i < 4; i = i + 1 ) begin $display( "BIG[ %0d : %0d ] = %0d", (8*(i+1))-1, (8*(i+1))-8, BIG[ 8*i +: 8 ] ); end for( i = 2; i < 4; i = i + 1 ) begin $display( "LITTLE[ %0d : %0d ] = %0d", (8*(i+1))-8, (8*(i+1))-1, LITTLE[ 8*i +: 8 ] ); end for( i = 3; i >= 0; i = i - 1 ) begin $display( "BIG[ %0d : %0d ] = %0d", (8*(i+1))-1, (8*(i+1))-8, BIG[ 8*i-1 -: 8 ] ); end for( i = 3; i >= 0; i = i - 1 ) begin $display( "LITTLE[ %0d : %0d ] = %0d", (8*(i+1))-8, (8*(i+1))-1, LITTLE[ 8*i-1 -: 8 ] ); end $display( "BIG[32] = %0d", BIG[32] ); $display( "BIG[39:32] = %0d", BIG[2*8+:8] ); $display( "LITTLE[32] = %0d", LITTLE[32] ); $display( "LITTLE[39:32] = %0d", LITTLE[2*8+:8] ); // Using a function call to get the index expression $display( "BIG[2*8+:8] = %0d", BIG[get_index_in_8(1)+:8] ); end
module top; integer A[4]; initial begin A = 10; end endmodule
module top; integer ARR[2][2][2][2]; integer i[4]; initial begin for( i[0] = 0; i[0] < 2; i[0] += 1 ) begin for( i[1] = 0; i[1] < 2; i[1] += 1 ) begin for( i[2] = 0; i[2] < 2; i[2] += 1 ) begin for( i[3] = 0; i[3] < 2; i[3] += 1 ) begin ARR[i[0]][i[1]][i[2]][i[3]] = $random; end end end end end endmodule
module top; reg [17:0] NUM; initial begin NUM = {18{1'b1}}; $display( "%d", NUM ); end endmodule
module top; reg [63:0] NUM_PACKED; reg [3:0] NUM_UNPACKED [16]; initial begin NUM_PACKED = {$urandom,$urandom}; $display( "%h", NUM_PACKED ); // Conversion to Unpacked {>>{NUM_UNPACKED}} = NUM_PACKED; $display( "%p", NUM_UNPACKED ); end endmodule
module top; integer NUM; initial begin NUM = {$urandom}; $display( "%h", NUM ); // Printing Index Slices $display( "%d", NUM[3] ); $display( "%h", NUM[3:0] ); end endmodule
module top; integer NUM; initial begin NUM = 0; $display( "%h", NUM ); // Printing The Varibale Aftre assigning x to one bit NUM[7] = 1'bx; $display( "%0h", NUM ); // When printing with %h, inly the slice which has an X will be X, while when printing with %0h, the entire value will be printed as X. $display( "%h", NUM ); $display( "%d", NUM ); $display( "%0d", NUM ); end endmodule
module top; integer NUM; initial begin NUM = $urandom; $display( "%b", NUM ); // Flipping the bits using steaming operator NUM = {<<{NUM}}; $display( "%b", NUM ); end endmodule