Fast polling

B

Břrge Strand

Guest
Do you guys have any good thoughts about polling an async clock?

I have a feeling I'm missing something about buffering of signals because I
keep missing the edges I poll for when I try go get the speed up.

I run my FPGA on 100MHz and have to cope with an asynchronous 11 or 16MHz
clock to dump some serial bits. Data bits are read by an external unit on
the positive edge of this clock. What I want to do is detect the positive
edge and then set up the new data bit out of the FPGA. This means the FPGA
outputs new data right after the previous bit was read.

I poll by doing the following:

always @(posedge clk_100MHz)
begin
prev <= clock_11MHz;
prevprev <= prev;

if ({prevprev, prev} == 2'b01) // we detect a positive edge a little
while after it happens ...
begin
// do whatever happens on the positive edge
end
end

This works just fine when I compare {prevprev,prev} to a rise. If I compare
{prev,clock_11MHz} to a rise, quite a few of them are missed. However, I
want to spend as few clock ticks as possible on this, so I thought about
doing something like this instead:

if ({clock_11MHz,edge_detected} == 2'b10) // clock is high, but the edge
hasn't been detected
begin
edge_detected <= 1; // clock has gone up
// do what ever happens on the positive edge
end
if (clock_11MHz == 0)
edge_detected <= 0; // clock has gone down, start looking for positive
edge.

But this method too misses a lot of edges. Is there some kind of buffering
(Xilinx) that would make this code work?


Greetings,


Břrge Strand
 
"Břrge Strand" <borge.strand.remove.if.not.spamming@sintef.no> writes:

But this method too misses a lot of edges. Is there some kind of buffering
(Xilinx) that would make this code work?
How are the phases of the two clocks at this time? If they are close
you are likely to run into metastability problems.

Petter
--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
"Břrge Strand" <borge.strand.remove.if.not.spamming@sintef.no> wrote
in message news:1066720291.947785@halvan.trd.sintef.no...

I run my FPGA on 100MHz and have to cope with an asynchronous 11 or 16MHz
clock to dump some serial bits. Data bits are read by an external unit on
the positive edge of this clock. What I want to do is detect the positive
edge and then set up the new data bit out of the FPGA. This means the FPGA
outputs new data right after the previous bit was read.

I poll by doing the following:

always @(posedge clk_100MHz)
begin
prev <= clock_11MHz;
prevprev <= prev;

if ({prevprev, prev} == 2'b01) // we detect a positive edge
// a little after it happens ...
begin
// do whatever happens on the positive edge
end
end

This works just fine when I compare {prevprev,prev} to a rise. If I
compare
{prev,clock_11MHz} to a rise, quite a few of them are missed. However, I
want to spend as few clock ticks as possible on this
Could you set up the next bit ahead of time, and then present it to
the external port using a FF clocked by the async clock? This sounds
like a nice application for Weinstein's "flancter" circuit, although
since your FPGA clock is so much faster than the external clock I've
modified it by adding a resynchroniser on the handshake flag.

The obvious advantage of this approach is that the external serial
data is exactly synchronous with the external clock. The drawback
is that it won't scale to arbitrary different clock frequencies.
But it should be comfortably OK with 11MHz and 16MHz.


// handshake mechanism
reg flancter_100MHz, flancter_11MHz;
reg hs1, hs2; // resynchroniser for "handshake"
wire handshake;

assign handshake = flancter_11MHz ^ flancter_100MHz;

// Internal 100MHz logic presents new value on "next_data"
// every time the external serial interface takes data away
//
always @(posedge clk_100MHz or posedge reset) begin
if (reset) begin
next_data <= 0;
hs1 <= 0;
hs2 <= 0;
flancter_100MHz <= 0;
end else begin
// Resynchroniser
{hs1, hs2} <= {handshake, hs1};
// Look for rising edge on hs1
if (hs1 && !hs2) begin
// We got a rise on the handshake.
next_data <= <new_data_from_internal_logic>;
flancter_100MHz <= flancter_11MHz;
end
end
end

// 11MHz serial-output logic takes data from the buffer
// and then toggles the "flancter" FF so that the 100MHz
// logic knows it's OK to present new data
//
always @(posedge clk_11MHz or posedge reset) begin
// This test for !handshake is probably trivially true,
// because it MUST have been set up already by the
// 100MHz logic...
if (reset) begin
serial_out <= 0;
flancter_11MHz <= 0;
end else if (!handshake) begin
serial_out <= next_data;
flancter_11MHz <= ~flancter_100MHz; // NB INVERSION!
end
end

--

Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * Perl * Tcl/Tk * Verification * Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail: jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 

Welcome to EDABoard.com

Sponsor

Back
Top