VHDL State Machine для инициализации ЖК-дисплея - PullRequest
0 голосов
/ 05 ноября 2011

Я пытаюсь реализовать инициализацию LCD спартанского 3AN.Я очень новичок в этом, поэтому каждый совет очень приветствуется.

Мой код выглядит следующим образом:

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    17:31:49 11/04/2011 
-- Design Name: 
-- Module Name:    LCD - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
--use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity LCD is
    Port ( clk : in  STD_LOGIC;
           LCD_DB : out  STD_LOGIC_VECTOR (7 downto 0);
           LCD_E : out  STD_LOGIC;
           LCD_RS : out  STD_LOGIC;
           LCD_RW : out  STD_LOGIC);
end LCD;

architecture Behavioral of LCD is

--      CAUTION!!!  When using 4-bit mode, FPGA must drive the LCD_DB<3:0> signals HIGH ( = '1' )   
--      MAQUINA DE ESTADOS INICIALIZACION
    type initialization_state is (A, B, C, D, E, F, G, H, I, done);
    signal iCurrentState: initialization_state := A;
    signal iNextState: initialization_state := A;
    signal cycleCounter: integer := 0;

--      MAQUINA DE ESTADOS

begin

    initializationLCD:
    process (clk) begin
        if (clk'event and clk = '1') then
            case iCurrentState is
                when A =>
                    if (cycleCounter = 750000) then
                        iCurrentState <= B;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when B =>
                    LCD_RS <= '1';
                    LCD_RW <= '0';
                    LCD_DB <= "00000001";
                    if (cycleCounter = 50000) then
                        iCurrentState <= C;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when C =>
                    if (cycleCounter = 50000) then
                        iCurrentState <= D;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when D =>
                    LCD_RS <= '1';
                    LCD_RW <= '0';
                    LCD_DB <= "00000010";
                    if (cycleCounter = 50000) then
                        iCurrentState <= E;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when E =>
                    if (cycleCounter = 50000) then
                        iCurrentState <= F;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when F =>
                    LCD_RS <= '1';
                    LCD_RW <= '0';
                    LCD_DB <= "00000100";
                    if (cycleCounter = 12) then
                        iCurrentState <= G;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when G =>
                    if (cycleCounter = 50000) then
                        iCurrentState <= H;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when H =>
                    LCD_RS <= '1';
                    LCD_RW <= '0';
                    LCD_DB <= "00001000";
                    if (cycleCounter = 12) then
                        iCurrentState <= I;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when I =>
                    if (cycleCounter = 50000) then
                        iCurrentState <= done;
                        cycleCounter <= 0;
                    else
                        cycleCounter <= cycleCounter + 1;
                    end if;
                when others =>
                    iCurrentState <= done;
            end case;
        end if;
    end process;

end Behavioral;

Итак, есть 2 вопроса:

  1. Этот код в порядке?Я знаю, что у меня гораздо больше кода, но я просто хочу посмотреть, хорошо ли я себя чувствую, что приводит меня к вопросу 2

  2. Я смоделировал с помощью ISim (Кстати, я нахожусь наXilinx 12.3) и состояние никогда не меняется всегда A, в моем коде чего-то не хватает?или, может быть, я симулирую это неправильно, вы можете сказать мне, как симулировать это?

Большое спасибо!

1 Ответ

2 голосов
/ 05 ноября 2011

Я вижу несколько вещей, некоторые из них стиль, некоторые нет:

  1. Не не используйте библиотеки std_logic_arith и std_logic_unsigned - они не стандарта IEEE и могут действительно повредить новичкам, потому что они отбирают много сильных типов VHDL обеспечивает. Вместо этого используйте numeric_std. Поиск в Интернете может рассказать вам больше.
  2. «Современный» макрос rising_edge() предпочтителен для проверки часов, потому что он также обрабатывает состояние L-> H (которое в FPGA / ASIC никогда не происходит, но в любом случае ...)
  3. У вас есть iNextState, который, кажется, не используется.
  4. У вас есть граничное условие, при котором ни один из выходов LCD не устанавливается при запуске. Либо добавьте сброс в FSM, либо вам нужно переосмыслить способ настройки выходов (см. Мили против автоматов в стиле Мура).
  5. Если у вас есть перечисление для initialization_state, возможно, вы захотите дать им более значимые имена и / или прокомментировать, что они должны делать в каждом штате.

В противном случае быстрый взгляд кажется нормальным. Как отмечали другие, 750K тактовых импульсов - это симуляция long , и, не видя кода тестового стенда, который управляет тактовой частотой, мы не знаем, сработает ли он. Я бы порекомендовал переключить 750K и все остальные в константы, которые вы можете изменить на очень маленькие значения для целей тестирования.

...