将游戏“ Snake”放在实验板上。第1部分:状态机

有空,我儿子和我学习数字电子学。最近,我们进入了关于有限状态机的章节。本主题充满了典型的任务,例如信号量或自动售货机。但是它们都很乏味而且太简单了,坦率地说,有些牵强。在研究了简单的示例之后,我想做一些更有趣,更复杂的事情。经典的游戏“蛇”引起了我的注意(我的儿子在电话上玩了它),我建议在状态机上制作它。毕竟,游戏的状态是最终的(特别是如果您将自己限制在一个小范围内),并且输入中只有4个按钮。这就是我们得到的。


蛇游戏(她是蛇,蟒蛇,蟒蛇等)是众所周知的。她来自遥远的70年代,但我不会重复她的故事,您可以在WikipediaHabré上阅读许多 文章。游戏中有相当简单的规则,并在同一时间令人上瘾的游戏))多亏了这一点,它经常被用来进行辅导代码样本 。在高级编程语言中,制作这样的游戏非常容易。但是在更有限的条件下,最有趣的开始是,例如,在LabVIEW上的实现。 FPGA上还有很多选项:链接1链接2链接3链接4。但是在标准系列的单独TTL芯片上还没有一个选项。这就是我们要做的。

看来FPGA解决方案对我们来说是最接近的,您可以从那里借用很多东西吗?但是在我看过的所有选项中,它们很容易分散在左右寄存器中。例如,经常为每个现场单元分配单独的比特或数字。我们不能用松散的粉末来做到这一点,因为每个新的寄存器都是一个单独的微电路,需要放置在某个地方然后连接。因此,我们排除了其他开发人员积累的所有经验,并将从头开始做所有事情。作为奖励,我们将收集k555 / kr1533系列国内(最好是苏联)的芯片上的所有东西,但ROM除外,必须重新购买。

问题的提法


我们将有这样的限制:一个大小为8×8单元(中文LED矩阵的字段,尾部长度为8单元。蛇可以穿过墙壁,但是我们首先不会处理与尾巴的相交(为了不使设计复杂化,您可以稍后添加)。要描述游戏的整个状态,我们需要:

  1. 磁头位置(X = 0..7,Y = 0..7,6位)
  2. 移动方向(↑↓←→,2位)
  3. 苹果位置(X,Y,6位)
  4. 尾巴长度(0..7,3位)
  5. 尾单元的位置(从0到7个,每个6位)

总共可以得到65位,即使我们每个取8位的寄存器,也只需要8个这样的微电路(和另一个触发器)来存储状态,这是很多的。

但是尾巴无法定位在任何想要的位置,而是从头部“长出”。因此,我们不能存储尾巴每个部分的完整坐标,而只能存储从前一个单元格(或头部)绘制方向的方向。然后,我们需要的是4×8 = 16位,而不是6×8 = 48位,这可以节省多达四个寄存器的情况!

自动机


让我们尝试在类似于Moore或Miles的计算机上执行所有操作。要实现这种自动机,只需要一点点状态存储器(寄存器)和组合逻辑就可以在它们之间进行切换。维基百科


图片

通常将状态机描述为状态图和它们之间的转换。有时候,创建到新状态的转换表更为方便,这是最简单的示例(来自Wikipedia):

例如,您可以在本文中找到有关更多信息和精美图片,例如关于哈布雷的文章

小题外话
, , . , ROM , ROM. ( , ).

, , .


, « » .



各种状态的蛇(如果不考虑苹果的位置)可以具有2 ^ 8 + 2 ^ 10 + ... + 2 ^ 24≈3200万。将它们写在表中是不可能的,甚至更不可能绘制过渡图。但是大多数过渡都是相同的(头部仅移动一个相邻的单元格,而尾部每转一格移动一节)。在这种情况下,我们无法描述每个单独的状态,而是根据前一个状态制定一个新状态。此外,我们可以将整个游戏分为几个平行的自动机:1)方向自动机,2)头部位置自动机,3)尾部自动机。并对其进行设置,这样会更加方便:

1) ,  │  
  ────────────────────┼───────────────────
   ←        ←/↓/↑     │ ←
   ←          →       │ →
   ↑        ↑/←/→     │ ↑
   ↑          ↓       │ ↓
   ......          │

