catalogue
2.2.2Vectors in more detail(Vector1)
2.2.3Vector part select(Vector2)
2.2.4Bitwise operators(Vectorgates)
2.2.6Vector concatenation operator(Vector3)
2.2.7Vector reversal 1(Vectorr)
2.2.8Replication operator(Vector4)
2.2.9More replication(Vector5)
preface
HDLbits website is as follows
Problem sets  HDLBits (01xz.net)
Starting from this issue, we continue to study the second chapter of Verilog Language of HDLbits. The content of this issue is 2.2 vectors
2.2.1Vectors(Vector0)
Vector uses a name to group related signals for operation. For example, wire [7:0] w; An 8bit vector named w is defined, which is equivalent to defining 8 independent wire signals.
Please note that the declaration of a vector places the dimension before the vector name, which is different from the syntax of C language. However, when selecting a bit, it is similar to the array in C language.
wire [99:0] my_vector; // Declare a vector of 100 elements
assign out = my_vector[10]; // Select a bit in the vector
Build a 3bit input circuit, and then output the same vector. In addition, split it into three separate 1bit outputs, connect the output o0 with the 0 bit of the output vector, connect the output o1 with the 1 bit of the output vector, and so on.
In the chart, a slash with a number next to it indicates the width of the vector (or bus), rather than drawing each wire in the vector separately.
Create a single input and single output module, which is wire type.
Solution:
module top_module( input [2:0] vec, output [2:0] outv, output o2, output o1, output o0 ); assign outv = vec; // This is ok too: assign {o2, o1, o0} = vec; assign o0 = vec[0]; assign o1 = vec[1]; assign o2 = vec[2]; endmodule
Also for simplicity, you can use assign {o2, o1, o0} = vec;
2.2.2Vectors in more detail(Vector1)
Vector uses a name to group related signals for operation. For example, wire [7:0] w; An 8bit vector named w is defined, which is equivalent to defining 8 independent wire signals.
Declaring Vectors
The vector must be declared as follows:
type [upper:lower] vector_name;
Type specifies the data type of the vector. Usually wire or reg. If you want to declare an input or output port, type can include additional port types (such as input or output). Here are some examples:
wire [7:0] w; // 8bit wire reg [4:1] x; // 4bit reg output reg [0:0] y; // 1bit reg that is also an output port input wire [3:2] z; // 6bit wire input (negative range is also allowed, [3:  2], i.e. 3, 2, 1, 0,  1,  2) output [3:0] a; // 4bit output wire. Unless otherwise specified, the default type is wire wire [0:7] b; // 8bit wire, where b[0] is the most important bit
The byte order (or "direction" in common) of a vector refers to whether the least significant bit has a lower index (small end order, such as [3:0]) or a higher index (large end order, such as [0:3]). In Verilog, once a vector is declared with a specific byte order, it must be used in the same way, for example, when wire [3:0 vec] is declared; After that, it is illegal to use vec[0:3]. It is a good practice to use consistent with the byte order, because strange errors will occur if vectors of different byte order are allocated or used together.
Implicit nets
Implicit nets are often a source of undetectable errors. If an undeclared vector appears / is referenced in an assign statement or an undeclared module, implicit nets will be implicitly generated in the module. Implicit nets is generally a wire variable. If it is used as a vector, it is likely to report an error. Instructions can be used
`default_nettype none
To disable the creation of Implicit nets.
wire [2:0] a, c; // Two vectors assign a = 3'b101; // a = 101 assign b = a; // B = 1 implicitly created wire assign c = b; // c = 001 < bug my_module i1 (d,e); // d and e are implicitly onebit wide if not declared. //(both d and e are implicitly declared as 1bit wire) // This could be a bug if the port was intended to be a vector. //If the module needs a vector, a bug occurs
add to ` default_nettype none Will cause the code to appear ERROR.
Unpacked vs. Packed Arrays
Vector bit width is usually declared before the vector name. The bit width represents the "packed" dimension of the vector, and each signal operates together (this is related to the simulator, but different from the hardware). The unpacked dimension is defined after the vector name. They are often used to declare vector arrays.
reg [7:0] mem [255:0]; // 256 unpacked elements, each of which is a 8bit packed vector //of reg. (there are 256 unpacked elements, each of which is an 8bit packdreg vector) reg mem2 [28:0]; // 29 unpacked elements, each of which is a 1bit reg.
Accessing Vector Elements: PartSelect
Accessing the entire vector is done with the vector name. For example: assign w = a;
Assign the 4bit vector a to the 8bit vector w (all declarations are described above). If the length of the left operand is different from that of the right operand, it will complement 0 or truncate as needed.
The partial selection operator can be used to access a portion of the vector:
w[3:0] // Only the lower 4 bits of w x[1] // The lowest bit of x x[1:1] // ...also the lowest bit of x z[1:2] // Two lowest bits of z b[3:0] // Illegal. Vector partselect must match the direction of the declaration. //Illegal operation. b when used, the byte order is opposite to that when declared b[0:3] // The *upper* 4 bits of b assign w[3:0] = b[0:3]; // Assign upper 4 bits of b to lower 4 bits of w. w[3]=b[0], //w[2]=b[1], etc. (assign the upper four bits of b to the lower four bits of w)
A Bit of Practice:
Construct a combinational circuit, divide the input 16 bit signal into high eight bits and low eight bits, and output them respectively.
Solution:
module top_module ( input [15:0] in, output [7:0] out_hi, output [7:0] out_lo ); assign out_hi = in[15:8]; assign out_lo = in[7:0]; // Concatenation operator also works: assign {out_hi, out_lo} = in; endmodule
Also for simplicity, you can use join operators assign {out_hi, out_lo} = in;
2.2.3Vector part select(Vector2)
A 32bit vector is considered to contain 4 bytes ([31:24], [23:16], etc.). A circuit is constructed to reverse the byte order of the 4byte vector.
AaaaaaaaBbbbbbbbCcccccccDddddddd => DdddddddCcccccccBbbbbbbbAaaaaaaa
This operation is usually used when the byte order of a piece of data needs to be exchanged, such as between the small end x86 system and the large end format used in many Internet protocols.
Solution:
module top_module( input [31:0] in, output [31:0] out ); assign {out[31:24],out[23:16],out[15:8],out[7:0]} = {in[7:0],in[15:8],in[23:16],in[31:24]}; endmodule
Hints: in the assign statement, slice selection can be used on the left or right.
Rational use of join operators can make the code more readable.
2.2.4Bitwise operators(Vectorgates)
Two three bit input circuits are constructed to output the bit or, logical or and inverse of two vectors respectively. Put the inverse of b in out_ The upper three bits of not (bits[5:3]), and the inverse of a is set to out_not third.
Bitwise vs. Logical Operators
As mentioned earlier, there are bitwise and logical operations of various Boolean operators (see 2.1.5). For a 1bit wire signal, the functions of the two operations are the same. However, when operating on vectors, the difference between the two operator types becomes very important!
Bitwise operator: bitwise operation between two Nbit vectors copies the operation of each bit in the vector and produces nbit output.
Logical operator: treat the entire vector as a Boolean value (nonzero is true, zero is false) and produce one bit output.
Check the simulation waveform to understand the difference between bitwise OR and logical or.
Solution:
module top_module( input [2:0] a, input [2:0] b, output [2:0] out_or_bitwise, output out_or_logical, output [5:0] out_not ); assign out_or_bitwise = a  b; assign out_or_logical = a  b; assign out_not[2:0] = ~a; // Partselect on left side is o. assign out_not[5:3] = ~b; //Assigning to [5:3] does not conflict with [2:0] //Assignment to [5:3] and [2:0] does not conflict endmodule
Hints: even if you can't assign a value to the wire signal multiple times, you can select the left side of the assign statement. You don't want to assign all to the entire vector in another statement.
Like C language, Verilog has bitwise OR () and logical or (). In some cases, it is better to use logical operation for Boolean expression and bit operation for signal processing.
2.2.5Fourinput gates(Gates4)
Construct a 4input (in[3:0]) combinational circuit.
There are three outputs:
 out_and:4 input and gate output
 out_or: 4 input or output of gate
 out_ XOR: output of 4input XOR gate
