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

本文是小编为大家收集整理的关于奇怪的VHDL行为的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

在以下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;

推荐答案

随机误差是由于持有人(n)未经初始化而引起的.我可以提出两种解决方案:

a)确保您的合成器工具允许(不忽略声明中的初始值),然后将其更新为:

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

这样,您确保所有信号在重置时都会获得有效的值.

其他推荐答案

这样的问题似乎在Stackoverflow上很常见.用户附带一块代码,并希望帮助解释为什么它不起作用.我不会告诉您该代码有什么问题,但是我将评论开发工作,可读和可测试的VHDL代码的过程.

我首先以粗体主张开始:RTL很容易.与验证相比,它是数字设计的微不足道部分.当然可以编写工作RTL而无需任何验证,但是设计复杂性随着代码行的数量而线性增长,但验证工作逐渐增长,毫无疑问,这些天的验证引起了很多关注.

>

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

例外,但是我要说的是,在使用功能性测试台进行锻炼之前,您不应该编写一条RTL行.您的测试台和通过测试和连接实体的设备模型可以利用您选择的设计和验证语言的全部功能,并且不仅限于可合成的子集.行为建模的副作用是它可以帮助您了解设计的规范.

因此总结:

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

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

本文地址:https://www.itbaoku.cn/post/2091022.html

问题描述

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;

推荐答案

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.

其他推荐答案

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?