找回密码
 注册
关于网站域名变更的通知
查看: 217|回复: 1
打印 上一主题 下一主题

转——俄罗斯方块游戏的软硬件设计

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-4-16 08:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
转——俄罗斯方块游戏的软硬件设计

. V. K: b0 A4 a* J! y  f
5 |7 A1 r! L  n$ S, z! ?
概述
: v5 R* j- ~, P  g4 y4 i
本篇主要介绍在上一篇在CPU的基础上添加外部中断和定时器中断等必要功能部件,以实现俄罗斯方块游戏所必须的硬件基础。
然后介绍一下软件设计流程。并附上最终演示效果。
* Q: E% N8 b* p# S) L! g- o/ l
(一)硬件设计
目前已经有了cpu,、 ps2,、vga三者结合的soc模块。然而俄罗斯方块游戏还需要一个定时器中断,用来控制向下匀速运动。一个外部中断检测外部的按键信息,并实施旋转变换的操作。此外,还添加了一个额外的定时器,用于产生随机的0-5的数字来生成随机图形。
5 a# ^3 }/ D( x. c; ?; K
中断机制:
IE寄存器     IE[0] = 定时器中断开关   IE[2]= 外部中断开关

% a1 j+ L  }% U; E
eret指令和epc寄存器   
# b# o8 o) G, k* C1 d
  在mips32指令集中有一条eret指令,用于返回中断前地址。epc寄存器用于存储中断来的时候下一条指令的地址。在中断开启的情况下,比如IE[2]=1;如果外部中断来(1),首先epc=next_pc,然后令pc等于事先规定好的中断服务程序的入口地址(本例中外部中断入口地址定义的是32’h14)。在进入外部中断的中断服务程序后,马上把IE寄存器整体左移4位。这样就可以避免进入中断后再重复进入中断的情况。在中断程序最后,以eret指令结尾。执行的操作是pc=epc;IE=IE>>4。返回到跳中断前的下一条指令。完成整个操作。

& d& x, v. v) j" l3 e4 k$ T) |$ ^2 Y1 U) m  L

8 g5 \7 d# \4 I+ K' m
- u7 X* J8 U% m- {# V2 c
下面是在外部,定时器和ps2中断的接入方法。这里注意cpu端的d_f_m出来的数据选择器要稍微改动一下,使之满足在timer1_write的时候把time1的数据接入的d_f_m
# T' t( m2 z7 D5 M/ t2 J

! j0 |, a/ Y8 V9 V1 ]- _% \3 H
- N/ G* [' L1 @# b  w
然后我们来看关键几处的verilog代码
1IE操作,如果intr1(定时器中断)=1或者外部中断(IE[2])开启、外部中断信号(ready)为1,则中断发生。IE<<4,关闭中断开关。如果eret指令,则IE>>4
reg [31:0]IE_register;
        always @(posedge clk)   begin
                if(IE_write) IE_register<=d_t_mem;
                else if((intr1&IE_register[0])||(ready&IE_register[2]))    IE_register<=IE_register<<4;
                else if(i_eret)        IE_register<=IE_register>>4;
) {  q1 p$ f/ V5 S7 H

* f7 C& k- o2 s) H. A& G) w
2PC操作,如果外部中断开关开启且外部中断来,epc=next_pc, pc=32’h14(外部中断服务程序入口地址)。如果定时器中断来,则epc=next_epcpc=32’h10(定时器中断服务程序地址)。

3 n. m# M5 }/ j
: K. D  p: j% q' K
    reg [31:0] pc;
        reg [31:0]epc;
    always @ (posedge clk or negedge clrn) begin
        if (!clrn) pc <= 0;               
                else if(IE_register[2]&ready)begin pc<=32'h14;epc<=next_pc; end
                else if(intr1) begin pc<=32'h10; epc<=next_pc;end
                else if(i_eret)  begin pc<=epc;end
                else         pc <= next_pc;
    end

) b, e6 l+ G" ^) x& N( i8 O
3)此外,为了程序运行时可以存放一些中间变量的结果,这里还定义了一个数据存储器(data_memory)。起初没有定义data_memory时,发现仅依靠r0~r31 32个寄存器放数据存储空间捉襟见肘。

: V+ K1 D- @/ q6 J1 |  p. |' D

( a% R- l' g) D8 ~
/ P5 v2 ^. l9 g3 V/ U
9 f& }, k  ^) i3 g) }$ H

+ e% }( t( s# c" o, d5 Z( f$ h5 r
3 q; Q- Y+ f9 j1 r. D! ~: i& p9 x; [
至此,一些必要的硬件设施就安排完善了。

+ f4 b8 `7 o5 p/ X( f* H* M  Q# L; ]) \
下面是具体的硬件地址定义信息
       #0x0000_0000     :0x0000_00(外部中断)0(timer1)0(time0)    IE
           #0x0000_0001     :0x0000_000(time1 run)0(time0run)   
           #0x0000_0002 计数器0: 只读0-5, 用来生成形状数字,生成伪随机数。
           #0x0000_0003 (timer1)定时器1: 可读写

: s0 M% ]9 C4 f' P* P1 F
           #外部存储空间(datamemory): #0xe000_0000----e000_001e     
  N9 q0 w1 _* {

0 F) \  M; \* |2 H5 H
(二)软件设计:

3 S  q2 Q) Z1 T5 V9 l0 k% l0 m
! K2 c& L0 {- z. l* T4 W

2 ~) Q, ~3 V, T
* b5 i. ^1 \3 {3 B5 q* H. n
由于俄罗斯方块的汇编语言程序有2000多行,不方便一一讲解。我这里只贴了大概的流程图。
总体思路是这样的,首先生成模块图形,然后定时器中断溢出一次则模块下降一格。定时器初值决定了下降速度。中断服务程序开头别忘了重新赋初值。
图形下降时如果碰到按键按左右按钮,则执行左右移位,这涉及到对应数据的左右搬移。
如果按向上键,则需要执行旋转操作。只要对数据应用旋转矩阵,就可以了。
比较难的一点是如何使模块停在下面的模块上,我的做法是首先把当先模块里的每个小方框位置记下,然后删除每个小方框中的数据。接着计算查看每个小方框下面那格是否有数据,如果有,则说明有东西,需要停下来,反之则可以继续下降,直到碰到底边为止。

, _2 x) h7 @/ I! A8 A! n' `4 o
右边界面还做了一点积分的小功能。
( ]# n& z' ?: O1 D, X' s8 j
(三)效果

" b  r8 s8 ?0 l0 X% s
$ q/ ^6 u% T. l+ z: n2 Y
( [# y. m9 v- d! Q; A' P9 I

该用户从未签到

2#
发表于 2019-4-16 17:10 | 只看该作者
虽然简易 但是效果还是不错的嘛
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-30 08:28 , Processed in 0.109375 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表