Solution:
module top_module( input [3:0] in, output out_and, output out_or, output out_xor ); assign out_and = in[3]&in[2]&in[1]&in[0]; assign out_or = in[3]in[2]in[1]in[0]; assign out_xor = in[3]^in[2]^in[1]^in[0]; endmodule
Another way is to use the reduction operator, which has only one operand.
assign out_ and = ∈ Equivalent to assign out_ and = in[3]&in[2]&in[1]&in[0];
2.2.6Vector concatenation operator(Vector3)
The slice selection operation is used to select the part of the vector. The join operator {a,b,c} is used to create a larger vector by joining smaller parts of the vector together.
{3'b111, 3'b000} => 6'b111000 {1'b1, 1'b0, 3'b101} => 5'b10101 {4'ha, 4'd10} => 8'b10101010 // 4'ha and 4'd10 are both 4'b1010 in binary // 4'ha and 4'd10 are binary 4'b1010
The join operator needs to know the width of each member (how else do you know the width of the result?). Therefore, {1,2,3} is illegal and will generate ERROR: the connection operator does not allow constants of undetermined size!
Join operators can be used as left and right sides of assignment statements.
input [15:0] in; output [23:0] out; assign {out[7:0], out[15:8]} = in; // Swap two bytes assign out[15:0] = {in[7:0], in[15:8]}; //ditto assign out = {in[7:0], in[15:8]}; // This is different from the previous. The 16 bit vector on the right expands to match the 24 bits on the left //Vector, so out[23:16]=0 //In the first two examples, out[23:16] is not assigned
A Bit of Practice:
Connect some input vectors together and re divide them into different output vectors. 5 input vectors: a, b, c, d, e and f, with 30 bits in total. w. x, y, z are all 8bit output vectors. The output should be the connection of the input vector, where the last two bits are 11
Solution:
module top_module ( input [4:0] a, b, c, d, e, f, output [7:0] w, x, y, z );// assign {w,x,y,z} = {a,b,c,d,e,f,2'b11}; endmodule
2.2.7Vector reversal 1(Vectorr)
Reverse the order of the 8bit vector and output it.
Solution:
module top_module( input [7:0] in, output [7:0] out ); assign {out[0],out[1],out[2],out[3],out[4],out[5],out[6],out[7]} = in; endmodule
Hint:
 assign out[7:0] = in[0:7]; It doesn't work because the bit order when Verilog uses vectors should be consistent with the definition
 One assign statement can be used for connection operators, which is more concise than eight
