Weird VHDL Behavior

独自空忆成欢 提交于 2019-12-25 07:30:47

问题


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

with

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

The program acts weird and crashes.

Here is the code:

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;

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;

回答1:


The random errors are due to Holder(n) being used uninitialized. I can propose two solutions:

A) make sure your synth tool allows it (does not ignore init values in declarations) and then update it as:

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

B) Your process' sensitivity list lacks a reset signal, like in

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

That way you make sure that all signals get a valid value upon reset.




回答2:


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.

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.

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.

So to summarize:

  1. Learn behavoural modelling, and learn it well. Writing efficient and correct models is essential to be able to develop good and efficient testbenches.
  2. Explore test-driven development. It applies well to hardware development too. A modular testbench make it easy to add new test cases - cases that exercises certain device features.
  3. Use behavoural models for both you device-under-test and for external components. Writing a behavoural implementation of the target design is not a waste. It will help you develop your testbench prior to any RTL being written.

So, where is your testbench?



来源:https://stackoverflow.com/questions/17430643/weird-vhdl-behavior

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!