1
\$\begingroup\$

The process should react on both rising and falling edges of the MainClk. The only difference is it can also reset variables if the rising clock conditions are met. Since I handle all possible clock conditions separately, why does it give me an error -

ERROR:Xst:827 - "D:/Projects/Xilinx/blincker/blinker_mod.vhd" line 47: Signal PixlCounter cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.

Here's the script:

COUNT4: PROCESS(MainClk)
BEGIN
    IF RISING_EDGE(MainClk) THEN
        IF  Stop = '1' OR SLEEP = '1' THEN
                FastCounter :=(OTHERS => '0');
                PixlCounter :=(OTHERS => '0');
        ELSIF (MainCounter >= 35) THEN
                IF FastCounter >= 3 THEN
                    FastCounter := (OTHERS => '0');
                    PixlCounter :=  PixlCounter + 1;
                ELSE FastCounter := FastCounter + 1;
                END IF;
        ELSE NULL;
        END IF;

    ELSIF FALLING_EDGE(MainClk) THEN
        IF (MainCounter >= 35) THEN
            IF FastCounter >= 3 THEN
                FastCounter := (OTHERS => '0');
                PixlCounter :=  PixlCounter + 1;
            ELSE FastCounter := FastCounter + 1;
            END IF;
        ELSE NULL;
        END IF;
    ELSE NULL;
    END IF;
END PROCESS COUNT4;

EDIT

