------------------------------------------------------------------------------- -- File: clock_divide.vhd -- -- Created by: Daniel Leder -- Date: 10/18/99 -- -- Purpose: to create a valid clock with a rising and falling edge -- using carry-save counter technique to increase performance -- -- Inputs: reset, clock and the two parts for the carry-save counter -- -- Outputs: the new clock -- -- NOTE: if you have a 10MHz clock and you want to get a 1 MHz clock -- the two parts should add upto 5, this is because for a 1MHz clock -- from a 10MHz clock still needs to have a 50% duty cycle. -- Therefore if you want to divide a clock divide the amount you -- want to divide the incoming clock by, by 2. ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; library lpm; use lpm.lpm_components.all; library work; use work.mp3_decode_pkg.all; use work.sdram_package.all; entity clock_divide is generic(counterwidth: positive := 5); port(clock: in std_logic; -- input clock reset, enable: in std_logic; -- reset count_part1: in std_logic_vector(counterwidth-1 downto 0); -- part1 of counter count_part2: in std_logic_vector(counterwidth-1 downto 0); -- part2 of counter divided_clock: out std_logic -- new output clock of new period and frequency ); end clock_divide; architecture behavioural of clock_divide is signal intermediate_clock: std_logic; -- intermediate clock used -- so that can just invert the -- value for toggling -- two parts that are going to be compared signal part1, part2: std_logic_vector(counterwidth-1 downto 0); -- indicate if the two parts have reached the desired count signal same_part1, same_part2: std_logic; -- have reached the desired total count signal count_elapsed: std_logic; -- clear the carry-save counter back to zero signal clear_count: std_logic; begin clear_count <= (reset or count_elapsed) or not enable; -- ensure that initial resets also seen -- instantiate the carry-save counter counter: cscounter generic map(counterwidth => counterwidth) port map(clock => clock, reset => clear_count, count_part1_out => part1, count_part2_out => part2 ); -- instantiate the two compare lpm modules compare1: lpm_compare generic map(LPM_WIDTH => counterwidth) port map(dataa => part1, datab => count_part1, aeb => same_part1 ); compare2: lpm_compare generic map(LPM_WIDTH => counterwidth) port map(dataa => part2, datab => count_part2, aeb => same_part2 ); -- will equal '1' when reached desired count count_elapsed <= same_part1 and same_part2; -- output the clock divided_clock <= intermediate_clock; -- to detect a rising edge on the count_elapsed to trigger -- a switch in output clock, this is to ensure that will switch -- at right time since count_elapsed will equal '0' soon after -- counter reset (a pulse) createclock: process (count_elapsed) begin if reset = '1' then intermediate_clock <= '0'; elsif rising_edge(count_elapsed) then intermediate_clock <= not intermediate_clock; end if; end process createclock; end behavioural;