Domanda

I'm trying to slow a 50MHz clock down to 25.175MHz for use in a VGA controller. I have a clock divider already, but am having trouble slowing the clock down whenever the resulting division of the current clock speed and the desired clock speed is not a whole number. I.E. 50000000/25175000 ~ 1.98. The clock divider compiles and runs, but outputs nothing if the division is a decimal number. Here's my code:

    LIBRARY IEEE;
    USE  IEEE.STD_LOGIC_1164.ALL;

    ENTITY Clockdiv IS PORT (
        Clkin: IN STD_LOGIC;
        Clk: OUT STD_LOGIC);
    END Clockdiv;

    ARCHITECTURE Behavior OF Clockdiv IS
        CONSTANT max: INTEGER := 50000000/25175000;
        CONSTANT half: INTEGER := max/2;
        SIGNAL count: INTEGER RANGE 0 TO max;
    BEGIN
        PROCESS
        BEGIN
            WAIT UNTIL Clkin'EVENT and Clkin = '1';

            IF count < max THEN
                count <= count + 1;
            ELSE
                count <= 0;
            END IF;

            IF count < half THEN
                Clk <= '0';
            ELSE
                Clk <= '1';
            END IF;
        END PROCESS;
    END Behavior;

I searched on google, and found using the REAL data type will allow you to use decimals, but when I changed the variables I'm using to REALs, Quartus gives me the error: Error (10414): VHDL Unsupported Feature error at Clockdiv.vhd(12): cannot synthesize non-constant real objects or values.

Then, if I change "count" to a CONSTANT type, I get the error: Error (10477): VHDL error at Clockdiv.vhd(18): name "count" must represent signal.

Does anybody know how I can slow a clock down to 25.175MHz? Also, does anybody know how to slow a clock down so that the compiler is happy with the resulting division being a decimal value?

Thanks

È stato utile?

Soluzione

Reals are, in general, not synthesisable, so you'll need to come up with an integer based solution.

That ratio is quite a tricky one because it's almost 2:1, but not quite. Most edge based clock divider circuits work only on one edge of the original clock, so the lowest ratio you can divide by is 2. In this case you'll have to work on both edges of the clock.

Once you've got that you need to have a counter that increments by the denominator of your ratio and is it's over the numerator then output a clock edge.

PROCESS
    BEGIN
        WAIT UNTIL Clkin'EVENT;

        IF count < max THEN
            count <= count + DENOMINATOR;
        ELSE
            count <= 0;
        END IF;

        IF count > NOMINATOR THEN
            Clk <= ~Clk;
        END IF;
    END PROCESS;

For this ratio I think the smallest way you can represent it is 2000/1007.

The trouble with this is that you'll get a clock that's basically 25MHz, but occasionally (each 2000 / 7 iterations) you'll get an extra edge. It won't be a 25.175MHz clock. Getting 25.175MHz from 50MHz is impossible without a PLL.

Altri suggerimenti

I've written plenty of VGA controllers, and just using a 25 MHz clock has never been much of a problem. If you absolutely want to get closer though, your FPGA probably has a clock manager of some sort (I'm only familiar with Xilinx devices), that will allow you to synthesize an output clock by multiplying and dividing an input clock.

Also, while using derived/gated clocks (clocks where you directly set the value in a process) will probably work for you in this case, it can lead to a lot of problems that can be hard to debug. A better solution is to generate clock enables, and then run everything on the same (fast) clock.

And a last thing, although it is probably as much a question of preferred style, but I usually use clocked process statements instead of WAIT statements (shown below with rising edge trigger, synchronous reset and a clock enable). I find it clearer to read and understand, and less prone to writing unsynthesizable constructs such as wait for 10ns;, or statements with multiple WAITs.

process(clk)
begin
    if(rising_edge(clk)) then
        if(sync_reset = '1') then
            --Reset logic
        elsif(clk_enable = '1') then
            --Actual functionality
        end if;
    end if;
end process;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top