横向进位阵列乘法器与 流水线横向进位阵列乘法器 Verilog


本文的知识来源于华中科技大学,谭志虎教授的计算机硬件系统设计,向他致敬
https://www.icourse163.org/course/HUST-1205809816?tid=1467135471

横向进位阵列乘法器

在这里插入图片描述

module lateral_carry_array_multiplier (
	input [4:0] in1,
	input [4:0] in2,

	output [9:0]product
);

wire [4:0] a0;
assign a0 = {5{in2[0]}}&in1;	//in2[0]?in1:0;
wire [4:0] a1;
assign a1 = {5{in2[1]}}&in1;
wire [4:0] a2;
assign a2 = {5{in2[2]}}&in1;
wire [4:0] a3;
assign a3 = {5{in2[3]}}&in1;
wire [4:0] a4;
assign a4 = {5{in2[4]}}&in1;


wire [4:0] cout1;
wire [4:0] sum1;
full_adder  u10 ( .in1 ( a0[1] ),	.in2 ( a1[0] ), .cin ( 0 ), 		.sum ( sum1[0] ), .cout( cout1[0]) );
full_adder  u11 ( .in1 ( a0[2] ), 	.in2 ( a1[1] ), .cin ( cout1[0] ), 	.sum ( sum1[1] ), .cout( cout1[1]) );
full_adder  u12 ( .in1 ( a0[3] ), 	.in2 ( a1[2] ), .cin ( cout1[1] ), 	.sum ( sum1[2] ), .cout( cout1[2]) );
full_adder  u13 ( .in1 ( a0[4] ), 	.in2 ( a1[3] ), .cin ( cout1[2] ), 	.sum ( sum1[3] ), .cout( cout1[3]) );
full_adder  u14 ( .in1 ( 0 ),	 	.in2 ( a1[4] ), .cin ( cout1[3] ), 	.sum ( sum1[4] ), .cout( cout1[4]) );

wire [4:0] cout2;
wire [4:0] sum2;
full_adder  u20 ( .in1 (  sum1[1] ), .in2 ( a2[0] ), .cin ( 0 ), 		.sum ( sum2[0] ), .cout( cout2[0]) );
full_adder  u21 ( .in1 (  sum1[2] ), .in2 ( a2[1] ), .cin ( cout2[0] ), .sum ( sum2[1] ), .cout( cout2[1]) );
full_adder  u22 ( .in1 (  sum1[3] ), .in2 ( a2[2] ), .cin ( cout2[1] ), .sum ( sum2[2] ), .cout( cout2[2]) );
full_adder  u23 ( .in1 (  sum1[4] ), .in2 ( a2[3] ), .cin ( cout2[2] ), .sum ( sum2[3] ), .cout( cout2[3]) );
full_adder  u24 ( .in1 ( cout1[4] ), .in2 ( a2[4] ), .cin ( cout2[3] ), .sum ( sum2[4] ), .cout( cout2[4]) );

wire [4:0] cout3;
wire [4:0] sum3;
full_adder  u30 ( .in1 (  sum2[1] ), .in2 ( a3[0] ), .cin ( 0 ), 		.sum ( sum3[0] ), .cout( cout3[0]) );
full_adder  u31 ( .in1 (  sum2[2] ), .in2 ( a3[1] ), .cin ( cout3[0] ), .sum ( sum3[1] ), .cout( cout3[1]) );
full_adder  u32 ( .in1 (  sum2[3] ), .in2 ( a3[2] ), .cin ( cout3[1] ), .sum ( sum3[2] ), .cout( cout3[2]) );
full_adder  u33 ( .in1 (  sum2[4] ), .in2 ( a3[3] ), .cin ( cout3[2] ), .sum ( sum3[3] ), .cout( cout3[3]) );
full_adder  u34 ( .in1 ( cout2[4] ), .in2 ( a3[4] ), .cin ( cout3[3] ), .sum ( sum3[4] ), .cout( cout3[4]) );

