Whenever it is tedious to encode a repeating pattern, you should use the generate statement:
module array_multiplier(a, b, y); parameter width = 8; input [width-1:0] a, b; output [width-1:0] y; wire [width*width-1:0] partials; genvar i; assign partials[width-1 : 0] = a[0] ? b : 0; generate for (i = 1; i < width; i = i+1) begin:gen assign partials[width*(i+1)-1 : width*i] = (a[i] ? b << i : 0) + partials[width*i-1 : width*(i-1)]; end endgenerate assign y = partials[width*width-1 : width*(width-1)]; endmodule
I checked this module using the following test stand: http://svn.clifford.at/handicraft/2013/array_multiplier/array_multiplier_tb.v
EDIT:
As @Debian asked for the pipelined version - here it is. This time using a for loop in the always-scope for part of the array.
module array_multiplier_pipeline(clk, a, b, y); parameter width = 8; input clk; input [width-1:0] a, b; output [width-1:0] y; reg [width-1:0] a_pipeline [0:width-2]; reg [width-1:0] b_pipeline [0:width-2]; reg [width-1:0] partials [0:width-1]; integer i; always @(posedge clk) begin a_pipeline[0] <= a; b_pipeline[0] <= b; for (i = 1; i < width-1; i = i+1) begin a_pipeline[i] <= a_pipeline[i-1]; b_pipeline[i] <= b_pipeline[i-1]; end partials[0] <= a[0] ? b : 0; for (i = 1; i < width; i = i+1) partials[i] <= (a_pipeline[i-1][i] ? b_pipeline[i-1] << i : 0) + partials[i-1]; end assign y = partials[width-1]; endmodule
Note that with many synthesis tools, you can also simply add (width) logging steps after the non-pipeline adder and allow the balancing tool to perform pipelining.
source share