0

I have been using '/' operator to perform divison in verilog. I am able to get the simulation results right but the thing is that my code was unable to get synthesized due to '/' operator. It was displaying the error "second operand of / should be a power of 2". How should I perform divison in Verilog HDL ?

Vineeth Ananthula
  • 85
  • 2
  • 5
  • 12
  • There are few algorithms for divisions, based on shift and add method. You may find them in digital circuits or computer design book. – Karan Shah Oct 29 '16 at 03:58

1 Answers1

1

The operator for division is not synthesizable as pointed by the error message, it's supposed to be used for simulation only.

What you need to do depends on the conditions of the division. You can use the repeated subtraction algorithm, which is the simplest solution.

The downside is that you get the result of your division in N clock cycles, where N in the integer part of the division, but you can set a flag bit for when the division is complete.

Here is the description of the algorithm, from Wikipedia:

while  N ≥ D do
  N := N − D
end
return N

Edit: For the sake of completeness to anyone reaching this question. Here is a synthetizable implementation of the algorithm. (This is not the best implementation, nor it has been fully tested )

module mod_div(
    input clk,
    input rst,
    input start,
    input  [7:0] num,
    input  [7:0] den,
    output [7:0] res,
    output [7:0] rem,
    output reg done
);
/* Registers to store the input arguments */
reg [7:0] num_r;
reg [7:0] den_r;
/* counts the number of times denominator fits in numerator */
reg [7:0] result_integer;
/* True if the algorithm is running */
reg working;


always @(posedge clk) begin
    if(rst == 1'b1)begin
        /* setting the working registers to 0 */
        num_r <= 8'b0;
        den_r <= 8'b0;
        working <= 1'b0;
        result_integer <= 'b0;
        done <= 'b0;
    end else if(start == 1'b1) begin
        /* Captures the parameters and starts the operation */
        num_r <= num;
        den_r <= den;
        working <= 1'b1;
        done <= 1'b0;
    end
    /* The actual algorithm */
    if (working == 1'b1 && start == 1'b0)begin
        if(num_r >= den_r) begin
            /* The division will give a proper fraction */
            num_r <= num_r - den_r;
            result_integer <= result_integer + 8'b1;
        end else begin
            working <= 'b0;
            done <= 1'b1;
        end
    end
end



/* The reminder of the division  */
assign rem = num_r;
/*The integer part is the number of times the divisor was substracted from the
* numerator*/
assign res = result_integer;

endmodule 

And also here is the test bench for this module:

module division_tb();

reg clk;
reg rst;
reg [7:0] numerator;
reg [7:0] denominator;
reg start;

wire [7:0] integer_result;
wire [7:0] reminder_result;
wire done_flag;

mod_div DUT (
     .clk(clk),
     .rst(rst),
     .start(start),
     .num(numerator),
     .den(denominator),
     .res(integer_result),
     .rem(reminder_result),
     .done(done_flag)
 );


always begin
    #10 clk = ~clk;
end

initial begin
    clk = 1'b0;
    rst = 1'b1;
#15 rst = 1'b0;
    numerator = 17;
    denominator = 5;
#1  start = 1;
#20 start = 0;
#200 $finish;
end

/* FOR GTK WAVE */
initial
  begin
    $dumpfile("shift.vcd");
    $dumpvars(0, division_tb);
  end

endmodule 

This is the result of the simulation using GTK-Wave: Division Simulation

In the image the division of 17/5 is being performed, to start the operation the start wire needs to be in 1 for at least 1 clock cycle, when the division is complete the flag done is set to 1 at that moment the result is in the output registers. For this example integer_part: 3 and the reminder is 2

GurstTavo
  • 336
  • 1
  • 3
  • 18