wire [4:0] cout4;
wire [4:0] sum4;
full_adder  u40 ( .in1 (  sum3[1] ), .in2 ( a4[0] ), .cin ( 0 ), 		.sum ( sum4[0] ), .cout( cout4[0]) );
full_adder  u41 ( .in1 (  sum3[2] ), .in2 ( a4[1] ), .cin ( cout4[0] ), .sum ( sum4[1] ), .cout( cout4[1]) );
full_adder  u42 ( .in1 (  sum3[3] ), .in2 ( a4[2] ), .cin ( cout4[1] ), .sum ( sum4[2] ), .cout( cout4[2]) );
full_adder  u43 ( .in1 (  sum3[4] ), .in2 ( a4[3] ), .cin ( cout4[2] ), .sum ( sum4[3] ), .cout( cout4[3]) );
full_adder  u44 ( .in1 ( cout3[4] ), .in2 ( a4[4] ), .cin ( cout4[3] ), .sum ( sum4[4] ), .cout( cout4[4]) );

assign product = {cout4[4], sum4, sum3[0], sum2[0], sum1[0], a0[0]};
	
endmodule
module full_adder (
	input in1,
	input in2,
	input cin,
	output sum,
	output cout
);

wire xor2;
assign xor2 = in1^ in2;								// reuse

assign sum = xor2^ cin;						

// assign cout = in1&in2| in1&cin| in2&cin;			// 3and 2or
// assign cout = in1&in2| cin&(in1|in2);			// one less and, 2and 2or
assign cout = (xor2&cin) | (in1&in2);				// resuse in1^in2, 2and 1or 
	
endmodule

流水线横向进位阵列乘法器

在这里插入图片描述

module real_papeline_lateral_carry_array_multiplier (
	input clk, 
	input rst_n,
	input [4:0] in1,
	input [4:0] in2,

	output [9:0]product
);

wire [4:0] a0;
assign a0 = {5{in2[0]}}&in1;	
wire [4:0] a1;
assign a1 = {5{in2[1]}}&in1;
wire [4:0] a2;
assign a2 = {5{in2[2]}}&in1;
wire [4:0] a3;
assign a3 = {5{in2[3]}}&in1;
wire [4:0] a4;
assign a4 = {5{in2[4]}}&in1;

wire [4:0] a00;
wire [5:0] a11;
wire [6:0] a22;
wire [7:0] a33;
wire [8:0] a44;

assign a00 = a0<<0;
assign a11 = a1<<1;
assign a22 = a2<<2;
assign a33 = a3<<3;
assign a44 = a4<<4;

wire [6:0] b11;
wire [7:0] b22;
wire [8:0] b33;
wire [9:0] b44;

