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.

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.

 Simulation Log
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.

 Simulation Log
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:

Suppose we want to initialize a 16-bit register counter to count from 0 to 15 in a clock cycle. We can use the replication operator to create a bit pattern that represents the binary values 0 to 15, and assign it to the counter register:


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

  always @(posedge clk) begin
    counter <= counter + 1;
  end
  
  // Initialize counter to 0 on reset
  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

In the above example, we use the replication operator {16{1'b0}} to create a 16-bit bit pattern consisting of 16 zeros (1'b0). This initializes the counter register to 0 at the start of the simulation.

 Simulation Log
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.

 Simulation Log
	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 = { {8{1'b1}}, input_num }; // extend with ones
    end else begin // if the sign bit is 0
      output_num = { {8{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.