下述乘法器是基于radix 4的booth乘法器,常用于集成电路IC的乘法器设计。
- 支持位宽可设置
- 支持signsign、signunsign、unsignsign、unsignunsign;
// +FHDR------------------------------------------------------------
// Copyright (c) 2023 COMPANY: Undefined variable..
// ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename : radix4_booth_mult.v
// Author :
// Created On :
// Last Modified :
// -----------------------------------------------------------------
// Description:
// radix 4 booth multipiler
// operate a can be int or uint, if(int) ,sign <= 1'b1 ,else sign <= 1'b0
// when multipiler used independently , op_b_cin <= 1'b0;
// when need to cascaded as WIDTH_A * (WIDTH_B*n) multipiler , op_b_cin <= (the highest bit of previous multipiler operate b)
//
// -FHDR------------------------------------------------------------
module radix4_booth_mult #(
parameter WIDTH_A = 4
,parameter WIDTH_B = 8
)(
input wire comp_en //Take the complement of the calculation result
,input wire sign_a //operate a sign flag,1'b1->signed,1'b0->unsigned
,input wire sign_b //operate b sign flag,1'b1->signed,1'b0->unsigned
,input wire [WIDTH_A-1:0] op_a //operate a data input
,input wire [WIDTH_B-1:0] op_b //operate b data input,used to booth coding
,input wire op_b_cin //booth coding carry in,when multipiler cascaded,use the highest bit of previous multipiler operate b
,output reg [(WIDTH_A+WIDTH_B)*(WIDTH_B/2+2)-1:0] prod //wallace tree partial product output
);
//==============================================================================================
//====== function ========
//==============================================================================================
//==============================================================================================
//====== parameter ========
//==============================================================================================
localparam BOOTH_NUM = WIDTH_B/2;
//==============================================================================================
//====== define signal ========
//==============================================================================================
//reg complement ;
reg signed_a ;
reg signed_b ;
reg [WIDTH_A-1:0] operate_a ;
reg [WIDTH_B:0] operate_b ;
wire [2:0] booth_code [BOOTH_NUM-1:0] ;
wire [WIDTH_A+1:0] temp_prod [BOOTH_NUM-1:0] ;
wire [BOOTH_NUM-1:0] temp_comp ;
wire [(WIDTH_A+WIDTH_B)*(BOOTH_NUM+2)-1:0] prod_pre ;
//==============================================================================================
//====== initialize signal ========
//==============================================================================================
//==============================================================================================
//====== behave of RTL ========
//==============================================================================================
//--------------------------------------------------------------------
//------ buffer the input signal ------
//--------------------------------------------------------------------
always@(*)begin
//complement = comp_en ;
signed_a = sign_a ;
signed_b = sign_b ;
operate_a = op_a ;
operate_b = {WIDTH_B+1{comp_en}}^{op_b,op_b_cin} ;
end
//--------------------------------------------------------------------
//------ ------
//--------------------------------------------------------------------
genvar i;
generate for(i=0;i<BOOTH_NUM;i=i+1) begin: distribute_a
assign booth_code[i] = operate_b[i*2 +: 3];
//assign booth_code[i] = {3{complement}} ^ operate_b[i*2 +: 3];
booth #(.WIDTH(WIDTH_A)) u_booth_0 (
.sign (signed_a ),
.code (booth_code[i] ),
.src_data (operate_a ),
.out_data (temp_prod[i] ),
.out_inv (temp_comp[i] )
);
assign prod_pre[(WIDTH_A+WIDTH_B)*i +: WIDTH_A+WIDTH_B] = {{(WIDTH_A+WIDTH_B-2*i-1){1'b0}},temp_prod[i],{2*i{1'b0}}};
assign prod_pre[(WIDTH_A+WIDTH_B)*BOOTH_NUM + 2*i +: 2] = {1'b0,temp_comp[i]};
end endgenerate
assign prod_pre[(WIDTH_A+WIDTH_B)*BOOTH_NUM + WIDTH_B +: WIDTH_A] = (signed_b|(~operate_b[WIDTH_B]))? {WIDTH_A{1'b0}} : operate_a;
assign prod_pre[(WIDTH_A+WIDTH_B)*(BOOTH_NUM+1) +: WIDTH_A+WIDTH_B] = {{BOOTH_NUM-1{2'b01}},2'b10,{WIDTH_A{1'b0}}};
//--------------------------------------------------------------------
//------ ------
//--------------------------------------------------------------------
always@(prod or prod_pre)begin
prod = prod_pre ;
end
endmodule
//*******************************************************************************************//
//
//*******************************************************************************************//
// +FHDR------------------------------------------------------------
// Copyright (c) 2023 COMPANY: Undefined variable..
// ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename : booth.v
// Author :
// Created On :
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------
module booth #(
parameter WIDTH = 8
) (
input sign
,input [2:0] code
,input [WIDTH-1:0] src_data
,output reg [WIDTH+1:0] out_data
,output reg out_inv
);
//==============================================================================================
//====== function ========
//==============================================================================================
//==============================================================================================
//====== parameter ========
//==============================================================================================
//==============================================================================================
//====== define signal ========
//==============================================================================================
wire [WIDTH:0] data_in ;
//==============================================================================================
//====== initialize signal ========
//==============================================================================================
//==============================================================================================
//====== behave of RTL ========
//==============================================================================================
assign data_in = {sign&src_data[WIDTH-1],src_data};
always @(*) begin
case(code)
// +/- 0*src_data
3'b000,
3'b111:
begin
out_data = {1'h1,{WIDTH+1{1'h0}}};
out_inv = 1'b0;
end
// + 1*src_data
3'b001,
3'b010:
begin
out_data = {~data_in[WIDTH], data_in};
out_inv = 1'b0;
end
// - 1*src_data
3'b101,
3'b110:
begin
out_data = { data_in[WIDTH],~data_in};
out_inv = 1'b1;
end
// + 2*src_data
3'b011:
begin
out_data = {~data_in[WIDTH], data_in[WIDTH-1:0], 1'b0};
out_inv = 1'b0;
end
// - 2*src_data
3'b100:
begin
out_data = { data_in[WIDTH],~data_in[WIDTH-1:0], 1'b1};
out_inv = 1'b1;
end
default:
begin
out_data = {1'h1,{WIDTH+1{1'h0}}};
out_inv = 1'b0;
end
endcase
end
endmodule