`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
// Company:
|
// Company:
|
// Engineer:
|
// Engineer:
|
//
|
//
|
// Create Date: 19:39:14 08/24/2011
|
// Create Date: 19:39:14 08/24/2011
|
// Design Name:
|
// Design Name:
|
// Module Name: divider
|
// Module Name: divider
|
// Project Name:
|
// Project Name:
|
// Target Devices:
|
// Target Devices:
|
// Tool versions:
|
// Tool versions:
|
// Description:
|
// Description:
|
//
|
//
|
// Dependencies:
|
// Dependencies:
|
//
|
//
|
// Revision:
|
// Revision:
|
// Revision 0.01 - File Created
|
// Revision 0.01 - File Created
|
// Additional Comments: Based on my description on youtube:
|
// Additional Comments: Based on my description on youtube:
|
// http://youtu.be/TEnaPMYiuR8
|
// http://youtu.be/TEnaPMYiuR8
|
//
|
//
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
module qdiv #(
|
module qdiv #(
|
//Parameterized values
|
//Parameterized values
|
parameter Q = 15,
|
parameter Q = 15,
|
parameter N = 32
|
parameter N = 32
|
)
|
)
|
(
|
(
|
input [N-1:0] i_dividend,
|
input [N-1:0] i_dividend,
|
input [N-1:0] i_divisor,
|
input [N-1:0] i_divisor,
|
input i_start,
|
input i_start,
|
input i_clk,
|
input i_clk,
|
output [N-1:0] o_quotient_out,
|
output [N-1:0] o_quotient_out,
|
output o_complete,
|
output o_complete,
|
output o_overflow
|
output o_overflow
|
);
|
);
|
|
|
reg [2*N+Q-3:0] reg_working_quotient; // Our working copy of the quotient
|
reg [2*N+Q-3:0] reg_working_quotient; // Our working copy of the quotient
|
reg [N-1:0] reg_quotient; // Final quotient
|
reg [N-1:0] reg_quotient; // Final quotient
|
reg [N-2+Q:0] reg_working_dividend; // Working copy of the dividend
|
reg [N-2+Q:0] reg_working_dividend; // Working copy of the dividend
|
reg [2*N+Q-3:0] reg_working_divisor; // Working copy of the divisor
|
reg [2*N+Q-3:0] reg_working_divisor; // Working copy of the divisor
|
|
|
reg [N-1:0] reg_count; // This is obviously a lot bigger than it needs to be, as we only need
|
reg [N-1:0] reg_count; // This is obviously a lot bigger than it needs to be, as we only need
|
// count to N-1+Q but, computing that number of bits requires a
|
// count to N-1+Q but, computing that number of bits requires a
|
// logarithm (base 2), and I don't know how to do that in a
|
// logarithm (base 2), and I don't know how to do that in a
|
// way that will work for everyone
|
// way that will work for everyone
|
|
|
reg reg_done; // Computation completed flag
|
reg reg_done; // Computation completed flag
|
reg reg_sign; // The quotient's sign bit
|
reg reg_sign; // The quotient's sign bit
|
reg reg_overflow; // Overflow flag
|
reg reg_overflow; // Overflow flag
|
|
|
initial reg_done = 1'b1; // Initial state is to not be doing anything
|
initial reg_done = 1'b1; // Initial state is to not be doing anything
|
initial reg_overflow = 1'b0; // And there should be no woverflow present
|
initial reg_overflow = 1'b0; // And there should be no woverflow present
|
initial reg_sign = 1'b0; // And the sign should be positive
|
initial reg_sign = 1'b0; // And the sign should be positive
|
|
|
assign o_quotient_out[N-2:0] = reg_working_quotient; // The division results
|
initial reg_working_quotient = 0;
|
|
initial reg_quotient = 0;
|
|
initial reg_working_dividend = 0;
|
|
initial reg_working_divisor = 0;
|
|
initial reg_count = 0;
|
|
|
|
|
|
assign o_quotient_out[N-2:0] = reg_quotient[N-2:0]; // The division results
|
assign o_quotient_out[N-1] = reg_sign; // The sign of the quotient
|
assign o_quotient_out[N-1] = reg_sign; // The sign of the quotient
|
assign o_complete = reg_done;
|
assign o_complete = reg_done;
|
assign o_overflow = reg_overflow;
|
assign o_overflow = reg_overflow;
|
|
|
always @( posedge i_clk ) begin
|
always @( posedge i_clk ) begin
|
if( reg_done && i_start ) begin // This is our startup condition
|
if( reg_done && i_start ) begin // This is our startup condition
|
// Need to check for a divide by zero right here, I think....
|
// Need to check for a divide by zero right here, I think....
|
reg_done <= 1'b0; // We're not done
|
reg_done <= 1'b0; // We're not done
|
reg_count <= N+Q-2; // Set the count
|
reg_count <= N+Q-1; // Set the count
|
reg_working_quotient <= 0; // Clear out the quotient register
|
reg_working_quotient <= 0; // Clear out the quotient register
|
reg_working_dividend <= 0; // Clear out the dividend register
|
reg_working_dividend <= 0; // Clear out the dividend register
|
reg_working_divisor <= 0; // Clear out the divisor register
|
reg_working_divisor <= 0; // Clear out the divisor register
|
reg_overflow <= 1'b0; // Clear the overflow register
|
reg_overflow <= 1'b0; // Clear the overflow register
|
|
|
reg_working_dividend[N+Q-2:Q] <= i_dividend[N-2:0]; // Left-align the dividend in its working register
|
reg_working_dividend[N+Q-2:Q] <= i_dividend[N-2:0]; // Left-align the dividend in its working register
|
reg_working_divisor[2*N+Q-3:N+Q-1] <= i_divisor[N-2:0]; // Left-align the divisor into its working register
|
reg_working_divisor[2*N+Q-3:N+Q-1] <= i_divisor[N-2:0]; // Left-align the divisor into its working register
|
|
|
reg_sign <= i_dividend[N-1] ^ i_divisor[N-1]; // Set the sign bit
|
reg_sign <= i_dividend[N-1] ^ i_divisor[N-1]; // Set the sign bit
|
end
|
end
|
else if(!reg_done) begin
|
else if(!reg_done) begin
|
reg_working_divisor <= reg_working_divisor >> 1; // Right shift the divisor (that is, divide it by two - aka reduce the divisor)
|
reg_working_divisor <= reg_working_divisor >> 1; // Right shift the divisor (that is, divide it by two - aka reduce the divisor)
|
reg_count <= reg_count - 1; // Decrement the count
|
reg_count <= reg_count - 1; // Decrement the count
|
|
|
// If the dividend is greater than the divisor
|
// If the dividend is greater than the divisor
|
if(reg_working_dividend >= reg_working_divisor) begin
|
if(reg_working_dividend >= reg_working_divisor) begin
|
reg_working_quotient[reg_count] <= 1'b1; // Set the quotient bit
|
reg_working_quotient[reg_count] <= 1'b1; // Set the quotient bit
|
reg_working_dividend <= reg_working_dividend - reg_working_divisor; // and subtract the divisor from the dividend
|
reg_working_dividend <= reg_working_dividend - reg_working_divisor; // and subtract the divisor from the dividend
|
end
|
end
|
|
|
//stop condition
|
//stop condition
|
if(reg_count == 0) begin
|
if(reg_count == 0) begin
|
reg_done <= 1'b1; // If we're done, it's time to tell the calling process
|
reg_done <= 1'b1; // If we're done, it's time to tell the calling process
|
|
reg_quotient <= reg_working_quotient; // Move in our working copy to the outside world
|
if (reg_working_quotient[2*N+Q-3:N]>0)
|
if (reg_working_quotient[2*N+Q-3:N]>0)
|
reg_overflow <= 1'b1;
|
reg_overflow <= 1'b1;
|
end
|
end
|
else
|
else
|
reg_count <= reg_count - 1;
|
reg_count <= reg_count - 1;
|
end
|
end
|
end
|
end
|
|
|