Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem with simple(ish) counter 3

Status
Not open for further replies.

cdchilds

Programmer
Dec 8, 2003
9
GB
Hi,

I am trying to synthesise the following VHDL description of a 16-bit counter using XST (in Xilinx ISE Webpack), but I am getting a synthesis error - "Bad synchronous description" on signal 'tmpcount'. Could anyone please give me a clue as to where I have gone wrong?

Thanks,

Chris.

------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter16 is
Port ( reset : in std_logic;
clock : in std_logic;
hold : in std_logic;
count : out std_logic_vector(15 downto 0);
overflow : out std_logic);
end counter16;

architecture Behavioral of counter16 is

signal holding : boolean;
signal missed : boolean;
signal tmpcount : std_logic_vector(15 downto 0);
signal tmpoverflow : std_logic;

begin

process (clock, hold)

begin
if clock'event then

if reset='1' then
tmpcount <= &quot;0000000000000000&quot;;
tmpoverflow <= '0';
holding <= false;
missed <= false;
elsif clock='1' then
if holding then
missed <= true;
else
if tmpcount = &quot;1111111111111111&quot; then
tmpoverflow <= '1';
end if;
tmpcount <= tmpcount + 1;
end if;
end if;

elsif hold'event then

if hold = '0' then
-- hold has just gone low

-- increment count if missed an edge
if missed then
if tmpcount = &quot;1111111111111111&quot; then
tmpoverflow <= '1';
end if;
tmpcount <= tmpcount + 1;
missed <= false;
end if;
-- no longer holding
holding <= false;
else
-- hold has just gone high
holding <= true;
end if;

end if;

end process;

count <= tmpcount;
overflow <= tmpoverflow;

end Behavioral;

------------

=========================================================================
* HDL Compilation *
=========================================================================
Compiling vhdl file C:/Xilinx/bin/testproject/counter16.vhd in Library work.
Entity <counter16> (Architecture <behavioral>) compiled.

=========================================================================
* HDL Analysis *
=========================================================================
Analyzing Entity <counter16> (Architecture <behavioral>).
ERROR:Xst:827 - C:/Xilinx/bin/testproject/counter16.vhd line 23: Signal tmpcount cannot be synthesized, bad synchronous description.
-->

Total memory usage is 57280 kilobytes
 
Wow!
Neee fooking chance ...

it's just some magic in it
there is a magic spell

<elsif/if> clk'event and clk= '1' then

which makes anything inside the &quot;if&quot;
a register clocked with clk

first you cannot change this spell (have you seen that action in &quot;Harry Potter&quot;?) neither splitting the
clk'event
and
clk='1'
to separate lines
nor adding any other condition to the line with this spell

second you cannot place two (such defined) clocks in one process
or more strictly - you cannot clock the register with two clocks (writing two separate processes would not help! this would make the C-MOS hardware burn immediately)

well it is extremely &quot;bad synchronous description&quot; indeed ;)))

shall be something like

begin

if reset='1' then
tmpcount <= &quot;0000000000000000&quot;;
tmpoverflow <= '0';
holding <= false;
missed <= false;


elsif clock'event and clock='1' then
if holding then
missed <= true;
else
if tmpcount = &quot;1111111111111111&quot; then
tmpoverflow <= '1';
end if;
tmpcount <= tmpcount + 1;
end if;

-- something with hold here or there ...

end if; -- and nothing more after this line
-- just end the process


and then add to it the hold signal but as a condition, not the clock (or reverse solution - make the hold a clock and a clock an ordinary signal controlling some conditions, but I don't think so)

If you need to detect a rising edge of the hold indeed you shall just apply series of two regs and detect the change this way ...

have fun
rgds

berett
 
Thanks Berett, your spell has helped me considerably :)

