Could you help me with this timing errors please?

Hi guys,
While playing around with the verilog code I came across various timing errors, some right out of the box, some popping up after making the slightest changes.
I forgot to write down what kind of errors (setup/hold) these were, but here goes:

Timing errors at the digital loop mux:

After reading an article entitled Discussion on the influencing factors of clock in FPGA design: http://www.kynix.com/Blog/439.html, I got rid of these by adding a pipeline stage between the DAC output od the input of the ADC buffer:

always @(posedge adc_clk)
begin
digital_loop_r <= digital_loop;
dac_a_r <= dac_a;
dac_b_r <= dac_b;
end

// transform into 2's complement (negative slope)
// looped DAC data are pipelined to avoid timing problems
assign adc_a = digital_loop_r ? dac_a_r : {adc_dat_a[14-1], ~adc_dat_a[14-2:0]};
assign adc_b = digital_loop_r ? dac_b_r : {adc_dat_b[14-1], ~adc_dat_b[14-2:0]};

Timing errors between the ADC input pins and ADC input register:

I resolved these by inverting the clock phase of clk_adc and clk_dac_1x

PLLE2_ADV #(
.BANDWIDTH ("OPTIMIZED"),
.COMPENSATION ("ZHOLD" ),
.DIVCLK_DIVIDE ( 1 ),
.CLKFBOUT_MULT ( 8 ),
.CLKFBOUT_PHASE ( 0.000 ),
.CLKOUT0_DIVIDE ( 8 ),
.CLKOUT0_PHASE ( 180.000 ), // originally 0
.CLKOUT0_DUTY_CYCLE ( 0.5 ),
.CLKOUT1_DIVIDE ( 8 ),
.CLKOUT1_PHASE ( 180.000 ), // originally 0
.CLKOUT1_DUTY_CYCLE ( 0.5 ),
.CLKOUT2_DIVIDE ( 4 ),
.CLKOUT2_PHASE ( 0.000 ),
.CLKOUT2_DUTY_CYCLE ( 0.5 ),
.CLKOUT3_DIVIDE ( 4 ),
.CLKOUT3_PHASE (-45.000 ),
.CLKOUT3_DUTY_CYCLE ( 0.5 ),
.CLKOUT4_DIVIDE ( 4 ), // 4->250MHz, 2->500MHz
.CLKOUT4_PHASE ( 0.000 ),
.CLKOUT4_DUTY_CYCLE ( 0.5 ),
.CLKOUT5_DIVIDE ( 4 ), // originally 4
.CLKOUT5_PHASE ( 0 ), // originally 0
.CLKOUT5_DUTY_CYCLE ( 0.5 ),
.CLKIN1_PERIOD ( 8.000 ),
.REF_JITTER1 ( 0.010 )
) pll (
// Output clocks
.CLKFBOUT (clk_fb_o ),
.CLKOUT0 (clk_adc ),
.CLKOUT1 (clk_dac_1x),
.CLKOUT2 (clk_dac_2x),
.CLKOUT3 (clk_dac_2p),
.CLKOUT4 (clk_ser ),
.CLKOUT5 (clk_pwm ),
// Input clock control
.CLKFBIN (clk_fb_i ),
.CLKIN1 (clk ),
.CLKIN2 (1'b0 ),
// Tied to always select the primary input clock
.CLKINSEL (1'b1 ),
// Ports for dynamic reconfiguration
.DADDR (7'h0 ),
.DCLK (1'b0 ),
.DEN (1'b0 ),
.DI (16'h0),
.DO ( ),
.DRDY ( ),
.DWE (1'b0 ),
// Other control and status signals
.LOCKED (pll_locked),
.PWRDWN (1'b0 ),
.RST (!rstn )
);

De-skewing clk_adc by adding a BUFG to the clock feedback loop also works, but I don’t know if this would introduce unacceptable jitter.
(Vivado reported 6ns of clock skew - geez!)

Timing errors at the PWM output:

These are easily resolved by adding a pipleine stage to the output signal:

module red_pitaya_pwm #(
int unsigned CCW = 32, // configuration counter width (resolution)
bit [8-1:0] FULL = 8'd156 // 100% value
)(
// system signals
input logic clk , // clock
input logic rstn, // reset
// configuration
input logic [CCW-1:0] cfg , // 
// PWM outputs
output logic pwm_o , // PWM output - driving RC
output logic pwm_s // PWM synchronization
);

reg [ 4-1: 0] bcnt ;
reg [16-1: 0] b ;
reg [ 8-1: 0] vcnt, vcnt_r;
reg [ 8-1: 0] v , v_r ;

reg pwm_o_r;

always @(posedge clk)
if (~rstn) begin
vcnt <= 8'h0 ;
bcnt <= 4'h0 ;
pwm_o_r <= 1'b0 ;
pwm_o <= pwm_o_r;
end else begin
vcnt <= (vcnt == FULL) ? 8'h1 : (vcnt + 8'd1) ;
vcnt_r <= vcnt;
v_r <= (v + b[0]) ; // add decimal bit to current value
if (vcnt == FULL) begin 
bcnt <= bcnt + 4'h1 ;
v <= (bcnt == 4'hF) ? cfg[24-1:16] : v ; // new value on 16*FULL
b <= (bcnt == 4'hF) ? cfg[16-1:0] : {1'b0,b[15:1]} ; // shift right
end
// make PWM duty cycle
pwm_o_r <= (vcnt_r <= v_r) ;
pwm_o <= pwm_o_r;
end

assign pwm_s = (bcnt == 4'hF) && (vcnt == (FULL-1)) ; // latch one before

endmodule: red_pitaya_pwm

And finally constant problems with the axi protocol converter interfacing the XADC IP.
Looks like the code barely manges to work at the configured 200MHz for clk_fpga3

Since nothing fast seems to be attached to this axi interface, I changed clk_fpga3 from 200MHz to 125MHz in the block design, and haven’t gotten any complaints since then.
The XADC data still are trickling in.

Am I heading in the right direction here?
Comments are welcome. :wink:

Cheers,
Joshua