Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Signal cannot be synthesized, bad synchronous description; yet another question.

Status
Not open for further replies.

jhonyrod

Newbie level 3
Newbie level 3
Joined
Mar 31, 2014
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
59
Hello,

I have to make a simple VHDL program on a Nexys 2 for a college assignment (the board is provided by the lab) that displays a simple message on the built in seven segment displays.

Thing is, the display refresh rate is always too high or too low, so I decided to use two push buttons of the board to change the clock divider's factor, either higher or lower, instead of changing the code and re-synthesize every time. That's when I ran into trouble and I get said message:
"Signal P cannot be synthesized, bad synchronous description.".

Here's the code itself:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity Main is
    Port ( D : out  STD_LOGIC_VECTOR (6 downto 0);
           S : out  STD_LOGIC_VECTOR (3 downto 0);
           UP: in   STD_LOGIC;
           DN: in   STD_LOGIC;
           C : in   STD_LOGIC);
end Main;
 
architecture Word of Main is
shared variable P   : natural :=0;
signal          DivC: STD_LOGIC_VECTOR(31 downto 0);
signal          Sel : STD_LOGIC_VECTOR(1  downto 0);
begin
 
    S   <=  "0111"      when Sel="00" else
            "1011"      when Sel="01" else
            "1101"      when Sel="10" else
            "1110"      when Sel="11";
    D   <=  "1001000"   when Sel="00" else
            "0000001"   when Sel="01" else
            "1110001"   when Sel="10" else
            "0001000"   when Sel="11";
            
    ClockSel: process (UP,DN)
    begin
        if ((P<DivC'High) and ((P-1)>DivC'Low)) then
            if      rising_edge(UP) then
                P:=P+1;
            elsif   rising_edge(DN) then
                P:=P-1;
            end if;
        else
            P:=1;
        end if;
        Sel <= DivC(P downto (P-1));
    end process ClockSel;
    
    ClockDiv: process (C)
    begin
        if rising_edge(C) then
            if DivC(31)='0' then
                DivC <= DivC+1;
            else
                DivC <= (others=>'0');
            end if;
        end if;
    end process ClockDiv;
end Word;



It may be good to know that I tried several combinations of "if" structures with no luck. Also, I tried splitting the ClockSel process, which made that message disappear, but an new one popped up:
"Multi-source on Integers in Concurrent Assignment."

I may post that other version of the code if needed, please let me know.

Thanks in advance.
 

Hi

First of all there are some serious issues in the code.

1. Do not use shared variable unless code is for testbench purposes, they are unsynthesizable.
2. Do not perform rising_edge() function on non clock inputs. Simple change it to if rising_edge(CLK) then if UP='1' then elsif DN='1' then
3. As simple clock divider use clock_enable driven by some counter
 
Last edited:

1. Do not use shared variable unless code is for testbench purposes, they are unsynthesizable.

Not true. They are perfectly synthesisable and even advised in certain situations. But they shouldnt be used here, or anywhere where the tool does not advise their use. So, basically, dont use them.

2. Do not perform rising_edge() function on non clock inputs. Simple change it to if rising_edge(CLK) then if UP='1' then elsif DN='1' then

This isnt the cause of the problem. The problem comes from trying to read two clock edges on the same register - this is not possible in an FPGA. What axcdd is suggesting is to use clock enables rather than inputs as clock - ie. use system clock for all registers, and use up and Dn as enables (after you have debounced them of course).

To the OP: I suggest reading the templates for synthesisable VHDL.
 
First of all thanks for the quick reply.

So should I change that variable P to a signal?
As for the ClockSel process, as I said I tried splitting it to avoid using 2 rising_edge() in a single process, but that other error then pops up. Here's a snippet of what I replaced it for:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ClockSelUP: process (UP)
    begin
        if rising_edge(UP) then
            if ((P<DivC'High) and ((P-1)>DivC'Low)) then
                P:=P+1;
            else
                P:=1;
            end if;
            Sel <= DivC(P downto (P-1));
        end if;
    end process ClockSelUP;
    
    ClockSelDN: process (DN)
    begin
        if rising_edge(DN) then
            if ((P<DivC'High) and ((P-1)>DivC'Low)) then
                P:=P-1;
            else
                P:=1;
            end if;
            Sel <= DivC(P downto (P-1));
        end if;
    end process ClockSelDN;



