dynamic_freq_div.vhd
99 lines
| 3.6 KiB
| text/x-vhdl
|
VhdlLexer
Alexis Jeandet
|
r530 | ------------------------------------------------------------------------------ | ||
-- This file is a part of the LPP VHDL IP LIBRARY | ||||
-- Copyright (C) 2009 - 2015, Laboratory of Plasmas Physic - CNRS | ||||
-- | ||||
-- This program is free software; you can redistribute it and/or modify | ||||
-- it under the terms of the GNU General Public License as published by | ||||
-- the Free Software Foundation; either version 3 of the License, or | ||||
-- (at your option) any later version. | ||||
-- | ||||
-- This program is distributed in the hope that it will be useful, | ||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
-- GNU General Public License for more details. | ||||
-- | ||||
-- You should have received a copy of the GNU General Public License | ||||
-- along with this program; if not, write to the Free Software | ||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
------------------------------------------------------------------------------ | ||||
-- Author : Alexis Jeandet | ||||
-- Mail : alexis.jeandet@member.fsf.org | ||||
------------------------------------------------------------------------------ | ||||
library IEEE; | ||||
use IEEE.STD_LOGIC_1164.ALL; | ||||
use IEEE.NUMERIC_STD.ALL; | ||||
entity dynamic_freq_div is | ||||
generic( | ||||
PRESZ : integer range 1 to 32:=4; | ||||
PREMAX : integer := 16#FFFFFF#; | ||||
CPTSZ : integer range 1 to 32:=16 | ||||
); | ||||
Port ( | ||||
clk : in STD_LOGIC; | ||||
rstn : in STD_LOGIC; | ||||
pre : in STD_LOGIC_VECTOR(PRESZ-1 downto 0); | ||||
N : in STD_LOGIC_VECTOR(CPTSZ-1 downto 0); | ||||
Reload : in std_logic; | ||||
clk_out : out STD_LOGIC | ||||
); | ||||
end dynamic_freq_div; | ||||
architecture Behavioral of dynamic_freq_div is | ||||
constant prescaller_reg_sz : integer := 2**PRESZ; | ||||
constant PREMAX_max : STD_LOGIC_VECTOR(PRESZ-1 downto 0):=(others => '1'); | ||||
signal cpt_reg : std_logic_vector(CPTSZ-1 downto 0):=(others => '0'); | ||||
signal prescaller_reg : std_logic_vector(prescaller_reg_sz-1 downto 0):=(others => '0'); | ||||
signal internal_clk : std_logic:='0'; | ||||
signal internal_clk_reg : std_logic:='0'; | ||||
signal clk_out_reg : std_logic:='0'; | ||||
begin | ||||
max0: if (UNSIGNED(PREMAX_max) < PREMAX) generate | ||||
internal_clk <= prescaller_reg(to_integer(unsigned(pre))) when (to_integer(unsigned(pre))<=UNSIGNED(PREMAX_max)) else | ||||
prescaller_reg(to_integer(UNSIGNED(PREMAX_max))); | ||||
end generate; | ||||
max1: if UNSIGNED(PREMAX_max) > PREMAX generate | ||||
internal_clk <= prescaller_reg(to_integer(unsigned(pre))) when (to_integer(unsigned(pre))<=PREMAX) else | ||||
prescaller_reg(PREMAX); | ||||
end generate; | ||||
prescaller: process(rstn, clk) | ||||
begin | ||||
if rstn='0' then | ||||
prescaller_reg <= (others => '0'); | ||||
elsif clk'event and clk = '1' then | ||||
prescaller_reg <= std_logic_vector(UNSIGNED(prescaller_reg) + 1); | ||||
end if; | ||||
end process; | ||||
clk_out <= clk_out_reg; | ||||
counter: process(rstn, clk) | ||||
begin | ||||
if rstn='0' then | ||||
cpt_reg <= (others => '0'); | ||||
internal_clk_reg <= '0'; | ||||
clk_out_reg <= '0'; | ||||
elsif clk'event and clk = '1' then | ||||
internal_clk_reg <= internal_clk; | ||||
if Reload = '1' then | ||||
clk_out_reg <= '0'; | ||||
cpt_reg <= (others => '0'); | ||||
elsif (internal_clk = '1' and internal_clk_reg = '0') then | ||||
if cpt_reg = N then | ||||
clk_out_reg <= not clk_out_reg; | ||||
cpt_reg <= (others => '0'); | ||||
else | ||||
cpt_reg <= std_logic_vector(UNSIGNED(cpt_reg) + 1); | ||||
end if; | ||||
end if; | ||||
end if; | ||||
end process; | ||||
end Behavioral; | ||||