How to handle asynchronous inputs?

N

Nevo

Guest
All,

I'm new to FPGA design and have run into a fundamental problem that I'm sure
has a cookbook answer that "everyone" knows. Unfortunately, I don't have a
formal education in digital electronics and am stumped.

To oversimplify, my design has two inputs: COUNT_UP and RESET_COUNTER. On
the rising edge of COUNT_UP, I increment a counter. On the rising edge of
RESET_COUNTER, I set the counter to zero. The two inputs are completely
asynchronous and have no relationship to each other.

When synthesizing the design, I get an error that my counter is
multi-source. I understand the error and what it means, but not how to solve
it.

I thought I'd use an internal register, RESET_NEEDED, and set that on the
rising edge of RESET_COUNTER, then do the actual clearing of the counter and
resetting RESET_NEEDED on the rising edge of COUNT_UP, but in that case
RESET_NEEDED is now a multi source signal and I'm chasing my tail.

Can anyone point me to the solution to this problem?

Thanks,

-Nevo
 
Nevo wrote:

Can anyone point me to the solution to this problem?
see the "rising level counter" example here:
http://home.comcast.net/~mike_treseler/

That's pretty close.

-- Mike Treseler
 
What you need to do is to construct the counter with only
processes that are rising edge clocked and level reset. This
is what the synthesis tool turns into D flip-flops with async.
resets. Normally a counter would have an asynchronous
reset that holds the counter reset as long as RESET_COUNTER
is active. If you need to only reset on the rising edge
of RESET_COUNTER (i.e. the pulse width high is not
controlled) you could use your second approach, however
you must realize that the process for RESET_NEEDED
can have only one clock and a level-triggered (not edge
triggered) reset. Multiple clock sources are what the
synthesis tool complains about. If you are willing to
wait for a rising edge of COUNT_UP to reset the counter,
realizing that this will result in the loss of your first up count
after reset, you can construct the reset term for
RESET_NEEDED using the COUNT_UP as a clock.
Something like:

reg RESET_NEEDED;
reg RESET_TAKEN; // reset term for RESET_NEEDED

always @ (posedge RESET_COUNTER or posedge RESET_TAKEN)
begin
if (RESET_TAKEN)
RESET_NEEDED <= 1'b0;
else
RESET_NEEDED <= 1'b1;
end

always @ (posedge COUNT_UP)
begin
RESET_TAKEN <= RESET_NEEDED;
end

This has the drawback that you won't get a second reset if
RESET_COUNTER
has another rising edge after the COUNT_UP edge that resets the
counter.
This is due to the fact that RESET_TAKEN will stay high until the
following
edge of COUNT_UP.

If you need to treat RESET_COUNTER as an asynchronous input what
you really need is to create a pulse from its rising edge and use that
pulse to asynchonously reset your counter. Depending on the technology
you are using, this can normally be done using some sort of delay
element
and a gate. In an FPGA, look-up tables can be used as delay elements.
Normally you need to pound the tools into submission to avoid having
the delays "optimized" away. For Xilinx XST, instantiating a LUT of
some
type will assure this does not happen. If you use this approach you
need
to be sure that your delay element has a minimum delay (not always
easy to get from the data sheets) that exceeds the reset pulse width
requirements of the internal flip-flops that make up your counter.

If you have a fast (with respect to COUNT_UP) clock, you can construct
a delay element using a shift register clocked by the fast clock. This
should have a minimum of two stages to give a minimum pulse width of
one fast_clock period:

reg [1:0] shift_reg;

always @ (posedge fast_clock)
begin
shift_reg <= {shift_reg[0], RESET_COUNTER};
end
assign RESET_NEEDED = RESET_COUNTER & !shift_reg[1];

HTH,
Gabor

Nevo wrote:
All,

I'm new to FPGA design and have run into a fundamental problem that I'm sure
has a cookbook answer that "everyone" knows. Unfortunately, I don't have a
formal education in digital electronics and am stumped.

To oversimplify, my design has two inputs: COUNT_UP and RESET_COUNTER. On
the rising edge of COUNT_UP, I increment a counter. On the rising edge of
RESET_COUNTER, I set the counter to zero. The two inputs are completely
asynchronous and have no relationship to each other.

When synthesizing the design, I get an error that my counter is
multi-source. I understand the error and what it means, but not how to solve
it.

I thought I'd use an internal register, RESET_NEEDED, and set that on the
rising edge of RESET_COUNTER, then do the actual clearing of the counter and
resetting RESET_NEEDED on the rising edge of COUNT_UP, but in that case
RESET_NEEDED is now a multi source signal and I'm chasing my tail.

Can anyone point me to the solution to this problem?

Thanks,

-Nevo
 

Welcome to EDABoard.com

Sponsor

Back
Top