----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    16:04:28 12/29/2008 
-- Design Name: 
-- Module Name:    pwm2 - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

entity pwm2 is
    Port ( clk : in  STD_LOGIC;
			  clk66 : in std_logic;
           reset : in  STD_LOGIC;
           address : in  STD_LOGIC_VECTOR (31 downto 2);
			  enable : in std_logic;
           byte_we : in std_logic_vector(3 downto 0);
			  data_read : out std_logic_vector(31 downto 0);
           data_write : in  STD_LOGIC_VECTOR (31 downto 0);
           pwm_out : out  STD_LOGIC_VECTOR (23 downto 0));
end pwm2;

architecture Behavioral of pwm2 is
   signal counter_66 : std_logic_vector(19 downto 0) := (others=>'0'); -- runs from 0 to 2^20-1=1048575 @ 66 MHz -> 62 Hz/15.9 ms

   signal pwm_ram_addr : std_logic_vector(10 downto 0);
   signal pwm_ram_out : std_logic_vector(15 downto 0);
	

   signal pwm_counter : std_logic_vector(14 downto 0) := (others=>'0');
   signal pwm_index   : std_logic_vector(4 downto 0) := (others=>'0');

begin


   counter_66_proc: process(clk66,reset) is
	begin
	   if(reset='1') then
		   counter_66<=(others=>'0');
			pwm_out<=(others=>'0');
		else
		   if rising_edge(clk66) then
				pwm_counter<=counter_66(17 downto 3);
				pwm_index<=pwm_ram_addr(4 downto 0);
			   counter_66<=counter_66+1;
            
				if(pwm_ram_out="000000000000000") then
					pwm_out(conv_integer(pwm_index))<='0';					
				else
					if(pwm_counter<4096) then
						pwm_out(conv_integer(pwm_index))<='1';
					elsif(pwm_counter>20480) then
						pwm_out(conv_integer(pwm_index))<='0';
					elsif(pwm_counter<pwm_ram_out) then
						pwm_out(conv_integer(pwm_index))<='1';
					else
						pwm_out(conv_integer(pwm_index))<='0';
					end if;
				end if;
			end if;
		end if;
	end process;

   pwm_ram_addr<="000000"&counter_66(2 downto 0)&counter_66(19 downto 18);
		
	register_block_lo: RAMB16_S9_S9
	   port map (
      CLKA  => clk, 
      ENA   => enable,
      WEA   => byte_we(0),
      ADDRA => address(12 downto 2),
      DIA   => data_write(7 downto 0),
      DOA   => data_read(7 downto 0),
      DIPA  => (others=>'0'),
      DOPA  => open,
      SSRA  => '0',

		CLKB  => clk66,
		ADDRB => pwm_ram_addr,
		DIB   => "00000000",
		DOB   => pwm_ram_out(7 downto 0),
		DIPB  => (others=>'0'),
      DOPB  => open,		
		ENB   => '1',
		SSRB  => '0',
		WEB   => '0');

	register_block_hi: RAMB16_S9_S9
	   port map (
      CLKA  => clk,
      ENA   => enable,
      WEA   => byte_we(1),
      ADDRA => address(12 downto 2),
      DIA   => data_write(15 downto 8),
      DOA   => data_read(15 downto 8),
      DIPA  => (others=>'0'),
      DOPA  => open,
      SSRA  => '0',

      CLKB  => clk66,		
		ENB   => '1',
		WEB   => '0',
		ADDRB => pwm_ram_addr,
	   DIB   => "00000000",
		DOB   => pwm_ram_out(15 downto 8),
		DOPB  => open,
		SSRB  => '0');

end Behavioral;