问题
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:
- Learn behavoural modelling, and learn it well. Writing efficient and correct models is essential to be able to develop good and efficient testbenches.
- 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.
- 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