-- ----------------------------------------------------------------------------- -- Copyright (c) 2013 Benjamin Krill -- -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be included in -- all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -- THE SOFTWARE. -- ----------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.dvi_package.all; entity sig is generic ( H_ACTIVE_PIXEL : unsigned(11 downto 0) := x"5a0"; H_BLANKING : unsigned(11 downto 0) := x"0dd"; H_SYNC_WIDTH : unsigned(11 downto 0) := x"03c"; H_SYNC_OFFSET : unsigned(11 downto 0) := x"050"; -- front porch V_ACTIVE_LINES : unsigned(11 downto 0) := x"21c"; V_BLANKING : unsigned(11 downto 0) := x"022"; V_SYNC_WIDTH : unsigned( 7 downto 0) := x"02"; V_SYNC_OFFSET : unsigned( 7 downto 0) := x"18" -- front porch ); port ( clk : in std_logic; rst_n : in std_logic; -- memory interface --address_o : out std_logic_vector(); -- display output en_stb_i : in std_logic; hsync_o : out std_logic; vsync_o : out std_logic; color_en_o : out std_logic; color_o : out color_t ); end sig; architecture sig of sig is signal h_cnt : unsigned(11 downto 0); signal v_cnt : unsigned(11 downto 0); signal one_screen : std_logic; signal h_state : unsigned(1 downto 0); signal h_state_i : unsigned(1 downto 0); signal v_state : unsigned(1 downto 0); signal v_state_i : unsigned(1 downto 0); constant SYNC_OFF : unsigned(1 downto 0) := "00"; constant SYNC : unsigned(1 downto 0) := "01"; constant SYNC_BACK : unsigned(1 downto 0) := "10"; constant ACTIVE_LINE : unsigned(1 downto 0) := "11"; constant H_SYNC_BACK : unsigned(11 downto 0) := H_BLANKING - H_SYNC_OFFSET - H_SYNC_WIDTH; constant V_SYNC_BACK : unsigned(11 downto 0) := V_BLANKING - V_SYNC_OFFSET - V_SYNC_WIDTH; begin hsync_o <= '1' when h_state = SYNC and v_state = ACTIVE_LINE else '0'; vsync_o <= '1' when v_state = SYNC else '0'; color_en_o <= '1' when h_state = ACTIVE_LINE and v_state = ACTIVE_LINE else '0'; color_o <= ((others => v_cnt(3)), (others => v_cnt(2)), (others => v_cnt(1))); process (clk, rst_n) begin if rst_n = '0' then h_cnt <= x"000"; v_cnt <= x"000"; v_state <= "00"; v_state_i <= "00"; h_state <= "00"; h_state_i <= "00"; one_screen <= '0'; elsif rising_edge(clk) then if v_state = ACTIVE_LINE and v_cnt = x"000" then one_screen <= '0'; elsif en_stb_i = '1' then one_screen <= '1'; end if; if one_screen = '1' and h_cnt = x"000" then h_state <= h_state_i; case h_state_i is when SYNC_OFF => h_cnt <= H_SYNC_OFFSET-1; when SYNC => h_cnt <= H_SYNC_WIDTH-1; when SYNC_BACK => h_cnt <= H_SYNC_BACK-1; when ACTIVE_LINE => h_cnt <= H_ACTIVE_PIXEL-1; when others => h_cnt <= x"000"; end case; elsif h_cnt /= x"000" then h_cnt <= h_cnt - "1"; end if; if one_screen = '1' and h_cnt = x"000" then h_state_i <= h_state_i + "01"; end if; if one_screen = '1' and v_cnt = x"000" and h_state = SYNC_OFF then v_state <= v_state_i; case v_state_i is when SYNC_OFF => v_cnt <= x"0" & V_SYNC_OFFSET; when SYNC => v_cnt <= x"0" & V_SYNC_WIDTH; when SYNC_BACK => v_cnt <= V_SYNC_BACK; when ACTIVE_LINE => v_cnt <= V_ACTIVE_LINES; when others => v_cnt <= x"000"; end case; elsif v_cnt /= x"000" and (h_state = ACTIVE_LINE and h_cnt = x"000") then v_cnt <= v_cnt - "1"; end if; if one_screen = '1' and v_cnt = x"000" then v_state_i <= v_state_i + "01"; end if; end if; end process; end sig;