RedditPP Mascot

RedditPP

r/FPGA • … • u/Wild_Meeting1428

Resolving timing issues of long combinatorial paths

**Solved:** I reordered registers between my function calls, by replacing my functions with modules, doing the pipelining only for the module itself. Interestingly, I could reduce registers with that approach. The whole chain had with my last attempt 13 pipline steps now it has 7 (2x4+1). Weirdly, Xilinx doesn't retime registers that far backwards.

\------------------------

I have the problem, that I have a long combinatorial path written in verilog. The path is that long for readability. My idea to get it to work, was to insert pipelining registers after the combinatorial non-blocking assign in the hope, the synthesis tool (vivado) would balance the register delays into the combinatorial logic, effectively making it to a compute pipeline.

But it seems, that vivado, even when I activate register retiming doesn't balance the registers, resulting in extreme negative slack of -8.65 ns (11.6 ns total).

The following code snipped in an \`always @(posedge clk)\` block shows my approach:

begin: S_NR2_S1 // ----- Newton–Raphson #2: y <- y * (2 - xn*y) ----- 2y - x_n*y² reg [IN_W-1:0] y_nr2_d1 , y_nr2_d2 , y_nr2_d3 , y_nr2_d4 , y_nr2_d5 , y_nr2_res ; reg [IN_W-1:0] shl_nr2_d1 , shl_nr2_d2 , shl_nr2_d3 , shl_nr2_d4 , shl_nr2_d5 , shl_nr2_res ; reg [IN_W-1:0] bad_nr2_d1 , bad_nr2_d2 , bad_nr2_d3 , bad_nr2_d4 , bad_nr2_d5 , bad_nr2_res ; reg [IN_W-1:0] sign_neg_nr2_d1, sign_neg_nr2_d2, sign_neg_nr2_d3, sign_neg_nr2_d4, sign_neg_nr2_d5, sign_neg_nr2_res;

y_nr2_res <= q_mul_u32_30(y_nr1, q_sub_ui(CONST_2P0, q_mul_u32_30(xn_nr1, y_nr1))); // final 1/xn in Q(IN_F) shl_nr2_res <= shl_nr1; bad_nr2_res <= bad_nr1; sign_neg_nr2_res <= sign_neg_nr1;

{y_nr2 , y_nr2_d1 , y_nr2_d2 , y_nr2_d3 , y_nr2_d4 , y_nr2_d5 } <= {y_nr2_d1 , y_nr2_d2 , y_nr2_d3 , y_nr2_d4 , y_nr2_d5 , y_nr2_res }; {shl_nr2 , shl_nr2_d1 , shl_nr2_d2 , shl_nr2_d3 , shl_nr2_d4 , shl_nr2_d5 } <= {shl_nr2_d1 , shl_nr2_d2 , shl_nr2_d3 , shl_nr2_d4 , shl_nr2_d5 , shl_nr2_res }; {bad_nr2 , bad_nr2_d1 , bad_nr2_d2 , bad_nr2_d3 , bad_nr2_d4 , bad_nr2_d5 } <= {bad_nr2_d1 , bad_nr2_d2 , bad_nr2_d3 , bad_nr2_d4 , bad_nr2_d5 , bad_nr2_res }; {sign_neg_nr2, sign_neg_nr2_d1, sign_neg_nr2_d2, sign_neg_nr2_d3, sign_neg_nr2_d4, sign_neg_nr2_d5} <= {sign_neg_nr2_d1, sign_neg_nr2_d2, sign_neg_nr2_d3, sign_neg_nr2_d4, sign_neg_nr2_d5, sign_neg_nr2_res}; end

How are you resolving timing issues in those cases, or what are the best practices to avoid that entirely?

![img](qmnv810qaf2g1)

![img](km84uckqaf2g1)

— 0