【发布时间】:2019-12-11 12:22:24
【问题描述】:
我正在做一个项目。 该项目的目标是使用 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;
【问题讨论】:
-
您需要实现产生视频帧的逻辑。您必须将其输出连接到 HDMI 端口才能发送到显示器。您的逻辑应该能够以某种方式调整/更新生成的视频帧数据,以应对您在键盘上键入的字符。
-
如果您想要额外的挑战(额外的功劳?),请尽量避免为整个帧分配缓冲区,并一次渲染一个字符行。
-
用 VGA 热身可能是一个有用的垫脚石(较低的复杂性,相同的想法)。
标签: fpga