奇怪的VHDL行为

时间:2013-07-02 16:17:29

标签: vhdl fpga xilinx hdl

在下面的VHDL代码中,当我使用逻辑或代码停止工作时,HD44780LCD崩溃,但当我删除逻辑或删除其中一个持有者时,代码再次开始工作。我正在使用Xilinx Spartan 3E入门板。 换句话说,当我更换

SendCommand <= Holder(0); 

SendCommand <= Holder(0) or Holder(1);

该程序很奇怪并且崩溃。

以下是代码:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity Main is
  port(
    CLK    : in  std_logic;
    RIGHT  : in  std_logic;
    left   : in  std_logic;
    UP     : in  std_logic;
    DOWN   : in  std_logic;
    SF_DSW : in  std_logic_vector(3 downto 0);
    LED    : out std_logic_vector(7 downto 0);
    LCD_E  : out std_logic;
    LCD_RS : out std_logic;
    LCD_RW : out std_logic;
    SF_D   : out std_logic_vector(11 downto 8)
    );
end Main;

architecture Behavioral of Main is
  component LCDS
    port(
      CLK       : in  std_logic;
      Enable    : in  std_logic;
      EnableCMD : in  std_logic;
      CMD       : in  std_logic_vector(7 downto 0);
      ASCII     : in  std_logic_vector (7 downto 0);
      LCD_E     : out std_logic;
      LCD_RS    : out std_logic;
      LCD_RW    : out std_logic;
      SF_D      : out std_logic_vector(11 downto 8)
      );
  end component;
  signal Char        : std_logic_vector(7 downto 0);
  signal SendChar    : std_logic;
  signal Command     : std_logic_vector(7 downto 0)  := X"80";
  signal SendCommand : std_logic;
  signal SDisable    : std_logic_vector(2 downto 0);
  signal Holder      : std_logic_vector(2 downto 0);
  constant MS3       : std_logic_vector(17 downto 0) := "100100100111110000";
begin
  DisplayDriver : LCDS
    port map(CLK, SendChar, SendCommand, Command, Char, LCD_E, LCD_RS, LCD_RW, SF_D);
  SendKey : process (CLK)
  begin
    if rising_edge(CLK) then
      if SDisable(0) = '0' then
        if left = '1' then Holder(0) <= '1'; SDisable(0) <= '1'; end if;
      elsif left = '1' and SDisable(0) = '1' then Holder(0) <= '0';
      else
        if left = '0' and SDisable(0) = '1' then SDisable(0) <= '0'; end if;
      end if;
      if SDisable(1) = '0' then
        if right = '1' then Holder(1) <= '1'; SDisable(1) <= '1'; end if;
      elsif right = '1' and SDisable(1) = '1' then Holder(1) <= '0';
      else
        if right = '0' and SDisable(1) = '1' then SDisable(1) <= '0'; end if;
      end if;
      if SDisable(2) = '0' then
        if UP = '1' then Holder(2) <= '1'; SDisable(2) <= '1'; end if;
      elsif UP = '1' and SDisable(2) = '1' then Holder(2) <= '0';
      else
        if UP = '0' and SDisable(2) = '1' then SDisable(2) <= '0'; end if;
      end if;
      if left = '1' then
        if ((Command > X"7F") and (Holder(0) = '1')) then
          Command <= Command -1;
        end if;
      elsif right = '1' then
        if ((Command < X"D1") and (Holder(1) = '1')) then
          Command <= Command +1;
        end if;
      end if;
      if UP = '1' then
        if Holder(2) = '1' then
          Char <= Char +1;
        end if;
      end if;
      if SF_DSW = X"0" then
        LED             <= X"00";
        LED(3 downto 0) <= left&right&DOWN&UP;
        LED(4)          <= ((left or right) or UP);
      elsif SF_DSW = X"1" then
        LED <= Char;
      elsif SF_DSW = X"2" then
        LED <= Command;
      end if;
      SendCommand <= (Holder(0));
      --Not working when 
      --SendCommand <= (Holder(0) or Holder(1));
      SendChar    <= Holder(2);
    end if;
  end process;
end Behavioral;

这是DisplayDriver组件代码如果它有用

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity LCDS is
  port(
    CLK       : in  std_logic;
    Enable    : in  std_logic;
    EnableCMD : in  std_logic;
    CMD       : in  std_logic_vector(7 downto 0);
    ASCII     : in  std_logic_vector (7 downto 0);
    LCD_E     : out std_logic;
    LCD_RS    : out std_logic;
    LCD_RW    : out std_logic;
    SF_D      : out std_logic_vector(11 downto 8)
    );
