01-13-2016 01:23 AM
Currently I am working on a project with Vivado 2014.3.1 & came across a cdc issue as shown in figure below.
i.e. timing violation between "up_xfer_toggle_reg" and "d_xfer_toggle_m1_reg" .
So used " xfer_vio " block as a synchronizer, as shown below.
(Is the usage correct ? Or should I use 2FF synchronizer : Because, had read online that usually 2FF design is used )
Due to the design which I used, as showed in the 2nd figure(above); timing violations got reduced reduced / number of failing points reduced.
Is the implementation of synchronizer proper ?
(Or should I use 2FF synchronizer)
If the implementation is right, can I assign the clock as asynchronous using constraint for removing the timing violations ?
If the implementation is NOT right, can you please specify any other way of doing it.
Thanks in advance,
01-13-2016 05:44 AM
01-17-2016 10:33 PM
Thanks for the reply venkata.
Tried it between 2 single bit register path. It helped. :-)
How can I proceed when the data path is between multi-bit regs ? ( If possible please explain ) Can you please point me to any topic / doc that i should go through ?
(This is my first experience with this kind of domain crossing . Sorry, if this is too basic to ask )
Thanks & regards,
01-17-2016 10:45 PM
01-18-2016 03:55 AM
Thanks for pointing me to those threads Shreyas.
By multi-bit I was referring to 'bus'.
Have used fifo for this purpose earlier(for other path).
Am not sure which one(fifo / FF for each bit in the reg) should be used [between regs 'd_data_cntrl' & 'up_xfer_data'] .
Can you please suggest ?
module d2l_l2d_up_xfer_cntrl ( up_rstn, up_clk, up_data_cntrl, up_xfer_done, d_rst, d_clk, d_data_cntrl); parameter DATA_WIDTH = 8; localparam DW = DATA_WIDTH - 1; input up_rstn; input up_clk; input [DW:0] up_data_cntrl; output up_xfer_done; input d_rst; input d_clk; output [DW:0] d_data_cntrl; // internal registers reg [ 5:0] up_xfer_count = 'd0; reg up_xfer_done = 'd0; reg up_xfer_toggle = 'd0; reg [DW:0] up_xfer_data = 'd0; reg d_xfer_toggle_m1 = 'd0; reg d_xfer_toggle_m2 = 'd0; reg d_xfer_toggle_m3 = 'd0; reg [DW:0] d_data_cntrl = 'd0; // internal signals wire d_xfer_toggle_s; always @(negedge up_rstn or posedge up_clk) begin if (up_rstn == 1'b0) begin up_xfer_count <= 'd0; up_xfer_done <= 'd0; up_xfer_toggle <= 'd0; up_xfer_data <= 'd0; end else begin up_xfer_count <= up_xfer_count + 1'd1; up_xfer_done <= (up_xfer_count == 6'd1) ? 1'b1 : 1'b0; if (up_xfer_count == 6'd1) begin up_xfer_toggle <= ~up_xfer_toggle; up_xfer_data <= up_data_cntrl; end end end assign d_xfer_toggle_s = d_xfer_toggle_m3 ^ d_xfer_toggle_m2; sync_block 2FF_sync ( .clk (d_clk), .data_in (up_xfer_toggle), .data_out (d_q) ); always @(posedge d_clk) begin if (d_rst == 1'b1) begin d_xfer_toggle_m1 <= 'd0; d_xfer_toggle_m2 <= 'd0; d_xfer_toggle_m3 <= 'd0; d_data_cntrl <= 'd0; end else begin // d_xfer_toggle_m1 <= up_xfer_toggle; d_xfer_toggle_m1 <= d_q; d_xfer_toggle_m2 <= d_xfer_toggle_m1; d_xfer_toggle_m3 <= d_xfer_toggle_m2; if (d_xfer_toggle_s == 1'b1) begin d_data_cntrl <= up_xfer_data; end end end endmodule