In order to produce cleaner, more understandable code, I decided to take the 'hold' functionality out of the counter and write a wrapper that implements the 'hold' functionality outside of the counter. (Another reason for doing this is that I still couldn't get the original counter to synthesise!)

I now have a synthesisable counter (without hold), but my wrapper will not synthesise (&quot;bad synchronous description&quot; again). I have stuck to the spell but I am still struggling. If anyone could shed any light on this I would be most grateful.

Thanks,

Chris.

**********************************************************

-------------------------------------------------------------
counter16simple (the standard counter without Hold)
-------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter16simple is
Port ( reset : in std_logic;
clock : in std_logic;
count : out std_logic_vector(15 downto 0);
overflow : out std_logic);
end counter16simple;

architecture Behavioral of counter16simple is

signal tmpcount : std_logic_vector(15 downto 0);
signal tmpoverflow : std_logic;

begin

process (clock, reset)

begin
if reset='1' then
tmpcount <= &quot;0000000000000000&quot;;
tmpoverflow <= '0';
elsif clock'event and clock='1' then
if tmpcount = &quot;1111111111111111&quot; then
tmpoverflow <= '1';
end if;
tmpcount <= tmpcount + 1;
end if;

end process;

count <= tmpcount;
overflow <= tmpoverflow;

end Behavioral;


-----------------------------------------------------
counter16 (the wrapper that implements Hold)
-----------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter16 is
Port ( reset : in std_logic;
clock : in std_logic;
hold : in std_logic;
count : out std_logic_vector(15 downto 0);
overflow : out std_logic);
end counter16;

architecture Behavioral of counter16 is

component counter16simple
Port ( reset, clock : in std_logic;
count : out std_logic_vector(15 downto 0);
overflow : out std_logic);
end component;

signal gatedClock : std_logic;

begin

-- Instantiation of counter16:
countersimple : counter16simple PORT MAP (reset => reset, clock => gatedClock, count => count, overflow => overflow);

process (clock, hold)

begin

gatedClock <= clock;

if clock'event and clock = '1' then

-- check to see if hold is high
if hold = '1' then
gatedClock <= '0';
end if;

end if;

end process;

end Behavioral;

 
OK

The process in counter16simple looks fine, if to exclude
the problem of single-use operation of tmpoverflow

if tmpcount = &quot;1111111111111111&quot; then
tmpoverflow <= '1';
end if;

If it gets high it never goes down. Questionable from functional point of view. But hardware OK ;)

The process in counter16 is a bad synchronous design indeed. The main problem is that the Gatedclock is a register clocked by the clock signal and simultaneously it is connected to the same clock signal directly. The eventual CMOS chip would burn.

It is hard to understand the purpose of the Gatedclock signal anyway. But I am pretty sure you cannot escape from the &quot;hold&quot; functionality problem by implementing another entities-components (very bad idea) or processes (somewhat better).

Lets forget it and go back to the roots - what is the hold supposed to do? Stop the counter? Or anything more? If that's just it - stopping the counter, it may be all done very simply. Regardless of its low/high/rising edge/falling edge active nature.

Just let us know ;)

 
Thanks for your prompt reply Berett. Maybe I need to clarify what I'm trying to do...

