|
发表于 2011-6-15 00:11:50
|
显示全部楼层
贴一个MIPS789里面用到的乘除法器。还有一个是 UCORE里面用的 ,下 一帖子上。
module muldiv(ready,rst,op1,op2,clk,dout,func);
input clk,rst;
wire sign;
input [4:0] func ;
input [31:0] op2, op1;
output [31:0] dout;
output ready;
reg [31:0] quotient, quotient_temp;
reg [63:0] dividend_copy, divider_copy, diff;
reg negative_output;
reg [63:0] product, product_temp;
reg [31:0] multiplier_copy;
reg [63:0] multiplicand_copy;
reg [6:0] mul_bit,div_bit;
wire ready = ((mul_bit==0)&&(div_bit==0));
wire [31:0] dividend, divider;
wire [31:0] remainder;
wire [31:0] multiplier,multiplicand;
reg [31:0] hi,lo;
assign dout = (func==`ALU_MFHI)?hi func==`ALU_MFLO)?lo:0;
assign remainder = (!negative_output) ?
dividend_copy[31:0] :
~dividend_copy[31:0] + 1'b1;
assign multiplier=op2;
assign multiplicand=op1;
assign dividend=op1;
assign divider = op2;
assign sign = ((func==`ALU_MULT)||(func==`ALU_DIV));
initial
begin
hi=0;
lo=0;
end
always @( posedge clk /*or negedge rst */)
if (~rst)
begin
mul_bit=0;
div_bit=0;
/*
hi=0;
lo=0;
*/
negative_output = 0;
end
else
begin
if((ready)&&((func==`ALU_MULT)||(func==`ALU_MULTTU)))
begin
mul_bit = 33;
product = 0;
product_temp = 0;
multiplicand_copy = (!sign || !multiplicand[31]) ?
{ 32'd0, multiplicand } :
{ 32'd0, ~multiplicand + 1'b1};
multiplier_copy = (!sign || !multiplier[31]) ?multiplier :~multiplier + 1'b1;
negative_output = sign &&
((multiplier[31] && !multiplicand[31])
||(!multiplier[31] && multiplicand[31]));
end
if ( mul_bit > 1 )
begin
if( multiplier_copy[0] == 1'b1 )
product_temp = product_temp +multiplicand_copy;
product = (!negative_output) ?
product_temp :
~product_temp + 1'b1;
multiplier_copy = multiplier_copy >> 1;
multiplicand_copy = multiplicand_copy << 1;
mul_bit = mul_bit - 1'b1;
end
else if (mul_bit == 1)
begin
hi = product[63:32];
lo = product[31:0];
mul_bit=0;
end
if((ready)&&((func==`ALU_DIV)||(func==`ALU_DIVU)))
begin
div_bit = 33;
quotient = 0;
quotient_temp = 0;
dividend_copy = (!sign || !dividend[31]) ?
{32'd0,dividend} :
{32'd0,~dividend + 1'b1};
divider_copy = (!sign || !divider[31]) ?
{1'b0,divider,31'd0} :
{1'b0,~divider + 1'b1,31'd0};
negative_output = sign &&
((divider[31] && !dividend[31])
||(!divider[31] && dividend[31]));
end
else if (div_bit > 1)
begin
diff = dividend_copy - divider_copy;
quotient_temp = quotient_temp << 1;
if( !diff[63] )
begin
dividend_copy = diff;
quotient_temp[0] = 1'd1;
end
quotient = (!negative_output) ?quotient_temp :~quotient_temp + 1'b1;
divider_copy = divider_copy >> 1;
div_bit = div_bit - 1'b1;
end
else if (div_bit == 1)
begin
lo = quotient;
hi = remainder;
div_bit=0;
end
end
endmodule |
|