Verilog 定点除法器设计

原理参考

  • top
module div_top #(  
        parameter M = 5,
        parameter N = 3
)
(         
        input                  clk,
        input                  rst,
        input                  en,
        input         [M-1:0]      divided,
        input         [N-1:0]      divisor,
        output        [M-1:0]    quotient,
        output        [N-1:0]      remainder
);
//save quotient and remainder lever by lever
wire [M-1:0] quotient_co [M-1:0];
wire [N-1:0] remainder_co [M-1:0];
//tansfer divided and divisor
wire [M-1:0] divided_kp [M-1:0];
wire [N-1:0] divisor_kp [M-1:0];
//the first level 
div_initial #(   .M(5),
                 .N(3)
            )
        u1  (
              .clk(clk),
              .rst(rst),
              .en(en),
              .divided_fir({{(N-1){1'b0}},divided[M-1]}),
              .divided(divided),
              .divisor(divisor),
              .divided_kp(divided_kp[0]),
              .divisor_kp(divisor_kp[0]),
              .quotient_co(quotient_co[0]),
              .remainder_co(remainder_co[0])
            );
//use loop to generate next level
genvar i;
generate
for (i=1; i <= M-1; i=i+1) begin:div_bit
        div_cell #(   .M(5),
                      .N(3)
            )
        u2  (
              .clk(clk),
              .rst(rst),
              .en(en),
              .divided_bit(divided_kp[i-1][M-i-1]),
              .divided(divided_kp[i-1]),
              .divisor(divisor_kp[i-1]),
              .divided_kp(divided_kp[i]),
              .divisor_kp(divisor_kp[i]),
              .quotient_ci(quotient_co[i-1]),
              .remainder_ci(remainder_co[i-1]),
              .quotient_co(quotient_co[i]),
              .remainder_co(remainder_co[i])
            );
   end
 endgenerate
 assign quotient = quotient_co[M-1];
 assign remainder = remainder_co[M-1];
endmodule

.divided_bit(divided_kp[i-1][M-i-1])//可实现二维下标访问

  • div_initial
module div_initial #(
        parameter M = 5,
        parameter N = 3
)
(         
        input                  clk,
        input                  rst,
        input                  en,
        input     [M-1:0]      divided,
        input     [N-1:0]      divisor,
        input     [N-1:0]      divided_fir,
        output reg   [M-1:0]      divided_kp,
        output reg   [N-1:0]      divisor_kp,
        output reg   [M-1:0]      quotient_co,
        output reg   [N-1:0]      remainder_co
);

always@(posedge clk or negedge rst) begin
  if (!rst) begin
    quotient_co <= 'b0;
    remainder_co <= 'b0;
  end
  else if (en) begin
//tansfer divided and divisor
    divided_kp <= divided;
    divisor_kp <= divisor;
    if (divided_fir>= divisor) begin  
      quotient_co <= 'b1;
      remainder_co <= divided_fir - divisor;
    end
    else begin 
    quotient_co <= 'b0;
    remainder_co <= divided_fir;
    end
  end
  else begin
    quotient_co <= 'b0;
    remainder_co <= 'b0;
  end
end
endmodule

  • div_cell
module div_cell #(
        parameter M = 5,
        parameter N = 3
)
(         
        input                  clk,
        input                  rst,
        input                  en,
        input                  divided_bit,
        input     [M-1:0]      divided,
        input     [N-1:0]      divisor,
        input     [M-1:0]    quotient_ci,
        input     [N-1:0]      remainder_ci,
        output reg   [M-1:0]      divided_kp,
        output reg   [N-1:0]      divisor_kp,
        output reg   [M-1:0]      quotient_co,
        output reg   [N-1:0]      remainder_co
);

always@(posedge clk or negedge rst) begin
  if (!rst) begin
    quotient_co <= 'b0;
    remainder_co <= 'b0;
  end
  else if (en) begin
//tansfer divided and divisor
    divided_kp <= divided;
    divisor_kp <= divisor;
    if ({remainder_ci,divided_bit} >= divisor) begin
      quotient_co <= (quotient_ci<<1) + 1'b1;               //quotient plu 1
      remainder_co <= {remainder_ci,divided_bit} - divisor; //calculate remainder
    end
    else begin 
    quotient_co <= quotient_ci<<1;
    remainder_co <= {remainder_ci,divided_bit};
    end
  end
  else begin
    quotient_co <= 'b0;
    remainder_co <= 'b0;
  end
end
endmodule

quotient_co <= (quotient_ci<<1) + 1’b1; //注意优先级()标注

  • test
module test ;
    parameter    M = 5 ;
    parameter    N = 3 ;
    reg          clk;
    reg          rst ;
    reg          en;
    reg [M-1:0]  divided ;
    reg [N-1:0]  divisor ;

    wire [M-1:0] quotient ;
    wire [N-1:0] remainder ;


div_top #(      .M(5),
                .N(3)
            )
        u1  (
              .clk(clk),
              .rst(rst),
              .en(en),
              .divided(divided),
              .divisor(divisor),
              .quotient(quotient),
              .remainder(remainder)
            );


    //clock
    always begin
        clk = 0 ; #5 ;
        clk = 1 ; #5 ;
    end

    //driver
    initial begin
        rst      = 1'b0 ;
        #8 ;
        rst      = 1'b1 ;

        #55 ;
        @(negedge clk ) ;
        en = 1'b1 ;
                divided  = 27;      divisor      = 5;
        #10 ;   divided  = 20;      divisor      = 3;
        #10 ;   divided  = 30;      divisor      = 4;
        #10 ;   divided  = 19;      divisor      = 4;
        #10 ;   divided  = 14;      divisor      = 1;
        repeat(32)    #10   divided   = divided + 1 ;
        divisor      = 7;
        repeat(32)    #10   divided   = divided + 1 ;
        divisor      = 5;
        repeat(32)    #10   divided   = divided + 1 ;
        divisor      = 4;
        repeat(32)    #10   divided   = divided + 1 ;
        divisor      = 6;
        repeat(32)    #10   divided   = divided + 1 ;
    end

  initial begin
  $fsdbDumpfile("div_top.fsdb");
  $fsdbDumpvars;
  #40000 $finish;
 end
 endmodule
  • 结果
  • 在这里插入图片描述

你可能感兴趣的:(IC,verilog)