奇怪的VHDL行为 [英] Weird VHDL Behavior

查看:109
本文介绍了奇怪的VHDL行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的VHDL代码中,当我使用逻辑或代码停止工作时,HD44780LCD崩溃,但是当我删除逻辑或删除一个固定器时,代码又开始工作.我正在使用Xilinx Spartan 3E入门板. 换句话说,当我替换

In the following VHDL code when i use logical or the code stops working the HD44780LCD crashes but when i remove the logical or and remove one of the holders the code starts to work again. I'm using Xilinx Spartan 3E starter board. In other words when I replace the

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组件代码

Here is the DisplayDriver Components Code If its useful

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;

推荐答案

类似的问题在stackoverflow上似乎很常见.用户附带了一段代码,并需要帮助来解释为什么它不起作用.我不会告诉您代码到底有什么问题,但是我将对开发有效,可读且可测试的VHDL代码的过程进行评论.

Questions like this seems to be common here on stackoverflow. A user comes with a piece of code and want help explaining why it does not work. I won't tell you exactly what's wrong with the code, but I will comment on the process of developing working, readable and testable VHDL code.

我首先要有一个大胆的声明:RTL很简单.与验证相比,它是数字设计的琐碎部分.当然,无需任何验证就可以编写有效的RTL,但是尽管设计复杂度随着代码行数的增加而线性增加,但是验证工作却呈指数级增长,也就不足为奇了,这些天验证也就不足为奇了.

I'll first start with a bold claim: RTL is easy. Compared to verification it is the trivial part of digital design. It is certainly possible to write working RTL without any verification, but whereas design complexity grows lineary with the number of lines of code, the verification effort grows expotensially it is no wonder that verification is getting a lot of attention these days.

这只是一个疯狂的猜测-我认为这是大学或学院实验室工作的一部分.如果是这样,我感到很奇怪,不需要您为设计提供测试平台.显然,您已经在设计上付出了很多努力.您应该期望至少在测试台中投入尽可能多的东西.一旦超越了琐碎的设计,您最终将花费大量的时间进行浪费大量的实验室测试,试图找出问题所在-在模拟器中很容易发现错误.

This is just a wild guess - I assume this is part of a lab assignment at a university or college. If so is true, I find it strange that you are not required to provide a testbench for your design. You clearly have put a lot of effort into your design; you should expect to put at least as much into your testbench. Once you go beyond a trivial design you will end up spending hours in wasted lab tests trying to figure out what is wrong - errors which would easily be found in a simulator.

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

There are be exceptions, but I would go as far as to say that you shouldn't write a single line of RTL before you have a functional testbench to exercise it with. Your testbench and behavoural models of the device-under-test and connected entities can take advantage the full power of your design and verification language of choice, and is not limited to the synthesizable subset. A side-effect of behavoural modelling is that it helps you understand the specification of your design.

所以总结一下:

  1. 学习行为建模,并学得很好.编写有效而正确的模型对于开发良好而有效的测试平台至关重要.
  2. 探索测试驱动的开发.它也很好地适用于硬件开发.模块化的测试平台可轻松添加新的测试用例-行使某些设备功能的用例.
  3. 针对待测设备和外部组件使用行为模型.编写目标设计的良好实现并不是浪费.它将帮助您在编写任何RTL之前开发测试平台.

那么,您的测试台在哪里?

So, where is your testbench?

这篇关于奇怪的VHDL行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