Basically the counter value will be read by some other process, but I want to make sure that the counter value can never change whilst reading it. (There may be better ways to do this, but it's more for proof-of-concept than functionality.) So what I have is a 'hold' signal that holds off the positive clock edge to the counter whilst it is high. So the reader does the following:

- Set hold high
- Read the counter value
- Set hold low

If a positive clock edge occurs whilst hold is high, it should be deferred until hold goes low, thereby preventing the counter from counting during a read.

I have tried all kinds of ways to implement this, including additional processes, but can't seem to find a way that is synthesisable.

Hope that clarifies what I'm trying to do...

Thanks,

Chris.
 
BTW, the idea of the overflow signal is that it should go high upon overflow, and stay high until reset. Would this code not achieve this? It seems to simulate OK, and I can't see why the code would not do it...?
 
Berett seems to be absent so I will add some to this.

Firstly I assume that you don't care about events during the hold? (ie you could have a secondary counter loging events during the hold, but it would be a lots more work/logic).

Personally I would not gate the clock, I would either use the hold signal either asyncronously or syncronously in the following fashion:

Async:
process (clock, reset,hold)

begin
if reset='1' then
tmpcount &lt;= &quot;0000000000000000&quot;;
tmpoverflow &lt;= '0';
elsif hold = '1' then
-- redundant assignments to show what
-- I am trying to do
tmpcount &lt;= tmpcount;
tmpoverflow &lt;= tmpoverflow;
elsif clock'event and clock='1' then
if tmpcount = &quot;1111111111111111&quot; then
tmpoverflow &lt;= '1';
end if;
tmpcount &lt;= tmpcount + 1;
end if;

end process;


Syncronously:
process (clock, reset)

begin
if reset='1' then
tmpcount &lt;= &quot;0000000000000000&quot;;
tmpoverflow &lt;= '0';
elsif clock'event and clock='1' then
if hold = '0' then
if tmpcount = &quot;1111111111111111&quot; then
tmpoverflow &lt;= '1';
end if;
tmpcount &lt;= tmpcount + 1;
else
-- redundant assignments showing intention.
tmpcount &lt;= tmpcount;
tmpoverflow &lt;= tmpoverflow;
end if;
end if;
end process;


That should work for you.

--
 
Thanks for your help VHDLguy.

With regard to the hold signal, it is partially true that I don't care about clock events during the hold, but I need to know that they have occurred so that they can be actioned when hold disappears. Maybe a timing diagram would help to explain:

Code:
clock   ____|¯¯¯¯|____|¯¯¯¯|____|¯¯¯¯|____|¯¯¯¯|____

hold    ____________|¯¯¯|_________|¯|_______|¯¯¯¯|__

desired ____|¯¯¯¯|______|¯¯|____|¯¯¯¯|____|¯¯¯¯|____
output

Effectively I want to use this modified clock as the clock to the counter. Basically I want to delay positive clock edges until hold goes low, with negative clock edges being unaffected. To do this, (I'm not sure but) I think I need to know which signal caused the process to execute (clock or hold), because simply knowing the levels of the two signals does not give me enough information - I need to know some kind of order of events. But I can't do this in VHDL, as Berett's magic spell forbids using more than one signalname'event statement.

Back to the code, I'm not sure that it will achieve what I am trying to do, probably because I haven't explained it well enough! However, you have demonstrated that I can use more than one else clause:

Code:
if a='1' then
...
elsif b='1' then
...
elsif c='1' then
...
elsif d='1' and d'event then
...
end if

which will be useful, so I am very grateful. All of this is a valuable learning experience for me, so thanks all for being so patient.

Chris.
 
Hmm. Seems like my indentation doesn't work. This website doesn't work very well from Netscape on solaris. Anyway, you should be able to understand it.

Im not sure that what you are implementing is the best way to get the solution that you require, but since I don't know the whole design I will try to implement exactly what you have shown.

Based on your nice diagram I tried to implement it like this:

process (clk, reset)
begin
if reset = '1' then
gated_hold &lt;= '0';
elsif clk'event and clk = '1' then
gated_hold &lt;= hold;
end if;
end process;

gated_clock &lt;= clock when (gated_hold = '1' and hold = '0')
else '0' when (gated_hold = '1' and hold = '1')
else clock;


But I think you will end up with a glitch due to the fact that the clock will go high before the gated_hold will go high.

Other than that, which won't work for you, I can't come up with some logic (at least in the short amount of time I spent on it).

You may want to rethink how you expect this to work.





--
 
Clock division
Debounce

I am had the same type of error as cdchilds "ERROR: Signal cnt cannot be synthesized, bad synchronous description."

The error came with this code:

process(button_in,cnt)
begin
if(cnt = 70000000)then --70M = 0.5sec at 80MHz
cnt <= 0;
if(rising_edge(CLK))then
if(cnt = 0) then
if(button_in = '1')then
leds <= "1111111111111111";
else
leds <= "0000000000000000";
end if;
end if;

cnt <= cnt + 1;

end if;
end process;
--------------------
The problem was solved by changing the second if statement into an elsif:

process(button_in,cnt)
begin
if(cnt = 70000000)then --70M =~ 0.5sec at 80MHz
cnt <= 0;
elsif(rising_edge(CLK))then
if(cnt = 0) then
if(button_in = '1')then
leds <= "1111111111111111";
else
leds <= "0000000000000000";
end if;
end if;

cnt <= cnt + 1;

end if;
end process;
 
Hmm... I know no VHDL.

It seems that all you are asking for is an asynchronous S-R flip-flop on the clock to the counter.

in abel:
Code:
 clk_hold = ( (clk & !hold)   // set term
              # clk_hold )    // hold term
            & !clk;           // over-ride reset

// [& = and, # = or, ! = not, // = single line comment]

How do you write that in VHDL? Am I being dim?

 
That won't work.

You would write that in vhdl simply using the real words:
clk_hold <= ((clk and not hold) or clk_hold) and not clk;

however you first condition requires clk to be 1, and you second requires clk to be 0. obviously they will never be true together. The only way it could work is if clk_hold was 1. while clk was 0. But that event never occurs since clk_hold will never change due to my first argument.

This problem can't be done in combinatorial logic since you need to know what hold was on the rising edge of clk. It could be almost done if you had another really fast clock to latch hold when clk transitioned, but that would leave you with glitches.

even thinking about this again, I can't come up with an answer. Anyone else? There must be something.

--
 
hmmm... actually richardst maybe you are right, but just implemented it wrong (or maybe I don't understand abel).

I got to thinking about why you said something about an s-r flip-flop but didn't seem to implement it... and decided that maybe an s-r flip-flop would do it.

so here tis:

hold_clk <= (clk and not hold);


nor1 <= s nor nor2;
nor2 <= r nor nor1;

s <= hold_clk;
r <= not clk;

result <= nor2;

I believe the output of nor2 is exactly as required, so I wired it up to signal result.

--
 
You are quite right to correct me, VHDLguy. The logic I meant to write was:

clk_hold <= ((clk and not hold) or clk_hold) and clk;

(I have deleted the last 'not') so clk_hold is set when the clock goes high but hold is low, and clears when clk falls.

clk_hold is then the desired_output of cdchilds' ascii art waveform of 24th Feb.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top