北京邮电大学
数字电路与逻辑设计实验
实验报告
实验名称:足球比赛游戏机
班级:
学号:
姓名
20##年11月8号
一、实验目的
(1)进一步掌握VHDL和Quartus II软件的使用;
(2)理解状态机的工作原理和设计方法;
(3)掌握利用EDA工具进行自顶向下的电子系统设计方法。
二、实验所用仪器及元器件
(1)计算机;
(2)EDA开发板及相应元器件。
三、实验内容
(1)基本内容
1、按下开始键后,点阵显示球场初始状态,黄色点表示球,红、绿点表示甲、乙双方的球员,上下各有四个点表示双方的球门。
2、甲、乙双方各有一组上下左右按键来控制自己的球员,当球员位于足球的上下左右四个点时,按下方向键可带球向对应的方向移动,如果移动方向正前方有对方球员,则球不能移动。
3、在没有球员踢球的时候,足球每秒随机向四个方向移动一格。
4、足球到四周边界线(点阵最外一圈的点)时,再继续向外踢球时,可以球不移动,等待球随机移动;也可以自己设定相关的出界规则。
5、足球进入球门,则胜方自动加 1 分,每方的分数用2 位数码管显示。
6、每场比赛时间为 90 秒,用数码管倒计时显示时间。计时到0 后,比赛停止,点阵显示胜利方(甲、乙或者平),直到再次按下比赛开始键后重新开始。
(2)提高要求
1、进球和比赛结束后点阵显示动画或者蜂鸣器播放音乐庆祝。
2、自拟其它功能。
四、系统设计
本次试验我把电路分为中心逻辑模块(center)和外围硬件驱动模块(按键keyboard,点阵显示screen,数码管显示digit,倒计时countdown,分频器clkgen)。
各部分把信号送给center,center对信号做出反应。
五.程序设计
(1) 点阵模块
点阵分成了两个小块,一部分负责扫描,即通过扫描显示输入图形,一部分负责图像的输入,这样做能简化程序结构,让程序思路更清晰。
扫描模块在1kHz的上升沿,列移位输出
由中心部件传过来的信号shenfu(胜负)为000时未分胜负,则显示甲乙球的对应坐标,否则根据胜负显示结果。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity screen is
port (
row: out std_logic_vector(7 downto 0);
rcol: out std_logic_vector(7 downto 0);
gcol: out std_logic_vector(7 downto 0);
p0_pos_row: in std_logic_vector(7 downto 0);
p0_pos_col: in std_logic_vector(7 downto 0);
p1_pos_row: in std_logic_vector(7 downto 0);
p1_pos_col: in std_logic_vector(7 downto 0);
p2_pos_row: in std_logic_vector(7 downto 0);
p2_pos_col: in std_logic_vector(7 downto 0);
shenfu: in std_logic_vector(2 downto 0);
clock: in std_logic
);
end entity screen;
architecture v of screen is
signal r: std_logic_vector(7 downto 0):="00000001";
signal rc: std_logic_vector(7 downto 0);
signal gc: std_logic_vector(7 downto 0);
begin
led_SCAN: process (clock)
begin
if rising_edge(clock) then
if (r = "10000000") then
r <= "00000001";
else
r(7 downto 1)<=r(6 downto 0);
r(0)<='0';
end if;
end if;
end process led_SCAN;
led_out: process (r,shenfu,p0_pos_row, p0_pos_col,p1_pos_row, p1_pos_col,p2_pos_row, p2_pos_col)
begin
case shenfu is
when "000"=>
if (r="00000001") then
rc<="00111100";
gc<="00000000";
elsif (r="10000000") then
gc<="00111100";
rc<="00000000";
else
if (r=p2_pos_row and r=p1_pos_row and r=p0_pos_row) then
rc<=p1_pos_col or p0_pos_col;
gc<=p2_pos_col or p0_pos_col;
elsif (r=p2_pos_row and r=p0_pos_row) then
gc<=p2_pos_col or p0_pos_col;
rc<="00000000";
elsif (r=p1_pos_row and r=p0_pos_row) then
rc<=p1_pos_col or p0_pos_col;
gc<="00000000";
elsif (r=p1_pos_row and r=p2_pos_row) then
gc<=p2_pos_col;
rc<=p1_pos_col;
elsif (r=p1_pos_row) then
gc<="00000000";
rc<=p1_pos_col;
elsif (r=p2_pos_row) then
rc<="00000000";
gc<=p2_pos_col;
elsif (r=p0_pos_row) then
gc<=p0_pos_col;
rc<=p0_pos_col;
else
gc<="00000000";
rc<="00000000";
end if;
end if;
when "100"=>
gc<=p0_pos_col;
case r is
when "00000001"=> rc<="00010000";
when "00000010"=> rc<="00010000";
when "00000100"=> rc<="00010000";
when "00001000"=> rc<="11111110";
when "00010000"=> rc<="10010010";
when "00100000"=> rc<="11111110";
when "01000000"=> rc<="10010010";
when "10000000"=> rc<="11111110";
when others => rc<="00000000";
end case;
when "010"=>
gc<=p0_pos_col;
case r is
when "00000001"=> rc<="11111111";
when "00000010"=> rc<="01000000";
when "00000100"=> rc<="00100000";
when "00001000"=> rc<="00010000";
when "00010000"=> rc<="0000100";
when "00100000"=> rc<="00000100";
when "01000000"=> rc<="00000010";
when "10000000"=> rc<="11111111";
when others => rc<="00000000";
end case;
when "001"=>
gc<=p0_pos_col;
case r is
when "00000001"=> rc<="00010000";
when "00000010"=> rc<="00010000";
when "00000100"=> rc<="00010000";
when "00001000"=> rc<="11111111";
when "00010000"=> rc<="00111000";
when "00100000"=> rc<="01010100";
when "01000000"=> rc<="00111000";
when "10000000"=> rc<="01111100";
when others => rc<="00000000";
end case;
when others => null;
end case;
end process led_out;
row<=not r;
rcol<=rc;
gcol<=gc;
end architecture v;
(2) 数码管模块
数码管模块根据输入的数字经过译码显示出来,只和输入的num有关,不会影响程序。
使用digit_translate进行译码,得到的结果在扫描到对应的时间输出
digit_translate由于多次使用,作为component调用,是一个4-7译码器。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity digit is
port (
cat: out std_logic_vector(5 downto 0);
outdata: out std_logic_vector(6 downto 0);
num5: in std_logic_vector(3 downto 0);
num4: in std_logic_vector(3 downto 0);
num3: in std_logic_vector(3 downto 0);
num2: in std_logic_vector(3 downto 0);
num1: in std_logic_vector(3 downto 0);
num0: in std_logic_vector(3 downto 0);
clock: in std_logic;
reset: in std_logic
);
end entity digit;
architecture digit_scan of digit is
COMPONENT digit_translate
PORT
(
num : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
decode : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
);
END COMPONENT;
signal temp_cat: std_logic_vector(5 downto 0);
signal num0_decode: std_logic_vector(6 downto 0);
signal num1_decode: std_logic_vector(6 downto 0);
signal num2_decode: std_logic_vector(6 downto 0);
signal num3_decode: std_logic_vector(6 downto 0);
signal num4_decode: std_logic_vector(6 downto 0);
signal num5_decode: std_logic_vector(6 downto 0);
signal outdata_temp: std_logic_vector(6 downto 0);
begin
m0:digit_translate port map(num0,num0_decode);
m1:digit_translate port map(num1,num1_decode);
m2:digit_translate port map(num2,num2_decode);
m3:digit_translate port map(num3,num3_decode);
m4:digit_translate port map(num4,num4_decode);
m5:digit_translate port map(num5,num5_decode);
process (clock, reset) is
begin
if (reset = '1') then
temp_cat<="000001";
elsif rising_edge(clock) then
if (temp_cat="100000") then
temp_cat<="000001";
else
temp_cat(5 downto 1)<=temp_cat(4 downto 0);
temp_cat(0)<='0';
end if;
end if;
end process;
process(temp_cat,num0_decode,num1_decode,num2_decode,num3_decode,num4_decode,num5_decode) is
begin
if (temp_cat="000001") then
outdata_temp<=num0_decode;
elsif (temp_cat="000010") then
outdata_temp<=num1_decode;
elsif (temp_cat="000100") then
outdata_temp<=num2_decode;
elsif (temp_cat="001000") then
outdata_temp<=num3_decode;
elsif (temp_cat="010000") then
outdata_temp<=num4_decode;
else
outdata_temp<=num5_decode;
end if;
end process;
cat<=not temp_cat;
outdata<=outdata_temp;
end architecture digit_scan;
(3) 倒计时模块
输入1Hz的时钟,start为高时开始倒计时,reset为高时倒计时归为80,时间到0时time_out输出为高
输出分为十位count_10和个位count输出。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity count_down is
port (
clock: in std_logic;
reset: in std_logic;
start: in std_logic;
time_out: out std_logic;
count_10: out std_logic_vector(3 downto 0);
count: out std_logic_vector(3 downto 0)
);
end entity count_down;
architecture my of count_down is
signal count_10_temp: std_logic_vector(3 downto 0);
signal count_temp: std_logic_vector(3 downto 0);
begin
process (clock,reset) is
begin
if (reset = '1') then
count_10_temp<="1001";
count_temp<="0000";
time_out<='0';
elsif rising_edge(clock) and start='1' then
if (count_temp="0000" and count_10_temp="0000") then
time_out<='1';
elsif (count_temp="0000") then
count_temp<="1001";
count_10_temp<=count_10_temp-1;
time_out<='0';
else
count_temp<=count_temp-1;
time_out<='0';
end if;
end if;
end process;
count_10<=count_10_temp;
count<=count_temp;
end architecture my;
(4) 键盘模块
键盘输出行扫描,输入列信号,
之后防抖、转码输出,屏蔽了多余的接口
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity keyboard is
port (
col : out std_logic_vector(3 downto 0);
row : in std_logic_vector(3 downto 0);
debug_key : out std_logic_vector(7 downto 0); --used for debug
p1_key: out std_logic_vector(3 downto 0);--player 1 (up,left,down,right)
p2_key: out std_logic_vector(3 downto 0);--player 2 (up,left,down,right)
reset: in std_logic;
clock: in std_logic); --1kHz
end entity;
architecture keyboard_main of keyboard is
signal temp_col: std_logic_vector(3 downto 0):="0001"; --col=not temp_col
signal keys:std_logic_vector(7 downto 0);
signal catch_row0: std_logic_vector(3 downto 0);
signal catch_row1: std_logic_vector(3 downto 0);
signal catch_row2: std_logic_vector(3 downto 0);
signal catch_row3: std_logic_vector(3 downto 0);
signal t0: integer range 0 to 99:=0;
signal t1: integer range 0 to 99:=0;
signal t2: integer range 0 to 99:=0;
signal t3: integer range 0 to 99:=0;
signal p1_key_out: std_logic_vector(3 downto 0);
signal p2_key_out: std_logic_vector(3 downto 0);
--signal step: std_logic_vector(1 downto 0);
begin
scan:process (clock) is
begin
if rising_edge(clock) then
if (temp_col="1000") then
temp_col<="0001";
else
temp_col(3 downto 1)<=temp_col(2 downto 0);
temp_col(0)<='0';
end if;
end if;
end process;
col<=not temp_col;
keys(7 downto 4)<=temp_col;
anti_shake:process (row,temp_col,clock) is
begin
if rising_edge(clock) then
if temp_col="0001" then --row0
if (row="1111") then --if any key was not pressed
t0<=0;
keys(3 downto 0)<="0000";
else
if t0=0 then
catch_row0<=row;
keys(3 downto 0)<="0000";
t0<=t0+1;
elsif catch_row0=row then
if t0=24 then --0.1s delay
t0<=0;
keys(3 downto 0)<=not catch_row0;
else
t0<=t0+1;
keys(3 downto 0)<="0000";
end if;
else
catch_row0<=row;
t0<=0;
keys(3 downto 0)<="0000";
end if;
end if;
elsif temp_col="0010" then --row1
if (row="1111") then
t1<=0;
keys(3 downto 0)<=not row;
else
if t1=0 then
catch_row1<=row;
keys(3 downto 0)<="0000";
t1<=t1+1;
elsif catch_row1=row then
if t1=24 then
t1<=0;
keys(3 downto 0)<=not row;
else
t1<=t1+1;
keys(3 downto 0)<="0000";
end if;
else
catch_row1<=row;
t1<=0;
end if;
end if;
elsif temp_col="0100" then --row2
if (row="1111") then
t2<=0;
keys(3 downto 0)<=not row;
else
if t2=0 then
catch_row2<=row;
keys(3 downto 0)<="0000";
t2<=t2+1;
elsif catch_row2=row then
if t2=24 then
t2<=0;
keys(3 downto 0)<=not row;
else
t2<=t2+1;
keys(3 downto 0)<="0000";
end if;
else
catch_row2<=row;
t2<=0;
end if;
end if;
else --row3
if (row="1111") then
t3<=0;
keys(3 downto 0)<=not row;
else
if t3=0 then
catch_row3<=row;
keys(3 downto 0)<="0000";
t3<=t3+1;
elsif catch_row3=row then
if t3=24 then
t3<=0;
keys(3 downto 0)<=not row;
else
t3<=t3+1;
keys(3 downto 0)<="0000";
end if;
else
catch_row3<=row;
t3<=0;
end if;
end if;
end if;
end if;
end process;
translate:process (clock,keys,reset) is --keys=col & row
begin
if rising_edge(clock) then
if reset='1' then
p1_key_out<="0000";
p2_key_out<="0000";
elsif (keys="01000010") then
p1_key_out<="1000"; --player 1 press up
p2_key_out<="0000";
---step<="01";
elsif (keys="10000001") then
p1_key_out<="0100"; --player 1 press left
p2_key_out<="0000";
---step<="01";
elsif (keys="01000001") then
p1_key_out<="0010"; --player 1 press down
p2_key_out<="0000";
---step<="01";
elsif (keys="00100001") then
p1_key_out<="0001"; --player 1 press right
p2_key_out<="0000";
---step<="01";
elsif (keys="01000100") then
p2_key_out<="1000";
p1_key_out<="0000";
---step<="01";
elsif (keys="10001000") then
p2_key_out<="0100";
p1_key_out<="0000";
---step<="01";
elsif (keys="01001000") then
p2_key_out<="0010";
p1_key_out<="0000";
---step<="01";
elsif (keys="00101000") then
p2_key_out<="0001";
p1_key_out<="0000";
---step<="01";
else
p1_key_out<="0000";
p2_key_out<="0000";
-- p2_key_out<=p2_key_out;
-- p1_key_out<=p1_key_out;
--p2_key_out<="0000";
---step<="00";
end if;
end if;
end process;
p1_key<=p1_key_out;
p2_key<=p2_key_out;
debug_key<=keys;
--debug_key(7 downto 4)<=p1_key_out;
--debug_key(3 downto 0)<=p2_key_out;
end keyboard_main;
(5) 中心逻辑模块
输入甲乙(p1、p2)的按键、时钟、开始信号、时间到信号,输出甲乙小球的位置,甲乙的得分,胜负状态等。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity center is
PORT
(
p1_key: in STD_LOGIC_VECTOR(3 DOWNTO 0);
p2_key: in STD_LOGIC_VECTOR(3 DOWNTO 0);
p0_pos_row: out std_logic_vector(7 downto 0);
p0_pos_col: out std_logic_vector(7 downto 0);
p1_pos_row: out std_logic_vector(7 downto 0);
p1_pos_col: out std_logic_vector(7 downto 0);
p2_pos_row: out std_logic_vector(7 downto 0);
p2_pos_col: out std_logic_vector(7 downto 0);
shenfu: out std_logic_vector(2 downto 0); --who win? p1"100" p2"010" eq"001"
p1_score_10: out std_logic_vector(3 downto 0);
p1_score: out std_logic_vector(3 downto 0);
p2_score_10: out std_logic_vector(3 downto 0);
p2_score: out std_logic_vector(3 downto 0);
clock: in std_logic;
reset: in std_logic;
start: in std_logic;
timeout: in std_logic;
start_out: out std_logic;
state_debug : out std_logic_vector(3 downto 0)
);
end entity center;
architecture m of center is
signal state: std_logic_vector(3 downto 0):="0001";
signal empty: std_logic_vector(9 downto 0);
signal random: std_logic_vector(3 downto 0):="0001";
signal p0_y: std_logic_vector(7 downto 0);
signal p0_x: std_logic_vector(7 downto 0);
signal p1_y: std_logic_vector(7 downto 0);
signal p1_x: std_logic_vector(7 downto 0);
signal p2_y: std_logic_vector(7 downto 0);
signal p2_x: std_logic_vector(7 downto 0);
signal p1_score_10_temp: std_logic_vector(3 downto 0);
signal p1_score_temp: std_logic_vector(3 downto 0);
signal p2_score_10_temp: std_logic_vector(3 downto 0);
signal p2_score_temp: std_logic_vector(3 downto 0);
signal jinqiu: std_logic:='0';
signal anjian: std_logic:='0';
signal p1_key_old: std_logic_vector(3 downto 0);
signal p2_key_old: std_logic_vector(3 downto 0);
begin
process (clock,p1_score_temp,p2_score_temp,empty) is
begin
if rising_edge(clock) then
if state="0001" then --reset
if start='1' then
state<="0010";
start_out<='1';
else
state<="0001";
start_out<='0';
end if;
elsif state="0010" then --game
if reset='1' then
state<="0001";
elsif timeout='1' then
state<="0100";
elsif jinqiu='1' then
state<="1000"; --jingqiu
elsif empty="1111101000" then
state<="0011"; --p0 random move
elsif anjian='1' then
state<="1111";
else
state<="0010";
end if;
elsif state="0100" then --time over
if reset='1' then
state<="0001";
else
state<="0100";
end if;
elsif state="1000" then --jingqiu
state<="0010";
elsif state="1111" then --wait for other input
if anjian='0' then
state<="0010";
else
state<="1111";
end if;
else
state<="0010";
end if;
end if;
end process;
process (p1_key,p2_key,state,clock) is
begin
if rising_edge(clock) then
if state="0001" then
p0_y<="00010000";
p0_x<="00010000";
p1_y<="00000010";
p1_x<="00001000";
p2_y<="01000000";
p2_x<="00001000";
jinqiu<='0';
p1_score_10_temp<="0000";
p1_score_temp<="0000";
p2_score_10_temp<="0000";
p2_score_temp<="0000";
random<="0010";
shenfu<="000";
elsif state="0010" then
empty<="0000000000";
if p1_key_old=p1_key and p2_key_old=p2_key then
anjian<='1';
else
anjian<='0';
p1_key_old<=p1_key;p2_key_old<=p2_key;
if p1_key="1000" then --p1 press up
if (p0_x=p1_x and p1_y(6 downto 0)=p0_y(7 downto 1)) then
if (not ((p0_x=p2_x) and p2_y(6 downto 0)=p0_y(7 downto 1)))and p0_y(7)='0' then
p1_y(7 downto 1)<=p1_y(6 downto 0);
p0_y(7 downto 1)<=p0_y(6 downto 0);
end if;
elsif (not (p2_x=p1_x and p1_y(6 downto 0)=p2_y(7 downto 1))) and p1_y(7)='0' then
p1_y(7 downto 1)<=p1_y(6 downto 0);
end if;
elsif p1_key="0010" then
if (p0_x=p1_x and p1_y(7 downto 1)=p0_y(6 downto 0) ) then
if (not (p0_x=p2_x and p2_y(7 downto 1)=p0_y(6 downto 0)))and p0_y(0)='0' then
p1_y(6 downto 0)<=p1_y(7 downto 1);
p0_y(6 downto 0)<=p0_y(7 downto 1);
end if;
elsif (not (p2_x=p1_x and p1_y(7 downto 1)=p2_y(6 downto 0)))and p1_y(0)='0' then
p1_y(6 downto 0)<=p1_y(7 downto 1);
end if;
elsif p1_key="0100" then
if (p0_y=p1_y and p1_x(6 downto 0)=p0_x(7 downto 1)) then
if (not (p0_x=p2_x and p2_y(6 downto 0)=p0_y(7 downto 1)))and p0_x(7)='0' then
p1_x(7 downto 1)<=p1_x(6 downto 0);
p0_x(7 downto 1)<=p0_x(6 downto 0);
p1_x(0)<='0';
end if;
elsif (not (p2_y=p1_y and p1_x(6 downto 0)=p2_x(7 downto 1)))and p1_x(7)='0' then
p1_x(7 downto 1)<=p1_x(6 downto 0);
p1_x(0)<='0';
end if;
elsif p1_key="0001" then
if (p0_y=p1_y and p1_x(7 downto 1)=p0_x(6 downto 0)) then
if (not (p0_x=p2_x and p2_y(7 downto 1)=p0_y(6 downto 0)))and p0_x(0)='0' then
p1_x(6 downto 0)<=p1_x(7 downto 1);
p0_x(6 downto 0)<=p0_x(7 downto 1);
p1_x(7)<='0';
end if;
elsif (not (p2_y=p1_y and p1_x(7 downto 1)=p2_x(6 downto 0)))and p1_x(0)='0' then
p1_x(6 downto 0)<=p1_x(7 downto 1);
p1_x(7)<='0';
end if;
elsif p2_key="1000" then
if (p0_x=p2_x and p2_y(7 downto 1)=p0_y(6 downto 0)) then
if (not (p0_x=p1_x and p1_y(7 downto 1)=p0_y(6 downto 0)))and p0_y(0)='0' then
p2_y(6 downto 0)<=p2_y(7 downto 1);
p0_y(6 downto 0)<=p0_y(7 downto 1);
end if;
elsif (not (p1_x=p2_x and p2_y(7 downto 1)=p1_y(6 downto 0)))and p2_y(0)='0' then
p2_y(6 downto 0)<=p2_y(7 downto 1);
end if;
elsif p2_key="0010" then
if (p0_x=p2_x and p2_y(6 downto 0)=p0_y(7 downto 1)) then
if (not (p0_x=p1_x and p1_y(6 downto 0)=p0_y(7 downto 1)))and p0_y(7)='0' then
p2_y(7 downto 1)<=p2_y(6 downto 0);
p0_y(7 downto 1)<=p0_y(6 downto 0);
end if;
elsif (not (p1_x=p2_x and p2_y(6 downto 0)=p1_y(7 downto 1))) and p2_y(7)='0' then
p2_y(7 downto 1)<=p2_y(6 downto 0);
end if;
elsif p2_key="0100" then
if (p0_y=p2_y and p2_x(6 downto 0)=p0_x(7 downto 1)) then
if (not (p0_x=p1_x and p1_y(6 downto 0)=p0_y(7 downto 1)))and p0_x(7)='0' then
p2_x(7 downto 1)<=p2_x(6 downto 0);
p0_x(7 downto 1)<=p0_x(6 downto 0);
p2_x(0)<='0';
end if;
elsif (not (p1_y=p2_y and p2_x(6 downto 0)=p1_x(7 downto 1)))and p2_x(7)='0' then
p2_x(7 downto 1)<=p2_x(6 downto 0);
p2_x(0)<='0';
end if;
elsif p2_key="0001" then
if (p0_y=p2_y and p2_x(7 downto 1)=p0_x(6 downto 0)) then
if (not (p0_x=p1_x and p1_y(7 downto 1)=p0_y(6 downto 0)))and p0_x(0)='0' then
p2_x(6 downto 0)<=p2_x(7 downto 1);
p0_x(6 downto 0)<=p0_x(7 downto 1);
p2_x(7)<='0';
end if;
elsif (not (p1_y=p2_y and p2_x(7 downto 1)=p1_x(6 downto 0)))and p2_x(0)='0' then
p2_x(6 downto 0)<=p2_x(7 downto 1);
p2_x(7)<='0';
end if;
end if;
end if;
if (p0_y="10000000") then
if (p0_x>="00000100" and p0_x<="00100000") then
jinqiu<='1';
if (p1_score_temp="1001") then
p1_score_temp<="0000";
p1_score_10_temp<=p1_score_10_temp+1;
else
p1_score_temp<=p1_score_temp+1;
end if;
end if;
elsif (p0_y="00000001") then
if (p0_x>="00000100" and p0_x<="00100000") then
jinqiu<='1';
if (p2_score_temp="1001") then
p2_score_temp<="0000";
p2_score_10_temp<=p2_score_10_temp+1;
else
p2_score_temp<=p2_score_temp+1;
end if;
end if;
end if;
elsif state="0100" then --time over
if p1_score_10_temp<p2_score_10_temp then
shenfu<="010"; --p2 win
elsif p1_score_10_temp>p2_score_10_temp then
shenfu<="100"; --p1_win
elsif p1_score_10_temp=p2_score_10_temp then
if p1_score_temp<p2_score_temp then
shenfu<="010"; --p2 win
elsif p1_score_temp>p2_score_temp then
shenfu<="100"; --p1 win
elsif p1_score_temp=p2_score_temp then
shenfu<="001"; --eq
end if;
end if;
elsif state="1000" then --jingqiu
p0_y<="00010000";
p0_x<="00010000";
p1_y<="00000010";
p1_x<="00001000";
p2_y<="01000000";
p2_x<="00001000";
shenfu<="000";
jinqiu<='0';
elsif state="0011" then --random move
empty<="0000000000";
if random(1 downto 0)="00" then
p0_x(7 downto 1)<=p0_x(6 downto 0);
elsif random(1 downto 0)="01" then
p0_x(6 downto 0)<=p0_x(7 downto 1);
elsif random(1 downto 0)="01" then
p0_y(7 downto 1)<=p0_y(6 downto 0);
else
p0_y(6 downto 0)<=p0_y(7 downto 1);
end if;
elsif state="1111" then
empty<=empty+1;
random<=random xor empty(3 downto 0);
if p1_key="0000" and p2_key="0000" then
anjian<='0';
else
anjian<='1';
end if;
end if;
end if;
end process;
p0_pos_row<=p0_y;
p0_pos_col<=p0_x;
p1_pos_row<=p1_y;
p1_pos_col<=p1_x;
p2_pos_row<=p2_y;
p2_pos_col<=p2_x;
p1_score_10<=p1_score_10_temp;
p1_score<=p1_score_temp;
p2_score_10<=p2_score_10_temp;
p2_score<=p2_score_temp;
state_debug<=state;
end architecture m;
(6) 分频器模块
输入25MHz,输出1MHz、1kHz、1Hz
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity clk_gen is
port (
clk_25MHz: in std_logic;
clk_1MHz: out std_logic;
clk_1kHz: out std_logic;
clk_1Hz : out std_logic);
end entity clk_gen;
architecture my of clk_gen is
signal count_25: integer range 0 to 24;
signal count_10: integer range 0 to 4;
signal count_100: integer range 0 to 49;
signal count_1000: integer range 0 to 499;
signal clk_temp_1MHz: std_logic;
signal clk_temp_1kHz: std_logic;
signal clk_temp_10Hz: std_logic;
signal clk_temp_1Hz: std_logic;
begin
process (clk_25MHz) is
begin
if rising_edge(clk_25MHz) then
if (count_25=12) then
count_25<=count_25+1;
clk_temp_1MHz<= not clk_temp_1MHz;
elsif (count_25=24) then
count_25<=0;
clk_temp_1MHz<= not clk_temp_1MHz;
else
count_25<=count_25+1;
end if;
end if;
end process;
process (clk_temp_1MHz) is
begin
if rising_edge(clk_temp_1MHz) then
if (count_1000=499) then
count_1000<=0;
clk_temp_1kHz<= not clk_temp_1kHz;
else
count_1000<=count_1000+1;
end if;
end if;
end process;
process (clk_temp_1kHz) is
begin
if rising_edge(clk_temp_1kHz) then
if (count_100=49) then
count_100<=0;
clk_temp_10Hz<= not clk_temp_10Hz;
else
count_100<=count_100+1;
end if;
end if;
end process;
process (clk_temp_10Hz) is
begin
if rising_edge(clk_temp_10Hz) then
if (count_10=4) then
count_10<=0;
clk_temp_1Hz<= not clk_temp_1Hz;
else
count_10<=count_10+1;
end if;
end if;
end process;
clk_1MHz<=clk_temp_1MHz;
clk_1kHz<=clk_temp_1kHz;
clk_1Hz<=clk_temp_1Hz;
end architecture my;
六、仿真波形及分析(由于时间原因未能完成仿真)
七、功能说明及资源利用情况
八、故障及问题分析
1.未设计球员的出界情况导致球员“丢失”。
2.不能在两个地方给同一个信号赋值。
3防抖电路设计不良导致按键不灵敏。
4状态的转移会在下一个时钟沿体现。
5仍然存在很多bug例如进一个球加2分,球员和足球同列时颜色会改变等。
6未能完成随机数的实现。
九、总结和结论
vhdl语言可以说是比较难以掌握的语言之一,它确实和其他语言不同,比如时钟的触犯,时序电路和逻辑电路,状态的转移等都非常有硬件编程的特色。对于本来就不精通于这类实验的我来说无疑是一次巨大的考验。说实话,上学期的数字电路实验课上所学的知识已经几乎忘光,我不得不重新开始对于vhdl语言的学习,经过几次预约的实验,与同学一起的学习与讨论,我还是克服了这道难关。我非常感谢唯一和我做同样实验的我的同学,它给予了我非常大的帮助,如果没有他,我可能真的无法完成此次实验。虽然最后的程序还是有不少bug,仿真也未能完成,“如果移动方向正前方有对方球员,则球不能移动”也未能实现,随机数还是无法正常使用,由于时间紧张,实验较难,而且我的水平也有限,无法在验收完前完成了。可是我相信我能够做到,实验虽然完结,学习的路却没有完结,我会更加努力,更好地掌握vhdl语言。