--- Quote Start ---
Hey,
I'm working with an Arria II GX. I've been having timing issues with the lpm_divide megafunction. I have created a divider using the MegaWizard Plug-In Manager that has a Numerator of 64-bits (signed, FixedPoint) and a Denominator of 32-bits (signed, FixedPoint).
I've been fighting the core's failing timing for so long that I decided to create a new project with the divider as the top-level. The only other file in the new project is my SDC file with my clock settings (150 MHz). After running Synthesis and Fitter over and over changing the core's internal latency, I've found that the core all by itself needs a latency of at least 40-45 cycles to pass timing in the TimeQuest Timing Analyzer (and this is with greatly increased Synthesis and Fitter settings optimized for Speed).
I realize that having the numerator at 64-bits is the maximum the core allows, but in our application I don't see any way around it. Does anyone have any ideas/hints that can help with this timing issue? The core is part of a much larger processor project, and it has become a real burden to close timing with these Div Cores crying all the time. I'm using Quartus II ver. 11.0. Any help is greatly appreciated.
--- Quote End ---
connect the divider to a slow clock domain(like 50Mhz).sync the input to the slow clock and sync the result to the 150Mhz.
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Target Devices:
// Tool versions:
//
// Create Date:
// Project Name:
// Project Top Name:
// Design Name:
// Module Top Name:
// Module Name:
// Description:
//
// Dependencies: numer / denom
// SYNC_LEN > 2
// delay equal to (DEL_LEN)*SYNC_LEN + 2 + (SYNC_LEN - DEL_LEN)
// Revision: 1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 10ps
module DIV_TOP# (
parameter CLK_SYS = 160_000_000,
parameter CLK_DIV = 40_000_000,
parameter SYNC_LEN = 3
)
(
input clk_div, // 40M
input clk_sys, //160MHz
input rst_n,
input div_start,
input [23:0] numer,
input [13:0] denom,
output reg div_done,
output [23:0] quotient,
output [13:0] remain
);
/********************************************************
Parameter
\********************************************************/
localparam U_DLY = 1;
localparam DEL_LEN = CLK_SYS / CLK_DIV;
/********************************************************
Signals
\********************************************************/
reg [SYNC_LEN-1:0] sync_shift;
reg [SYNC_LEN-1:0] sync_shift2;
reg div_start_flag;
reg div_valid;
wire div_en;
reg div_en_dly;
reg [23:0] div_num;
reg [13:0] div_dem;
reg [23:0] div_quo;
reg [13:0] div_rem;
wire [23:0] div_quo_w;
wire [13:0] div_rem_w;
/********************************************************
Main code
\********************************************************/
assign div_en = sync_shift[SYNC_LEN-1] ^ sync_shift[SYNC_LEN-2];
assign quotient = div_quo;
assign remain = div_rem;
always@(posedge clk_sys,negedge rst_n)
begin
if(rst_n==1'b0)
begin
div_start_flag <= 1'b0;
end
else if(div_start)
begin
div_start_flag <=# U_DLY ~div_start_flag;
end
end
always@(posedge clk_sys,negedge rst_n)
begin
if(rst_n==1'b0)
begin
div_num <= 'h0;
div_dem <= 'h0;
end
else if(div_start)
begin
div_num <=# U_DLY numer;
div_dem <=# U_DLY denom;
end
end
always@(posedge clk_sys,negedge rst_n)
begin
if(rst_n==1'b0)
begin
div_quo <= 'h0;
div_rem <= 'h0;
end
else if(div_valid)
begin
div_quo <=# U_DLY div_quo_w;
div_rem <=# U_DLY div_rem_w;
end
end
always@(posedge clk_sys,negedge rst_n)
begin
if(rst_n==1'b0)
begin
div_done <= 'b0;
end
else
begin
div_done <=# U_DLY div_valid;
end
end
always@(posedge clk_div,negedge rst_n)
begin
if(rst_n==1'b0)
begin
sync_shift <= 'h0;
end
else
begin
sync_shift <=# U_DLY {sync_shift[SYNC_LEN-2:0],div_start_flag};
end
end
always@(posedge clk_sys,negedge rst_n)
begin
if(rst_n==1'b0)
begin
sync_shift2 <= 'h0;
end
else
begin
sync_shift2 <=# U_DLY {sync_shift2[SYNC_LEN-2:0],div_en_dly};
end
end
always@(posedge clk_div,negedge rst_n)
begin
if(rst_n==1'b0)
begin
div_en_dly <= 1'b0;
end
else
begin
div_en_dly <=# U_DLY div_en;
end
end
always@(posedge clk_sys,negedge rst_n)
begin
if(rst_n==1'b0)
begin
div_valid <= 1'b0;
end
else
begin
div_valid <=# U_DLY ~sync_shift2[SYNC_LEN-1]&sync_shift2[SYNC_LEN-2];
end
end
/********************************************************
instance
\********************************************************/
DIV_24_14 DIV_U0(
.clken (div_en),
.clock (clk_div),
.denom (div_dem),
.numer (div_num),
.quotient (div_quo_w),
.remain (div_rem_w)
);
endmodule