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 TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

"Bad Synchronous Description" - How to fix?

Status
Not open for further replies.

jmcoreymv

Programmer
Jul 21, 2004
2
US
Im trying to program a 16 bit hardware divider (with only the first 4 bits being integer). When I try to synthesize it, Xilinx ISE gives me this error Signal NS cannot be synthesized, bad synchronous description. I can't figure out how to fix it. The following is my code if anyone can help: (btw I dont expect the logic to work yet)

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

entity divider is port(
dividend : in std_logic_vector(15 downto 0);
divisor : in std_logic_vector(15 downto 0);
start : in std_logic;
clk : in std_logic;
quotient : out std_logic_vector(15 downto 0);
done : out std_logic);
end divider;

architecture RTL of divider is
type statetype is (INIT,ALIGNDIVISOR,DIVIDE,ALIGNQUOTIENT);
signal PS,NS : statetype := INIT;
signal s_remainder,s_divisor,s_quotient : std_logic_vector(15 downto 0);
signal divisor_align_count, quotient_count, align_quotient_count : integer;
begin
quotient <= s_quotient;

sync: process(CLK)
begin
if rising_edge(CLK) then
PS<=NS;
end if;
end process;

comb: process(PS,dividend,divisor,start,s_remainder,s_divisor,s_quotient,
divisor_align_count, quotient_count, align_quotient_count)
begin

case PS is
when INIT =>
if rising_edge(start) then --Begin divide sequence
NS<=ALIGNDIVISOR;
s_remainder <= dividend;
s_divisor <= divisor;
s_quotient <= (others=>'0');
divisor_align_count <= 0;
quotient_count <= 15;
done <= '0';
else
NS<=INIT;
end if;

when ALIGNDIVISOR =>
if s_remainder = x"0000" then --Check for 0 dividend
NS<=ALIGNQUOTIENT;
s_quotient <= x"0000";
elsif s_divisor = x"0000" then --Check for 0 divisor
NS<=ALIGNQUOTIENT;
s_quotient <= x"FFFF";
elsif s_divisor = x"1000" then --Check for 1 divisor
NS<=ALIGNQUOTIENT;
s_quotient <= s_remainder;
elsif s_divisor(15) /= '1' then
divisor_align_count <= divisor_align_count + 1;
s_divisor <= s_divisor(14 downto 0) & '0'; --Align divisor to the left side of the register
NS<=ALIGNDIVISOR;
else
align_quotient_count <= 3 - divisor_align_count;
NS<=DIVIDE;
end if;

when DIVIDE =>
if s_remainder = x"0000" then
NS<=ALIGNQUOTIENT;
elsif s_divisor > s_remainder then
s_quotient(quotient_count) <= '0';
NS<=DIVIDE;
else
s_quotient(quotient_count) <= '1';
s_remainder <= s_remainder - s_divisor;
NS<=DIVIDE;
end if;
quotient_count <= quotient_count - 1;
s_divisor <= '0' & s_divisor(15 downto 1); --Right shift divisor

when ALIGNQUOTIENT =>
if align_quotient_count /= 0 then
s_quotient <= '0' & s_quotient(15 downto 1); --Right shift quotient
align_quotient_count <= align_quotient_count - 1;
NS<= ALIGNQUOTIENT;
else
NS<=INIT;
DONE<= '1';
end if;

when others =>
null;
end case;
end process;



end RTL;
 
NM, the problem was that I can't put a rising_edge(start) inside of the process;
 
one way to do that is keep a copy of start on the last clock and check to see if the last value was 0 and the current is 1... therefore its a rising edge.

old_start <= start;

-- rising edge check
if (start = '1' and old_start = '0') then
blah;
end if;

unless of course you wanted the whole process to be clocked by start, in which case you should have it outside the case statement.



--
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top