Я пытаюсь ознакомиться с Cyclone V FPGA, у меня есть Cyclone V GT Dev Kit.Комплект разработчика поставляется с 16x2 символьным ЖК-дисплеем (NHD-0216K3Z-NSW-BBW-V3).ЖК-дисплей подключен к FPGA через I2C, по умолчанию только 2 соединения SDA и SCL.Я просто пытаюсь заставить это сделать что-нибудь, но ничего не происходит.
Я написал некоторый код на VHDL и использовал ModelSim и SignalTap для отладки.Кажется, все в порядке, но ничего не происходит.На ЖК-дисплее отображается сообщение «Не подключен» и ничего не меняется.Процесс в конце - просто часы для использования в SignalTap для выборки.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity LCD_1 is
port (
dsw : in std_logic;
clk_50M : in std_logic;
led : out std_logic;
i2c_scl : out std_logic;
i2c_sda : inout std_logic
);
end entity;
architecture Behavioral of LCD_1 is
component PLL is
port (
refclk : in std_logic;
rst : in std_logic;
outclk_0 : out std_logic
);
end component;
signal clk_5M : std_logic;
signal clk_50k : std_logic := '0';
signal sig_i2c_scl : std_logic := '1';
signal sig_i2c_sda : std_logic := '1';
signal routine : integer := 0;
signal ack : std_logic := '0';
signal ack_returned : std_logic := '0';
signal bounce : std_logic := '0';
signal data : std_logic_vector (7 downto 0);
signal rst : std_logic := '0';
signal clk_10M : std_logic;
begin
PLL_Please : component PLL
port map(
refclk => clk_50M,
rst => rst,
outclk_0 => clk_10M
);
process(clk_50M)
variable count : integer range 0 to 1000;
begin
if rising_edge(clk_50M) then
case count is
when 1000 => clk_50k <= not clk_50k;
count := 0;
when others => count := count + 1;
end case;
end if;
end process;
process(clk_50M)
variable state : integer range 0 to 1000;
begin
if rising_edge(clk_50M) then
if dsw = '0' then
case state is
when 1000 => bounce <= '1';
when others => state := state + 1;
end case;
else
bounce <= '0';
state := 0;
end if;
end if;
end process;
data <= x"50" when routine = 0 else
x"FE" when routine = 1 else
x"70";
i2c_scl <= sig_i2c_scl;
i2c_sda <= sig_i2c_sda when ack <= '0' else 'Z';
ack_returned <= i2c_sda;
process(clk_50k, bounce)
variable state : integer range 0 to 13;
variable index : integer range 7 downto 0;
begin
if rising_edge(clk_50k) then
if bounce = '1' then
case state is
when 0 => sig_i2c_sda <= '0';
state := 1;
when 1 => sig_i2c_scl <= '0';
state := 2;
when 2 => sig_i2c_sda <= data(index);
state := 3;
when 3 => sig_i2c_scl <= '1';
if index = 0 then
state := 5;
else
state := 4;
end if;
when 4 => index := index - 1;
state := 1;
when 5 => index := 7;
state := 6;
when 6 => sig_i2c_scl <= '0';
state := 7;
when 7 => ack <= '1';
state := 8;
when 8 => sig_i2c_scl <= '1';
state := 9;
when 9 => state := 10;
when 10 => sig_i2c_scl <= '0';
if ack_returned = '1' then
state := 2;
elsif routine < 2 then
routine <= routine + 1 ;
state := 2;
else
state := 11;
end if;
ack <= '0';
when 11 => state := 12;
when 12 => sig_i2c_scl <= '1';
state := 13;
when 13 => sig_i2c_sda <= '1';
end case;
else
sig_i2c_scl <= '1';
sig_i2c_sda <= '1';
state := 0;
ack <= '0';
routine <= 0;
index := 7;
end if;
end if;
end process;
process(clk_10M)
variable counter : integer range 0 to 2000;
begin
if rising_edge(clk_10M) then
case counter is
when 1000 => counter := counter + 1;
led <= '1';
when 2000 => led <= '0';
counter := 0;
when others => counter := counter + 1;
end case;
end if;
end process;
end Behavioral;