Wrong - it's "hello Jonathan". I post on my own behalf.
Corporate disclaimer is partly so that there can be no
suggestion that I'm concealing anything, and partly because
(quite properly) my employers insist I include it.
In any normal modern FPGA or ASIC technology, you should always
try to use exactly one clock signal for all the flip-flops in a
design - or, at least, in any large block of a design. This
approach is known as "synchronous design" and it has many
important benefits, which you can easily find for yourself
by looking at a modern digital design text, or back through the
archives of this group or comp.arch.fpga.
There are some exceptions, of course.
For very low power designs, it is useful to be able to switch
off or slow the clock to blocks of the design. This is known
as "clock gating" and it needs special care.
For communications, multimedia and some other applications,
it is possible that part of the design is forced to use a
standardised clock speed that is different from other clocks
in your system. For example, you may have a 270MHz clock
derived from an incoming D1 digital video stream, but
perhaps you also need a locally generated 133MHz
clock for your CPU and memory subsystem. To get the data
from one zone of clocking ("clock domain") to another
requires special care and special techniques - Google for
"clock domain crossing" to find more.
Yes. But if the debouncer has an output "keypress", which goes true
for exactly one clock period, you can then use that keypress signal
as a clock-enable for other logic that has THE SAME CLOCK as the
debouncer. Therefore, all flip-flops have just one clock.
This is extremely easy to implement in VHDL. The following is
only a sketch - you will need to fill in various declarations
of signals, ports, etc. to complete it - I don't want to do
all your homework for you.
-- Number of clocks for which the keypress must be stable
constant debounce_cycles: integer := 10;
debouncer: process (clock)
variable resynch: std_logic;
variable previous_key: std_logic;
variable debounce_count: integer range 0 to debounce_cycles;
begin
if rising_edge(clock) then
-- Has the key_input state changed?
if previous_key /= resynch then
-- Yes, it changed. Reset the timeout.
debounce_count := debounce_cycles;
else
-- Key is stable. Has it been stable for long enough?
if debounce_count /= 0 then
-- Not yet. Continue counting.
debounce_count := debounce_count - 1;
else
-- Yes, it is stable. Update the output signal.
debounced_key <= resynch;
end if;
end if;
-- update the state
previous_key := resynch;
resynch := key_input;
end if; -- rising_edge
end process;
OK, so now we have a signal "debounced_key" that is a
stabilized version of the bouncy "key_input". Now let's
find when it was pushed, by edge-detecting it SYNCHRONOUSLY:
edge_detector: process (clock)
variable old: std_logic;
begin
if rising_edge(clock) then
if debounced_key = '1' and old = '0' then
-- Stable form of key made a 0->1 transition
keypress <= '1';
else
keypress <= '0';
end if;
old := debounced_key;
end if; -- rising_edge
end process;
Finally we can use the "keypress" signal to enable other
clocked logic, so that it operates only once per keypress
even though the clock is ticking much faster:
some_counter: process(clock)
begin
if rising_edge(clock) then
if synch_reset = '1' then
-- Unconditionally reset the counter
johnson_counter <= (others => '0');
elsif keypress = '1' then
-- We detected a keypress on this cycle, so
-- we should do something interesting
johnson_counter <=
(not johnson_counter(0)) &
johnson_counter(N-1 downto 1);
else
-- No keypress, so do nothing
null;
end if;
end if; -- rising_edge
end process;
You'll note that this design is fully synchronous. EVERY
flip-flop is clocked by the SAME clock, which can be as fast
as you like - don't forget, of course, that if the clock is
very fast then your debounce_cycles value will need to be
correspondingly large.
Ho hum, looks like I did the homework after all.
But it sounds as though it's not the solution the prof
wanted, so that's OK then
For extra credit, find how to get the Johnson counter
to count out of illegal states automatically (mine
doesn't).
For more extra credit, discuss
(a) why do I need the "resynch_key" variable at all -
why can't I just use the key_input signal directly?
(b) is it sufficient to have just one "resynch_key"
variable, or do I need two or more?
(c) what the blazes are you doing with a Johnson counter
anyhow?
--
Jonathan Bromley, Consultant
DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)://
www.MYCOMPANY.com
The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.