How to give division more clock cycles to settle? - Page 1
Forum section: electronics / general

author: Maister
author_rank: Contributor
timestamp: June 10, 2025, 12:05:37 pm
content: Howdy all!I recently came across a case where I needed to do a division of 2 fixed point variables. Both are type sfixed(10 downto -8) which should be 11Q8 FXP format.(The format does not matter, actually I had this problem with integers before.)Code:VHDL:resize(resize(x_sum , 10, -8) / resize(w_sum , 10, -8) , 10, -8);This is the division step in the calculation. As you can see, I am using just the slash "/" symbol for the division. Because the sythesis and fitter need to cascade to many adders and multipliers for this, I do not meet timing with this, which is even visible in the result being different every caculation with same inputs.When using a vendor IP block for division or writing your own iterative divider you can have a "result_valid" flag that you use for latching the result in the level above the divider. But how to let the design "wait" a few clock cycles until the division finishes with the slash "/" approach?My approach so far was as follows:Since I already have a state machine for all the calculations anyways, I gave it one more state and a timer before latching that division result:Code:VHDL:when DIVIDE1 =>-- go to some wait cycles for long combiational path of division-- this is the first wait cycletimer := 0;stage <= DIVIDE2;when DIVIDE2 =>if timer < 2 then -- Wait for ~2 additional cyclestimer := timer + 1;else-- latch the division's result nowif to_integer(w_sum) /= 0 thenx_result <= resize(resize(x_sum , 10, -8) / resize(w_sum , 10, -8) , 10, -8);y_result <= resize(resize(y_sum , 10, -8) / resize(w_sum , 10, -8) , 10, -8);elsex_result <= resize(x_sum, 10, -8);y_result <= resize(y_sum, 10, -8);end if;timer := 0;stage <= NEXT_STAGE;end if;This seems to have solved the issue for my current project on the actual hardware and together with the SDC commands to treat this as a multycycle_path:Code:SDC:set_multicycle_path -setup 4 \-from [get_registers {w_sum[*]}] \-to [get_registers {x_result[*]}]set_multicycle_path -setup 4 \-from [get_registers {w_sum[*]}] \-to [get_registers {y_result[*]}]set_multicycle_path -hold 3 \-from [get_registers {w_sum[*]}] \-to [get_registers {x_result[*]}]set_multicycle_path -hold 3 \-from [get_registers {w_sum[*]}] \-to [get_registers {y_result[*]}]set_multicycle_path -setup 4 \-from [get_registers {x_sum[*]}] \-to [get_registers {x_result[*]}]set_multicycle_path -setup 4 \-from [get_registers {y_sum[*]}] \-to [get_registers {y_result[*]}]set_multicycle_path -hold 3 \-from [get_registers {x_sum[*]}] \-to [get_registers {x_result[*]}]set_multicycle_path -hold 3 \-from [get_registers {y_sum[*]}] \-to [get_registers {y_result[*]}]... the static timing analysis also succeeds.Is this the way you would go about this or would you always use a division block / vendor IP that gives you a "division_ready" flag when it is finished?CheersPatrick

author: asmi
author_rank: Super Contributor
timestamp: June 11, 2025, 05:45:36 am
content: There are two ways to deal with this - either manually pipeline/create multistep fsm, or add some number of pipeline registers to the output and enable retiming, letting the toolchain to do the job for you.