我正在为FPGA编写一个LCD控制器,但遇到了一个非常奇怪的问题(至少对我来说)。本应向屏幕输出所需位的状态机行为不端,导致输出引脚"卡"在旧状态,而它显然已经转移到了以后的状态。
以下是状态机的相关部分:
PROCESS (clk)
VARIABLE count: INTEGER RANGE 0 TO clk_divider; -- clk_divider is a generic positive.
BEGIN
IF (clk'EVENT AND clk = '1') THEN
count := count + 1;
IF (count = clk_divider) THEN
EAUX <= NOT EAUX;
count := 0;
END IF;
END IF;
END PROCESS;
PROCESS (EAUX)
BEGIN
IF (EAUX'EVENT AND EAUX = '1') THEN
pr_state <= nx_state;
END IF;
END PROCESS;
PROCESS (pr_state)
BEGIN
CASE pr_state IS
WHEN EntryMode => --6=1,7=Cursor increment/decrement, 8=Display shift on/off
RSs <='0';
DB(7 DOWNTO 0) := "00000110";
nx_state <= WriteData;
WHEN WriteData => --Write data to LCD:
RSs <='1';
YLED <= '1';
DB(7 DOWNTO 0) := "01011111";
i := i + 1;
IF (i < chars) THEN
nx_state <= WriteData;
ELSE
i := 0;
nx_state <= ReturnHome;
END IF;
WHEN ReturnHome => --Return cursor
RSs <='0';
YLED <= '1';
DB(7 DOWNTO 0) := "01011111";
nx_state <= WriteData;
END CASE;
END PROCESS;
其中变量DB中的位被分配给信号DBOUT:
DBOUT : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) -- In entity
SHARED VARIABLE DB : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000"; -- In Architecture
DBOUT <= DB;
DBOUT输出(在.ucf文件中)为:
NET "DBOUT(0)" LOC = P10;
NET "DBOUT(1)" LOC = P11;
NET "DBOUT(2)" LOC = P12;
NET "DBOUT(3)" LOC = P13;
NET "DBOUT(4)" LOC = P15;
NET "DBOUT(5)" LOC = P16;
NET "DBOUT(6)" LOC = P18;
NET "DBOUT(7)" LOC = P19;
使用引脚上的示波器,我可以看到它显然被困在输出"EntryMode"位,"RS"被设置为低,而YLED(FPGA上的内部led)打开(在所有其他状态下都关闭)。真正奇怪的是(这花了很长时间才发现),如果我更改的EntryMode位
"00000110"
至
"00000100"
它成功地通过状态并输出正确的比特。其他的变化可能也是如此,但我真的不想测试太多。如有任何帮助或提示,我们将不胜感激!
更新:在流行的请求之后,我明确地在所有早期状态中将YLED设置为低,并将DB切换回信号。结果是,我根本无法达到后面的状态,或者至少无法停留在它们中(即使是在摆弄神奇的比特时,我想这是一件好事),因为YLED在启动FPGA后只停留了一瞬间。
Volnei Pedroni著,麻省理工学院出版社,2013年12月,"硬件中的有限状态机:理论与设计…",第279-290页有一个完整的例子,包括理论、状态机和VHDL代码。