【问题标题】:VHDL State Machine for LCD initialization用于 LCD 初始化的 VHDL 状态机
【发布时间】:2011-11-05 02:22:27
【问题描述】:

我正在尝试实现 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 进行了模拟(顺便说一句,我在 Xilinx 12.3 上)并且状态永远不会改变总是 A,我的代码是否遗漏了什么?或者我模拟的方式不对,你能告诉我如何模拟吗?

非常感谢!

【问题讨论】:

  • 您是否有正确的时钟信号并且 cycleCounter 是否递增?您可能等待的时间不够长...模拟器中 anything 的 750000 次循环需要一段时间。
  • 时钟为 50 Mhz。在模拟中,我放置了 20 ns 的周期。但正如我所说,似乎什么都没有发生。我想我没有很好地模拟这件事。如何模拟它?
  • 不要使用 IEEE.STD_LOGIC_ARITH.ALLIEEE.STD_LOGIC_UNSIGNED.ALL - 它们不是 IEEE 标准并且已弃用。使用numeric_std - 在互联网上搜索该词以获取更多信息。

标签: simulation vhdl state-machine spartan


【解决方案1】:

我看到的一些东西,有些是风格,有些不是:

  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 的枚举,您可能希望给它们起更有意义的名称和/或评论它们在每个州应该做什么。

否则,快速查看似乎没问题。正如其他人指出的那样,750K 时钟是一个long 模拟,并且没有看到驱动时钟的测试台代码,我们不知道它是否会工作。我建议将 750K 和所有其他参数转换为常数,您可以将其更改为非常小的值以进行测试。

【讨论】:

  • 好的,我会尽量不使用这些库并更正各州的名称。一件事我不知道它是否正确......在做 FSM 时,一位朋友告诉我有 2 个过程:1 个用于从当前状态更改为下一个状态,另一个用于转换......在我的代码中,对于我,我认为不需要2个过程还是我错了?可以像我在代码中那样实现状态转换吗?最后,当我模拟这个时,我总是为 iCurrentState 的值 A...它永远不会改变,是因为 750000 个周期吗?
  • 我将添加测试平台的代码,您有关于如何在 Xilinx 的 Isim 上模拟 FSM 的教程吗?非常感谢 !也许代码很好,也许我模拟错了。
  • 谢谢。确实我模拟错了。只需单击 lsim 周围的按钮并阅读并尝试理解即可解决我的小问题。
猜你喜欢
  • 2012-08-09
  • 1970-01-01
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多