Since the process occurs on the change of the MainClk (weather it's rising or falling), why is it not practical to simply check if it is rising or falling by if MainClk = '1' or = '0':

    COUNT4: PROCESS(MainClk)
BEGIN
    IF MainClk = '1' THEN
        IF  Stop = '1' OR Sleep = '1' THEN
                FastCounter :=(OTHERS => '0');
                PixlCounter :=(OTHERS => '0');
        ELSIF (MainCounter >= 35) THEN
                IF FastCounter >= 3 THEN
                    FastCounter := (OTHERS => '0');
                    PixlCounter :=  PixlCounter + 1;
                ELSE FastCounter := FastCounter + 1;
                END IF;
        ELSE NULL;
        END IF;

    ELSE
        IF (MainCounter >= 35) THEN
            IF FastCounter >= 3 THEN
                FastCounter := (OTHERS => '0');
                PixlCounter :=  PixlCounter + 1;
            ELSE FastCounter := FastCounter + 1;
            END IF;
        ELSE NULL;
        END IF;
    END IF;
END PROCESS COUNT4;
\$\endgroup\$
6
  • \$\begingroup\$ The hardware probably doesn't support dual edge clocking (in a single FF). \$\endgroup\$ – apalopohapa May 2 '14 at 20:27
  • \$\begingroup\$ @apalopohapa well, when I do not set the edge explicitly, the process reacts on both edges. \$\endgroup\$ – Nazar May 2 '14 at 20:41
  • \$\begingroup\$ You can use one edge, either rising or falling, but not both. \$\endgroup\$ – Joe Hass May 2 '14 at 20:57
  • \$\begingroup\$ @JoeHass If I do this 'IF RISING_EDGE(MainClk) THEN... ELSE...' - thus, specifying only one condition, it gives me the same error. Looks like it does not want to understand that by ELSE I mean the falling edge. Well, I seemed to went around this problem by changing the conditions to 'if MainClk = '1' then .... elsif MainClk = '0' then...'. However, can I consider it to be synchronous with the MainClk? \$\endgroup\$ – Nazar May 2 '14 at 21:10
  • 1
    \$\begingroup\$ If you want the equivalent of using both clock edges, why not synthesize a double-rate clock and use that? \$\endgroup\$ – stanri May 3 '14 at 14:31
2
\$\begingroup\$

The FPGA hardware doesn't allow for clocking both edges on one flip-flop.

What you can do, is use a double-rate clock to perform a process on both edges of the original clock. Once you have a double rate clock, it's a matter of creating an oscillating signal which indicates if it's falling or rising. As follows:

signal rising_edge : std_logic;

...

COUNT4: PROCESS(MainClkx2)
BEGIN
    IF RST = '1' THEN
    -- Change as needed
        rising_edge <= '0';
    ELSIF RISING_EDGE(MainClkx2) THEN
        rising_edge <= not rising_edge;
        if (rising_edge = '1') then 
            -- rising edge stuff
            IF  Stop = '1' OR SLEEP = '1' THEN
                    FastCounter :=(OTHERS => '0');
                    PixlCounter :=(OTHERS => '0');
            ELSIF (MainCounter >= 35) THEN
                IF FastCounter >= 3 THEN
                    FastCounter := (OTHERS => '0');
                    PixlCounter :=  PixlCounter + 1;
                ELSE 
                    FastCounter := FastCounter + 1;
                END IF;
            END IF;
        ELSIF (rising_edge = '0') then
            -- Falling Edge Stuff
            IF FastCounter >= 3 THEN
                FastCounter := (OTHERS => '0');
                PixlCounter :=  PixlCounter + 1;
            ELSE 
                FastCounter := FastCounter + 1;
            END IF;
        END IF;
    END IF;
END PROCESS COUNT4;

The double rate clock creates a rising edge for both the 'rising' and 'falling' case while still working within the hardware limitations. the rising_edge signal indicates which "half" of the normal-rate clock we're on.

The downside to this is that you are working with a double rate clock, which means that timing closure will be more difficult to achieve. It may be a good idea to narrow down parts of the design that have to be on this clock and drop everything else to a lower clock.

\$\endgroup\$
6
  • \$\begingroup\$ This means that I have to double the clock rate of the MainClk? \$\endgroup\$ – Nazar May 5 '14 at 13:30
  • \$\begingroup\$ Yep. If you're using Xilinx tools you can generate a double clock using the clocking wizard. xilinx.com/products/intellectual-property/clocking_wizard.htm \$\endgroup\$ – stanri May 5 '14 at 15:08
  • \$\begingroup\$ Although, I tried to stay with 20MHz crystal, it seems like I have no choice but to get a 40MHz one, and do the "rising edge" only. Also, wanted to ask: can I connect an output pin from the crystal directly to the input pin of the CPLD and use it as the MainClk? \$\endgroup\$ – Nazar May 5 '14 at 18:02
  • \$\begingroup\$ It depends on the crystal. The datasheet should indicate how it's to be wired. So yes, you should be able to connect it directly, but it may require more circuitry than that, or more than one pin to the FPGA. You can still use a 20Mhz crystal and generate a 40 Mhz one on the FPGA. 20 Mhz is pretty slow in FPGA terms, you should be fine. \$\endgroup\$ – stanri May 5 '14 at 19:07
  • \$\begingroup\$ Well, if I use this one and connect pad3/pin3 of the crystal to my clock input, will it work? I never interfaced a CPLD before, so just asking if this is the correct way to do it. Also, when I program it, there is no need in a crystal, right? Any guidelines on how long to wait for the crystal to stabilize? Thanks. \$\endgroup\$ – Nazar May 5 '14 at 19:39
3
\$\begingroup\$

why does it give me an error -

There's a single driver for each signal in a process, you can't clock the same storage elements off both edges of a clock. Synthesis won't treat a variable different from a signal. It's not the VHDL language's responsibility to insure shared variables are operated correctly, though you can imagine PixelCounter and FastCounter may only be assigned in this process.

A possible solution

Because you tried and we see the word pixel I take it you are up against a performance limit and can't simply double the clock speed.

Try two processes, FastCounter/PixelCounter with different names, operating off the two clock phases. You increment by two but one set has an LSB constant '0' and the other '1'. The incrementers are shorter by 1, the actual FastCounter, PixelCounter counters are one shorter in length.

A 2:1 mux with MainClk as the select is faster than the increment on the PixelCounter. You'd gate the select with (Stop or SLEEP).

Somewhere you may need a half clock delay on some signals requiring pipeline registers on the opposite clock phase.

(Stop or SLEEP) also resets both sets of counters.

And about now...

You realize you can instead simply multiplex the LSB constants and use a single set of counters in a single process - but the process of figuring out how to speed the counters up gave you the answer. It works because the shortened counters increment at half the speed or a period of one MainClk.

The MainCounter >= 35 expression tells you which phase of the MainClk is used in the LSB multiplexer select.

If you had provided declarations I would have edited it. Are FastCounter and PixelCounter global variables?

\$\endgroup\$
1
  • \$\begingroup\$ Thank you, David. I am not so experienced to easily follow your advice. But my overall impression is that I should double the frequency of the input clock. In that case, I will not need the "falling edge". \$\endgroup\$ – Nazar May 5 '14 at 17:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.