Electronic – How to design a two-stage synchronizer with a clock divider in Verilog

clocksystem-verilogverilog

I have a very fast clock called CLOCK_50 which I would like to slow down through the use of a clock divider. The output is clock. I also want to use a two-stage synchronizer for an asynchronous reset port reset0 which should output reset into the core. However, I'm not sure how to get these to work across different clock domains.

This is what I came up with. It generated several errors when compiled.

logic clock, reset1, reset2, reset;
logic [13:0] countCLK;

always_ff @(posedge CLOCK_50) begin
    reset1 <= reset0;
    reset2 <= reset1;
    reset <= reset2;
end

always_ff @(posedge CLOCK_50 or negedge reset) begin
    if (!reset) begin
        clock <= 1'b0;
        countCLK <= 14'b0;
    end

    else begin
        if (countCLK[13])
            clock <= ~clock;

        countCLK <= countCLK + 14'b1;
    end
end

And the warnings:

Warning (308040): (Medium) Rule C104: Clock signal source should drive only clock input ports. Found 1 nodes related to this rule.
    Warning (308010): Node  "clock"
Warning (308027): (Medium) Rule R105: The reset signal that is generated in one clock domain and used in another clock domain should be synchronized. Found 1 node(s) related to this rule.
    Warning (308010): Node  "reset"

Best Answer

What you have now is a three stage synchroniser running in the fast clock domain, so the reset output isn't a suitable synchronised reset for the core. Change the always block to be @(posedge clock). But there are other considerations:

For resets, you need to specify precisely how the reset should appear in the slow clock domain:

  • should it be synchronised on neither, one or two edges of the slow clock?
  • do you need a minimum length more than one cycle?
  • should it accept or reject input reset pulses shorter than a cycle?

Once you know the answers, you can design the reset circuitry. If you need to accept short input pulses, you need to use asynchronous clear on the first flop, and have it self set once the reset is delivered. The first flop is followed by the synchronisation chain.

On the clock divider

You don't mention which device you are using - if this is a hardware (FPGA - judging from the warnings) rather than theoretical exercise then I would advise you to use the technologies built into the device to do the clock division. In an FPGA instantiate a fPLL/PLL to output the lower speed clock, rather than inferring it from logic. This is still applicable for the ratio you have here: save yourself the 14 bit counter and use the built in. You can then easily add other derived clocks later, and take advantage of direct connections to the (skew-controlled) clock distribution network. For simulation, you can easily mock out the pll/replace it with a separate clock.

However what you might want is a gated clock enable (with the same period) rather than a new clock - it depends if the slow core can meet timing in the fast clock domain. I'd do this if the core is small (so power isn't an issue) trivial (so meets timing) and the clock change was only to meet some external bus requirements. This may make moving data between the core and the rest of the design easier.

If you were to use this inferred clock divider, there's no need to wire up reset logic for it. It will work and simulate fine if you initialise countCLK to zero in the Verilog so it has that value out of configuration.