verilog 任意位宽除法代码

verilog 任意位宽除法代码

废话不多说,直接贴代码:

`timescale 1ns / 1ps
module Divider_Module#(
    parameter                                       EXT_DIVIDEND_WIDTH      =   'd8                             ,
    parameter                                       EXT_DIVISOR_WIDTH       =   'd8                             ,
    parameter                                       DIVIDEND_WIDTH          =   EXT_DIVIDEND_WIDTH              ,
    parameter                                       DIVISOR_WIDTH           =   EXT_DIVISOR_WIDTH + 1           ,
    parameter                                       DIV_WIDTH               =   DIVIDEND_WIDTH + DIVISOR_WIDTH  ,
    parameter                                       DIV_STEP                =   DIVIDEND_WIDTH + 1'd1           ,
    parameter                                       WIDTH_DIVIDEND_DATA     =   DIV_WIDTH * DIV_STEP            ,
    parameter                                       WIDTH_DIVISOR_DATA      =   DIVISOR_WIDTH * DIV_STEP        
)(
    input                                           i_sys_clk               ,
    input                                           i_sys_reset             ,
    //----------------------------------------------------------
    input       [DIVIDEND_WIDTH-1:0]                i_dividend_data         ,
    input       [DIVISOR_WIDTH-1:0]                 i_divisor_data          ,
    input                                           i_divider_valid         ,
    //----------------------------------------------------------
    output      [DIVIDEND_WIDTH-1:0]                o_quotient_data         ,
    output      [DIVISOR_WIDTH-1:0]                 o_remainder_data        ,
    output                                          o_calculate_valid       
);


reg     [WIDTH_DIVIDEND_DATA- 1 :0]             r_dividend_data_step    ;
reg     [WIDTH_DIVISOR_DATA - 1 :0]             r_divisor_data_step     ;
reg     [DIV_STEP           - 1 :0]             r_valid                 ;

always@(posedge i_sys_clk)begin
    if(i_sys_reset  ==  'd1)begin
        r_dividend_data_step[DIV_WIDTH-1:0]     <=   'd0                ;
        r_divisor_data_step[DIVISOR_WIDTH-1:0]  <=   'd0                ;
        r_valid[0]                              <=   'd0                ;
    end
    else begin
        r_dividend_data_step[15:0]              <=   i_dividend_data    ;
        r_divisor_data_step[7:0]                <=   i_divisor_data     ;
        r_valid[0]                              <=   i_divider_valid    ;
    end
end

parameter SIZE = DIV_STEP;
genvar i;
generate
    for(i=1;i<SIZE;i=i+1)
    begin:div
        always@(posedge i_sys_clk)begin
            if(i_sys_reset  ==  'd1)begin
                r_dividend_data_step[(i+1)*DIV_WIDTH-1:i*DIV_WIDTH]             <=   'd0;
                r_divisor_data_step[(i+1)*DIVISOR_WIDTH-1:i*DIVISOR_WIDTH]      <=   'd0;
                r_valid[i]                                                      <=   'd0;
            end
            else begin
                if(r_dividend_data_step[i*DIV_WIDTH-2:i*DIV_WIDTH - DIVISOR_WIDTH-1] >= r_divisor_data_step[i*DIVISOR_WIDTH-1:(i-1)*DIVISOR_WIDTH])
                    r_dividend_data_step[(i+1)*DIV_WIDTH-1:i*DIV_WIDTH]         <=   
                            {r_dividend_data_step[i*DIV_WIDTH-2:i*DIV_WIDTH - DIVISOR_WIDTH - 1]-r_divisor_data_step[i*DIVISOR_WIDTH-1:(i-1)*DIVISOR_WIDTH],
                                r_dividend_data_step[i*DIV_WIDTH - DIVISOR_WIDTH - 2:(i-1)*DIV_WIDTH],1'd1}                                     ;
                else
                    r_dividend_data_step[(i+1)*DIV_WIDTH-1:i*DIV_WIDTH]         <=   r_dividend_data_step[i*DIV_WIDTH-1:(i-1)*DIV_WIDTH]<<1     ;

                r_divisor_data_step[(i+1)*DIVISOR_WIDTH-1:i*DIVISOR_WIDTH]  <=   r_divisor_data_step[i*DIVISOR_WIDTH-1:(i-1)*DIVISOR_WIDTH] ;
                r_valid[i]                                                  <=   r_valid[i-1]                                               ;
            end
        end
    end
endgenerate

assign  o_quotient_data             =   r_dividend_data_step[SIZE*DIV_WIDTH - DIVISOR_WIDTH - 1:(SIZE-1)*DIV_WIDTH] ;
assign  o_remainder_data            =   r_dividend_data_step[SIZE*DIV_WIDTH - 1:SIZE*DIV_WIDTH - DIVISOR_WIDTH]     ;
assign  o_calculate_valid           =   r_valid             [SIZE           - 1]                                    ;

endmodule

说明:全流水除法电路,消耗资源较多,但是保证了高流量,我简单仿真了几下,没有问题,当除数出现错误,为0时,我直接将valid拉低,仿真代码如下:

`timescale 1ns / 1ps

module sim_div();
    parameter                               DIVIDEND_WIDTH  = 'd8   ;
    parameter                               DIVISOR_WIDTH   = 'd8   ;
    parameter                               DIV_TEST_RANGE  = 'd250 ;

    reg                                     r_sys_clk               ;
    reg                                     r_sys_reset             ;
    reg         [DIVIDEND_WIDTH-1:0]        r_dividend_data         ;
    reg         [DIVISOR_WIDTH-1:0]         r_divisor_data          ;
    reg                                     r_divider_valid         ;
    wire        [DIVIDEND_WIDTH-1:0]        w_quotient_data         ;
    wire        [DIVISOR_WIDTH-1:0]         w_remainder_data        ;
    wire                                    w_calculate_valid       ;

initial begin
    r_sys_clk           =   'd0;
    r_sys_reset         =   'd1;
    r_dividend_data     =   'd0;
    r_divisor_data      =   'd0;
    r_divider_valid     =   'd1;
    #200;
    r_sys_reset         =   'd0;
    #400;
    test_div();
    
    
    #500;
    $finish;
end

always#5 r_sys_clk = ~r_sys_clk;

task test_div();
    
    integer i,j;
    begin
        for(i=1;i<DIV_TEST_RANGE;i=i+1)begin
            for(j=i;j<DIV_TEST_RANGE;j=j+1)begin
                repeat(1)@(posedge r_sys_clk);
                r_dividend_data =   j;
                r_divisor_data  =   i;
            end
        end
    end
endtask

Divider_Module #(
    .DIVIDEND_WIDTH(DIVIDEND_WIDTH),
    .DIVISOR_WIDTH(DIVISOR_WIDTH)
)Divider_Module_inst(
    .i_sys_clk                              (r_sys_clk             ),
    .i_sys_reset                            (r_sys_reset           ),
    .i_dividend_data                        (r_dividend_data       ),
    .i_divisor_data                         (r_divisor_data        ),
    .i_divider_valid                        (r_divider_valid       ),
    .o_quotient_data                        (w_quotient_data       ),
    .o_remainder_data                       (w_remainder_data      ),
    .o_calculate_valid                      (w_calculate_valid     )
);

endmodule

算法参考:

https://blog.csdn.net/qishi2014/article/details/51945027

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值