Skip to content

Instantly share code, notes, and snippets.

@jgibbard
Last active March 16, 2017 12:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jgibbard/532a4ff0c4115a5a3f33 to your computer and use it in GitHub Desktop.
Save jgibbard/532a4ff0c4115a5a3f33 to your computer and use it in GitHub Desktop.
VHDL Counter
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; USE ieee.std_logic_arith.all;
--This example shows how different speed signals can be created using both a counter method and a PLL
--PLL are very powerful and can be used to generate both fast or slower clk speeds as well as changing the phase of the signal.
--There are a limited amount of PLLs on an FPGA however a single PLL block in the FPGA can often be used to generate several different frequencies.
entity pll_test is port (
CLOCK_50 : in std_logic;
SW : in std_logic_vector(9 downto 0);
LEDG : OUT std_logic_vector(9 downto 0)
);
end pll_test;
architecture rtl of pll_test is
--Signals for 50MHz clk divider
signal clk_divide_count1 : std_logic_vector(31 downto 0) := (others => '0');
signal counter1 : std_logic_vector(9 downto 0) := (others => '0');
signal slow_clk1 : std_logic := '0';
--Signals for 100MHz clk divider
signal clk_divide_count2 : std_logic_vector(31 downto 0) := (others => '0');
signal counter2 : std_logic_vector(9 downto 0) := (others => '0');
signal slow_clk2 : std_logic := '0';
signal pll_clk : std_logic := '0';
begin
--Generates a slower clk so that the counting can be seen at human speeds!
slow_clock_gen_process1 : process(CLOCK_50)
begin
if rising_edge(CLOCK_50) then
if (clk_divide_count1 >= 5000000) then --50MHz clock counting to 5 million, therefore slow clock will have period of 0.1s [(1/(50*10^6))*(5*10^6) = 0.1]
clk_divide_count1 <= (others => '0'); --Reset clock divider
slow_clk1 <= '1'; --Pulse slow_clk for one clock period
else
clk_divide_count1 <= clk_divide_count1 + 1 ; --Increment clk_divide_count, NB this is not the output counter
slow_clk1 <= '0';
end if;
end if;
if rising_edge(CLOCK_50) then
if (slow_clk1 = '1') then
counter1 <= counter1 + 1 ; --Increment the output counter every 0.1s
end if;
end if;
end process;
--Identical process to above, however runs off 100MHz clk instead of 50MHz
slow_clock_gen_process2 : process(pll_clk)
begin
if rising_edge(pll_clk) then
if (clk_divide_count2 >= 5000000) then --100MHz clock counting to 5 million, therefore slow clock will have period of 0.05s
clk_divide_count2 <= (others => '0'); --Reset clock divider
slow_clk2 <= '1'; --Pulse slow_clk for one clock period
else
clk_divide_count2 <= clk_divide_count2 + 1 ; --Increment clk_divide_count, NB this is not the output counter
slow_clk2 <= '0';
end if;
end if;
if rising_edge(pll_clk) then
if (slow_clk2 = '1') then
counter2 <= counter2 + 1 ; --Increment the output counter every 0.05s
end if;
end if;
end process;
--Generates 100MHz clk from 50MHz clk via PLL
pll_inst : entity work.mw_pll port map (inclk0 => CLOCK_50, c0 => pll_clk);
LEDG(9 downto 0) <= counter1 when sw(0) = '1' else counter2; --Set LEDs to value of counter. Speed of counter depends on position of switch 0
end rtl;
--This VHDL example outputs a binary count to 10 leds.
--The counter increases at the rate of 0.1s when the input clk is 50MHz.
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; USE ieee.std_logic_arith.all;
entity test_design is port(
--These must match the names of the pins set in the pin asignment file
CLOCK_50 : in std_logic;
SW : in std_logic_vector(9 downto 0);
LEDG : out std_logic_vector(9 downto 0)
);
end test_design;
architecture rtl of test_design is
signal clk_divide_count : std_logic_vector(31 downto 0); --Stores the current count of the clock divider counter
signal counter : std_logic_vector(9 downto 0); --Stores the value of the output counter displayed on the LEDs
signal slow_clk : std_logic; --The new slow clock (Period set to 0.1s)
begin
slow_clock_gen_process : process(CLOCK_50)
begin
if rising_edge(CLOCK_50) then
if (clk_divide_count >= 5000000) then --50MHz clock counting to 5 million, therefore slow clock will have period of 0.1s [(1/(50*10^6))*(5*10^6) = 0.1]
clk_divide_count <= (others => '0'); --Reset clock divider
slow_clk <= '1'; --Pulse slow_clk for one clock period
else
clk_divide_count <= clk_divide_count + 1 ; --Increment clk_divide_count, NB this is not the output counter
slow_clk <= '0';
end if;
end if;
if rising_edge(CLOCK_50) then
if (slow_clk = '1') then
counter <= counter + 1 ; --Increment the output counter every 0.1s
end if;
end if;
end process;
LEDG(9 downto 0) <= counter; --Set LEDs to value of counter
end rtl;
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; USE ieee.std_logic_arith.all;
ENTITY test_design_tb IS
END test_design_tb;
ARCHITECTURE behavior OF test_design_tb IS
component test_design PORT(
CLOCK_50 : in std_logic;
reset : in std_logic;
LEDG : out std_logic_vector(9 downto 0)
);
end component;
signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal led_out : std_logic_vector(9 downto 0) := (others => '0');
constant clk_period : time := 1 ns;
BEGIN
uut: test_design PORT MAP (CLOCK_50 => clk, reset => rst, LEDG => led_out);
reset_process : process
begin
wait for 10 ns;
rst <= '1';
wait for 2 ns;
rst <= '0';
wait;
end process;
-- Clock process definitions( clock with 50% duty cycle is generated here.
clk_process :process
begin
clk <= '0';
wait for clk_period/2; --for 0.5 ns signal is '0'.
clk <= '1';
wait for clk_period/2; --for next 0.5 ns signal is '1'.
end process;
END;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment