Introduction: Synchronisers, Clock Domain Crossing, Clock Generators, Much More - Essential Tweak Circuits
In this blog, We will be seeing some circuits which I would like to call 'Tweak Circuits'. These micro-circuits will come handy for every RTL designer on numerous scenarios like clock domain crossing, reset signalling, internal clock generation etc. Let's see some of these circuits and scenarios where you may have to (or should have to !) use it in your design. We are gonna play around a bit with clock in these designs. I am presenting these circuits from my experience as an RTL designer so far. Kindly leave feedback if you have queries/suggestions :-)
All codes are in VHDL, I will try to add Verilog as well later on. But the ideas are same in any HDL ;-)
I will be adding more contents soon. Do follow me for updates.
Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.
Step 1: Multi-flop Synchroniser
When you send a single-bit signal from one clock domain to another clock domain (asynchronous), you SHOULD synchronise it to the destination clock domain to avoid metastability. For this purpose, We have to use flip-flop synchronisers. Traditional way is to use 2-flop synchronisers. I am presenting here with the VHDL code for a configurable multi-flop synchroniser in which you can configure more than 2 flops in synchroniser chain and increase MTBF or reduce metastability probability. I use this synchroniser to pass signal between synchronous clock domains of different clock periods as well, when I don't wanna put any multi-path clock constraining on such paths.
Generally hand-written RTL code is not recommended in designs for CDC crossing (especially data synchronisation). Specially hardened CDC cells are used to achieve this. This is one reason why I am not gonna talk about CDC data synchronisation. For eg: one popular RTL method is writing behavorial design of a mux-based data synchroniser. But it is noted that while this works in RTL behavioral simulation, synthesisers in ASIC/FPGA may give you a glitch-prone netlist which may fail CDC in gate-level simulation, and hence fail in the actual hardware as well ! Read here . Note that putting individual 2-flop synchroniser on each bit of databus IS NOT going to be safe CDC as well !
VHDL Code, Synthesis Notes:
Please note that you have to add a special placement constraint called ASYNC_REG if you are implementing this using Vivado. Altera should have a similar attribute (Which unfortunately I am not sure of). This attribute makes sure that all flops in the synchroniser chain will be placed close to each other in the FPGA for better MTBF. It is recommended to max-path constraint these paths instead of false-path constraints.
Library IEEE; use IEEE.std_logic_1164.all; Entity synchroniser is Generic(stages: natural := 2); -- No. of flops in synchroniser chain Port ( clk : in std_logic; -- Destination clock async_sig_i: in std_logic; -- Async signal driven by another clock domain sync_sig_o : out std_logic -- Synchronised signal out ); end synchroniser; <br>Architecture behav of synchroniser is -- Chain of flops signal flipflops: std_logic_vector(stages-1 downto 0) := (others => '0'); -- ONLY FOR XILINX VIVADO --------------------------- attribute ASYNC_REG : string; attribute ASYNC_REG of flip_flops: signals is "true"; ----------------------------------------------------- begin sync_sig_o <= (flipflops'high); -- Synchronised signal out process(clk) begin if rising_edge(clk) then flipflops <= flipflops(flipflops'high-1 downto 0) & async_sig_i; end if; end process; end behav;