点阵赛车游戏
姓名
班级
学号
一、
和任务
1.用8×8点阵进行5秒倒计时显示,如下图所示。
当5秒倒计时结束后,点阵显示下图所示的赛道和赛车的初始位置,赛车游戏开始,并开始计时,用两个数码管显示时间。图中的红色表示赛道,黄色表示赛车的初始位置,箭头表示赛车行进的方向。
要求:
用BTN1~BTN3三个按键分别控制赛车的左移、前进、右移,最终使赛车在不碰撞赛道的情况下走完全程(即图2中的绿色位置),游戏结束,点阵显示“V”图案,数码管显示走完全程所耗费的时间。
当游戏时间超过59秒,或者赛车在行进过程中碰撞赛道,游戏失败,点阵显示“X”图案。
通过按键BTN0进行复位,控制点阵返回到初始状态。
提高要求:
有多种游戏赛道可选,5秒倒计时显示后赛道随机出现。
赛车的初始位置随机出现。
在赛车行进过程中,赛道中随机出现障碍物(用8×8点阵中的一个LED表示),通过BTN1~BTN3三个按键的控制躲避障碍物,走完全程。若赛车碰到障碍物和赛道,则游戏失败。
系统
(包括设计思路、总体框图、分块设计)
总体框图:
仿真波形及波形分析
Button0按下,点阵显示5
1秒后,点阵显示4
2后,点阵显示3
3秒后,显示2
4秒后,显示1
5秒后,数码管显示5 9
两个向左按键,赛车碰壁,显示失败‘x’
又复位之后,又54321减下来
又开始重复。
源程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY saiche IS
PORT(
CLOCK:IN STD_LOGIC;
button0,button1,button2,button3:IN STD_LOGIC; --四个按键:复位键、右、上、左
ROW:OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --控制车道的横向量
COL_RED:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--控制车道的红色列向量
COL_GREEN:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--控制车道的绿色列向量
LIGHT:OUT STD_LOGIC_VECTOR(6 DOWNTO 0); --段选输出
LIGHT_EN:OUT STD_LOGIC_VECTOR(5 DOWNTO 0)--位选输出
);
END saiche;
ARCHITECTURE MLD OF saiche IS
SIGNAL CLK1hz,CLK_5K,CLK_1K,CLK_2K,CLK_100hz,CLK_200hz:STD_LOGIC; --1hz,5khz,1Khz,2Khz,100hz,200hz时钟信号
SIGNAL N:INTEGER RANGE 0 TO 6; --产生随机赛道时的判断数
SIGNAL NUM:INTEGER RANGE 0 TO 20; --0号赛道逐点扫描时点的序列
SIGNAL NUM1:INTEGER RANGE 0 TO 19; --1号赛道逐点扫描时点的序列
SIGNAL NUM2:INTEGER RANGE 0 TO 18; --2号赛道逐点扫描时点的序列
SIGNAL NUM3:INTEGER RANGE 0 TO 22; --3号赛道逐点扫描时点的序列
SIGNAL T_HIGH:INTEGER RANGE 0 TO 5; --倒计时高位
SIGNAL T_LOW:INTEGER RANGE 0 TO 9; --倒计时低位
SIGNAL COUNT200:INTEGER RANGE 0 TO 250000; --各分频用的计数
SIGNAL COUNT2:INTEGER RANGE 0 TO 50000;
SIGNAL COUNT3:INTEGER RANGE 0 TO 50000;
SIGNAL COUNT:INTEGER RANGE 0 TO 50000000;
SIGNAL COUNT1:INTEGER RANGE 0 TO 10000;
SIGNAL COUNT_100hz:INTEGER RANGE 0 TO 500000;
SIGNAL tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7,tmp8:std_logic;--消抖时用的临时信号
SIGNAL CNT,CNT1:INTEGER RANGE 0 TO 1000;
SIGNAL FAIL,SUCCESS,TIME_UP:STD_LOGIC;
--FAILS赛车碰到车道的失败信号,SUCCESS赛车到终点的成功信号 --TIME_UP 60s时间到的失败信号
SIGNAL START :INTEGER RANGE 0 TO 6; --START=1 54321计时到的开启信号
SIGNAL TIMES :INTEGER RANGE 0 TO 7; --点阵显示状态判别信号
SIGNAL SEL:STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL RST,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP: STD_LOGIC; -- 由四个按键经过消抖处理后,产生的四个控制信号
TYPE DIAN IS ARRAY(INTEGER RANGE <>) OF INTEGER RANGE 0 TO 7;
SIGNAL SX,SY ,SX1,SY1:INTEGER RANGE 0 TO 7;
--SX,SY赛车坐标,SX1,SY1障碍坐标
CONSTANT WY:DIAN(0 TO 18):=(0,0,0,1,2,3,3,3,4,4,4,5,6,7,7,7,4,5,6);
--0号赛道红绿色车道纵坐标,后三个是绿色车道纵坐标
CONSTANT WX:DIAN(0 TO 18):=(0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,7,7,7);
--0号赛道红绿色车道的横坐标,后三个是绿色车道横坐标
CONSTANT WY1:DIAN(0 TO 17):=(1,0,1,0,1,2,1,2,4,5,6,7,7,6,5,5,3,4);
--1号赛道红绿色车道纵坐标,后两个是绿色车道纵坐标
CONSTANT WX1:DIAN(0 TO 17):=(0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,7,7);
--1号赛道红绿色车道的横坐标,后两个是绿色车道横坐标
CONSTANT WY2:DIAN(0 TO 16):=(1,2,1,1,2,3,4,5,4,5,6,6,5,6,7,7,6);
--2号赛道红绿色车道纵坐标,后一个是绿色车道纵坐标
CONSTANT WX2:DIAN(0 TO 16):=(0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,7);
--2号赛道红绿色车道的横坐标,后一个是绿色车道横坐标
CONSTANT WY3:DIAN(0 TO 20):=(1,1,1,1,0,0,0,0,6,6,6,6,6,6,6,6,1,2,3,4,5);
--3号赛道红绿色车道的横坐标,后五个是绿色车道横坐标
CONSTANT WX3:DIAN(0 TO 20):=(0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,7,7,7,7,7);
--0号赛道红绿色车道的横坐标,后五个是绿色车道横坐标
SIGNAL STATE:INTEGER RANGE 0 TO 1;
TYPE FIGURE IS ARRAY(INTEGER RANGE <>) OF INTEGER RANGE 0 TO 9;
SIGNAL SHOW:FIGURE(9 DOWNTO 0); --数码显示
BEGIN
p1:PROCESS(CLOCK) --分频部分
BEGIN
IF CLOCK'EVENT AND CLOCK='1' THEN
COUNT<=COUNT+1;
COUNT1<=COUNT1+1;
COUNT_100hz<=COUNT_100hz+1;
COUNT200<=COUNT200+1;
COUNT2<=COUNT2+1;
COUNT3<=COUNT3+1;
IF COUNT<=24999999 THEN --1HZ分频
CLK1hz<='1';
ELSIF COUNT>24999999 AND COUNT<=49999999 THEN
CLK1hz<='0';
ELSIF COUNT=50000000 THEN
COUNT<=0;
END IF;
IF COUNT2<=9998 THEN
CLK_1K<='1';
ELSIF COUNT2>9998 AND COUNT2<=19997 THEN
CLK_1K<='0';
ELSIF COUNT2=19998 THEN
COUNT2<=0;
END IF;
IF COUNT3<=24999 THEN --1KHZ分频
CLK_2K<='1';
ELSIF COUNT3>24999 AND COUNT3<=49999 THEN
CLK_2K<='0';
ELSIF COUNT3=50000 THEN
COUNT3<=0;
END IF;
IF COUNT1<=4999 THEN --5KHZ分频
CLK_5K<='1';
ELSIF COUNT1>4999 AND COUNT1<=9999 THEN
CLK_5K<='0';
ELSIF COUNT1=10000 THEN
COUNT1<=0;
END IF;
IF COUNT_100hz<=249999 THEN --100HZ分频
CLK_100hz<='1';
ELSIF COUNT_100hz>249999 AND COUNT_100hz<=499999 THEN
CLK_100hz<='0';
ELSIF COUNT_100hz=500000 THEN
COUNT_100hz<=0;
END IF;
IF COUNT200<=124999 THEN --200HZ分频
CLK_200hz<='1';
ELSIF COUNT200>124999 AND COUNT200<=249999 THEN
CLK_200hz<='0';
ELSIF COUNT200=250000 THEN
COUNT200<=0;
END IF;
END IF;
END PROCESS;
P2: PROCESS(CLK_100hz,button0,button1,button2,button3,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7,tmp8) --消抖部分
BEGIN
IF(CLK_100hz'event AND CLK_100hz='0')THEN
tmp2<=tmp1;
tmp1<=button0;
tmp4<=tmp3;
tmp3<=button1;
tmp6<=tmp5;
tmp5<=button2;
tmp8<=tmp7;
tmp7<=button3;
END IF;
RST <= CLK_100hz AND tmp1 AND (NOT tmp2);
DIRECTION_RIGHT <=CLK_100hz AND tmp3 AND (NOT tmp4);
DIRECTION_UP <=CLK_100hz AND tmp5 AND (NOT tmp6);
DIRECTION_LEFT <=CLK_100hz AND tmp7 AND (NOT tmp8);
END PROCESS;
p0:PROCESS(CLK_1K) --产生随机数
BEGIN
IF CLK_1K'EVENT AND CLK_1K='1' THEN
if TIMES=0 THEN N<=N;
ELSE
IF N=6 THEN
N<=0;
ELSE N<=N+1;
END IF;
END IF;
END IF;
END PROCESS;
p3: PROCESS(CLK_2K)
BEGIN
IF CLK_2K'event AND CLK_2K='1' THEN
IF NUM=20 THEN
NUM<=0;
ELSE NUM<=NUM+1;
END IF;
IF NUM1=19 THEN
NUM1<=0;
ELSE NUM1<=NUM1+1;
END IF;
IF NUM2=18 THEN
NUM2<=0;
ELSE NUM2<=NUM2+1;
END IF;
IF NUM3=22 THEN
NUM3<=0;
ELSE NUM3<=NUM3+1;
END IF;
END IF ;
END PROCESS;
p4:PROCESS(CLK_5K)
BEGIN
if CLK_5K'EVENT AND CLK_5K='1' then
IF SEL="111" THEN
SEL<="000";
ELSE SEL<=SEL+'1';
END IF;
END IF;
END PROCESS;
p5: PROCESS(CLK1hz,START,T_HIGH,T_LOW,SUCCESS,FAIL)--数码管显示判断部分
BEGIN
IF START=5 THEN --54321游戏开始,START为瞬时值
T_HIGH<=5;T_LOW<=9; TIME_UP<='0'; CNT1<=0;
ELSIF CLK1hz'EVENT AND CLK1hz='1' THEN
IF SUCCESS='1'THEN --成功的话则显示成功所用时间
if CNT1=0 then
T_LOW<=9-T_LOW;
T_HIGH<=5-T_HIGH ;
CNT1<=CNT1+1;
ELSE T_LOW<=T_LOW;
T_HIGH<=T_HIGH ;
T_LOW<=T_LOW;
END IF;
ELSIF FAIL='1' THEN -- 失败则显示失败时刻值
T_LOW<=T_LOW;
T_HIGH<=T_HIGH ;
ELSIF SUCCESS='0' AND FAIL='0' THEN -- 正常则倒计时
If T_LOW=0 AND T_HIGH=0 THEN
TIME_UP<='1'; --时间到60S返回TIME_UP信号
ELSIF T_LOW=0 AND T_HIGH/=0 THEN T_LOW<=9;
T_HIGH<=T_HIGH-1;
ELSE
T_LOW<=T_LOW-1;
END IF;
END IF;
END IF;
END PROCESS;
P6:PROCESS(CLK_5K,T_HIGH,T_LOW,START) -- 数码管显示部分
BEGIN
IF START/=5 AND START/=6 THEN
LIGHT<="0000000";
ELSIF CLK_5K'EVENT AND CLK_5K='1' THEN
IF(STATE=1)THEN
STATE<=0;
ELSE STATE<=STATE+1;
END IF;
CASE STATE IS --数码管分次扫描
WHEN 1=>LIGHT_EN<="110111";
WHEN 0=>LIGHT_EN<="111011";
WHEN OTHERS=>LIGHT_EN<="111111";
END CASE;
SHOW(0)<=T_LOW;SHOW(1)<=T_HIGH;
CASE SHOW(STATE) IS --数码管数字显示设置
WHEN 9=>LIGHT<="1111011";
WHEN 8=>LIGHT<="1111111";
WHEN 7=>LIGHT<="1110000";
WHEN 6=>LIGHT<="1011111";
WHEN 5=>LIGHT<="1011011";
WHEN 4=>LIGHT<="0110011";
WHEN 3=>LIGHT<="1111001";
WHEN 2=>LIGHT<="1101101";
WHEN 1=>LIGHT<="0110000";
WHEN 0=>LIGHT<="1111110";
WHEN OTHERS=>LIGHT<="0000000";
END CASE;
END IF;
END PROCESS;
p7:PROCESS(RST,CLK_200hz,START,DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP,SX,SY )
--控制赛车部分
BEGIN
IF RST='1' THEN SX<=0;SY<=2;
ELSIF CLK_200hz'event AND CLK_200hz='1' THEN
--DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP脉宽5ms
--所以用CLK_200hz时钟
,避免过多检测到信号或没有检测到方向信号
SX1<=2;SY1<=3;
IF TIMES=0 THEN
IF DIRECTION_LEFT='1' then --赛车向左移一格
SY<=SY-1;
ELSIF (DIRECTION_RIGHT='1') then --赛车向右移一格
SY<=SY+1;
ELSIF (DIRECTION_UP='1') then --赛车向上移一格
SX<=SX+1;
END IF;
END IF;
end if;
END PROCESS;
p8: PROCESS (SX,SY,TIMES,CLK_5K,N) --成功失败判断部分
BEGIN
IF TIMES=0 THEN
IF CLK_5K'event AND CLK_5K='1' THEN
CASE N IS
WHEN 0=> --0号赛道判断部分
IF(
(SY=0 and SX=0)or
(SY=0 and SX=1)or
(SY=0 and SX=2)or
(SY=1 and SX=3)or
(SY=3 and SX=3)or
(SY=2 and SX=4)or
(SY=3 and SX=5)or
(SY=3 and SX=6)or
(SY=3 and SX=7)or
(SY=4 and SX=0)or
(SY=4 and SX=1)or
(SY=4 and SX=2)or
(SY=5 and SX=3)or
(SY=6 and SX=4)or
(SY=7 and SX=5)or
(SY=7 and SX=6)or
(SY=7 and SX=7)) then
FAIL<='1';
ELSIF (SY=4 and SX=7)or (SY=5 and SX=7)or (SY=6 and SX=7) then
SUCCESS<='1';
ELSE SUCCESS<='0';FAIL<='0';
END IF;
WHEN 1|4=> --1号赛道判断部分
IF(
(SY=1 and SX=0)or
(SY=0 and SX=1)or
(SY=1 and SX=2)or
(SY=0 and SX=3)or
(SY=1 and SX=4)or
(SY=2 and SX=5)or
(SY=1 and SX=6)or
(SY=3 and SX=3)or
(SY=2 and SX=7)or
(SY=4 and SX=0)or
(SY=5 and SX=1)or
(SY=6 and SX=2)or
(SY=7 and SX=3)or
(SY=7 and SX=4)or
(SY=6 and SX=5)or
(SY=5 and SX=6)or
(SY=5 and SX=7)) then
FAIL<='1';
ELSIF (SY=3 and SX=7)or (SY=4 and SX=7) then
SUCCESS<='1';
ELSE SUCCESS<='0';FAIL<='0';
END IF;
WHEN 2|5=> --2号赛道判断部分
IF(
(SY=1 and SX=0)or
(SY=2 and SX=1)or
(SY=1 and SX=2)or
(SY=1 and SX=3)or
(SY=2 and SX=4)or
(SY=3 and SX=5)or
(SY=4 and SX=6)or
(SY=3 and SX=3)or
(SY=5 and SX=7)or
(SY=4 and SX=0)or
(SY=5 and SX=1)or
(SY=6 and SX=2)or
(SY=6 and SX=3)or
(SY=5 and SX=4)or
(SY=6 and SX=5)or
(SY=7 and SX=6)or
(SY=7 and SX=7)) then
FAIL<='1';
ELSIF (SY=6 and SX=7) then
SUCCESS<='1';
ELSE SUCCESS<='0';FAIL<='0';
END IF;
WHEN 3|6=> --3号赛道判断部分
IF(
(SY=1 and SX=0)or
(SY=1 and SX=1)or
(SY=1 and SX=2)or
(SY=1 and SX=3)or
(SY=0 and SX=4)or
(SY=0 and SX=5)or
(SY=0 and SX=6)or
(SY=0 and SX=7)or
(SY=6 and SX=0)or
(SY=6 and SX=1)or
(SY=6 and SX=2)or
(SY=6 and SX=3)or
(SY=3 and SX=3)or
(SY=6 and SX=4)or
(SY=6 and SX=5)or
(SY=6 and SX=6)or
(SY=6 and SX=7)) then
FAIL<='1';
ELSIF (SY=4 and SX=7)or (SY=5 and SX=7)or (SY=1 and SX=7)or (SY=2 and SX=7)or(SY=3 and SX=7)then
SUCCESS<='1';
ELSE SUCCESS<='0';FAIL<='0';
END IF;
WHEN OTHERS => SUCCESS<='0';FAIL<='0';
END CASE;
END IF ;
END IF;
end process;
PROCESS(SEL,RST,SUCCESS,FAIL,N,NUM,NUM1,NUM2,NUM3,SX,SY,SX1,SY1,CLK1hz,START,TIMES,TIME_UP)
BEGIN
IF RST='1' THEN
TIMES<=5;
START<=0;
ELSIF START=6 THEN
IF SUCCESS='1' THEN TIMES<=7;
ELSIF TIME_UP='1' OR FAIL='1' THEN TIMES<=6;
END IF;
ELSIF CLK1hz'EVENT AND CLK1hz='1' then
IF TIMES=0 THEN TIMES<=0;
ELSE
TIMES<=TIMES-1;
END IF;
if START=6 then
START<=6;
else START<=START+1;
end if;
END IF;
case TIMES is
WHEN 7=> case SEL is --显示成功字符“V”
When "000"=> ROW<="01111111";COL_RED<="00000000";COL_GREEN<="00000000";
When "001"=> ROW<="10111111";COL_RED<="01000100";COL_GREEN<="00000000";
When "010"=> ROW<="11011111";COL_RED<="01000100";COL_GREEN<="00000000";
When "011"=> ROW<="11101111";COL_RED<="01000100";COL_GREEN<="00000000";
When "100"=> ROW<="11110111";COL_RED<="00101000";COL_GREEN<="00000000";
When "101"=> ROW<="11111011";COL_RED<="00010000";COL_GREEN<="00000000";
When "110"=> ROW<="11111101";COL_RED<="00000000";COL_GREEN<="00000000";
When "111"=> ROW<="11111110";COL_RED<="00000000";COL_GREEN<="00000000";
When others => ROW<="11111111";COL_RED<="00000000";COL_GREEN<="00000000";
End case;
WHEN 6=> case SEL is --显示失败字符“X”
When "000"=> ROW<="01111111";COL_RED<="10000001";COL_GREEN<="00000000";
When "001"=> ROW<="10111111";COL_RED<="01000010";COL_GREEN<="00000000";
When "010"=> ROW<="11011111";COL_RED<="00100100";COL_GREEN<="00000000";
When "011"=> ROW<="11101111";COL_RED<="00011000";COL_GREEN<="00000000";
When "100"=> ROW<="11110111";COL_RED<="00011000";COL_GREEN<="00000000";
When "101"=> ROW<="11111011";COL_RED<="00100100";COL_GREEN<="00000000";
When "110"=> ROW<="11111101";COL_RED<="01000010";COL_GREEN<="00000000";
When "111"=> ROW<="11111110";COL_RED<="10000001";COL_GREEN<="00000000";
When others => ROW<="11111111";COL_RED<="00000000";COL_GREEN<="00000000";
End case;
WHEN 5=> CASE SEL IS --显示字符“5”
When "000"=> ROW<="01111111";COL_RED<="00111100";COL_GREEN<="00000000";
When "001"=> ROW<="10111111";COL_RED<="00000100";COL_GREEN<="00000000";
When "010"=> ROW<="11011111";COL_RED<="00000100";COL_GREEN<="00000000";
When "011"=> ROW<="11101111";COL_RED<="00111100";COL_GREEN<="00000000";
When "100"=> ROW<="11110111";COL_RED<="00100000";COL_GREEN<="00000000";
When "101"=> ROW<="11111011";COL_RED<="00100000";COL_GREEN<="00000000";
When "110"=> ROW<="11111101";COL_RED<="00100000";COL_GREEN<="00000000";
When "111"=> ROW<="11111110";COL_RED<="00111100";COL_GREEN<="00000000";
When others => ROW<="11111111";COL_RED<="00000000";COL_GREEN<="00000000";
END CASE;
WHEN 4=> CASE SEL IS --4
When "000"=> ROW<="01111111";COL_RED<="00100100";COL_GREEN<="00000000";
When "001"=> ROW<="10111111";COL_RED<="00100100";COL_GREEN<="00000000";
When "010"=> ROW<="11011111";COL_RED<="00100100";COL_GREEN<="00000000";
When "011"=> ROW<="11101111";COL_RED<="00111100";COL_GREEN<="00000000";
When "100"=> ROW<="11110111";COL_RED<="00100000";COL_GREEN<="00000000";
When "101"=> ROW<="11111011";COL_RED<="00100000";COL_GREEN<="00000000";
When "110"=> ROW<="11111101";COL_RED<="00100000";COL_GREEN<="00000000";
When "111"=> ROW<="11111110";COL_RED<="00000000";COL_GREEN<="00000000";
When others => ROW<="11111111";COL_RED<="00000000";COL_GREEN<="00000000";
END CASE;
WHEN 3=> CASE SEL IS --3
When "000"=> ROW<="01111111";COL_RED<="00111100";COL_GREEN<="00000000";
When "001"=> ROW<="10111111";COL_RED<="00100000";COL_GREEN<="00000000";
When "010"=> ROW<="11011111";COL_RED<="00100000";COL_GREEN<="00000000";
When "011"=> ROW<="11101111";COL_RED<="00111100";COL_GREEN<="00000000";
When "100"=> ROW<="11110111";COL_RED<="00100000";COL_GREEN<="00000000";
When "101"=> ROW<="11111011";COL_RED<="00100000";COL_GREEN<="00000000";
When "110"=> ROW<="11111101";COL_RED<="00111100";COL_GREEN<="00000000";
When "111"=> ROW<="11111110";COL_RED<="00000000";COL_GREEN<="00000000";
When others => ROW<="11111111";COL_RED<="00000000";COL_GREEN<="00000000";
END CASE;
WHEN 2=> CASE SEL IS --2
When "000"=> ROW<="01111111";COL_RED<="00111100";COL_GREEN<="00000000";
When "001"=> ROW<="10111111";COL_RED<="00100000";COL_GREEN<="00000000";
When "010"=> ROW<="11011111";COL_RED<="00100000";COL_GREEN<="00000000";
When "011"=> ROW<="11101111";COL_