The behavior I try to get is that when the button is pressed the divisor shifts, so I reckon that If I use something like:

Code VHDL - [expand]
1
2
3
4
5
if rising_edge(C) then
  if UP='1' then XX;
  elsif DN='1' then XX;
  end if;
end if;


then it would shift once every clock tick, which I do not want; that's why I tried to use rising_edge. The only other solution I can think of is using a "wait until" statement, which is effectively the same.

Thanks for the help.
 

You need to forget about the code, and think about the hardware. The first code replicates the the same as the origional. You cannot use 2 edges on the same register. (and in VHDL, you can only drive a signal from a single process).

The second code IS what you want. You meed to learn about clocks - if the clock is too slow, then double the clock speed. All FPGAs can only use a single clock edge to clock.
 
Ok, so I've made a few modifications to the code; I really tried to think in terms of what the FPGA would be doing, and not just the code, but I lack a good understanding on how FPGAs work (TBH I blame it on my teacher).

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity Main is
    Port ( D : out  STD_LOGIC_VECTOR (6 downto 0);
           S : out  STD_LOGIC_VECTOR (3 downto 0);
           UP: in   STD_LOGIC;
           DN: in   STD_LOGIC;
           C : in   STD_LOGIC);
end Main;
 
architecture Word of Main is
signal  B       : boolean :=False;
signal  P       : natural :=0;
signal  DivC    : STD_LOGIC_VECTOR(31 downto 0);
signal  Sel     : STD_LOGIC_VECTOR(1  downto 0);
begin
 
    S   <=  "0111"      when Sel="00" else
            "1011"      when Sel="01" else
            "1101"      when Sel="10" else
            "1110"      when Sel="11";
    D   <=  "1001000"   when Sel="00" else
            "0000001"   when Sel="01" else
            "1110001"   when Sel="10" else
            "0001000"   when Sel="11";
                
    ClockSel:   process (UP,DN)
    begin
        if ((P<DivC'High) and ((P-1)>DivC'Low) and B=False) then
            if      UP='1' then
                P<=P+1;
            elsif   DN='1' then
                P<=P-1;
            end if;
        else
            P<=1;
        end if;
        Sel <= DivC(P downto (P-1));
    end process ClockSel;
    
    ClockDiv:   process (C)
    begin
        if rising_edge(C) then
            while (UP='1' or DN='1') loop
                B<=True;
            end loop;
            if DivC(31)='0' then
                DivC <= DivC+1;
            else
                B<=False;
                DivC <= (others=>'0');
            end if;
        end if;
    end process ClockDiv;
end Word;



I'm still skeptical about it not going nuts on the clock divider if I don't include that new signal "B".

My intention now is that you have a whole clock cycle to push the buttons, and if they stay pressed it keeps B True, so that it prevents the divisor from hopping to the next index of DivC after each clock cycle.

I guess that it is highly unlikely for the click of the button to coincide with the rising edge of C, unless the FPGA uses that same internal clock to scan through the inputs, i.e. it only refreshes the inputs (and outputs?) values each clock period.

Thing is, it synthesizes, but I've got a couple of warnings:
"Line 30: One or more signals are missing in the process sensitivity list(...) The missing signals are: <P>, <B>, <DivC>."
(I didn't include them because I don't need to trigger that process if the values of those signals change)
"Found 31-bit latch for signal <P>(...)"

It seems that it can't be simulated using ISim, it just inmediately stops after I click the Run button.
 

I'm surprized to hear that ISE synthesises the while loop inside the clock edge sensitive condition which hardware-wise doesn't seem to make any sense.

The senitivity lists warnings are signalling a possible mismatch in functional simulation, but don't affect operation of synthesized code.

But there's at least one construct that will never work in synthesized hardware: counting in a combinational process (P<=P+1 or P< P-1).
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top