Search code examples
vhdlclockquartushardware

Generating 2 clock pulses in VHDL


Although I have completed a university course in digital logic, I am new to VHDL design and I am hoping if someone can help me create 2 clock signals which depend on the state of one another.

I am using a 50 MHz clock on a DE2-115 FPGA board that is used to create a 5MHz clock (named dclk_5). However, the simulation is showing the two signal but only up to 200 ns of run time and won't run any longer. Why doesnt the simulation run longer than 200 ns?

datasheet of the 2 clocks:

https://gyazo.com/485e354bf8cfef984757e2014fa8fde3

Alternative VHDL Design for testing dclk_5 and clk_50 which synthesizes but simulation is not correct:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity DCLK_top is
port(
    clk_50  : in std_logic;
    sw         : in std_logic;
    dclk_5  : out std_logic
);

end DCLK_top;

architecture behaviour of DCLK_top is
    signal clk_counter          : integer range 0 to 10 := 0;
    signal dclk_counter         : integer range 0 to 8  := 0;
    signal dclk_pause_counter   : integer range 0 to 7  := 0;

    signal dclk_pause               : std_logic := '0';
    signal clk_pause_counter    : integer range 0 to 7 := 0;

begin
    dclk_proc : process(clk_50)
    begin

        if(clk_50'event and clk_50='1' ) then
            clk_counter <= clk_counter+1;

            if(clk_counter=10) then
                clk_counter <= 0;
            end if;

            if(clk_counter<5) then
                dclk_5 <= '0';
            else
                dclk_5 <= '1';
            end if;
        end if;

    end process dclk_proc;
end architecture behaviour; 

Picture of simulation:

https://gyazo.com/ad902a9a8066144692f2672484672b8d


Solution

  • Well, your code in not that bad, but there is one problem.

    clk_counter <= clk_counter+1;
    if(clk_counter=10) then
        clk_counter <= 0;
    end if;
    

    So the <= assignment is not assigned until the end of the process. So clk_counter is 9 for the whole process. It will be set to 10, but not until the end of the process, so the if-statement does not trigger. So the next evaluation of the process, clk_counter is 10. Now the if-statement /will/ trigger. However, before that you want to assign 10+1 = 11 to clk_counter.... But that is not allowed, because the range of clk_counter is 0 to 10. You could set the range to 11 and this will not happen. but then the code does not do what you want it to do. So, cleaner code is better imho. E.g.:

    if(clk_counter<10) then
        clk_counter <= clk_counter+1;
    else
        clk_counter <= 0;
    end if;
    

    You could also separate the assignment of dclk from the process. E.g.:

    dclk <= '0' when (clk_counter<5) else '1';
    

    But this is not glitch friendly. You should preferably clock your assignment, like you are already doing.