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 ?
-
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 Answers
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:
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

- 336
- 1
- 3
- 18
-
I already implemented the same in verilog. It was showing an error: " Set_interation_limit XX" – Vineeth Ananthula Oct 29 '16 at 15:24