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

library UNISIM;
use UNISIM.vcomponents.all;

entity clock_divider is
generic (
        G_DIVISOR : positive := 2
);
port (
        
        i_clk : in std_logic;
        i_rst : in std_logic;
        
        o_clk : out std_logic
        
);
end entity clock_divider;

architecture behavioral of clock_divider is

subtype t_counter is natural range 0 to ( G_DIVISOR - 1 );
signal s_counter : t_counter := 0;

constant C_COUNTER : t_counter := G_DIVISOR / 2 - 1;

signal s_clk_divided : std_logic;
attribute clock_signal : string;
attribute clock_signal of s_clk_divided : signal is "yes";

begin

        assert ( G_DIVISOR > 1 ) report "The divisor should be greater than 1" severity failure;
        
        counting : process( i_clk )
        begin
                if( rising_edge(i_clk) ) then
                        if( i_rst = '1' ) then
                                s_counter <= 0;
                                s_clk_divided <= '0';
                        else
                                if( s_counter = t_counter'high ) then
                                        s_counter <= 0;
                                        s_clk_divided <= '0';
                                else
                                        s_counter <= s_counter + 1;
                                        if( s_counter = C_COUNTER ) then
                                                s_clk_divided <= '1';
                                        end if;
                                end if;
                        end if;
                end if;
        end process counting;
        
        BUFR_inst : BUFR
        generic map (
                BUFR_DIVIDE => "BYPASS", -- "BYPASS", "1", "2", "3", "4", "5", "6", "7", "8"
                SIM_DEVICE => "VIRTEX6") -- Specify target device, "VIRTEX4", "VIRTEX5", "VIRTEX6"
        port map (
                O => o_clk, -- Clock buffer output
                CE => '1', -- Clock enable input
                CLR => '0', -- Clock buffer reset input
                I => s_clk_divided -- Clock buffer input
        );
                                        
end architecture;