Rakesh
Rakesh

Reputation: 283

How to handle data going from a clock domain to another clock domain whose clock is divide by 2 version of the first clock?

I have the following code.

module tb;

reg clk;
reg clk_2;
reg [15:0] from_flop;
reg [15:0] to_flop;

initial begin
        clk = 0; 
        clk_2 = 0;
        from_flop = 1;
end

always #10 clk = ~clk;


always @(posedge clk) begin
        clk_2 <= ~clk_2;
end


always @(posedge clk) begin
        from_flop <= from_flop + 1; 
end

always @(posedge clk_2) begin
        to_flop <= from_flop; 
end

endmodule

However, at time instant 10ns, from_flop and to_flop both get value = 2. This is contrary to what I was expecting. I was expecting from_flop to change from 1 to 2 at 10ns, and to_flop to change from x to 1 at 10ns.

Why is this happening and how to code such that this doesn't happen?

Upvotes: 2

Views: 683

Answers (2)

Greg
Greg

Reputation: 19104

Usually assignments in a sequential block are use non-blocking (<=) assignments. The one notable except is for generating derived clocks, which should use blocking (=) assignments. Blocking assignments in sequential blocks are legal; but you need to know what you are doing or you will get a functional mismatch between RTL simulation and circuit. That said, you still needed to error on the side of caution when using this approach.

A flip-flop has has a clock to Q delay, there for any derived clocks will have a phase offset from its parent clock. Some synthesizing tools may compensate the offset for you, however you will need to specify all cases where this should happen to the synthesizer; it will not figure it out for you. This means you should not create derived clocks sporadically across the design. All derived clocking signals need to be generated from one dedicated module; this keeps it manageable.

In most cases you should not create any derived clock. Instead, sample every other clock by adding an extra flip-flop.

always @(posedge clk) begin
  from_flop <= from_flop + 1; 
  if (transfer_n==1'b0) begin
    to_flop <= from_flop;
  end
  transfer_n <= ~transfer_n;
end

This strategy keeps the design in one clock domain which usually makes synthesis easier with better timing. The area impact from the extra flop in minimal can easily be less then the area penalty from the added buffers needed to keep the derived clocks aligned.

Upvotes: 2

Matthew
Matthew

Reputation: 13967

The problem is this line:

clk_2 <= ~clk_2;

You are using a non-blocking assignment, when perhaps you wanted a blocking assignment:

clk_2 = ~clk_2;

Non-blocking assignments are scheduled after blocking assignments, so the always @(posedge clk) begin will always be clocked before always @(posedge clk_2) begin.

Obviously, this isn't synthesisable code. So, this is a simulation (scheduling) issue. If you are going to synthesise something with this functionality, consider very carefully how you generate the divided clock.

http://www.edaplayground.com/x/AyQ

Upvotes: 0

Related Questions