用于LCD初始化的VHDL状态机

时间:2011-11-05 02:22:27

标签: simulation vhdl state-machine spartan

我正在尝试实现Spartan 3AN的LCD的初始化。我对此非常陌生,所以每个建议都非常受欢迎。

我的代码如下:

----------------------------------------------------------------------------------
-- 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;

所以有两个问题:

  1. 这段代码好吗?我知道我还有更多的代码要做,但我只是想看看我做得好,是什么让我回答问题2

  2. 我用ISim模拟(BTW我在Xilinx 12.3上)并且状态永远不会改变总是A,我的代码遗漏了什么?或者我可能以错误的方式模拟这个,你能告诉我如何模拟吗?

  3. 非常感谢!

1 个答案:

答案 0 :(得分:2)

我看到的一些事情,有些是风格,有些则不是:

  1. 使用std_logic_arithstd_logic_unsigned库 - 它们不是 IEEE标准,并且真的会伤害初学者,因为它会带走一个很多VHDL提供的强类型。请改用numeric_std。互联网搜索可以告诉你更多。
  2. “现代”宏rising_edge()是时钟检查的首选,因为它还处理L-> H状态(在FPGA / ASIC中从未发生,但无论如何......)
  3. 您的iNextState似乎未被使用。
  4. 您有一个边界条件,其中没有LCD输出在启动时设置。向FSM添加重置,或者您需要重新考虑输出的设置方式(参见Mealy与Moore风格的FSM)。
  5. 如果你有initialization_state的枚举,你可能想给他们更有意义的名字和/或评论他们应该在每个州做什么。
  6. 否则,快速看起来很好。正如其他人所指出的,750K时钟是仿真,并且没有看到驱动时钟的测试平台代码,我们不知道它是否会起作用。我建议将750K和其他所有内容切换为常量,您可以将其更改为非常小的值以进行测试。