使用VHDL和I2C的Altera Cyclone V GT开发套件上的16x2字符LCD

时间:2019-05-29 21:57:31

标签: vhdl fpga i2c lcd intel-fpga

我想使自己熟悉Cyclone V FPGA,我有一个Cyclone V GT开发套件。开发套件带有一个16x2字符LCD(NHD-0216K3Z-NSW-BBW-V3)。 LCD通过I2C连接到FPGA,默认情况下只有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;

0 个答案:

没有答案