***Supplementary content***
I know you'd love to know how to do this using circular statements:
Build a composite always block. This creates combinatorial logic that evaluates the same results as the sequential code. The for loop describes the circuit at the behavior level, not the structure level. Therefore, they can only be used in program blocks (such as the always block). The circuits created (wire s and gates) do not require any iteration: it only produces the same results as when the iteration occurs. In fact, the logic synthesizer iterates at compile time to determine what circuit to generate. (in contrast, the Verilog emulator will execute loops sequentially during the simulation.)
always @(*) begin for (int i=0; i<8; i++) // int is the type of SystemVerilog, and integer is used in pure Verilog out[i] = in[8i1]; end
This can also be done using the generate for loop. The generate loop looks like a programmatic for loop, but it is conceptually very different and not easy to understand. Generate loops are used to instantiate "things" (unlike program loops, which do not describe actions). These "things" are assign statements, module instantiations, net/variable declarations, and procedure blocks (not created in procedures). The generate loop (and genvars) is evaluated entirely at compile time. You can think of the generate block as a form of preprocessing that generates more code and then runs it through the logic synthesizer. In the following example, the generate for loop first creates eight assign statements at compile time, and then synthesizes them. Note that due to its intended use (generating code at compile time), there are some restrictions on how to use them.
For example: 1. In Quartus, you need a generate for loop to attach a named begin and block (in this case, it is called "my_block_name"). 2. In the circulatory system, genvars are readonly.
generate genvar i; for (i=0; i<8; i = i+1) begin: my_block_name assign out[i] = in[8i1]; end endgenerate
The translation of this topic is stumbling. I hope I can come back and optimize it in the future!
2.2.8Replication operator(Vector4)
In the 2.2.6 concatenation operator, concatenation operators concatenate vectors to form larger vectors. But for connecting the same vectors together, use
a = {b,b,b,b,b,b};
It's too boring. The copy operator can repeat a vector and connect them together:
{num{vector}} Copy the vector num times, Num must be a constant. And you need two sets of braces!
{5{1'b1}} // 5'b11111 (or 5'd31 or 5'h1f) {2{a,b,c}} // Equivalent to {a,b,c,a,b,c} {3'd5, {2{3'd6}}} // 9'b101_110_110. It is the connection between the first vector and two second vectors
A Bit of Practice:
The common use of the copy operator is to expand a smaller signed number to a larger number while retaining its sign bit. This is done by copying the sign bit (most significant bit) of the smaller number to the left. For example, 4'b0101 (5) 8'b00000101 extended to 8bit (5) , and 4'b1101 (3) 8'b11111101 extended to 8bit (3).
Build a circuit that extends 8bit symbol bit to 32bit. This requires connecting copies of 24 symbol bits (i.e., copying bits [7] 24 times), followed by the 8bit number itself.
Solution:
module top_module ( input [7:0] in, output [31:0] out );// assign out = {{24{in[7]}},in[7:0]}; // assign out = { replicatesignbit , theinput }; endmodule
Note that the copy operator requires two sets of braces!!!
2.2.9More replication(Vector5)
For five 1bit signals (a, b, c, d, e), the comparison calculation of each bit is output respectively. If the two compared bits are equal, 1 is output (i.e. the same or operation).

out[24] = ~a ^ a; // a == a, so out[24] is always 1. out[23] = ~a ^ b; out[22] = ~a ^ c; ... out[ 1] = ~e ^ d; out[ 0] = ~e ^ e;
As shown in the figure above, using the copy and join operators will be easier.
 The above vectors are copied 5 times for each input, and then connected together
 The following vector connects five inputs together and then copies them five times
Solution:
module top_module ( input a, b, c, d, e, output [24:0] out ); wire [24:0] top, bottom; assign top = { {5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}} }; assign bottom = {5{a,b,c,d,e}}; assign out = ~top ^ bottom; // Bitwise XNOR // It can be replaced by the following line (but it is much less readable) // assign out = ~{ {5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}} } ^ {5{a,b,c,d,e}}; endmodule
In fact, it's OK to clarify the order of copy and connection. In addition, the copy operator needs two sets of braces!
2.2 it's finally over. The translation of this issue is stumbling. I hope I can get a different harvest in the future. See you next time!