微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 自己做的除法器

自己做的除法器

时间:10-02 整理:3721RD 点击:

这是本人做的除法器是32位除以32位(根据小学除法的原理写的),可以看到商和余数。
在modelsim上可以通过功能验证,但是用synplify综合总是出错,希望各位同胞不吝赐教。
本人的编程风格很是问题,不知道有什么好的编程风格,望请推荐。
本人是在校学生,没有任何流片经验,很困惑前段的代码如何写才能方便后面的布局布线,不知道要是优化的话应该从何下手,请赐教。非常谢谢
感谢小编解答,按照小编的要求改后,又遇到问题,问题如图所示




module division(reset,clk,a,b,load,quotient,remainder);
input reset,clk,load;
input [31:0] a,b;   
output [31:0] quotient,remainder;
reg [31:0] bshift,remainder_temp,quotient,remainder;
wire [11:0] a_dec;
wire [11:0] b_dec;
wire [31:0] atemp,btemp;
reg [4:0] num,number;
wire [4:0] counter0;
wire [4:0] counter1;
reg shift_start,start;
genvar i;
//minusend bit width
p_decoder8 p80(reset,a[31:24],a_dec[11:9]);
p_decoder8 p81(reset,a[23:16],a_dec[8:6]);
p_decoder8 p82(reset,a[15:8],a_dec[5:3]);
p_decoder8 p83(reset,a[7:0],a_dec[2:0]);
assign counter0[4]=a_dec[11]|a_dec[10]|a_dec[9]|a_dec[8]|a_dec[7]|a_dec[6],
       counter0[3]=a_dec[11]|a_dec[10]|a_dec[9]|a_dec[5]|a_dec[4]|a_dec[3],
       counter0[2]=counter0[4]?(counter0[3]?a_dec[11]:a_dec[8])counter0[3]?a_dec[5]:a_dec[2]),
       counter0[1]=counter0[4]?(counter0[3]?a_dec[10]:a_dec[7])counter0[3]?a_dec[4]:a_dec[1]),
       counter0[0]=counter0[4]?(counter0[3]?a_dec[9]:a_dec[6])counter0[3]?a_dec[3]:a_dec[0]);
//subtrahend bit width
p_decoder8 p84(reset,b[31:24],b_dec[11:9]);
p_decoder8 p85(reset,b[23:16],b_dec[8:6]);
p_decoder8 p86(reset,b[15:8],b_dec[5:3]);
p_decoder8 p87(reset,b[7:0],b_dec[2:0]);
assign counter1[4]=b_dec[11]|b_dec[10]|b_dec[9]|b_dec[8]|b_dec[7]|b_dec[6],
       counter1[3]=b_dec[11]|b_dec[10]|b_dec[9]|b_dec[5]|b_dec[4]|b_dec[3],
       counter1[2]=counter0[4]?(counter0[3]?b_dec[11]:b_dec[8]):(counter0[3]?b_dec[5]:b_dec[2]),
       counter1[1]=counter0[4]?(counter0[3]?b_dec[10]:b_dec[7]):(counter0[3]?b_dec[4]:b_dec[1]),
       counter1[0]=counter0[4]?(counter0[3]?b_dec[9]:b_dec[6]):(counter0[3]?b_dec[3]:b_dec[0]);
//temporary regiser
generate
for (i=0;i<32;i=i+1) begin:g1
load l0(a,atemp,load,reset);
load l1(b,btemp,load,reset);
end
endgenerate
always @(posedge clk)
if(reset)
  begin
    num=5'b0;
    number=5'b0;
    bshift=32'b0;
    shift_start=0;
    quotient=32'b0;
    remainder=32'b0;
  end
else
  if(load)   
    if(a>=b)
      begin
        num=counter0-counter1;
        shift_start=1;
        bshift=btemp;
        remainder_temp=atemp;
        number=counter0-counter1+1;
      end
    else
      begin
        shift_start=0;
        quotient=32'b0;
        remainder_temp=atemp;
      end
  else if(shift_start)
    begin
    if(!num)
      begin
        shift_start=0;
        start=1;
        num=5'b0;
      end
    else
      begin
        shift_start=1;
        bshift=bshift<<1;
        start=0;
      end
    num=num-1;
    end
  else if(start)
    begin
      
        if(number)
         if(remainder_temp>=bshift)
           begin
           remainder_temp=remainder_temp-bshift;
           quotient[number-1]=1'b1;
           bshift=bshift>>1;
           end
         else
           begin
           remainder_temp=remainder_temp;
           quotient[number-1]=1'b0;
           bshift=bshift>>1;
           end
       else if(!number)
         start=0;
      number=number-1;  
    end
  else if(start==0)
    remainder=remainder_temp;            
     
endmodule
//submodule priority decoder
module p_decoder8(reset,a,b);
input [7:0] a;
input reset;
output [2:0] b;
reg [2:0] b;
always @(a,reset)
if(reset)
  b=3'b000;
else
  begin   
    if(a[7]==1'b1)
      b=3'b111;
    else if(a[6]==1'b1)
      b=3'b110;
    else if(a[5]==1'b1)
      b=3'b101;
    else if(a[4]==1'b1)
      b=3'b100;
    else if(a[3]==1'b1)
      b=3'b011;
    else if(a[2]==1'b1)
      b=3'b010;
    else if(a[1]==1'b1)
      b=3'b001;
    else
      b=3'b000;
  end
endmodule
//submodule load
module load(a,b,load,reset);
input a,load,reset;
output b;
reg b;
always @(posedge load,posedge reset)
  if(reset)
    b=1'b0;
  else
    b=a;   
endmodule

一个信号只在一个always里赋值。
想清楚这个always是要做组合逻辑还是时序逻辑,决定用= 还是 <=赋值。
不是时钟或复位信号不要用posedge 或 negedge触发
算法方面,很惭愧,看不懂,能说说思路么。

直接代码复制粘贴上来,解决的人会比较多的。


不好意思我写得程序比较乱
    就是小学的做除法时候用的算法
移位比较的除法器


小学的时候用的是10进制,现在换成2进制就可以了



    说的也是



多谢赐教   
但是我想用一个复位信号能复位全部的,这样就不能分开写了,并且分开写还要有更多的判断条件,岂不是更麻烦

你这段描述是要写D-flop吗?如果是的话问题来了,clock呢?flop有load端吗?
module dff(a,b,load,reset);
input a,load,reset;
output b;
reg b;
always @(posedge load,posedge reset)
  if(reset)
    b=1'b0;
  else
    b=a;   
endmodule

供参考
http://fpgaw.com/home/space.php?uid=2634



    抱歉,忘记改了,应该是load模块,因为我想做一个载入模块,不是所有的信号都会要



    看了你贴的报错的地方,这个不是错误啊,只是warning,警告而已嘛。说有一些逻辑被优化掉了,你检查一下,这些是否可以被优化掉。没有功能的信号本来就是可以被优化的。

贴一个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)?hifunc==`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



抱歉,最近有考试所以没上网
   
谢谢,我发现问题了,因为计数器number改变时number的第一个值没有赋给quotient[number],所以才会出警告。已经修改完毕



    谢谢,参考了,不过好像算法差不多

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top