3

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

Eric Townsend
  • 201
  • 2
  • 6
  • 13
  • What board are you working on? It might come with a digital clock manager (DCM) that could offer a better division result and simpler implementation. I know the Spartan 3a boards from Xilinx have them – Paul Seeb Jun 18 '12 at 19:31
  • I'm using an Altera DE1 board for this. The FPGA on this board has 4 PLLs, but as far as I know, it does not have a digital clock manager as Paul Seeb mentioned. So, I guess my next question is, how do I take advantage of a PLL in Quartus to use as the clock divider? – Eric Townsend Jun 19 '12 at 19:45
  • if you have PLL's you can make higher/lower frequency clocks as long as the hardware can attain the desired frequency. I think that most DCMs do it this way. For instance, doubling clock speed is achieved by XORing your clock with and 90deg phase shifted clock signal – Paul Seeb Jun 19 '12 at 20:13
  • You can find more information on the PLLs here: http://www.altera.com/literature/hb/cyc2/cyc2_cii51007.pdf I assume that Quartus probably also has some nice wizardish way of configuring them. – sonicwave Jun 20 '12 at 06:20
  • Awesome, I figured out how to use the PLLs on this chip. It works perfectly now. Thank you everyone so much for your help! – Eric Townsend Jun 20 '12 at 22:53

2 Answers2

4

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.

Paul S
  • 7,645
  • 2
  • 24
  • 36
  • Would you like to elaborate how does the code work? Why adding the denominator help? And why comparing greater than the nominator when you want to toggle the clock? – Unknown123 Oct 27 '19 at 05:44
2

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;
sonicwave
  • 5,952
  • 2
  • 33
  • 49
  • Wait statements are absolutely synthesizable. There may be instances when the synthesizer can't implement what you've asked for (e.g. you're inferring registers sensitive to both edges, which would be a problem for the code in my answer), but the OP's use is fine in many tools (Synopsys Design-Compiler for one). – Paul S Jun 27 '12 at 16:00
  • Fair enough, I've tweaked my answer. I'm probably influenced by that in 90% of the cases where I've seen it used, it's been by people asking why their `wait for xxx ns;` code can't be synthesized ;) – sonicwave Jun 28 '12 at 06:30
  • Ahhh, agreed. `wait for xxx ns;` hasn't got a hope of being synthesized. – Paul S Jun 28 '12 at 14:13
  • One advantage of the `wait until clk'event and clk == '1'` style is that in simulation the process doesn't wake up on negative edges only to fail the `if rising_edge` and go back to sleep again. It's **very very** minor though. – Paul S Jun 28 '12 at 14:19