基于VHDL的FPGA蛇形游戏
我用VHDL编写了一个蛇游戏,使用Altera的DE2-115 FPGA。我用VGA协议将FPGA与显示器连接起来,以显示游戏 我在显示snake和在显示器上移动snake时遇到了一个问题(FPGA有4个,上/下/左/右) 在代码中,每次推底处于低状态时,使用SQ_X1和SQ_Y1进行移动 还有其他方法做动作吗?无需按下任何底部(使用循环或类似的方式),并在按下底部以模拟蛇的运动时改变方向基于VHDL的FPGA蛇形游戏,vhdl,fpga,Vhdl,Fpga,我用VHDL编写了一个蛇游戏,使用Altera的DE2-115 FPGA。我用VGA协议将FPGA与显示器连接起来,以显示游戏 我在显示snake和在显示器上移动snake时遇到了一个问题(FPGA有4个,上/下/左/右) 在代码中,每次推底处于低状态时,使用SQ_X1和SQ_Y1进行移动 还有其他方法做动作吗?无需按下任何底部(使用循环或类似的方式),并在按下底部以模拟蛇的运动时改变方向 ARCHITECTURE behavior OF hw_image_generator IS SI
ARCHITECTURE behavior OF hw_image_generator IS
SIGNAL SQ_X1,SQ_Y1: INTEGER RANGE 0 TO 1688:=400; --initial position X
SIGNAL SQ_X2,SQ_Y2: INTEGER RANGE 0 TO 1688:=600; --initial position Y
SIGNAL DRAW: STD_LOGIC;
BEGIN
SQ(column,row,SQ_X1,SQ_Y1,DRAW); -- function that print a square (head of snake with SQ variables)
PROCESS(disp_ena, row, column, down, up, left, right)
BEGIN
IF(disp_ena = '1') THEN --display time
IF (column=19 or column=1901 or row=19 or row=1181) THEN -- print the border
red <= (OTHERS => '1');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSE
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
END IF;
IF (DRAW = '1') THEN -- it comes from a package that print a square (head of snake)
red <= (OTHERS => '1');
green <= (OTHERS => '1');
blue <= (OTHERS => '1');
END IF;
--up, down right and left are input of FPGA (push bottom)
--SQs are the current postions of X and Y and the add is to make the movement
IF(up='0' AND down='1' AND right='1' AND left='1' )THEN
IF (SQ_X1-40 > 20) THEN
SQ_X1<=SQ_X1-40;
END IF;
END IF;
IF(up='1' AND down='0' AND right='1' AND left='1')THEN
IF (SQ_X1+40 < 1180) THEN
SQ_X1<=SQ_X1+40;
END IF;
END IF;
IF(tup='1' AND down='1' AND right='0' AND left='1')THEN
IF (SQ_Y1+40 < 1900) THEN
SQ_Y1<=SQ_Y1+40;
END IF;
END IF;
IF(up='1' AND down='1' AND right='1' AND left='0')THEN
IF (SQ_Y1-40 > 20) THEN
SQ_Y1<=SQ_Y1-40;
END IF;
END IF;
END IF;
END PROCESS;
END BEHAVIOR;
hw_映像_生成器的架构行为是
信号SQ_X1,SQ_Y1:整数范围0至1688:=400--初始位置X
信号SQ_X2,SQ_Y2:整数范围0至1688:=600--初始位置Y
信号提取:标准逻辑;
开始
SQ(列、行、SQ_X1、SQ_Y1、绘图);--打印正方形的函数(带SQ变量的蛇头)
进程(显示、行、列、下、上、左、右)
开始
如果(disp_ena='1'),则——显示时间
如果(column=19或column=1901或row=19或row=1181),则--打印边框
红色“1”);
绿色“0”);
蓝色“0”);
其他的
红色“0”);
绿色“0”);
蓝色“0”);
如果结束;
如果(DRAW='1'),那么——它来自一个打印正方形(蛇头)的包
红色“1”);
绿色“1”);
蓝色“1”);
如果结束;
--上、下、右、左为FPGA输入(推底)
--SQs是X和Y的当前位置,add用于进行移动
如果(向上='0'和向下='1'以及向右='1'和向左='1'),则
如果(SQ_X1-40>20),则
SQ_X1首先,我建议您将显示器和位置更新功能拆分为单独的流程,以使事情更清楚 您似乎已经拥有了显示过程所需的一切,除了Paebbels在评论中提到的,这应该是一个同步(即计时)过程。我假定您的时钟名为
clk
PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN
--display time
IF(disp_ena = '1') THEN
-- print the border
IF (column=19 or column=1901 or row=19 or row=1181) THEN
red <= (OTHERS => '1');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSE
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
END IF;
IF (DRAW = '1') THEN
red <= (OTHERS => '1');
green <= (OTHERS => '1');
blue <= (OTHERS => '1');
END IF;
END IF;
END IF;
END PROCESS;
然后,创建方向状态进程
process(clk) begin
if rising_edge(clk) then
if rst = '1' then
direction <= DIR_UP;
else
if up = '0' then
direction <= DIR_UP;
elsif down = '0' then
direction <= DIR_DOWN;
elsif left = '0' then
direction <= DIR_LEFT;
elsif right = '0' then
direction <= DIR_RIGHT;
end if;
end if;
end if;
end process;
如果更新太快,您可能需要使用计数器再次划分此信号的频率,但至少您的计数器不必以百万计。根据此信号,您现在可以更新您的位置,如下所示:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
-- adapt starting position to your taste
SQ_X1<= 100;
SQ_Y1<= 100;
elsif update_ce = '1' then
case direction is
when DIR_UP =>
if SQ_X1 - 1 > 20 then
SQ_X1 <= SQ_X1 - 1;
end if;
when DIR_DOWN =>
if SQ_X1 + 1 < 1180 then
SQ_X1 <= SQ_X1 + 1;
end if;
when DIR_LEFT =>
if SQ_Y1 - 1 > 20 then
SQ_Y1 <= SQ_Y1 - 1;
end if;
when others =>
-- DIR_RIGHT
if SQ_Y1 - 1 > 20 then
SQ_Y1 <= SQ_Y1 - 1;
end if;
end case;
end if;
end if;
end process;
过程(clk)
开始
如果上升沿(clk),则
如果rst='1',则
--根据您的口味调整起始位置
SQ_X1 20那么
SQ_X1
如果SQ_X1+1<1180,则
SQ_X1
如果SQ_Y1-1>20,则
SQ_Y1
--对
如果SQ_Y1-1>20,则
这个设计好像没有时钟!?没有钟它怎么工作?你模拟过你的代码吗?嗨,佩伯!时钟位于提供行和列的当前位置的其他模块中,因此在该模块中不需要时钟。对于拼写Ben Voigt,非常抱歉!我还在学英语!XDSo,如果这个模块没有时钟,谁应该综合翻译这行SQ_X1这不是好的风格,在99.99%的设计中有一个错误。另一个clk是处理这个状态机,因为问题已经解决了!谢谢佩培尔!因为启用哪个时钟周期并不重要,所以您可以用并发分配update_ce@ben voigt替换整个进程,您完全正确。在这种情况下,我会在同步进程中这样做,因为1)它通过将更新进程逻辑从时钟启用生成逻辑中分离出来来帮助改进时序,2)它只需要一个触发器,3)额外的一个时钟周期延迟在这里不是问题。谢谢你的评论。这让我意识到,在这个过程中,我实际上并没有使用更新。刚修好。:)我有其他模块,每个时钟提供当前行和列,所以在这种情况下不需要。对于Philippe的意见,这是正确的解决方案,提前感谢您的想法!我用一个时钟做运动,用正确的分频器加上运动,用四个B-U-T-T-O-N-S XD分配每个方向,所以在这种情况下,它可以做我想要的。还有一个问题(我有一个X和Y的随机位置来生成蛇的食物,使其变大)我如何做蛇的运动?我的意思是当蛇向右/向左/向上/向下转弯时,所有的尾巴都跟随头部的运动。。。谢谢
signal update_ce : std_logic;
-- (...)
process(clk) begin
if rising_edge(clk) then
-- adapt the value to your taste
if disp_ena = '1' and column = 1901 and row = 1181 then
update_ce <= '1';
else
update_ce <= '0';
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
-- adapt starting position to your taste
SQ_X1<= 100;
SQ_Y1<= 100;
elsif update_ce = '1' then
case direction is
when DIR_UP =>
if SQ_X1 - 1 > 20 then
SQ_X1 <= SQ_X1 - 1;
end if;
when DIR_DOWN =>
if SQ_X1 + 1 < 1180 then
SQ_X1 <= SQ_X1 + 1;
end if;
when DIR_LEFT =>
if SQ_Y1 - 1 > 20 then
SQ_Y1 <= SQ_Y1 - 1;
end if;
when others =>
-- DIR_RIGHT
if SQ_Y1 - 1 > 20 then
SQ_Y1 <= SQ_Y1 - 1;
end if;
end case;
end if;
end if;
end process;