library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_arith.all ;
use ieee.std_logic_unsigned.all ;
library altera_mf ;
use altera_mf.all ;

-- the simply ROTOZOOM project
-- 800x600 pixel rezolution   with 72 Hz refresh rate
entity rotozoom is
  port
      ( clk     : in     std_logic ;                     -- 50 MHz
      rst     : in     std_logic ;                     -- active low ( '0' )
      v_sync   : buffer std_logic ;                     -- to monitor
      h_sync   : out     std_logic ;                     -- to monitor
      sync     : out     std_logic ;                     -- to DAC
      blank   : out     std_logic ;                     -- to DAC
      dac_clk : out     std_logic ;                     -- to DAC
      rgb     : out     std_logic_vector ( 29 downto 0 )   -- to DAC
        ) ;
  -- pin location for Altera DE2 evaluation board
  attribute altera_chip_pin_lc             : string ;
  attribute altera_chip_pin_lc of clk     : signal is "@N2" ;
  attribute altera_chip_pin_lc of rst     : signal is "@G26" ;
  attribute altera_chip_pin_lc of dac_clk : signal is "@B8" ;
  attribute altera_chip_pin_lc of blank   : signal is "@D6" ;
  attribute altera_chip_pin_lc of sync     : signal is "@B7" ;
  attribute altera_chip_pin_lc of v_sync   : signal is "@D8" ;
  attribute altera_chip_pin_lc of h_sync   : signal is "@A7" ;
  attribute altera_chip_pin_lc of rgb     : signal is "@A8,@C9,@D9,@G10,@F10,@C8,@E10,@F11,@H12,@H11,
                                                        @D12,@E12,@D11,@G11,@A10,@B10,@D10,@C10,@A9,@B9,
                                                        @B12,@C12,@B11,@C11,@J11,@J10,@G12,@F12,@J14,@J13" ;
end entity rotozoom ;

architecture arc_rotozoom of rotozoom is
  signal xcnt                 : std_logic_vector ( 10 downto 0 ) ;
  signal ycnt                 : std_logic_vector ( 9 downto 0 ) ;
  signal ddrff_rst             : std_logic ;
  signal v_sync_delay         : std_logic ;
  signal counter_64           : std_logic_vector ( 5 downto 0 ) ;
  signal x0, y0, x1, y1       : std_logic_vector ( 15 downto 0 ) ;
  signal dac_clk_vec           : std_logic_vector ( 0 downto 0 ) ;
  signal small_step, big_step : std_logic_vector ( 9 downto 0 ) ;
  component altddio_out
      generic (
        extend_oe_disable       : string ;
        intended_device_family : string ;
        invert_output           : string ;
        lpm_type               : string ;
        oe_reg                 : string ;
        width                   : natural
          ) ;
      port (
        dataout   : out std_logic_vector ( 0 downto 0 ) ;
        outclock : in   std_logic ;
        datain_h : in   std_logic_vector ( 0 downto 0 ) ;
        aclr     : in   std_logic ;
        datain_l : in   std_logic_vector ( 0 downto 0 )
          ) ;
  end component altddio_out ;

begin
 
  ddrff_rst <= not rst ;
  dac_clk   <= dac_clk_vec( 0 ) ;
  altddio_out_component : altddio_out
      generic map (
        extend_oe_disable       => "UNUSED",
        intended_device_family => "Cyclone II",
        invert_output           => "OFF",
        lpm_type               => "altddio_out",
        oe_reg                 => "UNUSED",
        width                   => 1
          )
      port map (
        outclock => clk,
        datain_h => "1",
        aclr     => ddrff_rst,
        datain_l => "0",
        dataout   => dac_clk_vec
          ) ;

  process( clk, rst ) is
      variable rgb_bit : std_logic ;
  begin
      if ( rst = '0' ) then
        xcnt         <= ( others => '0' ) ;
        ycnt         <= ( others => '0' ) ;
        v_sync       <= '0' ;
        h_sync       <= '0' ;
        sync         <= '0' ;
        blank         <= '0' ;
        rgb           <= ( others => '0' ) ;
        x0           <= ( others => '0' ) ;
        x1           <= ( others => '0' ) ;
        y0           <= ( others => '0' ) ;
        y1           <= ( others => '0' ) ;
        v_sync_delay <= '0' ;
        counter_64   <= ( others => '0' ) ;
        small_step   <= conv_std_logic_vector ( 20, 10 ) ;
        big_step     <= conv_std_logic_vector ( 100, 10 ) ;
      elsif rising_edge ( clk ) then
        rgb_bit       := x0( 15 ) xor y0( 15 ) ;
        v_sync_delay <= v_sync ;
        if ( ( ( not v_sync ) and v_sync_delay ) = '1' ) then
            counter_64 <= counter_64+1 ;
        end if ;
        if ( counter_64( 4 downto 0 ) = 31 ) then
            if ( small_step > 500 ) then
              small_step <= conv_std_logic_vector ( 20, 10 ) ;   --20
            else
              small_step <= small_step+5 ;
            end if ;
            if ( big_step > 600 ) then
                                  big_step <= conv_std_logic_vector ( 100, 10 ) ;
            else
                big_step <= big_step+7 ;
            end if ;
        end if ;
        if ( xcnt = 1039 ) then
            xcnt <= ( others => '0' ) ;
            if( ycnt = 665 ) then
              ycnt <= ( others => '0' ) ;
            else
              ycnt <= ycnt + 1 ;
            end if ;
        else
            xcnt <= xcnt + 1 ;
        end if ;
        if ( xcnt > 856 ) and ( xcnt <= 976 )then
            h_sync <= '1' ;
        else
            h_sync <= '0' ;
        end if ;
        if( ycnt > 637 ) and ( ycnt <= 643 )then
            v_sync <= '1' ;
        else
            v_sync <= '0' ;
        end if ;
        if( xcnt > 799 ) or ( ycnt > 599 )then
            sync   <= '0' ;
            blank <= '0' ;
        else
            sync   <= '1' ;
            blank <= '1' ;
        end if ;
        if ( ycnt = 599 ) then
            x0 <= ( others => '1' ) ;
            x1 <= ( others => '1' ) ;
            y0 <= ( others => '1' ) ;
            y1 <= ( others => '1' ) ;
        elsif ( xcnt = 799 ) then
            x0 <= x1 - small_step ;
            y0 <= y1 + big_step ;
            x1 <= x1 - small_step ;
            y1 <= y1 + big_step ;
        else
            x0 <= x0 + big_step ;
            y0 <= y0 + small_step ;
        end if ;
        if ( xcnt > 799 or ycnt > 599 ) then
            rgb <= ( others => '0' ) ;
        else
            rgb <= ( others => rgb_bit ) ;
        end if ;
      end if ;
  end process ;
end architecture arc_rotozoom ;