Reputation: 98
I am working on a design which should detect the first match of two rising edges of two asynchronous clocks of different frequencies.
code something like this may work for simulation.
fork
@posedge clkA
begin
a=$time
end
@posedge clkB
begin
b=$time
end
join
if (a=b) then some code.
this code may work for simulation but if I want some synthesizable hardware logic what else can I use?
Upvotes: 3
Views: 3689
Reputation: 16228
It is not possible to reproduce in HW the behavior you described. The reason for this is that you compare the times exactly.
First of all, you need to explain what do you mean by "detect the first match of two rising edges". Given that two async clocks have variable (and unpredictable) phase relationship, the task of detecting simultaneous edges will (usually) be stated in terms of how much time is "simultaneous".
For example: detect when rising edges are spaced at most 5ns in time.
BTW, I assume here that both frequencies in question are known.
Please describe your problem in more details.
EDIT: This question became hardware question, which is not related to Verilog. It is not clear whether any of the solutions proposed here may work (and it is my personal belief that they won't). I submitted the same question at EE Stack Exchange - it is a place for HW questions, and there is higher chance that it will be answered there.
Upvotes: 2
Reputation: 19104
Too pull this off, first make dual-edge,dual-clock flip-flop. Start off with a dual clock D flip-flop Patent US6320442 B1. Now substitute the sub flip-flops with dual edge D flip-flops Patent US5793236 A or Patent US5327019 A. Each patent has diagrams of the circuit design.
With the custom flop, create a small pipeline sampling the history of the clocks. Look for a zero to one transition.
Example:
wire [1:0] historyA, historyB;
// dualedge_dualclock_dff ( output Q, input D, clkA, clkB, rst_n)
dualedge_dualclock_dff dedc_histA1( .Q(historyA[1]), .D(historyA[0]), .* );
dualedge_dualclock_dff dedc_histA0( .Q(historyA[0]), .D(clkA), .* );
dualedge_dualclock_dff dedc_histB1( .Q(historyB[1]), .D(historyB[0]), .* );
dualedge_dualclock_dff dedc_histB0( .Q(historyB[0]), .D(clkB), .* );
wire dual_posedge_match = ({historyA,historyB} == 4'b0101);
Dual-edge flops and dual-clock flops are not common design practices. Excessive timing analysis will be needed and tools might complain about the cell. Plus, steps need to be taken for patent uses compliance with the law.
Upvotes: 1
Reputation: 901
This one is kind of tricky but if you can get a third clock that is twice as fast as the fastest clock between the two that you need to detect and can accept a one cycle delay of detection (the one cycle is in reference to the third clock domain) then it is possible.
what you will need to do is set up to registers for each clk domain like this:
input clk1, clk2'
...
reg clk1_in, clk1_out;
reg clk2_in, clk2_out;
wire clk1_posedge, clk2_posedge;
//take in the clock value, you should register this so that way jitter on the line does not mess with it
always@(posedge clk3)begin
clk1_in <= clk1;
clk2_in <= clk2;
end
always@(posedge clk3)begin
clk1_out <= clk1_in;
clk2_out <= clk2_in;
end
//now you need to detect the posedge for each signal independently, you can use and and gate for this
assign clk1_posedge = (~clk1_out && clk1_in);
assign clk2_posedge = (~clk2_out && clk2_in);
// now just and the two together
assign pulse_detected = clk1_posedge && clk2_posedge
you need clk 3 to be twice as fast, otherwise you get aliasing (look up nyquist freq)
so what happens is the first register for the clock domain will be be high and if it is the just getting high then the second register will still be low for that cycle.
Upvotes: 2