Avoiding "Bad Synchronous Description" Error when Synthesizing

T

Takuon Soho

I have learned how to set up a process
properly with clk and reset signals so that it will
synthesize properly without getting the dreaded
"bad synchronous description" error.

But here I have 3 signals - a clk (of course),
a start signal, and a MessageRcvd signal.

I am supposed to accumulate a count
by adding 1 to a counter
only after getting a "Start" signal (hi).

Whenever the "MsgRcvd" signal goes
hi, I must output the count and clear the counter.

Whatever I try keeps running into the "bad synchrnous"
problem.

Question: Should I break this into two seperate processes
or is it doable in 1?? Can 2 processes have a common
variable (the counter?)

I was going to try to re-write it as a state machine

Here is one thing I tried (clearly wrong because
sw_linexx and send_xx are set low by
1 clock signal and set high by another).

Thanks for any suggestions.
Tak (VHDL newbie, obviously).


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.all;

entity count12 is port (
clk: in std_logic;
start: in std_logic
msgRcvd: in std_logic;
sw_linex: out std_logic;
send_xx: out std_logic := '0';
bus_0_11: out std_logic_vector(11 downto 0);
);
end count12;

architecture behavioral of count12 is
begin


process(clk,start,msgRcvd)

subtype counter_ty is integer range 0 to 4095;
variable my_counter : counter_ty := 0;
variable msgFlag :integer := 0; --make it a boolean flag later

begin

if (rising_edge(start)) then
msgFlag := 1;
end if;

if (rising_edge(clk) and msgFlag = 1) then
sw_linex <= '0';
send_xx <= '0';
my_counter := my_counter + 1;
elsif
(rising_edge(msgRcvd)) then
send_xx <= '1';
sw_linex <= '1';
msgFlag := 0;
bus_0_11 <= conv_std_logic_vector(my_counter, 12);
end if;

end process;

end behavioral;
 
E

Egbert Molenkamp

Takuon Soho said:
I have learned how to set up a process
properly with clk and reset signals so that it will
synthesize properly without getting the dreaded
"bad synchronous description" error.

But here I have 3 signals - a clk (of course),
a start signal, and a MessageRcvd signal.

I am supposed to accumulate a count
by adding 1 to a counter
only after getting a "Start" signal (hi).

Whenever the "MsgRcvd" signal goes
hi, I must output the count and clear the counter.

Whatever I try keeps running into the "bad synchrnous"
problem.

Question: Should I break this into two seperate processes
or is it doable in 1?? Can 2 processes have a common
variable (the counter?)

I was going to try to re-write it as a state machine

Here is one thing I tried (clearly wrong because
sw_linexx and send_xx are set low by
1 clock signal and set high by another).

Thanks for any suggestions.
Tak (VHDL newbie, obviously).


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.all;

entity count12 is port (
clk: in std_logic;
start: in std_logic
msgRcvd: in std_logic;
sw_linex: out std_logic;
send_xx: out std_logic := '0';
bus_0_11: out std_logic_vector(11 downto 0);
);
end count12;

architecture behavioral of count12 is
begin


process(clk,start,msgRcvd)

subtype counter_ty is integer range 0 to 4095;
variable my_counter : counter_ty := 0;
variable msgFlag :integer := 0; --make it a boolean flag later

begin

if (rising_edge(start)) then
msgFlag := 1;
end if;

if (rising_edge(clk) and msgFlag = 1) then
sw_linex <= '0';
send_xx <= '0';
my_counter := my_counter + 1;
elsif
(rising_edge(msgRcvd)) then
send_xx <= '1';
sw_linex <= '1';
msgFlag := 0;
bus_0_11 <= conv_std_logic_vector(my_counter, 12);
end if;

end process;

end behavioral;
The rising_edge with different signal names (clk and msgRcvd) is not
(mostly) supported by synthesis tools.
The synchronous frame work you learned was probably something like:

