bcrist/re4k

GitHub: bcrist/re4k

逆向工程 Lattice ispMach4000 CPLD 的熔丝映射,提供 S 表达式格式的配置数据以便开发自定义编程库。

Stars: 7 | Forks: 2

# Lattice ispMach4000 CPLD 的 Fusemaps 本代码库包含 Lattice 大多数常用 LC4k CPLD 的逆向工程 Fusemap。 数据以文本文件形式提供,包含机器和人类可读的 S 表达式,描述了控制每个功能的熔丝位置。 这些旨在用于生成库,以便可以使用所需的任何编程语言创建 CPLD 配置。 现有库包括: * Zig: [Zig-LC4k](https://github.com/bcrist/Zig-LC4k) * VHDL: [LC4K Core](https://github.com/devsaurus/lc4k_core) 如果您为另一种语言构建了库/绑定,请告诉我,以便我将其列在此处! ## 设备列表 | |TQFP44|TQFP48|TQFP100|TQFP128|TQFP144|csBGA56|csBGA64|csBGA132|csBGA144|ucBGA64|ucBGA132| |:-----------|:----:|:----:|:-----:|:-----:|:-----:|:-----:|:-----:|:------:|:------:|:-----:|:------:| |LC4032V/B/C | ✔️ | ✔️ | | | | | | | | | | |LC4032ZC | | ✔️ | | | | ✔️ | | | | | | |LC4032ZE | | ✔️ | | | | | ✔️ | | | | | |LC4064V/B/C | ✔️ | ✔️ | ✔️ | | | | | | | | | |LC4064ZC | | ✔️ | ✔️ | | | ✔️ | | ✔️ | | | | |LC4064ZE | | ✔️ | ✔️ | | | | ✔️ | | ✔️ | ✔️ | | |LC4128V | | | ✔️ | ✔️ | ✔️ | | | | | | | |LC4128B/C | | | ✔️ | ✔️ | | | | | | | | |LC4128ZC | | | ✔️ | | | | | ✔️ | | | | |LC4128ZE | | | ✔️ | | ✔️ | | | | ✔️ | | ✔️ | 目前不支持 LC4256 及更大型的设备。 汽车级(LA4xxx)变体可能使用与其 LC 对应产品相同的 Fusemap,但这只是推测。 请不要将此项目用于任何汽车或其他安全关键型应用。 ## 简介 如果您还没有阅读过 Lattice 数据手册,请先阅读您的设备的相关内容。 通常,我尽量使用与数据手册中相同的术语。 如果您不确定某个首字母缩略词或术语的含义,也可以参考本文档末尾的词汇表。 您可以在 `schematics` 目录中找到显示每种设备结构的 PDF 和 KiCAD 格式原理图。 ## 通用 Fusemap 布局 所有 LC4k 设备都将熔丝逻辑布局为 2D 网格,具有 100 或 95 行, 以及可变数量的列,具体取决于设备中 GLB 的数量。 JEDEC 文件逐行列出这些熔丝, 并且当通过 JTAG 对设备进行编程时,每一行都在单独的 SDR 事务中交付。 每个 GLB 使用至少 86 列的一块, 并且 GLB 并排放置, 但是它们通常不是从左到右排序的 (GLB "A" 的块不一定在 GLB "B" 的块的左侧)。 前 72 行包含 PT 和 GI 路由熔丝。 Fusemap 的这一部分是密集封装的; 每个逻辑熔丝都对应一位 FLASH 存储器并控制设备的行为。 其余行具有多种用途,并且是稀疏封装的; 大多数位实际上并不对应 FLASH 存储单元,并且总是读为 `1`,即使在尝试将其编程为 `0` 之后也是如此。 通常,每个宏单元切片对应单列,包含配置该宏单元切片的熔丝。 这些列按两个一组排列,通常有 8 个大部分未使用的列将每对隔开。 只有 95 行的设备每对宏单元只有一个 I/O 单元。 与其将所有 I/O 单元配置熔丝放在同一列中, 不如将一半的熔丝移到相邻宏单元的列中, 从而减少所需的总行数。 每个 GLB 都有一些块配置位,放置在宏单元切片列的左侧和右侧的“边框”中。 这包括用于配置块时钟源/极性、共享 PT 极性、将共享 PT 使能路由到 GOE 总线等的熔丝。 最后,全局配置通常放置在某个 GLB 区域右边缘的一个模糊的环形小结构中。 这包括仅输入引脚、GOE 极性和振荡器/定时器(在 ZE 设备中)的配置。 ## S 表达式文件 每个设备的逆向工程 Fusemap 由 `LC4xxx/LC4xxx*_*/.sx` 中的一组 S 表达式文件组成。 还有一个合并文件 `LC4xxx/LC4xxx*_*.sx`,其中包含所有单个文件的数据。 每个特定文件中数据的含义在下面进行了解释。 如果在阅读相应部分后,任何文件的语法仍然让您感到困惑, 请提出 issue,以便我尝试更好地记录它。 ### `grp.sx` (global_routing_pool) 每个 GLB 有 36 个 GI “槽”,它们(连同其补码)用作该 GLB 中乘积项的输入。 每个 GI 可以从全局路由池中的一组固定信号中选择。 选项对于 GLB 中的每个 GI “槽”是不同的, 但设备中的每个 GLB 对同一个 GI 槽使用相同的选项。 每个槽的选项数量取决于设备类型 (具有更多 GLB 的设备具有更多的 GRP 信号, 因此为了使每个信号有多种可能的路由, 每个 GLB 必须具有更多可能的选项)。 对于具有偶数个 GI 选项的设备, 选项熔丝存储在 GLB 块的最左侧, 使用 `N/2` 列(其中 `N` 是选项数量)。 这里使用“独冷”(one-cold)编码;即,每个选项有一个熔丝, 并且每个 GI 只应有一个熔丝被编程为 0。 对于具有奇数个 GI 选项的设备,GLB 被组织成对, 并且每对共享相同的 GI 路由熔丝列。第一行包含用于其中一个 GLB 的熔丝, 第二行包含用于另一个 GLB 的熔丝。 ### `pterms.sx` (product_terms) 在前 72 行内,每列 (上面用于 GI 路由的列除外) 代表单个乘积项。 每两行对应一个 GI 槽, 第一行代表非反相 GI 信号, 第二行代表同一信号的反相版本。 将乘积项内的熔丝编程为 0 意味着相应的信号必须被断言, 乘积项才能输出 `true`。 另一种思考方式是,熔丝值与信号进行“或”运算,结果 传入乘积项的“与”门。 因此,如果没有 PT 熔丝设置为 0,PT 将始终产生 `true`。 如果任何 GI 的两个熔丝都设置为 0,PT 将始终产生 `false`。 当 lpf4k fitter 想要使 PT 为 `false` 时, 它将前十几行左右的所有熔丝设置为 0。 目前尚不清楚为什么他们选择只设置那些。 可能仅将一对设置为 0 可能会产生静态冒险, 如果映射到该槽的 GI 发生变化的话。 但在这种情况下,将所有 GI 对设置为零不是最好的吗? 在测试中,这似乎按预期工作, 所以我建议这样做。 我最好的猜测是,这可能是旧设备系列的遗留物, 那些设备使用灵敏放大器而不是全 CMOS 逻辑。 将所有熔丝设置为 0 可能会导致此类设备的功耗更高。 乘积项被分成 5 个一组, 每个集群与一个宏单元相关联。 此外,每个 GLB 有 3 个额外的乘积项, 可用于特定目的, 但在 GLB 中的所有宏单元之间共享。 这些 PT 始终位于 GLB 块的最后 3 列中。 ### `cluster_routing.sx` (cluster_routing) 每个乘积项可以选择用于与该宏单元相关的特殊目的(见下文), 或者可以将它们相加(“或”运算)并馈入宏单元的逻辑输入。 由于简化为积之和的逻辑方程通常需要超过 5 个乘积项, 因此集群可以保留其和, 或者可以将其“捐赠”给多达三个附近的宏单元之一。 然后,每个集群根据路由到该集群的任何中间和创建第二个和。 即使集群没有“保留”自己的原始和,它也可以接收“捐赠”(或多个)。 因此,第二个和可以代表多达 20 个乘积项,所有这些都具有恒定的传播延迟。 某些特定集群的最大 PT 数 < 20: * MC 0 的集群只能接收来自集群 1 或集群 2 的和,因此包括其自身在内,最大有 15 个 PT。 * MC 14 的集群只能接收来自集群 13 或集群 15 的和,因此包括其自身在内,最大有 15 个 PT。 * MC 15 的集群只能接收来自集群 14 的和,因此包括其自身在内,最大有 10 个 PT。 集群和只能路由到一个其他集群; 它不能被复制并发送到多个相邻集群。 ### `wide_routing.sx` (wide_routing) 在需要非常大量乘积项但输出很少的情况下, 上述第二个和的输出可以重定向到索引为 `(N+4)%16` 的集群 (其中 `N` 是当前集群索引)。 这在数据手册中被称为“SuperWIDE(tm)”引导逻辑。 请注意,这与 `cluster_routing` 在几个方面不同: * 它“回绕”,因此集群 15 可以路由到集群 3。 * 它可以“链接”,使得 GLB 中的任何宏单元都可以潜在地使用每个 PT 集群,如果 GLB 中的其他 MC 不需要集群的话。 * 使用此功能会增加最大传播延迟(但不相等;经过宽路由的 PT 将比最终集群的 20-PT 组中的 PT 慢)。 当宏单元的集群路由到另一个集群时, 宏单元会看到恒定的低电平(假)值作为其逻辑输入。 ### `input_bypass.sx` (macrocell_data) 宏单元寄存器的数据/切换输入可以配置为直接来自宏单元的输入焊盘, 而不必通过 GRP、PT、集群路由等传输。 这减少了最小建立时间。 从技术上讲,当宏单元配置为组合逻辑时,也可以使用此功能, 但这样做没有太大意义, 因为这只会使宏单元反馈信号与输入缓冲器信号相同。 您可以使用 ORM 偏移来创建三态线路驱动器,其中输入和输出都是引脚, 并且 OE 信号由 CPLD 逻辑控制。 这将产生跨越线路驱动器的尽可能快的传播延迟, 但如果传播延迟如此关键, 您最好只输出 OE 信号并使用外部三态缓冲器或总线开关。 ### `zerohold.sx` (zero_hold_time) 当宏单元配置为输入寄存器时, 可以添加额外的延迟以将最小保持时间降至 0。 这也意味着建立时间增加。 这由影响整个芯片的单个熔丝控制。 数据来自乘积项逻辑的寄存器不受此熔丝影响, 因为内部传播延迟意味着无论如何都不需要保持时间。 ### `pt0_xor.sx` (pt0_xor) 每个宏单元包含一个 XOR 门。 XOR 门的输出通往宏单元寄存器的数据/切换输入, 并可选地通往宏单元反馈/ORM 输入(当 MC 处于组合模式时)。 XOR 门的输入之一始终是来自 PT 集群路由器的逻辑输入。 XOR 门的第二个输入可以是恒定值, 或者是宏单元第一个乘积项 PT0 的结果。 当它源自 PT0 时,该乘积项将从其集群和中移除。 当 PT0 未重定向时,逻辑 0 被馈送到 XOR(可选反相;见下文)。 请注意,数据手册的宏单元原理图(图 5) 描述了输入寄存器 MUX 馈送到 XOR 输入之一, 但是在测试真实设备时, 我们看到当 `input_register` 熔丝被清除时,XOR 门完全被旁路。 这意味着输入寄存器 MUX 实际上位于 XOR 输出之后。 这是有道理的,因为输入寄存器的想法是使建立时间尽可能短。 ### `invert.sx` (invert) XOR 门的第二个输入可以使用此熔丝进行反相。 当源自 PT0 时,这意味着 PT0 可以被视为 36 输入“或”门 而不是 36 输入“与”门(通过德摩根变换; 当然,您也必须使用每个 PT0 输入的补码)。 当启用反相器但 XOR 不是 PT0 时, 第二个 XOR 输入变为恒定高电平, 因此来自 PT 集群路由器的逻辑和被反相。 同样,一种思考方式是您可以将宏单元用作“和之积” 而不是“积之和”。 ### `mc_func.sx` (macrocell_function) 每个宏单元可以实现四种基本电路之一: * 纯组合逻辑 * 透明锁存器 * D 触发器 * T 触发器 后 3 种都充当单比特存储元件, 因此具有一些与组合宏单元无关的额外配置: * 时钟源 * 时钟使能源 * 上电初始化 * 异步置位/复位 这些功能描述如下。 ### `clock_source.sx` (clock_source) 当宏单元用作寄存器时, 它需要一个时钟信号,可以是以下八个选项之一: * 四个块时钟信号(见下文) * GLB 的共享时钟 PT * 宏单元的 PT1 * 宏单元的 PT1,反相 * 恒定低电平/假 当它源自 PT1 时,该乘积项将从其集群和中移除。 当宏单元配置为 D 或 T 触发器时,时钟在上升沿触发。 如果源可以反相,它实际上会翻转以在下降沿触发。 当配置为锁存器时,当时钟信号为高时它将是透明的, 当时钟信号为低时它将被锁存。 ### `bclk_polarity.sx` (bclk_polarity) 四个 BCLK 时钟选择选项来自专用输入引脚 (通常是四个,但某些设备只有两个)。 使用这些避免了使用宏单元 PT 或 GLB 的共享时钟 PT 作为时钟的需要。 这些时钟的极性可以为每个 GLB 独立配置。 它以固定对进行配置, 其中每个 BCLK 可以是其中一个时钟的非反相版本, 或是另一个时钟的反相版本。 因此,您可以两个时钟都非反相,两个时钟都反相, 或者任一时钟的互补对。 ### `ce_source.sx` (clock_enable_source) 时钟使能在为高时禁止寄存器内容的更新。 当宏单元配置为组合逻辑时,它无效。 对于透明锁存器,它的作用实际上就像时钟与 CE 进行“与”运算一样; 只要两者都为高,锁存器就处于透明模式; 如果任一变低,它锁存当前值。 对于 D 和 T 触发器,这意味着只要 CE 在触发沿期间为低, 该周期就不会发生变化。 这与简单地将 CE 与时钟信号进行“与”运算不同; CE 不需要在整个时钟为高期间保持低电平。 CE 信号有四种可能的来源: * 宏单元的 PT2 * 宏单元的 PT2,反相 * GLB 的共享时钟 PT * 恒定高电平/真 共享时钟 PT 与用作时钟选项的 PT 相同, 并且在 GLB 内,同一个 PT 可以用作某些 MC 的时钟和其他 MC 的 CE。 当它源自 PT2 时,该乘积项将从其集群和中移除。 请注意,PT2 也可用于异步置位/复位信号(见下文)。 ### `shared_pt_clk_polarity.sx` (shared_pt_clk_polarity) 每个 GLB 的共享时钟 PT 可以选择反相。 这会影响 GLB 内的所有使用,既作为时钟也作为时钟使能。 ### `init_state.sx` (init_state) 当宏单元配置为寄存器时, 其上电时的初始状态可以配置。 可以为每个宏单元独立选择此配置。 ### `init_source.sx` (init_source) 当宏单元配置为寄存器时, 信号可用于将寄存器异步置位或复位为其上电状态。 当此信号保持为高时,宏单元被强制进入其上电状态。 此信号的来源只有两个选项: * 宏单元的 PT3 * GLB 的共享 init PT 这意味着如果 GLB 的共享 init PT 不是恒定假, 该 GLB 中任何不想使用复位信号的寄存器必须使用 PT3 作为恒定假。 如果 PT3 用作源,该乘积项将从其集群和中移除。 ### `shared_pt_init_polarity.sx` (shared_pt_init_polarity) 每个 GLB 的共享初始化 PT 可以选择反相。 ### `async_source.sx` (async_source) 可选的第二个异步置位/复位信号可以源自 PT2。 当信号保持为高时,宏单元被强制进入其上电状态的补码状态。 还要注意,PT2 也可以用作 CE 信号的来源, 虽然可以同时将其用于两者, 但通常您无法为两者使用相同的 PT 逻辑, 因此通常您会将其用于其中一个。 当 PT2 用作异步置位/复位时,该乘积项将从其集群和中移除。 ### `pt4_oe.sx` (pt4_output_enable) 当此熔丝被编程时, PT4 从宏单元的集群和中移除, 并改为路由到 ORM。 从那里,它可以选择作为此宏单元输出的输出使能信号, 或某些附近宏单元的输出使能信号(见下文)。 未使用时,呈现给 ORM 的 OE 信号为恒定假。 ### `output_routing.sx` (output_routing) 通常,宏单元切片的 I/O 单元将输出由其相应宏单元产生的信号, 但是有一个内置的“输出路由多路复用器”(ORM), 允许进行有限的重定向,以获取来自宏单元偏移量高达 +7 的输出信号。 请注意,此偏移量也会回绕,因此 MC 15 的 I/O 也可以从 MC 0-6 中选择。 PT4 OE 信号(如果使用)也是来自同一个 MC。 ### `output_routing_mode.sx` (output_routing_mode) 对于非 ZE 系列设备,ORM 可以被旁路,这会略微减少输出延迟。 此外,如果只需要组合逻辑输出, 则可以旁路整个宏单元逻辑块, 最多 5 个 PT。 有几个可用的选项: * 输出由 ORM 选择的正常信号 * 旁路 ORM 并始终输出此宏单元的反馈信号,无论 ORM 配置如何 * 输出此集群的 5-PT 和 * 输出此集群的 5-PT 和,反相 这些选项均不影响 PT4 OE 信号的路由; 它始终通过 ORM 路由。 当使用 5-PT 和选项之一时, PT 集群仍使用正常的集群路由规则进行路由, 这与单个 PT 重定向用于特殊用途时不同。 仍然可以使用掩埋式宏单元, 但您必须小心隔离原始的 5-PT 集群和,例如 * 将其路由到另一个集群 * 路由另一个始终为真的集群并使用 PT0 作为单个 PT 宏单元 * 使用掩埋式宏单元作为输入寄存器 ### `oe_source.sx` (output_enable_source) 每个 I/O 单元的输出驱动器在其输出使能信号为高时有效。 OE 信号可以从 8 个来源之一中选择: * 4 个全局输出使能之一 * 来自 ORM 的 PT4 输出使能信号 * 来自 ORM 的 PT4 输出使能信号,反相 * 恒定高电平(仅输出) * 恒定低电平(仅输入) ### `goes.sx` (goe_polarity) 所有设备都有 4 个全局 OE 信号。 这些信号的极性可以全局配置, 它们的来源取决于设备。 LC4032 设备的来源: * GOE0: 共享 PT OE 总线位 0 * GOE1: 共享 PT OE 总线位 1 * GOE2: A0 输入缓冲器 * GOE3: B15 输入缓冲器 其他设备的来源: * GOE0: 可选;共享 PT OE 总线位 0,或数据手册中注明的特定输入缓冲器 * GOE1: 可选;共享 PT OE 总线位 1,或数据手册中注明的特定输入缓冲器 * GOE2: 共享 PT OE 总线位 2 * GOE3: 共享 PT OE 总线位 3 ### `goes.sx` (shared_pt_oe_bus) 共享 PT OE 总线是一组 2 或 4 个全局信号(取决于设备类型,如上所述), 其中每个位可以连接到任何 GLB 的共享使能 PT (注意这与 ZE 设备上的 power guard 功能共享)。 如果多个 GLB 配置为驱动同一条 PT OE 总线, 它的行为将如同仅使用第一个(编号最低的)GLB 一样。 如果在这种情况下它们对 PT 求和本来会很方便, 但遗憾的是,出于某种原因它们没有这样做。 如果没有 GLB 配置为驱动 PT OE 总线, 它被拉高(如果极性熔丝为 1)或拉低(如果极性熔丝为 0)。 不过这真的没有理由利用这一点,因为每个输出单元都可以 配置为“始终输出”或“始终高阻抗”,而无需使用任何 GOE 信号。 ### `drive.sx` (drive_type) 每个输出一个熔丝控制输出是开漏还是推挽。 开漏也可以通过输出恒定低电平并使用 OE 来启用或禁用它来模拟, 但这对宏单元中可完成的逻辑量有很大限制; 只有单个 PT 可以路由到 OE 信号。 ### `slew.sx` (slew_rate) 每个输出一个熔丝控制该驱动器的压摆率。 根据数据手册, 使用慢压摆率会使输出缓冲器传播延迟增加大约 1ns, 这意味着上升和下降时间可能是正常情况的两倍左右。 ### `threshold.sx` (input_threshold) Lattice fitter 允许从大约半打选项中选择每个输入信号的电压标准,包括: * 1.8V LVCMOS * 2.5V LVCMOS * 3.3V LVCMOS * 3.3V LVTTL (5V 耐受) * 3.3V PCI (5V 耐受) 数据手册和 IBIS 模型对设备中使用的实际输入结构相当含糊, 但事实证明此配置仅影响每个输入的一个熔丝, 因此看来该熔丝选择高或低输入转换阈值。 一般来说,高阈值适用于 2.5V 或 3.3V 信号, 低阈值适用于 1.8V 或 1.5V 信号。 此外,数据手册提到仅当 VCCO 为 3.3V 时输入才耐受 5V, 因此保护二极管可能钳位到该电源轨而不是 VCC。 以下主要是基于数据手册中发布的限制对实际 Vth 的猜测, 并假设阈值始终以 VCC 为参考, 而不是使用 VCCO 或内部固定电压参考。 | Vth | `-V` | `-B` | `-C`/`-ZC` | `-ZE` | |:---------------|:-------------------------:|:-------------------------:|:---------------------------:|:------------------------:| | low | 0.28×VCC | 0.36×VCC | 0.5×VCC | 0.5×VCC | | high | 0.4×VCC | 0.5×VCC | 0.73×VCC | 0.68×VCC (下降沿)
0.79×VCC (上升沿) | ### `bus_maintenance.sx` (bus_maintenance) 2 个熔丝允许选择四种输入端接选项之一: * 上拉 * 下拉 * 总线保持 * 浮动/high-Z 在 ZE 系列设备中,可以为每个输入引脚单独配置此项。 在其他系列中,只有一组熔丝适用于整个设备。 ### `bus_maintenance.sx` (bus_maintenance_extra) 在某些非 ZE 设备上, 将总线维护设置为浮动会导致 fitter 切换额外的熔丝 ,除了两个全局总线维护熔丝之外。 这仅发生在裸芯片具有未键合到任何封装引脚的 I/O 单元的设备上。(例如 TQFP-44 封装) 通常,这些额外的 I/O 单元保留为输入, 但如果允许输入浮动,这可能会导致过度的功耗, 因此 fitter 通过设置适当的 OE MUX 熔丝将它们变为输出。 ### `power_guard.sx` (power_guard) 在 ZE 系列设备中,输入信号可以被“屏蔽”, 以便不需要时,高频信号不会在芯片中传播太远。 这可以降低动态功耗。 通常,当 GLB 的共享使能 PT 为高时,Power Guard 被禁用。 也可以使用此处定义的熔丝永久禁用各个输入的 Power Guard。 如果您需要将共享使能 PT 用于 GOE,这可能是必要的。 ### `osctimer.sx` (osctimer) ZE 系列设备包含一个低精度 5 MHz 振荡器以及一个可以将其降至较低频率的分频器。 启用时,这些信号会替换特定宏单元的宏单元反馈信号。 # Fitter 错误与不确定性 在试图让 LPF4k fitter 做我想做的事情的过程中, 我遇到了一些错误, 以及一些使无法使用某些硬件功能的限制。 在这些情况下,我已尽力通过真实硬件手动进行逆向工程, 但我无法访问每个设备变体, 因此我也不得不做出一些假设。 我会尝试在这里记录这些。 ### Fitter 不会路由所有 GOE 尽管每个设备中有四个 GOE, 但在任何特定设计中,fitter 永远不会路由超过两个。 如果您添加比这更多的唯一方程, 它将开始使用 PT4 作为额外方程的单个 OE。 我尝试添加一堆虚拟逻辑乘积项,以便没有空闲的 PT 可用, 但这并不能说服它改变做法; 它只会大喊分配所有内容失败。 也无法强制 fitter 将共享 PT OE 放置在特定的 GLB 中。 这意味着我不得不对共享 PT OE 总线熔丝的位置做出一些假设, 但基于对 LC4032ZE 和 LC4064ZC 设备的测试, 如果它们不适用于所有设备,我会感到惊讶。 ### 反相 GOE 信号 当尝试使用后缀 `.OE-` 创建低电平有效 GOE 时, fitter 报告列出了正确的方程, 但生成的 JEDEC 文件与仅使用 `.OE` 的文件相同。 为了强制它实际编程 GOE 极性熔丝, 您可以改为反相源信号, 但这仅在其直接来自 OE 引脚时才有效。 否则它只会使用共享 PT OE 中的补码信号。 这意味着每个设备实际上只能定位两个 GOE 极性熔丝。 我们必须通过假设它们都在一个连续块中来推断其他熔丝的位置。 ### Fitter 不会设置共享 PT init 极性 与上面的错误有些相似, fitter 将拒绝路由使用 `.AR-` 或 `.AS-` 的设计。 据推测,这是因为当 PT3 用于初始化时,它无法反转 PT3 的输出。 但是当来自共享 PT 时,有一个可配置的极性; 只是无法让 fitter 使用它。 如上所述,如果您反相单个信号,它只会将其编码在共享 PT 本身。 因此,我们必须根据我们已知的共享 PT 时钟极性熔丝位置来推断此熔丝的位置, 并通过硬件测试进行验证。 ### LC4128ZE_TQFP100 缺少 CLK0 的 Power Guard 熔丝 为该特定设备上的此引脚启用 Power Guard 实例不会导致写入任何熔丝。 然而 fitter 没有给出任何警告, 并且该封装变体的其他专用时钟 Power Guard 熔丝与此匹配, 除了这一个熔丝。 这让我假设 fitter 源代码中的一行可能被删除或发生了其他情况, 导致它跳过了此熔丝。 我添加了一个特殊情况,以将其强制设置为它(极有可能)应该是的熔丝。 ### LC4064ZC_csBGA56 专用输入 数据手册列出该设备有 32 个 I/O 和 12 个仅输入引脚(4 个时钟和 8 个专用输入)。 我相信 8 个专用输入中的两个实际上只连接到常规宏单元。 有相当多的证据支持这一假设: * 没有其他 LC4064 或 LC4128 封装拥有超过 6 个专用输入,即使某些设备(例如 `LC4064ZC_csBGA132`)具有未连接的引脚。人们会认为,如果裸芯片实际上有 8 个专用输入,他们会尽可能将它们连接到引脚。 * TQFP-44 中的 LC4064 使用了一种技巧,即只有一半的宏单元具有相应的 I/O 单元,从而导致 JEDEC 高度减少为 95,但该设备的 JEDEC 高度为 100,因此内部它可能具有全套 64 个 I/O 单元,其中一半未连接。 * 用于球 F8 的 GI 路由熔丝与公开它的封装中宏单元 C12 的 I/O 的熔丝完全相同。 * 用于球 E3 的 GI 路由熔丝与公开它的封装中宏单元 A15 的 I/O 的熔丝完全相同。 因此,在 `pins.csv` 文件中,我将球 E3 和 F8 分别列为对应于宏单元 A15 和 C12 的 I/O。 尝试将这些引脚分配为输出会导致 fitter 发出警告, 因此有一些我无法使用 fitter 进行逆向工程的熔丝。 在这些情况下,我只是从 `LC4064ZC_TQFP100` 封装中的相应宏单元复制熔丝位置, 假设它使用相同的裸芯片。 此外,似乎存在一个与球 F8 和 E1 的输入阈值熔丝有关的 fitter 错误。 fitter 切换球 E1 上输入的两个输入阈值熔丝, 而球 F8 上的输入没有切换任何熔丝。 由于 F8 是“奇怪”的专用输入之一, 我为此使用了 TQFP100 封装中 C12 宏单元的输入阈值熔丝, 就像我对输出配置熔丝所做的那样。 然后我可以从 fitter 为球 E1 切换的熔丝中排除该熔丝, 从而只产生一个该球的剩余正确熔丝。 我没有任何这些设备可以进行物理测试,因此为了安全起见, 您可能只想避免在该特定设备上完全使用球 E1、E3 和 F8。 ### Fitter 报告缺少 GI 数据 对于 `LC4064ZC_csBGA56`,第二列(GI 18-35)并不总是显示在 fitter GI 摘要中。 对于某些其他设备,“仅输入”引脚被错误地列为源自宏单元反馈信号。 例如,对于 `LC4128ZC_TQFP100`,引脚 12 的来源列为“mc B-11”, 但设置的 GI MUX 熔丝是对应于 `LC4128V_TQFP144` 中引脚 16 的熔丝之一; 在该设备中是 MC B14 和 ORP B^11。 因此,在这种情况下,fitter 似乎写入的是 I/O 单元的 ID,而不是实际的引脚号。 ## 词汇表 #### GLB Generic Logic Block(通用逻辑块):一组 36 个 GI、83 个 PT、16 个 MC 以及与其关联的其他逻辑。每个设备包含两个或更多 GLB。 #### GRP Global Routing Pool(全局路由池):可用作 GLB 输入的所有信号的集合。这包括所有 I/O 单元引脚、来自所有 MC 的反馈、专用时钟引脚以及(在某些设备中)专用输入引脚。 #### GI Generic Input(通用输入):每个 GLB 36 个信号之一,可用于该 GLB 的乘积项。 #### PT Product Term(乘积项):多达 36 个信号(或其补码)相“与”。 #### MC Macrocell(宏单元):单个触发器或组合逻辑“输出”。 #### MC 切片 Macrocell Slice(宏单元切片):一个 5-PT 集群、宏单元、路由逻辑和 I/O 单元。每个 GLB 包含 16 个 MC 切片,以及 3 个共享 PT、BCLK 和 GI 配置。 #### ORM Output Routing Multiplexer(输出路由多路复用器):允许宏单元及其关联的 OE 乘积项被分流到附近的不同引脚。 #### BCLK Block Clock(块时钟):每个 GLB(“块”)可以独立配置专用时钟输入的极性。 #### BIE Block Input Enable(块输入使能):对于 ZE 系列设备,可以动态屏蔽输入以降低动态功耗。 #### GOE Global Output Enable(全局输出使能):多达四个信号,可以来自特定输入引脚,或来自 BIE 共享 PT。 #### CE Clock Enable(时钟使能) #### LE Latch Enable(锁存器使能) #### AS Asynchronous (pre)Set(异步预置) #### AR Asynchronous Reset/clear(异步复位/清除) ## 复制步骤 如果您想尝试添加其他设备,或者只是想重现此处提交的 .sx 文件,可以按照以下构建步骤操作: 1. 确保 ispLEVER Classic 2.1 安装在 `C:\ispLEVER_Classic2_1` 并且您拥有有效的许可证。特别是 `C:\ispLEVER_Classic2_1\ispcpld\bin\lpf4k.exe` 需要工作,但不使用其他任何东西。 2. 确保已安装 Zig 并从 `generate/` 目录运行 `zig build -Doptimize=ReleaseSafe`。 3. (可选)确保已安装 LIMP 并从代码库根目录运行 `limp -R .`。这将重新生成 Ninja makefiles。 4. 确保已安装 Ninja 并从代码库根目录运行 `ninja`。 注意:在 `temp/` 目录中创建了大量临时文件(然后被删除)。我发现为代码库和 `ispLEVER_Classic2_1` 目录添加 Windows Defender 排除项可以显着加快该过程。
标签:CPLD, EDA, FPGA, ispMACH4000, Lattice半导体, LC4k, S-Expressions, VHDL, Zig, 云资产清单, 可编程逻辑器件, 嵌入式系统, 数字电路, 熔丝图, 硬件安全, 硬件描述, 芯片配置, 逆向工程