点阵赛车游戏
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
点阵赛车游戏实验报告
姓名
班级
学号
一、要求和任务
1.用8×8点阵进行5秒倒计时显示,如下图所示。
2.当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=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=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,T IME_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_RED<="00111100";COL_GREEN<="00000000";
When "100"=>
ROW<="11110111";COL_RED<="00000100";COL_GREEN<="00000000";
When "101"=>
ROW<="11111011";COL_RED<="00000100";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 1=> case SEL is --显示字符“1”
When "000"=>
-ROW<="01111111";COL_RED<="00001000";COL_GREEN<="00000000";
When "001"=>
ROW<="10111111";COL_RED<="00001000";COL_GREEN<="00000000";
When "010"=>
ROW<="11011111";COL_RED<="00001000";COL_GREEN<="00000000";
When "011"=>
ROW<="11101111";COL_RED<="00001000";COL_GREEN<="00000000";
When "100"=>
ROW<="11110111";COL_RED<="00001000";COL_GREEN<="00000000";
When "101"=>
ROW<="11111011";COL_RED<="00001000";COL_GREEN<="00000000";
When "110"=>
ROW<="11111101";COL_RED<="00001000";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 0=> --扫描赛车和赛道
COL_RED<="00000000"; COL_GREEN<="00000000";ROW<="11111111";
CASE N IS
WHEN 0 =>
CASE NUM IS
WHEN 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15=> --扫描0号红色赛道
--COL_RED(WY(NUM-1))<='0';ROW(WX(NUM-1))<='1';
COL_RED(WY(NUM))<='1';ROW(WX(NUM))<='0';
WHEN 16|17|18=> --扫描0号绿色赛道
COL_GREEN(WY(NUM))<='1';ROW(WX(NUM))<='0';
WHEN 19=> --扫描赛车坐标
COL_RED(SY)<='1';COL_GREEN(SY)<='1';ROW(SX)<='0';
WHEN 20=> -扫描障碍坐标
COL_RED(SY1)<='1';ROW(SX1)<='0';
WHEN OTHERS=>
COL_RED<="00000000";
COL_GREEN<="00000000";ROW<="11111111";
END CASE;
WHEN 1|4=>
CASE NUM1 IS
WHEN 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15=> --扫描1号红色赛道COL_RED(WY1(NUM1))<='1';ROW(WX1(NUM1))<='0';
WHEN 16|17=> --1号绿色赛道
COL_GREEN(WY1(NUM1))<='1';ROW(WX1(NUM1))<='0';
WHEN 18=> --扫描赛车坐标
COL_RED(SY)<='1';COL_GREEN(SY)<='1';ROW(SX)<='0';
WHEN 19=> --扫描赛车坐标
COL_RED(SY1)<='1';ROW(SX1)<='0';
WHEN OTHERS=>
COL_RED<="00000000";
COL_GREEN<="00000000";ROW<="11111111";
END CASE;
WHEN 2|5=>
CASE NUM2 IS
--WHEN 0=>
WHEN 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15=>
--COL_RED(WY(NUM-1))<='0';ROW(WX(NUM-1))<='1';
COL_RED(WY2(NUM2))<='1';ROW(WX2(NUM2))<='0';
WHEN 16=>
COL_GREEN(WY2(NUM2))<='1';ROW(WX2(NUM2))<='0';
WHEN 17=>
COL_RED(SY)<='1';COL_GREEN(SY)<='1';ROW(SX)<='0';
WHEN 18=>
COL_RED(SY1)<='1';ROW(SX1)<='0';
WHEN OTHERS=>
COL_RED<="00000000";
COL_GREEN<="00000000";ROW<="11111111";
END CASE;
WHEN 3|6 =>
CASE NUM3 IS
WHEN 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15=>
COL_RED(WY3(NUM3))<='1';ROW(WX3(NUM3))<='0';
WHEN 16|17|18|19|20=>
COL_GREEN(WY3(NUM3))<='1';ROW(WX3(NUM3))<='0'; -
WHEN 21=>
COL_RED(SY)<='1';COL_GREEN(SY)<='1';ROW(SX)<='0';
WHEN 22=>
COL_RED(SY1)<='1';ROW(SX1)<='0';
WHEN OTHERS=>
COL_RED<="00000000";
COL_GREEN<="00000000";ROW<="11111111";
END CASE;
When others =>
ROW<="11111111";COL_RED<="00000000";COL_GREEN<="00000000";
END CASE;
When others =>
ROW<="11111111";COL_RED<="00000000";COL_GREEN<="00000000";
END CASE;
END PROCESS;
END MLD;
五、功能说明
用BTN1~BTN3三个按键分别控制赛车的左移、前进、右移,最终使赛车在不碰撞赛道的情况下走完全程(即图2中的绿色位置),游戏结束,点阵显示“V”图案,数码管显示走完全程所耗费的时间。
当游戏时间超过59秒,或者赛车在行进过程中碰撞赛道,游戏失败,点阵显示“X”图案。
通过按键BTN0进行复位,控制点阵返回到初始状态。
附加功能:
有多种游戏赛道可选,5秒倒计时显示后赛道随机出现。
在赛车行进过程中,赛道中随机出现障碍物(用8×8点阵中的一个LED表示),通过BTN1~BTN3三个按键的控制躲避障碍物,走完全程。
若赛车碰到障碍物和赛道,则游戏失败。
六、资源利用情况
a)系统时钟CLK 50MHZ
b)拨码开关 BTN1,BTN2,BTN3,BTN0
c)数码管控制选通CAT0—CAT5
d)点阵行显示ROW[0]—ROW[7]
e)点阵列显示COL_RED[0]—COL_RED[7],COL_GREEN[0]—COL_GREEN[7]
f)数码管显示AA,AB,AC,AD,AE,AF,AG
逻辑单元:
七、故障及问题分析
1.仿真波形时,分频系数过大,导致仿真无法进行,改了分频系数后,才能进行仿真。
2.在组合电路中,用选择判断语句时,经常会出现锁存器,导致仿真停滞不前的状况,
那么就在其开头,加时钟控制,使其成为时序控制电路,则可有效避免,或者在每个进程开头赋初值。
3.刚开始并不知道点阵里的二极管和书上画的极性相反,出来时完全不对,自己探索了
好久才知道;另外扫描频率过大,点阵亮度太小,以致看不到图形,调整扫描频率后,则可看到。
4.当成功后数码管本应显示所耗用的时间,可是由于判断语句有问题,一直显示的是成
功时的时刻值,改了程序后才可正确显示。
5.加了按键消抖之后,用过大或过小的频率判断会出现一次走几步或没有走到的问题。
用200hz时钟判断则可有效避免:
IF CLK_200hz'event AND CLK_200hz='1' THEN
--DIRECTION_LEFT,DIRECTION_RIGHT,DIRECTION_UP脉宽5ms
--所以用CLK_200hz时钟检测,避免过多检测到信号或没有检测到方向信号
IF DIRECTION_LEFT='1' then --赛车向左移一格
SY<=SY-1;
ELSIF (DIRECTION_RIGHT='1') then --赛车向右移一格
SY<=SY+1;
ELSIF (DIRECTION_UP='1') then --赛车向上移一格
SX<=SX+1;
八、总结和心得
1.一定弄清楚VHDL基本用法,这样写代码或改代码才有效果,否则会很盲目。
2.别一股脑将所有模块一次写完,自认为很正确,最后才发现错误百出,即使编译通
过后,只是改了VHDL语言用法错误,至于模块之间信号是否传递到位还是不清楚,下载出来还是问题百出。
所以一定要先调试好每个模块,确保万无一失,在组合。
3.多利用仿真,观察结果,它是程序的形象显示,会帮你解决很多问题。
4.别人的错误,你也要留心,因为你极有可能遇到类似的问题。
优秀的人见贤思齐,
伟大的人看错助己。
5.灵感来源于交流,我从别人那借鉴了不少。
6.不要轻易放弃,不达目的,誓不罢休。
附:参考资料
《现代数字电路与逻辑设计实验教程》北京邮电大学出版;
《VHDL入门、解惑、经典实例、经验总结》黄仁北京航空航天大学出版;
《VHDL数字控制系统设计范例》林明权电子工业出版。