Verilog的整数除法

发布于:2025-04-16 ⋅ 阅读:(22) ⋅ 点赞:(0)

1、可变系数除法实现----利用除法的本质

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/15 13:45:39
// Design Name: 
// Module Name: divide_1
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module divide_1
    (
    // clk and rst_n
        input   wire            sys_clk         ,
        input   wire            sys_rst_n       ,
    // dividend and divisor        
        input   wire            enIn            ,
        input   wire [7:0]      dividend        ,
        input   wire [3:0]      divisor         ,
        
        output  wire            busy            ,
        output  wire            enOut           ,
        output  wire            warning         ,
        output  wire [7:0]      quotient        ,
        output  wire [3:0]      remainder
    );
    
    localparam  IDLE    =   1'b0    ;
    localparam  S_CALC  =   1'b1    ;
    
    reg         current_state   ;
    reg         next_state      ;
    
    reg         lockDivs        ;
    reg  [7:0]  DivA            ;
    reg  [3:0]  DivB            ;
    reg         counting , ending   ;
    reg  [7:0]  counter         ;
    
    reg         out_busy        ;
    reg         out_enOut       ;
    reg         out_warning     ;
    reg  [7:0]  out_quotient    ;
    reg  [3:0]  out_remainder   ;
    
    
    
    
    
    wire [7:0]  extDivB =   { 4'b0,DivB }   ;
    
    always@( posedge sys_clk )
    begin
        if( sys_rst_n == 1'b0 )
        begin
            current_state   <=  IDLE    ;
            DivA            <=  8'b0    ;
            DivB            <=  4'b0    ; 
            counter         <=  8'b0    ;
            out_enOut       <=  1'b0    ;
            out_warning     <=  1'b0    ;
            out_quotient    <=  8'b0    ;
            out_remainder   <=  4'd0    ;
        end
        else
        begin
            current_state   <=  next_state  ;
            // DivA  DivB  counter
            if( lockDivs == 1'b1 )
            begin
                DivA    <=  dividend    ;
                DivB    <=  divisor     ;
                counter <=  8'b0        ;
            end
            else if( counting == 1'b1 )
            begin
                DivA    <=  DivA - extDivB  ;
                counter <=  counter + 1'b1  ;
            end
            //out_enOut
            out_enOut   <=  ending  ;
            // out_warning
            if( ending == 1'b1 )
            begin
                if( DivB == 4'b0 )
                begin
                    out_warning <=  1'b1    ;
                end
                else
                begin
                    out_warning <=  1'b0    ;
                end
                // out_quotient
                out_quotient    <=  counter ;
                // our_remainder
                out_remainder   <=  DivA[3:0]   ;
            end
        end
    end
    
    always@( current_state , enIn , DivA , extDivB )
    begin
        out_busy    <=  1'b0    ;
        lockDivs    <=  1'b0    ;
        counting    <=  1'b0    ;
        ending      <=  1'b0    ;
        case( current_state )
            IDLE    :
                begin
                    if( enIn == 1'b1 )
                    begin
                        lockDivs    <=  1'b1    ;
                        next_state  <=  S_CALC  ;
                    end
                    else
                    begin
                        next_state  <=  IDLE    ;
                    end
                end
            S_CALC  :
                begin
                    out_busy    <=  1'b1    ;
                    if( DivA < extDivB || extDivB == 8'b0 )
                    begin
                        ending      <=  1'b1    ;
                        next_state  <=  IDLE    ;  
                    end
                    else
                    begin
                        counting    <=  1'b1    ;
                        next_state  <=  S_CALC  ;
                    end
                end
            default :
                begin
                    next_state  <=  IDLE    ;
                end
        endcase
        
    end
    
    assign  busy        =   out_busy        ;
    assign  enOut       =   out_enOut       ;
    assign  warning     =   out_warning     ;
    assign  quotient    =   out_quotient    ;
    assign  remainder   =   out_remainder   ;
    
endmodule

tb

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/15 15:24:32
// Design Name: 
// Module Name: tb_divide_1
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_divide_1(

    );
    
    
    reg                     sys_clk         ;
    reg                     sys_rst_n       ;       
    reg                     enIn            ;
    reg  [7:0]              dividend        ;
    reg  [3:0]              divisor         ;
    
    wire                    busy            ;
    wire                    enOut           ;
    wire                    warning         ;
    wire [7:0]              quotient        ;
    wire [3:0]              remainder       ;
    
    
    initial
    begin
        sys_clk     =   1'b0    ;
        sys_rst_n   =   1'b0    ;
        
        enIn        =   1'b0    ;
        dividend    =   8'b0    ;
        divisor     =   4'b0    ;
        #50
        enIn        =   1'b1    ;
        dividend    =   8'd110  ;
        divisor     =   4'd10   ; 
        sys_rst_n   =   1'b1    ; 
        #20
        enIn        =   1'b0    ;
        #200
        $finish ;      
    end
    
 
    always #5
    begin
        sys_clk =   ~sys_clk    ;
    end
    
    divide_1        divide_1_inst
    (
        .sys_clk         (sys_clk),
        .sys_rst_n       (sys_rst_n),       
        .enIn            (enIn),
        .dividend        (dividend),
        .divisor         (divisor),
        .busy            (busy),
        .enOut           (enOut),
        .warning         (warning),
        .quotient        (quotient),
        .remainder       (remainder)
    );
    
    
    
    
    
endmodule

 

         但是这种做法运算一次最多需要256的clk,所以需要减小消耗的实现

2、可变系数除法实现----利用除法的竖式求解

3、可变系数除法实现----利用乘法实现除法


网站公告

今日签到

点亮在社区的每一天
去签到