counter with reset which is synchronous with one of two clocks

T

Thunder

I have two clocks- clk and clk_fast, and a counter which is supposed
to count the number of rising edges of clk_fast. Also count must reset
during every rising edge of clk. I use a one-bit signal called 'res'
which serves the purpose of resetting count. I have the following code
for the purpose.

process(clk,res,clk_fast)
begin
if (clk'event and clk='1') then
res <= '1';
elsif (clk_fast'event and clk_fast='1' and res='1' ) then
res <= '0';
end if;
end process;

process(clk_fast,res)
begin
if (res'event and res='1' )then
cnt <= 0;
elsif (clk_fast'event and clk_fast='1') then
cnt <= cnt + 1;
end if;
end process;

The above code generates an error message saying "Signal cnt cannot be
synthesized, bad synchronous description."
Similar error for 'res' too.

Could u please help me out with it?
 
J

Jonathan Bromley

I have two clocks- clk and clk_fast, and a counter which is supposed
to count the number of rising edges of clk_fast. Also count must reset
during every rising edge of clk. I use a one-bit signal called 'res'
which serves the purpose of resetting count. I have the following code
for the purpose.

Why not simply capture the count value on each rise of clk, and
then report the difference between successive captured counts?
Much easier to describe.

And I don't see you taking any care over resynchronising the
slow clock to the fast one. That's a recipe for trouble.

You are trying to use two different clocks within the same
clocked process, which will never work for synthesis. And
in any case, that would give you a design with two clock
domains - it's good to avoid this if possible.

How about this...

port (clk, clk_fast, global_reset: in std_logic;
clk_period: out std_logic_vector(7 downto 0) );
...
signal clk_resync, clk_resync2: std_logic;
signal count, stored_count: unsigned (7 downto 0);
...
process (clk_fast, global_reset)
begin
if global_reset = '1' then

clk_resync <= '0';
clk_resync2 <= '0';
count <= (others => '0');
stored_count <= (others => '0');
clk_period <= (others => '0');

elsif rising_edge(clk_fast) then

clk_resync <= clk; -- resynchroniser
clk_resync2 <= clk_resync; -- for the edge detector
count <= count + 1; -- counter runs unconditionally
-- Whenever we see a rise on clk, we measure the period:
if clk_resync = '1' and clk_resync2 = '0' then
-- synchronous detection of rising edge on clk
clk_period <= std_logic_vector(count - stored_count);
stored_count <= count;

-- interesting enhancement possibility:
-- elsif count = stored_count then
-- the counter overflowed! clk period is too long.

end if;

end if;
end process;

And now it's all nicely synchronous with clk_fast, it will
simulate OK because you have a global reset (not really
needed in hardware, but essential for simulation), and
the input "clk" is properly resynchronised to the fast
clock.

There are many, many improvements you could make to this
frequency counter, but it's not a bad start.
--
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)
http://www.MYCOMPANY.com

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

Jonathan Bromley

Why not simply capture the count value on each rise of clk, and
then report the difference between successive captured counts?
Much easier to describe.

But more expensive; it costs an extra subtracter and a register.
Synchronously resetting a counter is generally almost free.
The only reason to do it the way I first described would be
if the counter is running *very* fast, and needs to be implemented
using some clever pipelined incrementer. And in that case, the
subtraction step would need pipelining too. So I need to
think again!
How about this...
ever so slightly modified version...

port (clk, clk_fast, global_reset: in std_logic;
clk_period: out std_logic_vector(7 downto 0) );
...
signal clk_resync, clk_resync2: std_logic;
signal count: unsigned (7 downto 0);
...
process (clk_fast, global_reset)
begin
if global_reset = '1' then

clk_resync <= '0';
clk_resync2 <= '0';
count <= (others => '0');
clk_period <= (others => '0');

elsif rising_edge(clk_fast) then

clk_resync <= clk; -- resynchroniser
clk_resync2 <= clk_resync; -- for the edge detector
count <= count + 1; -- counter runs unless cleared
-- Whenever we see a rise on clk, we measure the period:
if clk_resync = '1' and clk_resync2 = '0' then
-- synchronous detection of rising edge on clk
clk_period <= std_logic_vector(count);
count <= to_unsigned(1, count'length);

-- interesting enhancement possibility:
-- elsif count = 0 then
-- the counter overflowed! clk period is too long.

end if;

end if;
end process;

Sorry, folks.
--
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)
http://www.MYCOMPANY.com

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

anupam.jain21

But more expensive; it costs an extra subtracter and a register.
Synchronously resetting a counter is generally almost free.
The only reason to do it the way I first described would be
if the counter is running *very* fast, and needs to be implemented
using some clever pipelined incrementer. And in that case, the
subtraction step would need pipelining too. So I need to
think again!


ever so slightly modified version...

port (clk, clk_fast, global_reset: in std_logic;
clk_period: out std_logic_vector(7 downto 0) );
...
signal clk_resync, clk_resync2: std_logic;
signal count: unsigned (7 downto 0);
...
process (clk_fast, global_reset)
begin
if global_reset = '1' then

clk_resync <= '0';
clk_resync2 <= '0';
count <= (others => '0');
clk_period <= (others => '0');

elsif rising_edge(clk_fast) then

clk_resync <= clk; -- resynchroniser
clk_resync2 <= clk_resync; -- for the edge detector
count <= count + 1; -- counter runs unless cleared
-- Whenever we see a rise on clk, we measure the period:
if clk_resync = '1' and clk_resync2 = '0' then
-- synchronous detection of rising edge on clk
clk_period <= std_logic_vector(count);
count <= to_unsigned(1, count'length);

-- interesting enhancement possibility:
-- elsif count = 0 then
-- the counter overflowed! clk period is too long.

end if;

end if;
end process;

Sorry, folks.
--
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.

I do not understand How will this reset the count on the slow clock?

regards,
Anupam Jain
 
J

Jonathan Bromley

I do not understand How will this reset the count on the slow clock?

Well, it doesn't exactly *reset* the counter - it jams it
to 1 in the line "count <= to_unsigned(1, count'length)".
Obviously you could force to 0 if you prefer, but then
your clock period measurement would be off by 1.

Have you tried it in simulation? It worked for me.
--
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)
http://www.MYCOMPANY.com

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top