如何在带有FPGA板的HDMI屏幕上显示?

时间:2019-12-11 12:22:24

标签: fpga

我正在做一个项目。 该项目的目标是使用FPGA板将USB键盘和HDMI显示器相互连接。这意味着我们想在按下键时在显示屏上显示键盘的每个字母和字符。

对于该项目,我选择了Digilent基于FPGA Xilinx Spartan6构建的Altys板。

目前,我已经将键盘与FPGA板相连,并且可以从键盘接收数据。这意味着当我按电路板上的字母LED时,它们会点亮。 我还为每个字母实现了led序列。

现在,我尝试将键盘上的字母发送到具有HDMI输出端口的显示器,但是遇到了一些麻烦。

是否有人有任何想法或代码可以通过FPGA板的HDMI端口显示某些内容?

感谢您的帮助

键盘连接的代码

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

entity main is
    port(
        k_clk: in std_logic;
        k_d: inout std_logic;
        Led: out std_logic_vector(7 downto 0);
        clk: in std_logic;
        char: out std_logic_vector(7 downto 0)
    );
end main;


architecture Behavioral of main is

signal s_k_clk: std_logic :='0';
signal ch: std_logic_vector(7 downto 0) :=(others=>'0');
signal k_clk1: std_logic;

--signal pulseInternal : std_logic;
signal makeCodeTemp : std_logic_vector(7 downto 0);
signal makeCode : std_logic_vector(7 downto 0);
signal data : std_logic_vector(21 downto 0);
signal charTemp :std_logic_vector(7 downto 0);
--signal char :std_logic_vector(7 downto 0);
begin
--------------------------------------------------------------
makeCodeTemp <= data(9 downto 2); -- Scan code window
makeCode(7) <= makeCodeTemp(0);
makeCode(6) <= makeCodeTemp(1);
makeCode(5) <= makeCodeTemp(2);
makeCode(4) <= makeCodeTemp(3);
makeCode(3) <= makeCodeTemp(4);
makeCode(2) <= makeCodeTemp(5);
makeCode(1) <= makeCodeTemp(6);
makeCode(0) <= makeCodeTemp(7);
--------------------------------------------------------------
    Led(7 downto 0) <= ch(7 downto 0);
    k_clk1<=k_clk xor s_k_clk;
    p0:process(clk)
        begin
        if rising_edge(clk)then
            s_k_clk<=k_clk;
        end if;
    end process;

    p1:process(clk)
        begin
        if rising_edge(clk)then 
            if (k_clk1='1') then 
                data(21 downto 1) <= data(20 downto 0);
                data(0) <= k_d;
                --ch<=ch+1;
            end if;
        end if;
        end process;


    p2:process(clk)
    begin
         if rising_edge(clk) then
              if data(20 downto 13) = x"0F" then                                         char <= charTemp;
                  end if;
         end if;
    end process;

    p3:process(clk)
    begin
         if rising_edge(clk) then
              if charTemp=x"41" then
                ch(0)<='1';
                elsif charTemp=x"42" then
                ch(1)<='1';
                elsif charTemp=x"43" then
                ch(2)<='1';
                elsif charTemp=x"44" then
                ch(3)<='1';
elsif charTemp=x"45" then
                ch(4)<='1';
                end if;
         end if;
    end process;


