——————数字电路与逻辑设计实验报告—————基于VHDL的简易俄罗斯方块实验名称简易俄罗斯方块姓名班级电信工程学院04107班学号辅导老师高英日期2006年11月6日◆摘要俄罗斯方块游戏是我们熟知的经典小游戏之一,本实验通过硬件编成实现了简易的俄罗斯方块游戏机。
VHDL是一种标准的,规范的硬件描述语言,在电子设计领域有着广泛的应用。
它具有很强的电路描述和建模能力,能从多个层次多电路进行描述和建模,从而大大简化了硬件设计任务,提高了设计效率和可靠性。
本实验基于VHDL语言,利用电路中心开发的实验板,用一个4×4点阵做为基本显示屏,一个发光点表示一个图形,完成俄罗斯方块游戏的基本功能:下落、左右移动、消行和显示得分情况,当某一列到顶时游戏结束。
关键字俄罗斯方块游戏VHDL 点阵◆设计任务利用电路中心开发的实验板,用点阵做为显示屏,一个发光点表示一个方块,完成下落、左右移动、消行和显示得分情况,当某一列到顶时游戏结束,数码管显示的分数保持不变。
◆设计思路由于实验中只用到了16个点来完成显示功能,所以选用一个16位的向量STATUS(0 TO 15)来存储各点状态,再用两个整型数分别控制当前点的坐标,但是这样控制会涉及到乘法运算,因此改为4个4位向量STAN(0 TO 3),每个向量代表一行点阵,这样做不仅使控制简单,而且在扫描显示的时候很方便,代码也很简洁。
设计包括2个大的元件,一个是RUSSIA,其功能是存储状态,分频,完成左右下移动以及计分等功能;另一个是RUSSIA_SCAN,主要完成点阵扫描和数码管译码。
具体设计是这样的:4个向量STA0,STA1,STA2,STA3记录游戏状态,点的坐标由COL 和ROW来控制。
设置两个指针FLAG和ROW4,如果四列中有一列都为1,表示游戏结束了,置FLAG为1,程序进入NULL;当最后一行及STA3=”1111”时,置ROW4=1,当ROW4=1时,表示要消行,加分,并且将上一行的值赋到下一行。
游戏继续,如按下左键或右键,程序更根据下一状态决定是否左移或右移。
(BTN1为复位RESET,BTN2为左,BTN3为右)若无键按下,则根据情况当前点是否需要自动下移。
源代码底层文件1:russia.vhd------ russia.vhd------osom------6/11/06LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_SIGNED.ALL;ENTITY RUSSIA ISPORT(CLK :IN STD_LOGIC; -------时钟频率,选用低频RESET :IN STD_LOGIC; -------复位键LEFT :IN STD_LOGIC; -------左移键RIGHT :IN STD_LOGIC; -------右移键SCORES :OUT INTEGER RANGE 0 TO 15; -------分数STA0 : OUT STD_LOGIC_VECTOR(0 TO 3) ; -------以下为四行状态寄存STA1 : OUT STD_LOGIC_VECTOR(0 TO 3) ;STA2 : OUT STD_LOGIC_VECTOR(0 TO 3) ;STA3 : OUT STD_LOGIC_VECTOR(0 TO 3) );END RUSSIA;ARCHITECTURE MOVING OF RUSSIA ISSIGNAL STATU0 : STD_LOGIC_VECTOR(0 TO 3) ;SIGNAL STATU1 : STD_LOGIC_VECTOR(0 TO 3) ;SIGNAL STATU2 : STD_LOGIC_VECTOR(0 TO 3) ;SIGNAL STATU3 : STD_LOGIC_VECTOR(0 TO 3) ;SIGNAL FLAG : STD_LOGIC; -------game over 标志SIGNAL FP :INTEGER RANGE 0 TO 499; -------1000分频SIGNAL CLK1 :STD_LOGIC;SIGNAL SCOR_TEMP :INTEGER RANGE 0 TO 15;SIGNAL ROW4 :STD_LOGIC; -------消行标志SIGNAL ROW,COL:INTEGER RANGE 0 TO 3; -------点的坐标控制BEGINP1:PROCESS(CLK,RESET)BEGINIF RESET='1' THENFP<=0;CLK1<='0';ELSIF(CLK'EVENT AND CLK='1')THENIF FP=2 THENFP<=0;CLK1<=NOT CLK1;ELSEFP<=FP+1;END IF;END IF;END PROCESS; --------p1用来分频P2:PROCESS(CLK1,RESET)BEGINIF RESET='1' THEN --------系统初始化STATU0<="0100";STATU1<="0000";STATU2<="0000";STATU3<="0000";FLAG<='0';SCOR_TEMP<=0;ROW4<='0';ROW<=0;COL<=1;ELSIF(CLK1'EVENT AND CLK1='1')THENIF FLAG='1' THEN --------game over 进入空循环NULL;ELSIF ROW4='1' THEN --------消行STATU3<=STATU2;STATU2<=STATU1;STATU1<=STATU0;ROW4<='0';SCOR_TEMP<=SCOR_TEMP+1; --------加分ELSIF (STATU0(0)='1' AND STATU1(0)='1' AND STATU2(0)='1' AND STATU3(0)='1' ) OR(STATU0(1)='1' AND STATU1(1)='1' AND STATU2(1)='1' ANDSTATU3(1)='1' )OR(STATU0(2)='1' AND STATU1(2)='1' AND STATU2(2)='1' AND STATU3(2)='1' )OR(STATU0(3)='1' AND STATU1(3)='1' AND STATU2(3)='1' AND STATU3(3)='1') THENFLAG<='1'; --------判断四列中是否有一列全为1,是则FLAG<='1' ELSIF STATU3="1111"THENROW4<='1'; --------可以消行了ELSIF RIGHT='1' AND COL<3 THEN --------右移判断CASE ROW ISWHEN 0=>IF STATU0(COL+1)='0' THENCOL<=COL+1;STATU0(COL+1)<='1';STATU0(COL)<='0'; END IF ;WHEN 1=>IF STATU1(COL+1)='0' THENCOL<=COL+1;STATU1(COL+1)<='1';STATU1(COL)<='0'; END IF ;WHEN 2=>IF STATU2(COL+1)='0' THENCOL<=COL+1;STATU2(COL+1)<='1';STATU2(COL)<='0'; END IF ;WHEN OTHERS=>IF STATU3(COL+1)='0' THENCOL<=COL+1;STATU3(COL+1)<='1'; STATU3(COL)<='0'; END IF ;END CASE;ELSIF LEFT='1' AND COL>0 THEN ---------左移判断CASE ROW ISWHEN 0=>IF STATU0(COL-1)='0' THENCOL<=COL-1;STATU0(COL-1)<='1';STATU0(COL)<='0'; END IF ;WHEN 1=>IF STATU1(COL-1)='0' THENCOL<=COL-1;STATU1(COL-1)<='1';STATU1(COL)<='0'; END IF ;WHEN 2=>IF STATU2(COL-1)='0' THENCOL<=COL-1;STATU2(COL-1)<='1';STATU2(COL)<='0'; END IF ;WHEN OTHERS=>IF STATU3(COL-1)='0' THENCOL<=COL-1;STATU3(COL-1)<='1'; STATU3(COL)<='0'; END IF ;END CASE; --------以下elsif语句为点的下移处理ELSIF ROW=0 AND STATU1(COL)='0' THENROW<=ROW+1;STATU1(COL)<='1';STATU0(COL)<='0';ELSIF ROW=1 AND STATU2(COL)='0' THENROW<=ROW+1;STATU2(COL)<='1';STATU1(COL)<='0';ELSIF ROW=2 AND STATU3(COL)='0' THENROW<=ROW+1;STATU3(COL)<='1';STATU2(COL)<='0';ELSE ROW<=0;COL<=1;STATU0(1)<='1';---不能下移则产生一个新的点END IF;END IF;END PROCESS;SCORES<=SCOR_TEMP;STA0<=STATU0;STA1<=STATU1;STA2<=STATU2;STA3<=STATU3;END;底层文件2:RUSSIA_SCAN.vhd----- RUSSIA_SCAN.vhd-----osom------6/11/06LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;ENTITY RUSSIA_SCAN ISPORT(CLK: IN STD_LOGIC;RESET: IN STD_LOGIC;STA0 : IN STD_LOGIC_VECTOR(0 TO 3); -------以下为4行的状态STA1 : IN STD_LOGIC_VECTOR(0 TO 3) ;STA2 : IN STD_LOGIC_VECTOR(0 TO 3) ;STA3 : IN STD_LOGIC_VECTOR(0 TO 3) ;SCORE: IN INTEGER RANGE 0 TO 15; -------分数COL : OUT STD_LOGIC_VECTOR(0 TO 3); -------点阵显示的行列控制ROW : OUT STD_LOGIC_VECTOR(0 TO 3);DISP : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);------数码管译码CAT : OUT STD_LOGIC_VECTOR(5 DOWNTO 0) ------数码管选择);END RUSSIA_SCAN;ARCHITECTURE BEHAVE OF RUSSIA_SCAN ISSIGNAL CP :INTEGER RANGE 0 TO 3;SIGNAL ROWT,COLT:STD_LOGIC_VECTOR(0 TO 3);SIGNAL DISPT:STD_LOGIC_VECTOR(6 DOWNTO 0);BEGINPROCESS(CLK,SCORE,RESET)BEGINIF RESET='1' THENDISPT<="0000000";ROWT<="0000";COLT<="1111";CP<=0;ELSIF CLK'EVENT AND CLK='1' THENIF CP=3 THENCP<=0;ELSECP<=CP+1;END IF;CASE CP IS --------对时钟4分频,用于点阵扫描WHEN 0 =>ROWT<="1000";COLT<=NOT STA0; -------采用行扫描法WHEN 1 =>ROWT<="0100";COLT<=NOT STA1;WHEN 2 =>ROWT<="0010";COLT<=NOT STA2;WHEN OTHERS=>ROWT<="0001";COLT<=NOT STA3;END CASE;CASE SCORE IS --------分数译码WHEN 0 =>DISPT<="1111110"; --------0WHEN 1 =>DISPT<="0110000"; --------1WHEN 2 =>DISPT<="1101101"; --------2WHEN 3 =>DISPT<="1111001"; --------3WHEN 4 =>DISPT<="0110011"; --------4WHEN 5 =>DISPT<="1011011"; --------5WHEN 6 =>DISPT<="1011111"; --------6WHEN 7 =>DISPT<="1110000"; --------7WHEN 8 =>DISPT<="1111111"; --------8WHEN 9 =>DISPT<="1111011"; --------9WHEN 10 =>DISPT<="1110111"; -------10WHEN 11 =>DISPT<="0011111"; -------11WHEN 12 =>DISPT<="1001110"; -------12WHEN 13 =>DISPT<="0111101"; -------13WHEN 14 =>DISPT<="1001111"; -------14WHEN 15 =>DISPT<="1000111"; -------15WHEN OTHERS=>DISPT<="0000000";END CASE;END IF;END PROCESS;ROW<=ROWT;COL<=COLT;DISP<=DISPT;CAT<="011111"; -------选择第一个数码管END;顶层文件RUSSIABLOCK.vhd------ RUSSIABLOCK.vhd-----osom------6/11/06LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_SIGNED.ALL;ENTITY RUSSIABLOCK I SPORT(CLK : IN STD_LOGIC; -----------低频时钟RESET : IN STD_LOGIC; -----------开始复位键LEFT : IN STD_LOGIC; -----------左移RIGHT : IN STD_LOGIC; -----------右移COL OUT STD_LOGIC_VECTOR(0 TO 3); ---------- 列ROW : OUT STD_LOGIC_VECTOR(0 TO 3); ---------- 行DISP : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);-------- 数码管显示分数CAT : OUT STD_LOGIC_VECTOR(5 DOWNTO 0) ------数码管选择);END RUSSIABLOCK;ARCHITECTURE RBLOCK OF RUSSIABLOCK ISSIGNAL FENSHU : INTEGER RANGE 0 TO 15;SIGNAL STA0,STA1,STA2,STA3 : STD_LOGIC_VECTOR(0 TO 3) ;COMPONENT -----------元件例化申明RUSSIA PORT(CLK :IN STD_LOGIC;RESET :IN STD_LOGIC;LEFT :IN STD_LOGIC;RIGHT :IN STD_LOGIC;SCORES :OUT INTEGER RANGE 0 TO 15;STA0 : OUT STD_LOGIC_VECTOR(0 TO 3) ;STA1 : OUT STD_LOGIC_VECTOR(0 TO 3) ;STA2 : OUT STD_LOGIC_VECTOR(0 TO 3) ;STA3 : OUT STD_LOGIC_VECTOR(0 TO 3));END COMPONENT;COMPONENT -----------元件例化申明RUSSIA_SCAN PORT( CLK: IN STD_LOGIC;STA0 : IN STD_LOGIC_VECTOR(0 TO 3) ;STA1 : IN STD_LOGIC_VECTOR(0 TO 3) ;STA2 : IN STD_LOGIC_VECTOR(0 TO 3) ;STA3 : IN STD_LOGIC_VECTOR(0 TO 3) ;SCORE: IN INTEGER RANGE 0 TO 15;COL : OUT STD_LOGIC_VECTOR(0 TO 3);ROW : OUT STD_LOGIC_VECTOR(0 TO 3);DISP : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);CAT : OUT STD_LOGIC_VECTOR(5 DOWNTO 0));END COMPONENT;BEGIN --------------元件例化C1:RUSSIA PORT MAP(CLK,RESET,LEFT,RIGHT,FENSHU,STA0,STA1,STA2,STA3); C2:RUSSIA_SCAN PORT MAP(CLK,STA0,STA1,STA2,STA3,FENSHU,COL,ROW,DISP,CAT); END;仿真波形◆实验中所遇到的问题1.由于初次设计较大的硬件程序,所以开始遇到的问题比较多。