注册
登录
新闻动态
其他科技
返回
Yamaha DX7 合成器巧妙的指数电路,逆向工程
作者:
糖果
发布时间:
2024-05-09 04:26:36 (4天前)
来源:
/reverse-engineering-yamaha-dx7_28.html
Yamaha DX7 数字合成器于 1983 年发布并变得非常流行,定义了 1980 年代流行音乐的声音。由于微处理器在 1980 年代初期不够快,DX7 使用了两个定制的数字芯片:EGS“包络”芯片生成频率和包络数据,并将其馈送到生成声音波形的 OPS“操作员”芯片。OPS芯片的关键部分是指数电路,用于频率计算和包络应用。在这篇博文中,我详细检查了这个由 ROM、移位器和其他电路实现的电路,并提取了 ROM 的数据。 我通过合成一百多张显微镜照片创建了下面的高分辨率模具照片。在边缘周围,您可以看到连接到焊盘的 64 条焊线;这些将硅芯片连接到芯片的 64 个引脚。芯片有一层金属,从顶部的白色线条可见。(电源和地线是粗金属线。)在金属下面,多晶硅布线层呈红色或绿色。最后,下面的硅是灰色的。我在之前的DX7文章中对芯片进行了整体讨论;现在我将专注于指数电路。 ![](/user/files/h8nqmDo2g7FUYxcdfK8hUMW1lDmxKHCuaYe2Bzaa7Ag.jpg) DX7 的 YM21280 Operator 芯片的模具照片。单击此照片(或任何其他照片)以获得放大版本。 DX7 是第一款在商业上取得成功的数字合成器。DX7 使用一种称为 FM 合成的技术以数字方式生成声音,而不是模拟合成器的模拟振荡器和滤波器。这个想法是你从一个正弦波(载波信号)开始,然后用另一个信号(调制信号)扰乱它。调制信号会改变载波的相位(进而改变频率),从而产生复杂的谐波结构。这些信号在整个系统中都表示为数字值;数模转换器 (DAC) 将数字表示转换为用于合成器输出的模拟电压。 频率调制的数字实现使用包含数字化正弦波的查找表。通过以特定速率在表格中步进索引,您可以产生固定频率的正弦波。通过用另一个信号扰动这个索引,你可以产生一个调制的正弦波。DX7 通过 ROM 中的正弦波表、控制频率的增量值以及在每个时间步长上将增量添加到表索引(即相位角)的加法器来实现这一点。DX7 有 96 个振荡器,因此它可以跟踪 96 个独立的相位角;这些存储在相位累加器中。频率调制由操作器电路实现,它允许振荡器干扰其他振荡器。(这是 FM 合成的一个非常简要的概述;请参阅我之前的有关更多详细信息,请参阅DX7 逆向工程文章。) #### 对数和指数 在硬件中,乘法比加法慢得多,尤其是使用 1980 年代的技术。DX7 中的解决方案是将值表示为以 2 为底的对数,因为对数相加等效于将值相乘。通过对总和应用 2 x,可以将对数值转换回线性值。 对数的第一个作用是输入到芯片的频率:提供给芯片的相位增量值是对数的。动机是音符频率呈指数相关:例如,增加一个八度音程会使频率增加一倍。通过使用对数,音符计算可以通过加法来完成。 其次,每个振荡器都有一个相关的包络,它根据时变曲线改变输出电平。1 要将信号乘以包络电平,正弦波信号和包络均以对数表示。因此,乘法被加法取代。(通过在波形 ROM 中存储 log 2 (sin(x)) 而不是 sin(x)可以方便地获得正弦波信号的对数,因此对数是“免费”获得的。) 下面的框图显示了指数电路的结构,该电路通过计算 2 x将对数值转换为线性值。指数电路有点复杂,无法将快速、高精度的指数计算放入芯片上的小空间。该电路采用由 4 位整数部分和 10 个小数位组成的 14 位输入值,因此对于 0≤x<16 ,它计算 2 x。2 该电路使用 ROM 查找和移位来快速计算值。 ![](/user/files/NA8nA2xiNK6jQj5DU6x0XF3vQwV5LLE7Ms-Upw6J9po.jpg) 求幂电路框图。输入位以绿色表示。 ROM 采用 10 位输入地址(0 到 1023),表示x值 0 到 1023/1024。一种称为增量编码的技术用于减小 ROM 的大小。delta 编码的思想是,如果值变化缓慢,则两个值之间的差异远小于值本身。3 具体来说,只有每四个值显式存储在 ROM 中;该值称为“绝对”值。7 接下来的三个值存储为增量,即该值与前一个绝对值之间的差值。增量适合 4 位4,比 11 位绝对值节省了相当多的费用。加法器电路将绝对值与差值相加,从而产生所需的指数值。 指数电路的最后一步是对来自 ROM 的值执行二进制移位。按输入整数部分中的位数进行移位会产生最终的指数值。6 在移位之前,先将 1 添加到 ROM 的值中,因此该位不占用 ROM 中的空间。5 芯片有两种求幂电路:一种用于计算频率,一种用于计算信号(正弦和包络路径)。两者的大部分电路是相同的,但频率指数产生 22 位输出,而信号指数只有 14 位输出。 #### 仔细观察模具 下图标记了芯片的引脚和主要功能块。在本文中,我将重点介绍以红色突出显示的两个指数电路,但我将总结其他块。用移位寄存器实现的 96 个相位累加器是芯片的最大块。ROM 保存正弦波函数和指数函数。(有两个相同的指数 ROM,带有相关的加法器和移位器电路。)其他主要模块应用包络、保存配置数据、计算组合振荡器的运算符、定义不同的运算符算法以及缓冲输出值。 ![](/user/files/BHU1ES555PFyh4etm9U70t_YXjbkSEHG7VmsJkooSf8.jpg) 贴上主要功能块的标签。这张照片显示了芯片的金属层。(点击查看更大的版本。) #### 晶体管 为了解释裸片照片,我将首先展示如何在 NMOS 集成电路中构建晶体管(下图)。硅的区域掺杂有杂质以创建具有所需特性的扩散区域。晶体管可以看作是一个开关,允许电流在称为源极和漏极的两个扩散区域之间流动。晶体管由栅极控制,栅极由一种称为多晶硅的特殊硅制成。栅极上的高电压允许电流在源极和漏极之间流动,而低电压阻止电流流动。这些微小的晶体管组合起来形成逻辑门和其他电路。 ![](/user/files/mmWF6qzcNnDqDtFsZm6emQErlbfWp92bLbfc54wVFW0.jpg) 在集成电路中实现的 NMOS 晶体管 (MOSFET) 的结构。 为了使晶体管更加可见,我从芯片上去除了金属层,从而得到了下面的高分辨率芯片照片。(颜色是由于我的蚀刻工艺导致氧化层厚度的变化。) ![](/user/files/f87YZEt3TwKvVYO2cssUfIf42PgWoJ6dpSbMoIqVL_A.jpg) 去除金属层的 DX7 的 YM21280 操作员芯片的芯片照片。单击此照片(或任何其他照片)以获得放大版本。 #### 只读存储器 下图显示了指数 ROM 之一。ROM 由晶体管网格构成:128 行 x 32 列。8 在每个网格点,可以存在一个晶体管,代表一个位;或者可以不存在晶体管,代表 0 位。9 在顶部,解码器根据地址的 5 位激活 ROM 中 32 条垂直选择线之一。ROM 被排列成 8 行(或更少,取决于压缩)的组。多路复用器根据地址的三位选择每组中的一位。这会产生一个 20 位的输出。最后,输出逻辑根据地址产生所需的增量值。结果是 11 位绝对值和 4 位增量值。 ![](/user/files/Roeq2iIOGiM9VWAuKC1ncHWWalPDrJmIG_UjyChrkTI.jpg) 标有主要组件的 ROM。 放大 ROM 会显示各个晶体管。大的苍白区域是掺杂的硅,形成晶体管源极和漏极。多晶硅选择线是垂直的。当多晶硅线穿过掺杂硅区时形成晶体管。指示的硅区域接地,将每个晶体管的一侧拉低。圆圈是硅和上面的金属线之间称为通孔的连接。(金属线已被移除,但水平波浪线显示了金属所在的位置。) ![](/user/files/57epsC2KF0LVvW0SeFwjXho-df31woaOhLXJB108LsA.jpg) ROM 的 4×4 部分特写,显示其结构。 每个位通过网格位置处是否存在晶体管来存储在 ROM 中。(在制造过程中,硅掺杂模式控制晶体管是否存在。)当 32 条选择线中的一条被激活时,该列中的所有晶体管将打开,将相应的输出线拉低。但如果缺少晶体管,相应的输出线将保持高电平。因此,通过激活选择线从 ROM 读取值,将 ROM 值读到输出线上。通过查看 ROM 中的硅图案,我确定了存储在 ROM 中的 1 和 0 序列,总共 4 KB。 #### 多路复用器 在应用增量处理之前,ROM 有 256 个 20 位条目。为了使布局更有效,ROM 以 8 位为一组存储位,(概念上)为每个输出位组织为 8 行,每行 32 个条目(列)。每个输出位都有一个多路复用器,它根据控制 8 条多路复用器选择线的另外 3 条地址线来选择组中的 8 位之一。 ![](/user/files/6oLq7rQjKY-CM6g-rVAIHDPdl9u5phCaMq-c9v_XgYM.jpg) ROM 中的多路复用器。 每个多路复用器(上图)由 8 个传输晶体管实现。一个晶体管被激活,让该行的位通过,而未选择的行被阻止。多路复用器的输出进入左侧的逻辑电路。 仔细观察裸片照片会发现一些多路复用器没有全部八行。这是减少 ROM 大小的关键优化。如果一行中的所有位都为 0,则该行可以从 ROM 中完全消除。10 #### delta 逻辑和加法器 ROM 产生 20 个输出位,11 位用于“绝对”值,9 位用于三个增量值。一些逻辑电路利用增量中的某些结构将 ROM 的 9 位扩展为三个四位增量。11 要获得2 x -1值,必须将 11 位绝对值和 4 位增量相加。这是通过 ROM 左侧的加法器电路实现的。加法器的一个有趣特性是它被流水线化以最小化进位传播的延迟。加法器在上一篇文章中讨论过,这里不再赘述。 #### 位移位器 我将讨论的最后一个构建块是位移位器,它实现了指数计算的整数部分。它将值向左移动 0 到 15 位,相当于乘以 2 的幂。移位器分为两层:底层移动 0、1、2 或 3 个位置。上层移动 0、4、8 或 12 个位置。两层的组合允许在 0 和 15 位位置之间进行任何移位。两层之间的接线将输出从第一层分配到第二层。每个输出进入四个输入,每个输入间隔 4 位以提供更大的移位。 ![](/user/files/moElGG0dSVolK63ICYMIFL04g8VLOvLng6MPL9r4brI.jpg) 移位器电路。 下图显示了移位器的一部分,该部分移位 0、1、2 或 3 个位置,由水平线控制。移位器由多路复用器构成,类似于 ROM 中的多路复用器,可选择四个输入之一。我用绿色突出显示了其中的一位。如果“shift 0”线被激活,最右边的绿色晶体管(圆圈)将打开,绿色输入位将从最右边的输出退出。同样,如果“shift 1”线被激活,第二个绿色晶体管将打开,绿色位将退出向左移动一个位置。“shift 2”和“shift 3”线将导致绿色位向左移动两个或三个位置。其余的晶体管(黑色圆圈)以相同的方式移动其他位。结果是所有位都将移位 0、1、2 或 3 个位置。第二个移位器类似,不同之处在于输入线连接到相距四个位置的多路复用器。 ![](/user/files/EgE8vdKqpt0PqHN6bCleHkgvo1OjaSrJvnNmjlz53GQ.jpg) 移位器电路的细节。 #### 结论 计算指数是 DX7 声音合成的关键部分。该芯片需要非常快速地计算指数,比 CORDIC 等算法可以运行的速度更快,但简单的 ROM 会太大。该芯片通过使用增量编码、ROM 压缩和移位器电路解决了这一难题。这些技术将 ROM 大小减少了近 64%。12 通过仔细检查电路,我对生成的确切值进行了逆向工程。通过使用这些值,DX7 模拟器可能能够获得更高的精度。 ![](/user/files/PaoP5c3TeYdwdIr0-uq5JRPcRn3C0BaFpw8KPXCRMjg.jpg) DX7 的 OPS 芯片采用 64 针陶瓷封装,针脚交错。这称为四列直插封装 (QIP)。 下一步是对芯片的正弦波ROM进行逆向工程,实现log-sin功能。例如,该 ROM 使用许多与指数 ROM 相同的技术,但存储增量的方式不同。我在 Twitter 上发布了我的最新博客文章,所以请关注我@kenshirriff以获取更新。我也有一个RSS 提要。如果您对 ROM 数据感兴趣,我还写了关于从8087 浮点芯片中提取常量的文章。 感谢 Jacques Mattheij 和 Anthony Richardson 提供芯片和讨论。14 #### 注释和参考 对于输出信号,包络赋予音符更真实的声音;典型的声音在第一次播放时具有尖锐的起音,然后音量衰减。该级别一直持续到松开按键,然后迅速消失。然而,DX7 也将包络应用于调制信号,允许音符的音色随时间变化。 ↩ 求幂电路的准确值如下所示。假设 14 位输入值是int.frac,其中int是 4 位整数部分,frac是 10 位小数部分。来自 ROM 的 12 位输出值,在增量加法器和附加前导 1 位之后,正好由round(2 frac ×2048) 给出。移位器应用 0 到 15 位的左移,然后将结果截断为 22 位或 14 位,分别用于频率和信号求幂。最终结果是 圆的(2压裂×2048)<< INT >> 5,和 轮(2压裂×2048)<< INT >> 13分别 (其中 << 和 >> 是位移运算符)。 在这两种情况下,当输入具有最大整数部分(即 15)时,固定 1 位于输出的最左侧位置。(这是必要的,因为否则该值将被截断,或者最左边的位将不被使用。)然而,输入整数部分为 0,频率电路仍然有 7 位输出,而包络电路产生值 0 (因为所有的位都在移位中丢失了)。 ↩ 另一种芯片 Yamaha YMF262 (1988) 用于计算机声卡,例如 Sound Blaster 16。(该芯片也称为FM Operator Type-L 的OPL3。)它使用 FM 合成,但与DX-7。该芯片由 Matthew Gambrell 和 Olli Niemitalo进行逆向工程,他们对芯片进行了解封并读出了 ROM 内容。 OPL3 指数 ROM 在某些方面与 DX7 相似,但也有很大不同。OPL3 芯片的长度为 256 个样本,而不是 1024 个,并且保存 10 位值,而不是 12 位值。两种芯片都使用 delta 编码,但 OPL3 对每个绝对值都有一个 delta 编码值,而 DX7 有三个 delta 编码值。 ↩ 下图显示了小数范围内的指数函数 2 x。连续元素之间的差异相当小,因此 4 位增量值就足够了。存储 4 位差值而不是 11 位绝对值可以节省大量空间。 ![](/user/files/_srlxC7Tuv7IN0lgEn4T8sVvykiO1nOkNwqDzTKAV2w.jpg) 小数范围内的 2 x图表。 由于指数函数是凸的,因此指数表中最大的delta在右边,具体为(2 1023/1024 -2 1020/1024 )×2048 ≈ 8.3。增量几乎适合三位,但需要四位。 ↩ ROM 存储 2 x -1 而不是 2 x,因为所有值都有一个前导值。具体来说,对于 0≤x<1,1≤2 x <2。将 1 添加到 ROM 的输出而不是将其显式存储在 ROM 中会减小 ROM 的大小。 在数学上,如果输入值被拆分为整数和小数部分:int+frac,则 2 int+frac = 2 int ×2 frac。乘以 2 int与执行二进制向左移位int位相同。 ↩ delta 编码中的绝对值是完整的、显式的值。它与绝对值函数|x| 无关。 ↩ 芯片上的两个指数 ROM 是相同的,只是一个是水平的,一个是垂直的。这使得行和列的引用有点不明确;希望这一切都有意义。 ↩ ROM 中的晶体管是代表 1 还是 0 有点随意,因为信号在使用前会反转几次。晶体管会导致 ROM 的那条线被拉低,因此在基本级别上,晶体管代表 0。但是,在指数 ROM 中,该值立即反转,因此晶体管在最终结果中代表 1 位。 ↩ ROM 分两个阶段运行,由时钟控制。在第一阶段,行和多路复用器都被拉高。在第二阶段,激活所需的 ROM 列。如果有晶体管,它们会将行拉低。通过选定的多路复用器晶体管,这会将多路复用器拉低。然后多路复用器输出被反转,所以有晶体管的位置代表逻辑1,没有晶体管代表逻辑0。在这个电路中,如果完全省略一行和多路复用器晶体管,多路复用器将保持其高预充电值,代表逻辑0。因此,可以消除ROM中所有为0的行,从而节省空间。 ↩ 下面的示意图显示了生成绝对数据和增量的逻辑实现。11 个绝对数据位简单地采用相应的多路复用器输出并将其反转。每个多路复用器还有一个晶体管,可在时钟相位 1 上将其预充电至 +5。(增量多路复用器也有预充电晶体管,但我在原理图中省略了它们以避免混乱。) ![](/user/files/gkDOxtEMyTqR6nN_ZMg9eEWBlSiqoQID_6p_zpxU3HM.jpg) 逻辑电路图。 增量位逻辑实现四种不同的情况。条目 0 为绝对值提供 0 的增量值。后面跟着三个条目,用于存储为增量的值。(在所有四种情况下,该值都是通过将绝对值和增量相加来计算的。)两个低位地址位选择条目。如果 ROM 中的 9 位标记为 AI,则连续的 4 位增量条目为 0000(“绝对”值没有增量)、00AB、0CDE、FGHI。三个条目使用地址的最高位(位 9)在一半的范围内强制增量位为 1。这是另一种优化,因此这些区域不需要存储在 ROM 中。 ↩ 指数电路采用 14 位输入并产生 22 位输出。将所有这些值保存在 ROM 中将占用超过 360 KB,这在 1980 年代是不切实际的。移位器的使用将存储要求显着降低到 1024 个 11 位值 (11 Kb)。ROM 压缩技术将其减少到仅 4 KB,几乎减少了 64%。在本节中,我分解了 ROM 压缩的实现方式。 大部分节省来自增量编码,它使用 256 个 11 位“绝对”值和 768 个 4 位增量值。这将存储减少到大约 5.9 Kb,节省了大约 48%。其余的节省来自通过各种技术消除 ROM 中的行。ROM 的结构为 32 位行。未压缩,ROM 将需要 184 行。但是,如果一行中的值都为 0,由于多路复用器的构造,该行可以完全省略。13 由于指数曲线增长缓慢,对于大拉伸,绝对值的最高位为 0,因此可以消除许多行。具体而言,对于 8 行中的 4 行,最高位为零,对于 8 行中的 3 行,下一位为零,对于 1 行,下一位为零。这样,绝对值存储可以省去8行。 增量位在大部分时间也是零。第一个增量的前两位始终为 0,第二个增量的最高位也是如此。这由逻辑电路处理,消除了 24 行 ROM。从有时为零的增量位中消除了另外 12 个零行。最后,逻辑电路在它们始终为 1 的半间隔内强制 3 个增量位为 1,从而无需再增加 12 行。 总而言之,零行消除从绝对值数据中节省了 8 行,从增量数据中节省了 36 行。通过强制位为 1,另外 12 行被保存。这将 ROM 从潜在的 188 行减少到它所拥有的 128 行,缩小了近 32%。 从概念上讲,ROM 中的行可以被视为带有上拉电阻的 NOR 门。但是,实现方式略有不同:行在一个时钟阶段预充电至 +5,然后通过晶体管放电(或不放电)接地。与常规 NMOS 上拉相比,这降低了功耗。(现代电路使用 CMOS 而不是 NMOS,以避免上拉的静态功耗。) ![](/user/files/YHy1lqbogyx3u04esGgmcIDk-TLgw6QNunKEhOVWe7c.jpg) ROM 及其预充电电路。这有点难以解释。行线是金属的,右边的地线也是金属。其他地线和预充电线是硅材料的。时钟和列选择线(未标记)是多晶硅。 另一个优化是 ROM 中全为 1 的行省略了晶体管,并且输出线直接接地。这会略微降低功耗,因为该行线不会充电和放电。但是,它不会节省任何空间,因为该行实际上仍然存在。(相反,全为 0 的行被完全省略。) 有关 DX7 内部结构的更多信息,请参阅 DX7 技术分析、 DX7 硬件、 OPLx 解封和我之前的 DX7 文章从芯片照片对 Yamaha DX7 合成器的声音芯片进行逆向工程。
收藏
举报
1 条回复
动动手指,沙发就是你的了!
登录
后才能参与评论