Sunteți pe pagina 1din 16

Clock Domain Synchronization & Synthesis

Oct 7, 2009 Doug Tiedt Lead Digital Engineer, ZMDA Inc.

What ? Why?
What? Transferring data between 2 different clock domains. Data may be lost or duplicated if transfer is not synchronous to target Why? Consumer devices / PCs have more interfaces every day protocols with different clock frequencies Common situation is a fast processor or controller to slow interface Low Power operation clock device at slower speed High Speed operation GHz range

Concerns
Communication between clock domains needs to be designed such that information is not missed or duplicated. Communication between asynchronous domains needs to be designed so that (setup, hold) timing relationships are satisfied. Transfer of data must avoid metastability in target domain 2 serial flops is rule of thumb (1 in 106 chance / flop) May use 3+ flops in critical and/or GHz applications
D
CLK_FAST

Q
CLK_SLOW

Single Bit Synchronization


Target clock is faster than Source clock
D Q
CLK_SLOW CLK_FAST

D Q

D Q

D Q

Target clock is slower than Source clock (but synchronous)

D Q
CLK_FAST Handshake Logic CLK_SLOW

D Q

Bus Synchronization
Clock skew between bits in each domain prevents syncing entire bus in same manner
D Q D Q

0
D Q

0
D Q

1
D Q
CLK_A

D Q
CLK_B

Bus Synchronization
D Q D Q

0
D Q

0
D Q

1
D Q
CLK_A

D Q
CLK_B

Solutions: Create a valid or load bit, and synchronize that across domains Perhaps one can guarantee the source domain has been stable & propagation time met before clocking target register?

Speed Matching FIFO


Source and target clock domains are asynchronous and the product requirements varies which is faster. Source produces a lot of data faster than target can handle it need to buffer data Source produces data much slower than target can handle it want to buffer data until its worth the targets attention Designer may still need to handle FIFOs empty and full flags across domains.

Clock Tree Synthesis


Synthesis typically does daisy chain buffering, need balanced clock skew and delay
Loads unbalanced

CLK_BAD

CLK_GOOD

All loads balanced

Clock Tree Synthesis


Generally want to minimize clock skew. Might try increasing maximum insertion delay allowed to give tool more freedom to minimize skew. Clock insertion delay less important but does matter for timing analysis across PVT variation. Generated clocks need to be balanced with system clock, hence flops generating clocks need to be on a clock tap earlier in the tree Clock gating does the tool trace through non-buffer logic or treat that gate as a leaf in the clock tree? Timed (late or early) clocks not as common anymore(?), was used for timing fixes and trying to save a cycle point

What does Clock Tree Synthesis Do?


Traces through design until coming to a leaf pin (clk, set, rst of flop; specified leaf or excluded pin; Removes existing buffers & inverters. Balances wire and pin loads Generates a topology to best satisfy user constraints. If run after initial layout, it will move gates in netlist with PLACED attribute. Clock tree components have FIXED attribute.

Synthesis
Bottom-Up synthesis still needed for large designs, Top-Down works fine with smaller designs (50 100K gates). Synthesis scripts need to be developed with cooperation of designers: timing, scan, false paths May want to consider clock tree synthesis for large fanout nets (LFO) such as reset or test signals (scan shift) Good idea to quickly scan netlist:
1. 2. 3.

Do you see the flops used that you expect? Were attributes you set carried outdoes the netlist have a ripple carry adder or a CLA? Excessive buffering fixing a race path with a long chain of buffers wont work across corner PVT conditions anyway.

Code Style Matters for Synthesis


Some coding styles are not synthesis friendly create false dependencies Consider instantiating any asynchronous flops or logic
the resulting netlist is at the mercy of the tool and the library Will probably make RS flop out of synchronous D-flop with an async clear or set but which one? Which edge will the synthesizer choose? Want to make this flop controllable to improve scan coverage by gating off async signal.

Do you really want a priority encoding scheme in the logic?


Yes, sometimes either logical or timing reasons Other times may actually want a case statement or use assignments

Code Style Matters for Synthesis


For loops are unrolled during synthesis: the expression is

duplicated as many times as the loop index. Some optimizations not done inside a for loop. Always block should only contain sensitivity list and register assignments that are applicable see example Good coding practice to keep the sequential and combinational logic in separate blocks too. Use uni-directional busses whenever possible: simplifies logic, timing & false constraints, and synthesis constraints.

How to Confuse the Synthesizer


Actual original code:
always @(serial_out or scan_mode or pads_high_z_md or out_sel or ss or pdm_c_out) begin sda_data_out = serial_out; //default values sda_open_drain = 1'b0; sda_high_z = 1'b0; if (scan_mode) begin sda_high_z = 1'b1; //sdi input in scan mode end else if (pads_high_z_md) begin sda_high_z = 1'b1; //set pad to high-z if in the pads high-z test mode end else

How to confuse the Synthesizer


begin case (out_sel) `I2C_MODE : begin sda_open_drain = 1'b1; //set pad to open drain in I2C mode end `SPI_MODE : begin if (ss) begin sda_high_z = 1'b1; //if ss is high then set output to high-z end else begin sda_high_z = 1'b0; end end `PDM_MODE : begin sda_data_out = pdm_c_out; //send out the capacitive pdm end endcase // case(out_sel) end end

How to Confuse the Synthesizer


The former verilog code was legal and simulated correctly. After synthesis there were false dependencies between this code

and other verilog code pieces within module


Probably the result of the synthesizer attempting to optimize Incorrect simulation results

Same code fragment after rewrite:


//SDA/MISO/PDM_C/SDI pad assign sda_data_out = (out_sel == `PDM_MODE) ? pdm_c_out : serial_out; assign sda_high_z = scan_mode || pads_high_z_md || ((out_sel == `SPI_MODE) && ss); assign sda_open_drain = (out_sel == `I2C_MODE);

S-ar putea să vă placă și