process(reset,clk)
begin
if reset='1' then
-- here the reset stuff
elsif rising_edge(clk) then
-- here the synchronous logic.
-- no rising_edge, falling_edge or 'event
end if;
end process;
Whenever the "MsgRcvd" signal goes hi
How long is this signal at least high?
If it is at least one clock period high you could load the signal in a
flipflop ("MsgRcvdPrev").
If MsgRcvdPrev='0' and MsgRcvd='1' then "increment counter"
(Note: probably you need also 1 or 2 flipflops for synchonization?)

In case your MsgRcvd is short high, compared to the clock period, you could
model an SR latch. Set the latch with the MsgRcvd and reset the latch from
your synchronous description. (You can not detect two or more short high
pulses within one clock period).

Egbert Molenkamp
 
J

james_pannozzi

Thanks, I think I can take the approach of making everything
synchrnous to the clock signal and yes the MsgRcvd is at least
one clock signal high.

If I make everything synchonous to the clock signal, then an I follow
the well known reset/clk paradigm that you mentioned?

How is it done with 3 signals instead of 2?

Thanks
Tak
 
E

Egbert Molenkamp

Thanks, I think I can take the approach of making everything
synchrnous to the clock signal and yes the MsgRcvd is at least
one clock signal high.

If I make everything synchonous to the clock signal, then an I follow
the well known reset/clk paradigm that you mentioned?

How is it done with 3 signals instead of 2?

Thanks
Tak

Something like:

architecture ...
signal MsgRcvdPrev : std_logic;
begin

process(reset,clk)
...
begin
if reset='1' then
-- here the reset stuff
elsif rising_edge(clk) then
if MsgRcvdPrev='0' and MsgRcvd='1' then
-- now you have detect the '1' (I Assumed it is long enough high)
send_xx <= '1';
sw_linex <= '1';
msgFlag := 0;
bus_0_11 <= conv_std_logic_vector(my_counter, 12);
end if
MsgRcvdPrev <= MsgRcvd; -- flipflop
end if;
end process;

Egbert Molenkamp
 
T

Takuon Soho

Thanks, this is idea interesting.

But, I ended up breaking counter stuff into a seperate process
and then it synthesized fine. Did'nt use up much macrocells
either.

Thanks everyone.

Tak.
 
C

Charles Bailey

Logic like this is SOOO much easier if you just make everything
synchronous.
A synchronous process should have only the clock in the sensitivity
list. (Actually, I prefer to WAIT on a clock edge and not have a
sensitivity list at all; even simpler.)
If this is going to be synthesized into real logic, you shouldn't put
initial values on any ports or signals. You must design the logic so
that a reset sequence gets it into a known state.

Try something like this:

entity count12 is port (
clk: in std_logic;
reset: in std_logic;
start: in std_logic;
msgRcvd: in std_logic;
sw_linex: out std_logic;
send_xx: out std_logic;
bus_0_11: out std_logic_vector(11 downto 0)
);
end count12;

architecture behavioral of count12 is
begin

process
subtype counter_ty is integer range 0 to 4095;
variable my_counter : counter_ty;
variable counting : bit;

begin
wait until clk='1';
if reset='1' then
counting := '0';
send_xx <= '0';
sw_linex <= '0';
else
if start='1' then
my_counter := 0;
counting := '1';
elsif msgRcvd='1' then
bus_0_11 <= conv_std_logic_vector(my_counter, 12);
counting := '0';
elsif counting='1' then
my_counter := my_counter + 1;
end if;
send_xx <= msgRcvd;
sw_linex <= msgRcvd;
end if;
end process;

end behavioral;

You didn't say whether the start or msgRcvd inputs were synchronous to
the clock or how wide they were. If not, then you need to add
synchronizing latches to the above circuit. The reset signal needs to
be synchronous to the clock also.

In a synchronous circuit, everything happens on a clock edge. You
shouldn't try to trigger on edges of any other signals. Think of these
other inputs as levels that are stable during the clock period and
change on the clock edge. If they aren't, then add synchronizing
latches to make it so.

Charles Bailey
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top