library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.NUMERIC_STD.all; use work.all; -- on the cyclone iv -- i_clk/4 = 19.676158 -- the scope's pixel clock is 19.66080 -- (p-0.25)*19.66080 = p * 19.676158 --p=1/[4*(1-(19.676158/19.66080))]=320.04 entity hp_lcd_driver is generic (input_video_width : natural := 2; video_width : natural :=2; addr_width : natural := 18; phase_slip : natural := 320; i_clk_multiple : natural := 4; use_pclk : natural := 0; target : string := "artix7"); port (clk_50m : in std_logic; sys_rst_n : in std_logic; video : in std_logic_vector(input_video_width -1 downto 0); hsync_in : in std_logic; vsync_in : in std_logic; pclk_in : in std_logic; r_out : out std_logic; b_out : out std_logic; g_out : out std_logic; hsync_out : out std_logic; vsync_out : out std_logic; hdmi_c_p : out std_logic; hdmi_c_n : out std_logic; hdmi_r_p : out std_logic; hdmi_r_n : out std_logic; hdmi_g_p : out std_logic; hdmi_g_n : out std_logic; hdmi_b_p : out std_logic; hdmi_b_n : out std_logic; hdmi_vcc : out std_logic; i_clk_out : out std_logic; led : out std_logic); end hp_lcd_driver; architecture Behavioral of hp_lcd_driver is signal video_lut : std_logic_vector (video_width-1 downto 0); signal wr_addr : std_logic_vector(addr_width-1 downto 0); signal wr_data : std_logic_vector(video_width-1 downto 0); signal wr_data_b : std_logic_vector(video_width-1 downto 0); signal wr_en : std_logic; signal rd_addr : std_logic_vector(addr_width-1 downto 0); signal rd_data : std_logic_vector(video_width-1 downto 0); signal r : std_logic_vector(7 downto 0); signal g : std_logic_vector(7 downto 0); signal b : std_logic_vector(7 downto 0); signal clk_locked : std_logic; signal i_clk : std_logic; signal o_clk : std_logic; signal o_clk_x2 : std_logic; signal o_clk_phy : std_logic; signal sys_rst : std_logic; signal pa : natural; signal epk : std_logic; signal ic : natural; signal h : natural; signal v : natural; signal c : natural; signal t : std_logic; begin -- clocking: -- i_clk is 4*(nominal) 20MHz to give us 4 choices of sampling position -- o_clk is the output pixel clock -- o_clk_x2 is used by the spartan serdes -- o_clk_phy is used the the hdmi phy (cylone4 it's o_clk x5, spartan 6 it's o_clk x 10) clkgen : entity work.clkgen port map ( sys_rst_n => sys_rst_n, clk_in => clk_50m, i_clk => i_clk, o_clk => o_clk, o_clk_x2 => o_clk_x2, o_clk_phy => o_clk_phy, locked => clk_locked ); video_lut <= "1111" when video(0)='1' else "1011" when video(1)='1' else "1100" when video(2)='1' else "1010" when video(3)='1' else "0011" when video(4)='1' else "1110" when video(5)='1' else "1001" when video(6)='1' else "1101" when video(7)='1' else "0000"; process (i_clk, sys_rst_n) begin if sys_rst_n = '0' then ic <= 0; pa <= phase_slip; epk <= '0'; elsif rising_edge(i_clk) then if ic = 0 then epk <= '1'; if pa = 0 then pa <= phase_slip; ic <= i_clk_multiple; else ic <= i_clk_multiple-1; pa <= pa -1; end if; else if epk = '1' then epk <= '0'; end if; ic <= ic-1; end if; end if; end process; i_clk_out <= epk; input0 : entity work.input_stage generic map( video_width => video_width, addr_width => addr_width, clk_multiple => i_clk_multiple, -- HP54502A -- phase => 1, -- h_front_porch => 200, -- h_active => 592, -- v_front_porch => 1, -- v_active => 384, -- frame_start => 383, -- h_stride => 384, -- v_stride => 262143, -- HP54522A phase => 1, h_front_porch => 190, h_active => 640, v_front_porch => 22, v_active => 384, frame_start => 383, h_stride => 384, v_stride => 524287, phase_slip => phase_slip, use_pclk => use_pclk ) port map ( sys_rst_n => sys_rst_n, clk => i_clk, video_in => video_lut, pclk_in => pclk_in, hsync_in => not hsync_in, vsync_in => not vsync_in, video_out => wr_data, addr_out => wr_addr, wren_out => wr_en ); -- -- process (i_clk) begin -- if sys_rst_n='0' then -- h<=0; -- v<=0; -- wr_addr <=(others =>'0'); -- elsif rising_edge(i_clk) then -- if h /= 383 then -- h<=h+1; -- wr_addr <= std_logic_vector(unsigned(wr_addr)+1); -- else -- h<=0; -- if v /= 591 then -- v<=v+1; -- wr_addr <= std_logic_vector(unsigned(wr_addr)+1); -- else -- v<=0; -- wr_addr <=(others =>'0'); -- end if; -- end if; -- end if; -- end process; -- -- wr_en <= '1'; -- -- wr_data <="01" when (h=0) or (h=383) or (v=0) or (v=591) -- else "00"; -- vram0 : entity work.vram generic map ( video_width => video_width, addr_width => addr_width ) port map ( wr_clk => i_clk, wr_en => wr_en, wr_addr => wr_addr, wr_data => wr_data, rd_clk => o_clk, rd_addr => rd_addr, rd_data => rd_data ); -- r<=x"00"; -- b<=x"00"; r<=x"ff" when rd_data(0)='1' else x"00"; -- r<=x"ff" when rd_data(0)='1' and rd_data(3)='1' else -- x"80" when rd_data(0)='1' else -- x"00"; g<=x"ff" when rd_data(1)='1' and rd_data(3)='1' else x"80" when rd_data(1)='1' else x"00"; b<=x"ff" when rd_data(2)='1' and rd_data(3)='1' else x"80" when rd_data(2)='1' else x"00"; --"ff" when rd_data(1) = '1' else -- x"80" when rd_data(0) = '1' else -- ix"00"; output0 : entity work.output_stage -- didn't work for me from this thing, only from mac, works at 60Hz xrandr --newmode "$M" 18.24 384 400 440 600 592 593 596 613 -HSync +Vsync -- Modeline "384x592_80.00" 25.40 384 408 448 512 592 593 596 620 -HSync +Vsync generic map ( target => target, addr_width => addr_width, -- h_active => 384, -- h_sync_start => 400, -- h_sync_end => 440, -- h_total => 640, -- v_active => 592, -- v_sync_start => 593, -- v_sync_end => 596, -- v_total => 613, -- h_stride => 1, -- v_stride => 384 -- HP54502A -- h_active => 384, -- h_sync_start => 400, -- h_sync_end => 440, -- h_total => 660, -- v_active => 592, -- v_sync_start => 593, -- v_sync_end => 596, -- v_total => 613, -- h_stride => 1, -- v_stride => 384 -- HP54522A h_active => 384, h_sync_start => 400, h_sync_end => 456, h_total => 660, -- h_active => 417, -- h_sync_start => 440, -- h_sync_end => 480, -- h_total => 660, v_active => 640, v_sync_start => 641, v_sync_end => 644, v_total => 650, h_stride => 1, v_stride => 384 -- h_active => 640, -- h_sync_start=>656, -- h_sync_end =>752, -- h_total=>800, -- -- v_active =>480, -- v_sync_start=>490, -- v_sync_end=>492, -- v_total=>525, -- h_stride=>1, -- v_stride=>384 ) port map( clk_locked => clk_locked, clk => o_clk, clk_x2 => o_clk_x2, clk_phy => o_clk_phy, sys_rst_n => sys_rst_n, vsync_in => not vsync_in, r_in => r, g_in => g, b_in => b, addr_out => rd_addr, r_out => r_out, g_out => g_out, b_out => b_out, hsync_out => hsync_out, vsync_out => vsync_out, hdmi_c_p => hdmi_c_p, hdmi_c_n => hdmi_c_n, hdmi_r_p => hdmi_r_p, hdmi_r_n => hdmi_r_n, hdmi_g_p => hdmi_g_p, hdmi_g_n => hdmi_g_n, hdmi_b_p => hdmi_b_p, hdmi_b_n => hdmi_b_n ); process (clk_50m, c) begin if rising_edge(clk_50m) then if c < 19999999 then c <=c+1; else c <=0; t <=not t; end if; end if; end process; led <= t; end Behavioral;