2) ,  │  
  ─────────────────────┼──────────────
   ←             (x,y) │ (x-1, y)
   →             (x,y) │ (x+1, y)
   ↑             (x,y) │ (x, y-1)
   ↓             (x,y) │ (x, y+1)

3) ,                       │  
  ─────────────────────────────────────────┼──────────────────────────
   ←            (t1,t2,t3,t4,t5,t6,t7,t8)  │ (←,t1,t2,t3,t4,t5,t6,t7)
   ......                               │


方向


让我们从定向机器开始。如果您仔细考虑,可以将其组装在单独的逻辑上。但是,由于整个任务已经很大,我决定从EEPROM 创建查找表并手动写入转换表会更容易它将有6个输入,这意味着只有64个值,我们可以将其简单地驱动到十六进制编辑器中。




对于头部定位机,编写这样的表格将更加困难。但它实际上仅包含2个操作:+1和-1。它们可以在4位加法器K155IM6上实现。对于+1,我们将使用b'0001添加坐标,对于-1将使用b'1111添加坐标(实际上在附加代码中为-1 )。我们将需要两个加法器(分别用于x和y),有点逻辑,并将状态存储在8位寄存器IR27中(我们仍然需要很多):



让我们将其组装在板上,为进行验证,我们将立即将LED矩阵与两个解码器连接。具有反向输出的解码器是ID7,对于直接输出的解码器,可以带K561ID1(CD4028),但我手边没有。另一种选择是采用8个晶体管作为键,但是我不想这样做,所以我不得不愚蠢地花了另一个EEPROM(在那里只写了8个单元)。将新的头位置放在顶部的单独板上的逻辑另一个题外话





让我们休息一下,保存试验板(和一些芯片盒)。我们将再次利用以下事实:通过将表写入ROM,可以用LUT替换任何组合电路。但是对于这么大的桌子怎么办呢?我们将使用另一个技巧-我们将做相反的事情:用我们的逻辑电路替换EEPROM并将其放入编程器中。未使用的支脚通过电阻器接地。(如果您深入研究程序员的设置,则无法完成此操作) 现在,我们将以ROM形式读取逻辑图并获取一个表。我们用相同的编程器将其写入一个真正的EEPROM,而不是由单独的元件构成。







尾巴


尾巴的长度(在我们的限制内)为2至8个细胞。要存储此长度,可以使用带有帐户解析输入的常规计数器。实际上,它将是相同的有限状态机,其中新状态S'等于S + 1或仅等于S(如果帐户被禁止)。尾巴本身(或者说尾巴的生长方向)将存储在两个8位的寄存器中。从理论上讲,可以使用现成的移位寄存器(例如IR8),但由于暂不使用它们,因此使用了相同的IR27。在每个步骤中,当前磁头的移动方向都写入寄存器的第一位,第二个和下一个写入前一个的值。为了从中获得尾巴生长的方向,我们只需要反转一位即可。录制时您可以立即执行此操作,但我认为最好将其余电路取反。

方案


总的来说,我们的下一台机器采用以下形式:该图片(与其他所有人一样)都是可单击的。 从理论上讲,这是一个相当“纯粹”的部分。输出编码摩尔机的几乎完美的例子U1负责新方向,U2负责磁头的位置,这些位置存储在U5中。U3和U4用于尾部,其长度存储在U6中(并增加)。 接下来,我们将需要显示屏幕上的所有内容,并且还将有一个太空船,只是形式更脏。除了原始的随机数生成器之外,还包括具有不同时钟信号的电路与其他故障之间的过渡。







小计


希望本文引起您的兴趣,我将尽力快速完成第二部分。

并且,如果您已经陷入战斗,备有面包板,微电路和点屏,那么本文将附带ROM电路和固件文件。小型扰流板:要重复进行设计,您将需要大约6个原型,4个EEPROM 28C16和略多于2打的其他芯片。

好吧,应该是这样:喜欢,分享,转发,注册,按钟声等。。。))今天,感谢您的关注!未完待续…



使用ROM固件和通用的

UPD 方案存档:第二部分在此处提供

All Articles