end LCDS;

architecture Behavioral of LCDS is
  type Conf is (S1, S2, S3, S4, Done);
  type Initx is (FuncSet, DisplaySet, DisplayOn, MWait, Custom, Done);
  type DelaySet is (MS5000, MS1000, MS2, US300, NS500, US160, none);
  type Chars is (A, none);
  signal Conf_s      : Conf      := S1;
  signal Init_s      : Initx;
  signal Chars_s     : Chars     := none;
  signal SDisable    : std_logic := '0';
  signal SDisableCMD : std_logic := '0';
  signal DelaySet_s  : DelaySet;
  signal Counter     : std_logic_vector(29 downto 0);
  signal XLatch      : std_logic := '0';
begin
  Display : process(CLK, Enable, EnableCMD)
  begin
    if rising_edge(CLK) then
      LCD_RW <= '0';
      if SDisable = '0' then
        if Enable = '1' then Chars_s <= A; SDisable <= '1'; end if;
      elsif Enable = '1' and SDisable = '1' then Chars_s <= none;
      else
        if Enable = '0' and SDisable = '1' then SDisable <= '0'; end if;
      end if;
      if SDisableCMD = '0' then
        if EnableCMD = '1' then Init_s <= Custom; SDisable <= '1'; end if;
      elsif EnableCMD = '1' and SDisableCMD = '1' then Init_s <= Done;
      else
        if EnableCMD = '0' and SDisableCMD = '1' then SDisableCMD <= '0'; end if;
      end if;
      if DelaySet_s = none then
        if not (Conf_s = Done) then
          case Conf_s is
            when S1 =>
              LCD_RS     <= '0';
              SF_D       <= X"3";
              DelaySet_s <= MS2;
              Conf_s     <= S2;
              LCD_E      <= '1';
            when S2 =>
              LCD_RS     <= '0';
              SF_D       <= X"3";
              DelaySet_s <= US160;
              Conf_s     <= S3;
              LCD_E      <= '1';
            when S3 =>
              LCD_RS     <= '0';
              SF_D       <= X"3";
              DelaySet_s <= US160;
              Conf_s     <= S4;
              LCD_E      <= '1';
            when S4 =>
              LCD_RS     <= '0';
              SF_D       <= X"2";
              DelaySet_s <= US160;
              Conf_s     <= Done;
              LCD_E      <= '1';
            when others => null;
          end case;
        elsif not(Init_s = Done) then
          case Init_s is
            when FuncSet =>
              if XLatch = '0' then
                LCD_RS     <= '0';
                SF_D       <= X"2";
                XLatch     <= '1';
                DelaySet_s <= US300;
                LCD_E      <= '1';
              else
                LCD_RS     <= '0';
                SF_D       <= X"8";
                XLatch     <= '0';
                delaySet_s <= US300;
                Init_s     <= DisplaySet;
                LCD_E      <= '1';
              end if;
            when DisplaySet =>
              if XLatch = '0' then
                LCD_RS     <= '0';
                SF_D       <= X"0";
                XLatch     <= '1';
                delaySet_s <= US300;
                LCD_E      <= '1';
              else
                LCD_RS     <= '0';
                SF_D       <= X"8";
                XLatch     <= '0';
                delaySet_s <= US300;
                Init_s     <= DisplayOn;
                LCD_E      <= '1';
              end if;
            when DisplayOn =>
              if XLatch = '0' then
                LCD_RS     <= '0';
                SF_D       <= X"0";
                XLatch     <= '1';
                delaySet_s <= US300;
                LCD_E      <= '1';
              else
                LCD_RS     <= '0';
                SF_D       <= X"F";
                XLatch     <= '0';
                delaySet_s <= MS2;
                Init_s     <= MWait;
                LCD_E      <= '1';
              end if;
            when MWait =>
              XLatch     <= '0';
              LCD_E      <= '0';
              DelaySet_s <= MS2;
              Init_s     <= Done;
            when Custom =>
              if XLatch = '0' then
                LCD_RS     <= '0';
                SF_D       <= CMD(7 downto 4);
                XLatch     <= '1';
                delaySet_s <= US300;
                LCD_E      <= '1';
              else
                LCD_RS     <= '0';
                SF_D       <= CMD(3 downto 0);
                XLatch     <= '0';
                delaySet_s <= MS2;
                Init_s     <= MWait;
                LCD_E      <= '1';
              end if;
            when others => null;
          end case;
        elsif Chars_s = A then
          case Chars_s is
            when A =>
              if XLatch = '0' then
                LCD_RS     <= '1';
                SF_D       <= ASCII(7 downto 4);
                XLatch     <= '1';
                DelaySet_s <= US300;
                LCD_E      <= '1';
              else
                LCD_RS     <= '1';
                SF_D       <= ASCII(3 downto 0);
                XLatch     <= '0';
                DelaySet_s <= US160;
                LCD_E      <= '1';
                Chars_s    <= none;
              end if;
            when others => null;
          end case;
        end if;
      else
        case DelaySet_s is
          when MS5000 =>

            if Counter < "1110111001101011001010000000" then
              Counter <= Counter + 1;
            else
              LCD_E      <= '0';
              Counter    <= (others => '0');
              DelaySet_s <= none;
            end if;
          when MS1000 =>
            if Counter < "10111110101111000010000000" then
              Counter <= Counter + 1;
            else
              LCD_E      <= '0';
              Counter    <= (others => '0');
              DelaySet_s <= none;
            end if;
          when MS2 =>
            if Counter < "11000011010100000" then
              Counter <= Counter + 1;
            else
              LCD_E      <= '0';
              Counter    <= (others => '0');
              DelaySet_s <= none;
            end if;
          when US300 =>
            if Counter < "11101010011000" then
              Counter <= Counter + 1;
            else
              LCD_E <= '0';
              Counter    <= (others => '0');
              DelaySet_s <= none;
            end if;
          when US160 =>
            if Counter < "1111101000000" then
              Counter <= Counter + 1;
            else
              LCD_E      <= '0';
              Counter    <= (others => '0');
              DelaySet_s <= none;
            end if;
          when NS500 =>
            if Counter < "11001" then
              Counter <= Counter + 1;
            else
              LCD_E      <= '0';
              Counter    <= (others => '0');
              DelaySet_s <= none;
            end if;
          when others => null;
        end case;
      end if;
    end if;
  end process;