serial_carry_adder #(
    .WIDTH ( 6 ))
 u1 (
    .in1                     ( {1'b0, a00}   ),
    .in2                     ( a11   ),
    .cin                     ( 1'b0   ),

    .sum                     ( b11   )
);

reg [6:0] pro1;
reg [6:0] a22_r;
reg [7:0] a33_r;
reg [8:0] a44_r;
always@(posedge clk or negedge rst_n)	
	if(!rst_n) begin
		pro1 <= 7'd0;
		a22_r	<= 7'd0; 
		a33_r	<= 8'd0;
		a44_r	<= 9'd0;
	end
	else	begin 
		pro1 <= b11;
		a22_r	<= a22; 
		a33_r	<= a33;
		a44_r	<= a44;
	end

serial_carry_adder #(
    .WIDTH ( 7 ))
 u2 (
    .in1                     ( pro1   ),
    .in2                     ( a22_r   ),
    .cin                     ( 1'b0   ),

    .sum                     ( b22   )
);

reg [7:0] pro2;
reg [7:0] a33_r_r;
reg [8:0] a44_r_r;

always@(posedge clk or negedge rst_n)	
	if(!rst_n) begin
		pro2 <= 8'd0;
		a33_r_r	<= 8'd0;
		a44_r_r	<= 9'd0;
	end
	else	begin 
		pro2 <= b22;
		a33_r_r	<= a33_r;
		a44_r_r	<= a44_r;
	end
	
serial_carry_adder #(
    .WIDTH ( 8 ))
 u3 (
    .in1                     ( pro2   ),
    .in2                     ( a33_r_r   ),
    .cin                     ( 1'b0   ),

    .sum                     ( b33   )
);

reg [8:0] pro3;
reg [8:0] a44_r_r_r;

always@(posedge clk or negedge rst_n)	
	if(!rst_n) begin
		pro3 <= 9'd0;
		a44_r_r_r <= 9'd0;
	end
	else begin
		pro3 <= b33;
		a44_r_r_r <= a44_r_r;
	end

serial_carry_adder #(
    .WIDTH ( 9 ))
 u4 (
    .in1                     ( pro3   ),
    .in2                     ( a44_r_r_r   ),
    .cin                     ( 1'b0   ),

    .sum                     ( b44   )
);

reg [9:0] pro4;
always@(posedge clk or negedge rst_n)	
	if(!rst_n) 
		pro4 <= 10'd0;
	
	else 
		pro4 <= b44;
	
assign product = pro4;

endmodule
module serial_carry_adder#(
	parameter WIDTH = 8
)(
	input [WIDTH-1:0] 	in1,
	input [WIDTH-1:0] 	in2,
	input 				cin,
	output	[WIDTH:0]	sum
);

wire [WIDTH:0]cout;
assign cout[0] = cin;

genvar i;
generate
	for(i=0; i<WIDTH; i=i+1)
		begin	:gf
			full_adder ufa(
				.in1	(in1[i]),
				.in2	(in2[i]),
				.cin	(cout[i]),
				.sum	(sum[i]),
				.cout	(cout[i+1])
			);
		end
endgenerate

assign sum[WIDTH] = cout[WIDTH];
		

endmodule


TB

`timescale  1ns / 1ps

module tb_papeline_lateral_carry_array_multiplier;

// papeline_lateral_carry_array_multiplier Parameters
parameter PERIOD  = 10;


// papeline_lateral_carry_array_multiplier Inputs
reg   clk                                  = 0 ;
reg   rst_n                                = 0 ;
reg   [4:0]  in1                           = 0 ;
reg   [4:0]  in2                           = 0 ;

// papeline_lateral_carry_array_multiplier Outputs
wire  [9:0]  product                       ;


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    #(PERIOD*2) rst_n  =  1;
	@(posedge clk)	
	in1 = 2;
	in2 = 4;
	@(posedge clk)
	in1 = 3;
	in2 = 5;
	@(posedge clk)
	in1 = 8;
	in2 = 16;
	@(posedge clk)
	in1 = 9;
	in2 = 17;
	@(posedge clk)
	in1 = 31;
	in2 = 31;
	@(posedge clk)
	in1 = 30;
	in2 = 29;
	@(posedge clk)
	in1 = 0;
	in2 = 31;
	@(posedge clk)
	in1 = 31;
	in2 = 0;
	@(posedge clk)
	in1 = 16;
	in2 = 16;
	@(posedge clk)
	in1 = 31;
	in2 = 15;
	@(posedge clk);
end

real_papeline_lateral_carry_array_multiplier  u1 (
    .clk                     ( clk            ),
    .rst_n                   ( rst_n          ),
    .in1                     ( in1      [4:0] ),
    .in2                     ( in2      [4:0] ),

    .product                 ( product  [9:0] )
);

// initial
// begin

//     $finish;
// end

endmodule

在这里插入图片描述

总结

不知道这样的流水线写法是不是对的,我没有想到更好的办法。
但是,这种流水线的写法,还能被叫做横向进位吗,我很迷茫。
似乎是的,因为每一行的对应元素相加,进位都是给了高位。
但是这样的流水线写法真的是对的吗?写法优美吗?

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值