charTemp <= x"41" when makeCode = x"1C" else --A        
            x"42" when makeCode = x"32" else --B        
            x"43" when makeCode = x"21" else --C        
            x"44" when makeCode = x"23" else --D        
            x"45" when makeCode = x"24" else --E        
            x"46" when makeCode = x"2B" else --F        
            x"47" when makeCode = x"34" else --G        
            x"48" when makeCode = x"33" else --H        
            x"49" when makeCode = x"43" else --I        
            x"4A" when makeCode = x"3B" else --J        
            x"4B" when makeCode = x"42" else --K        
            x"4C" when makeCode = x"4B" else --L        
            x"4D" when makeCode = x"3A" else --M        
            x"4E" when makeCode = x"31" else --N        
            x"4F" when makeCode = x"44" else --O        
            x"50" when makeCode = x"4D" else --P        
            x"51" when makeCode = x"15" else --Q        
            x"52" when makeCode = x"2D" else --R        
            x"53" when makeCode = x"1B" else --S        
            x"54" when makeCode = x"2C" else --T        
            x"55" when makeCode = x"3C" else --U        
            x"56" when makeCode = x"2A" else --V        
            x"57" when makeCode = x"1D" else --W        
            x"58" when makeCode = x"22" else --X        
            x"59" when makeCode = x"35" else --Y        
            x"5A" when makeCode = x"1A" else --Z        
            x"30" when makeCode = x"45" else --0        
            x"31" when makeCode = x"16" else --1        
            x"32" when makeCode = x"1E" else --2        
            x"33" when makeCode = x"26" else --3        
            x"34" when makeCode = x"25" else --4        
            x"35" when makeCode = x"2E" else --5        
            x"36" when makeCode = x"36" else --6        
            x"37" when makeCode = x"3D" else --7        
            x"38" when makeCode = x"3E" else --8        
            x"39" when makeCode = x"46" else --9        
            x"2F" when makeCode = x"5A" else --ENTER    
            x"5C" when makeCode = x"66" else --Backspace
            x"00";                           --Null
end Behavioral;

** HDMI显示代码:**

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;

entity dvid is
    Port ( clk_tmds0  : in  STD_LOGIC;
           clk_tmds90 : in  STD_LOGIC;
           clk_pixel  : in  STD_LOGIC;
           red_p      : in  STD_LOGIC_VECTOR (7 downto 0);
           green_p    : in  STD_LOGIC_VECTOR (7 downto 0);
           blue_p     : in  STD_LOGIC_VECTOR (7 downto 0);
           blank      : in  STD_LOGIC;
           hsync      : in  STD_LOGIC;
           vsync      : in  STD_LOGIC;
           red_s      : out STD_LOGIC;
           green_s    : out STD_LOGIC;
           blue_s     : out STD_LOGIC;
           clock_s    : out STD_LOGIC);
end dvid;

architecture Behavioral of dvid is
   COMPONENT TDMS_encoder
   PORT(
      clk     : IN  std_logic;
      data    : IN  std_logic_vector(7 downto 0);
      c       : IN  std_logic_vector(1 downto 0);
      blank   : IN  std_logic;          
      encoded : OUT std_logic_vector(9 downto 0)
      );
   END COMPONENT;

    COMPONENT qdr
    PORT(
        clk0  : IN std_logic;
        clk90 : IN std_logic;
        data  : IN std_logic_vector(3 downto 0);          
        qdr   : OUT std_logic
        );
    END COMPONENT;

   signal encoded_r, encoded_g, encoded_b : std_logic_vector(9 downto 0);

   -- for the control frames (blanking)
   constant c_red     : std_logic_vector(1 downto 0) := (others => '0');
   constant c_green   : std_logic_vector(1 downto 0) := (others => '0');
   signal   c_blue    : std_logic_vector(1 downto 0);

    signal   latched_r : std_logic_vector(9 downto 0) := (others => '0');
    signal   latched_g : std_logic_vector(9 downto 0) := (others => '0');
    signal   latched_b : std_logic_vector(9 downto 0) := (others => '0');

    signal   buffer_r : std_logic_vector(9 downto 0) := (others => '0');
    signal   buffer_g : std_logic_vector(9 downto 0) := (others => '0');
    signal   buffer_b : std_logic_vector(9 downto 0) := (others => '0');

    -- one hot encoded. Initial Value is important to sync with pixel chantges!
    signal   state     : std_logic_vector(4 downto 0) := "10000"; 

    signal   bits_r    : std_logic_vector(3 downto 0) := (others => '0');
    signal   bits_g    : std_logic_vector(3 downto 0) := (others => '0');
    signal   bits_b    : std_logic_vector(3 downto 0) := (others => '0');
    signal   bits_c    : std_logic_vector(3 downto 0) := (others => '0');

    -- output shift registers
    signal   sr_r      : std_logic_vector(11 downto 0):= (others => '0');
    signal   sr_g      : std_logic_vector(11 downto 0):= (others => '0');
    signal   sr_b      : std_logic_vector(11 downto 0):= (others => '0');
   signal   sr_c      : std_logic_vector(9 downto 0) := "0111110000";

    -- Gives a startup delay to allow the fifo to fill
    signal delay_ctr    : std_logic_vector(3 downto 0) := (others => '0');
