Multi-bit Verilog wires and variables can be clubbed together to form a bigger multi-net wire or variable using concatenation operators { and } separated by commas. Concatenation is also allowed to have expressions and sized constants as operands in addition to wires and variables.

Size of each operand must be known in order to calculate the complete size of concatenation.

What You'll Learn

  • How the concatenation operator joins signals into a wider value
  • How the replication operator repeats a value, including nested replication
  • How to sign-extend a value with concatenation and replication
  • Illegal uses of concatenation, and other common mistakes

Verilog Concatenation Example


	wire 		a, b; 		// 1-bit wire
	wire [1:0] res; 		// 2-bit wire to store a and b
	
	// res[1] follows a, and res[0] follows b
	assign res = {a, b}; 	
	
	
	wire [2:0] c;
	wire [7:0] 	res1;
	
	// res[0] follows c[2]
	// res[2:1] is always 0
	// res[4:3] follows c[1:0]
	// res[5] follows a
	// res[6] follows b
	assign res1 = {b, a, c[1:0], 2'b00, c[2]};

Here is a working design example of concatenation of inputs to form different outputs. Concatenated expressions can be simply displayed or assigned to any wire or variable, not necessarily outputs.


module des (input [1:0] 	a,
 input [2:0] 	b,
 output [4:0]	out1,
 output [3:0] 	out2 
 );
 
 assign out1 = {a, b};
 assign out2 = {a[1], 2'b01, b[2]};
 
endmodule 

module tb;
 reg [1:0] a;
 reg [2:0] b;
 wire [4:0] out1;
 wire [3:0] out2;
 
 des u0 (a, b, out1, out2);
 
 initial begin
 a <= 0;
 b <= 0;
 
 $monitor("[%0t] a=%b b=%b, out1=%b out2=%b", $time, a, b, out1, out2);
 
 #10 a <= 3;
 #5 b <= 5;
 #10 a <= 2;
 #5 b <= 1;
 
 #10 $finish;
 end
endmodule

Note that out2[2:1] is always a constant 2'b01.

Output
xcelium> run
[0] a=00 b=000, out1=00000 out2=0010
[10] a=11 b=000, out1=11000 out2=1010
[15] a=11 b=101, out1=11101 out2=1011
[25] a=10 b=101, out1=10101 out2=1011
[30] a=10 b=001, out1=10001 out2=1010
Simulation complete via $finish(1) at time 40 NS + 0

Replication Operator

When the same expression has to be repeated for a number of times, a replication constant is used which needs to be a non-negative number and cannot be X, Z or any variable. This constant number is also enclosed within braces along with the original concatenation operator and indicates the total number of times the expression will be repeated.


	wire a;
	wire [6:0] res;
	
	assign res = {7{a}};
	
	{2'bz{2'b0}} // Illegal to have Z as replication constant
	{2'bx{2'b0}} // Illegal to have X as replication constant

Replication expressions cannot appear on the left hand side of any assignment and cannot be connected to output or inout ports.


module des;
 reg [1:0] a;
 reg [2:0] b;
 
 initial begin
 a <= 2;
 b <= 4;
 
 #10;
 $display("a=%b b=%b res=%b", a, b, {{2{a}}, {3{b}}});
 end
 
endmodule

Note that a got repeated twice and b got repeated thrice.

Output
xcelium> run
a=10 b=100 res=1010100100100
xmsim: *W,RNQUIE: Simulation is complete.

Operands will be evaluated only once when the replication expression is executed even if the constant is zero.

The Verilog replication operator {} is commonly used in digital design to create bit patterns for initializing registers, memory arrays, or lookup tables. Here is an example:

For example, a 16-bit counter register can be cleared to zero by replicating a single 0 bit 16 times. The counter below counts up on every clock edge, and its starting value is set with {16{1'b0}}:


module counter(input clk,
 output reg [15:0] counter);

 always @(posedge clk) begin
 counter <= counter + 1;
 end
 
 // Initialize counter to 0 at the start of the simulation
 initial begin
 counter <= {16{1'b0}};
 end

endmodule

Nested Replication

A replication expression is allowed to be used inside regular concatenation expressions. Taking the above example as base, a and b has been included into the total concatenated expression.


module des;
 reg [1:0] a;
 reg [2:0] b;
 
 initial begin
 a <= 2;
 b <= 4;
 
 #10;
 $display("a=%b b=%b res=%b", a, b, {a, b, 3'b000, {{2{a}}, {3{b}}}});
 end
 
endmodule

Here, a and b are concatenated first, followed by 3'b000 and the replicated value from the previous example.

Output
xcelium> run
a=10 b=100 res=101000001010100100100
xmsim: *W,RNQUIE: Simulation is complete.

Illegal usage


 module des;
 reg [1:0] a;
 reg [2:0] b;
 reg [3:0] _var;

 initial begin
 a <= 2;
 b <= 4;
 _var <= 3;

 // This is illegal because variables cannot be used
 // as replication constant
 $display("a=%b b=%b res=%b", a, b, {_var{a}});
 end
 endmodule

This results in a compilation error as shown below.

Output
	Top level design units:
		des
 $display("a=%b b=%b res=%b", a, b, {_var{a}});
 |
xmelab: *E,NOTPAR (./testbench.sv,12|45): Illegal operand for constant expression [4(IEEE)].

Verilog Sign Extension

In Verilog, sign extension is a way of extending a signed number with fewer bits to a wider signed number by replicating the sign bit. Basically, it is used when performing arithmetic or logical operations on numbers with different bit widths.

For example, let's say we have a 4-bit two's complement number, -3, represented as 1101. If we want to add this number to another 8-bit two's complement number, say -10, represented as 11110110, we first need to sign extend the 4-bit number to 8 bits to make it compatible with the 8-bit number. To sign extend the 4-bit number, we replicate its most significant bit (the sign bit) to fill the additional bits, resulting in 11111101. We can then add this sign-extended 4-bit number to the 8-bit number using normal Verilog arithmetic operations.

Here's an example of how to sign extend a 4-bit signed number to an 8-bit signed number in Verilog using concatenation discussed above:


module sign_extension(input signed [3:0] input_num,
 output reg signed [7:0] output_num);

 always @(*) begin
 if (input_num[3] == 1'b1) begin // if the sign bit is 1
 output_num = { {4{1'b1}}, input_num }; // extend with ones
 end else begin // if the sign bit is 0
 output_num = { {4{1'b0}}, input_num }; // extend with zeros
 end
 end

endmodule

In this example, the input is a 4-bit signed number called input_num, and the output is an 8-bit signed number called output_num. The sign bit of the input number is checked, and if it's 1, the output number is extended with ones, otherwise it's extended with zeros.

Note that the syntax for sign extension may vary depending on the specific implementation and tools being used.

Common Beginner Mistakes

Mistake #1: Omitting the Replication Constant

When using the replication operator—a special form of concatenation—beginners often forget that the multiplier must be enclosed in its own set of braces, such as {4{a}}. Writing {4{a}} is correct, but forgetting the outer braces or the count will result in a syntax error.

Mistake #2: Concatenating Unsized Constants

Verilog requires all elements within a concatenation { } to have a strictly defined bit-width. Using an unsized integer like {a, 5} is illegal because the compiler doesn't know if 5 should be 32 bits or 3 bits, leading to unpredictable results or compilation failure. Always use sized literals like {a, 3'b101}.

Mistake #3: Incorrect LSB/MSB Ordering

The concatenation operator fills the resulting bus from left to right: the first signal listed always becomes the most-significant part of the concatenation's own result. Beginners often reverse the intended bit order by writing {lsb, msb} when they meant {msb, lsb}. Note this describes the concatenation itself -- if the destination vector is unusually declared in ascending order (e.g. [0:7] instead of [7:0]), its own bit-numbering determines which physical bit position ends up holding that most-significant part.

Mistake #4: Using Concatenation on the Left-Hand Side (LHS) without Matching Widths

Concatenation is often used on the LHS of an assignment to split a bus or capture a carry bit, such as {carry, sum} = a + b. A common mistake is not ensuring the total number of bits on the LHS exactly matches the width of the RHS expression, which can lead to bits being dropped or unexpected zero-padding.

Best Practice: Use concatenation to make your code more readable when performing bit-swapping or bus-merging. It is much cleaner than using multiple assignment statements for individual bit ranges.

Summary

In this tutorial, you learned:

  • {a, b} joins operands, with the leftmost operand in the most significant bits
  • Every operand of a concatenation needs a known size, so unsized constants are not allowed
  • {n{x}} repeats x exactly n times, and n must be a non-negative constant
  • A replication can be nested inside a concatenation, but cannot be used on the left-hand side of an assignment
  • A concatenation on the left-hand side splits a value, as in {cout, sum} = a + b
  • Sign extension replicates the sign bit in front of the value
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5
Cron Job Starts