---------------------------------------------------------------------------------- -- Company: c't magazin -- Engineer: Carsten Meyer, cm@ctmagazin.de -- -- Create Date: 14:11:15 06/05/2010 -- Design Name: -- Module Name: tft_timing - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: Timing-Interface für analoges LC-Display 7" DPF 480*234 -- -- 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; use ieee.numeric_std.all; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity tft_timing is Port ( PCLK : in STD_LOGIC; -- Pixeltakt 10 MHz vom Display VSTART_i : in STD_LOGIC; -- Vertical Start vom Display ca. 55 Hz HSTART_i : in STD_LOGIC; -- Horizontal Start vom Display ca. 14,7 kHz VCOM_i : in STD_LOGIC; -- AC-Komponente Vcom vom Display adj_h: in std_logic_vector(9 downto 0); -- Koordinaten für Test-Fadenkreuz horizontal adj_v: in std_logic_vector(9 downto 0); -- Koordinaten für Test-Fadenkreuz vertikal HPIXEL: out std_logic_vector(9 downto 0); -- max. 1024 x 1024 Pixel VPIXEL: out std_logic_vector(9 downto 0); PIXELADR: out std_logic_vector(19 downto 0); TEXTADR : out STD_LOGIC_VECTOR (11 downto 0); -- 4096 Zeichen möglich VIDEOTEST: out STD_LOGIC; CHARLINE : out STD_LOGIC_VECTOR (3 downto 0); -- Zeile innerhalb Zeichen, 16 Zeilen pro char möglich TEXTCOL : out STD_LOGIC_VECTOR (6 downto 0); -- 128 Zeichen pro Zeile möglich TEXTROW : out STD_LOGIC_VECTOR (4 downto 0) -- 32 Textzeilen möglich ); end tft_timing; architecture Behavioral of tft_timing is constant screen_h: STD_LOGIC_VECTOR(9 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(480, 10); -- Breite 480 Pixel constant screen_v: STD_LOGIC_VECTOR(9 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(234, 10); -- Höhe 234 Pixel constant col_h: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(60, 7); -- Breite in Zeichen constant col_v: STD_LOGIC_VECTOR(4 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(20, 5); -- Höhe in Zeichen constant ofs_v: integer:= 3; -- vertical position constant charheight: integer:= 12; signal v_count : STD_LOGIC_VECTOR(9 DOWNTO 0) :=(others =>'0'); signal h_adr, v_adr : STD_LOGIC_VECTOR(9 DOWNTO 0) :=(others =>'0'); signal c_adr : STD_LOGIC_VECTOR(19 DOWNTO 0):=(others =>'0'); signal charlinecount : STD_LOGIC_VECTOR(3 DOWNTO 0) :="0000"; signal textrowcount : STD_LOGIC_VECTOR(4 DOWNTO 0) :=(others =>'0'); signal vstart,vstart_d,hstart,hstart_d : STD_LOGIC:='0'; signal video_h,video_v : STD_LOGIC:='0'; -- nur für Test-Animation gebraucht signal reset, Ball_on, Direction : std_logic; signal Size : std_logic_vector(9 DOWNTO 0); signal Ball_X_motion,Ball_Y_motion : std_logic_vector(9 DOWNTO 0); signal Ball_Y_pos, Ball_X_pos : std_logic_vector(9 DOWNTO 0):=CONV_STD_LOGIC_VECTOR(200,10); --- begin HPIXEL<=h_adr; VPIXEL<=v_adr; PIXELADR <= (v_adr * screen_h) + h_adr; CHARLINE<=charlinecount; TEXTCOL<=h_adr(9 downto 3); TEXTROW<=textrowcount; TEXTADR <= (textrowcount * col_h) + h_adr(9 downto 3); -- Testausgang Frame mit mittigem Kreuz und springendem "Ball" video_h <= '1' when (h_adr = 0) or (h_adr = adj_h) or (h_adr = 479) else '0'; -- Test erste und letzte Pixel-Spalte video_v <= '1' when (v_adr = 0) or (v_adr = adj_v) or (v_adr = 233) else '0'; -- Test erste und letzte Pixel-Reihe process(PCLK) begin if rising_edge(PCLK) then VIDEOTEST <= (video_h or video_v or Ball_on) xnor VCOM_i; end if; end process; -- TFT-Timing, vom Display vorgegeben process(PCLK) begin if falling_edge(PCLK) then -- wg. jitter bei rising_edge -- One-shots für VSTART und HSTART vstart<='0'; if (vstart_d='0') and (VSTART_i='1') then vstart<='1'; end if; vstart_d<=VSTART_i; -- hstart<='0'; -- if (hstart_d='0') and (HSTART_i='1') then -- hstart<='1'; -- end if; -- hstart_d<=HSTART_i; --Counter vert und hor h_adr<=h_adr+1; if HSTART_i='1' then -- Zeilenanfang h_adr<=(others =>'0'); v_count<=v_count+1; if v_count >= ofs_v then -- Offset für erste Scan-Zeile des Analog-Displays v_adr<=v_adr+1; charlinecount<=charlinecount+1; end if; if charlinecount=charheight then charlinecount<=(others =>'0'); textrowcount<=textrowcount+1; end if; end if; if vstart='1' then -- Frame-Anfang charlinecount<=(others =>'0'); textrowcount<=(others =>'0'); h_adr<=(others =>'1'); v_count<=(others =>'0'); v_adr<=(others =>'0'); end if; end if; end process; -- Ende des Timing-Generators -- Testbild: Springender "Ball", aus XILINX-Demo übernommen Size <= CONV_STD_LOGIC_VECTOR(8,10); Process (Ball_X_pos, Ball_Y_pos, h_adr, v_adr, Size) begin IF ('0' & Ball_X_pos <= h_adr + Size) AND (Ball_X_pos + Size >= '0' & h_adr) AND ('0' & Ball_Y_pos <= v_adr + Size) AND (Ball_Y_pos + Size >= '0' & v_adr ) THEN Ball_on <= '1'; ELSE Ball_on <= '0'; END IF; end process; Move_Ball: process begin -- Move ball once every vertical sync WAIT UNTIL vstart'event and vstart = '1'; -- Bounce off top or bottom of screen IF ('0' & Ball_Y_pos) >= CONV_STD_LOGIC_VECTOR(230,10) - Size THEN Ball_Y_motion <= not CONV_STD_LOGIC_VECTOR(6,10); ELSIF Ball_Y_pos <= Size + Size THEN Ball_Y_motion <= CONV_STD_LOGIC_VECTOR(4,10); END IF; IF ('0' & Ball_X_pos) >= CONV_STD_LOGIC_VECTOR(480,10) - Size THEN Ball_X_motion <= not CONV_STD_LOGIC_VECTOR(3,10); ELSIF Ball_X_pos <= Size + Size + adj_h THEN Ball_X_motion <= CONV_STD_LOGIC_VECTOR(5,10); END IF; -- Compute next ball Y position Ball_Y_pos <= Ball_Y_pos + Ball_Y_motion; Ball_X_pos <= Ball_X_pos + Ball_X_motion; end process Move_Ball; end Behavioral;