begin   
   c_blue  <= vsync & hsync;

TDMS_encoder_red:   TDMS_encoder PORT MAP(clk => clk_pixel, data => red_p,   c => c_red,   blank => blank, encoded => encoded_r);
TDMS_encoder_green: TDMS_encoder PORT MAP(clk => clk_pixel, data => green_p, c => c_green, blank => blank, encoded => encoded_g);
TDMS_encoder_blue:  TDMS_encoder PORT MAP(clk => clk_pixel, data => blue_p,  c => c_blue,  blank => blank, encoded => encoded_b);

qdr_r: qdr PORT MAP(clk0 => clk_tmds0, clk90 => clk_tmds90, data => bits_r(3 downto 0), qdr => red_s);
qdr_g: qdr PORT MAP(clk0 => clk_tmds0, clk90 => clk_tmds90, data => bits_g(3 downto 0), qdr => green_s);
qdr_b: qdr PORT MAP(clk0 => clk_tmds0, clk90 => clk_tmds90, data => bits_b(3 downto 0), qdr => blue_s);
qdr_c: qdr PORT MAP(clk0 => clk_tmds0, clk90 => clk_tmds90, data => bits_c(3 downto 0), qdr => clock_s);

    process(clk_pixel)
    begin
        -- Just sample the encoded pixel data, to give a smooth transition to high speed domain
        if rising_edge(clk_pixel) then
            buffer_r <= encoded_r;
            buffer_g <= encoded_g;
            buffer_b <= encoded_b;
        end if;
    end process;

   process(clk_tmds0)
   begin
      if rising_edge(clk_tmds0) then 
            bits_r <= sr_r(3 downto 0);
            bits_g <= sr_g(3 downto 0);
            bits_b <= sr_b(3 downto 0);
            bits_c <= sr_c(3 downto 0);
            case state is 
                when "00001" =>
                    sr_r <= "00" & latched_r;
                    sr_g <= "00" & latched_g;
                    sr_b <= "00" & latched_b;
                when "00010" =>
                    sr_r <= "0000" & sr_r(sr_r'high downto 4);
                    sr_g <= "0000" & sr_g(sr_g'high downto 4);
                    sr_b <= "0000" & sr_b(sr_b'high downto 4);
                when "00100" =>
                    sr_r <= latched_r & sr_r(5 downto 4);
                    sr_g <= latched_g & sr_g(5 downto 4);
                    sr_b <= latched_b & sr_b(5 downto 4);
                when "01000" =>
                    sr_r <= "0000" & sr_r(sr_r'high downto 4);
                    sr_g <= "0000" & sr_g(sr_g'high downto 4);
                    sr_b <= "0000" & sr_b(sr_b'high downto 4);
                when others =>
                    sr_r <= "0000" & sr_r(sr_r'high downto 4);
                    sr_g <= "0000" & sr_g(sr_g'high downto 4);
                    sr_b <= "0000" & sr_b(sr_b'high downto 4);
            end case;

            -- Move on to the next state
            state       <= state(state'high-1 downto 0) & state(state'high);

            -- Move the TMDS clock signal shift register
            sr_c <= sr_c(3 downto 0) & sr_c(sr_c'high downto 4);
            if delay_ctr(delay_ctr'high) = '0' then 
                delay_ctr <= delay_ctr +1;
            end if;

            -- Move the encoded pixel data into the fast clock domain
            latched_r <= buffer_r;
            latched_g <= buffer_g;
            latched_b <= buffer_b;
      end if;
   end process;

end Behavioral;


1 个答案:

答案 0 :(得分:0)

请参阅本用户指南,该指南涵盖了在atlys板上实现HDMI作为参考设计。 https://www.xilinx.com/support/documentation/application_notes/xapp495_S6TMDS_Video_Interface.pdf