end Behavioral;

2 个答案:

答案 0 :(得分:1)

随机错误是由于Holder(n)未初始化使用。我可以提出两个解决方案:

A)确保你的synth工具允许它(不会忽略声明中的init值),然后将其更新为:

signal Holder      : std_logic_vector(2 downto 0) := (others => '0');

B)您的过程敏感度列表缺少重置信号,如

process_name : process (rst, clk)
begin
    if    (rst = '1') then -- or '0' if active-low async. reset
         ... set initial value for all signals
    elsif rising_edge(clk) then

这样,您可以确保所有信号在重置时都获得有效值。

答案 1 :(得分:1)

这样的问题似乎在stackoverflow上很常见。用户附带一段代码,并希望获得帮助,解释它无法正常工作的原因。我不会告诉你代码到底有什么问题,但我会评论开发工作,可读和可测试的VHDL代码的过程。

我首先要提出一个大胆的主张:RTL很简单。与验证相比,它是数字设计的重要部分。在没有任何验证的情况下编写工作RTL当然是可能的,但是设计复杂性随着代码行数的增加而变得一致,验证工作在表面上增长,难怪验证这些日子引起了很多关注。

这只是一个疯狂的猜测 - 我认为这是大学或学院实验室任务的一部分。如果是这样,我发现很奇怪您不需要为您的设计提供测试平台。你显然已经为你的设计付出了很多努力;你应该期望至少放入你的测试平台。一旦你超越了一个琐碎的设计,你最终会花费数小时浪费实验室测试,试图找出错误 - 在模拟器中很容易发现的错误。

有一些例外情况,但我会说你在使用功能测试平台之前不应该写一行RTL。您的测试平台和被测设备以及连接实体的行为模型可以充分利用您选择的设计和验证语言的全部功能,而不仅限于可综合子集。行为建模的副作用是它可以帮助您理解设计的规范。

总结一下:

  1. 学习行为建模,并深入学习。编写高效且正确的模型对于开发优质高效的测试平台至关重要。
  2. 探索测试驱动的开发。它也适用于硬件开发。模块化测试平台可以轻松添加新的测试用例 - 具有某些设备功能的案例。
  3. 对被测设备和外部组件使用行为模型。编写目标设计的行为实现并不浪费。它将帮助您在编写任何RTL之前开发测试平台。
  4. 那么,你的测试平台在哪里?