第1章:网表基础回顾

各位同学好,我是老张。做逆向分析这么多年,我最大的体会就是——网表基础不牢,后面全白干。今天咱们先聊聊最基础的东西:标准单元库、网表层级结构、还有连接关系。

你可能会问:「这些东西我早就会了,还用学?」嗯,我当年也这么想。直到有一次,我接手一个别人做到一半的逆向项目,发现他把一个AOI22的引脚接反了,整个模块的功能分析全错。从那以后,我每次拿到网表,都会先花半小时确认基础结构。

1.1 标准单元库——逆向分析的「字母表」

标准单元库是什么?说白了,就是芯片设计里的「字母表」。就像你学英语要先认识26个字母一样,做网表逆向,你得先认识标准单元。

每个标准单元,本质上是一个预先设计好的逻辑功能块。比如反相器、与非门、或非门、触发器、锁存器……这些单元在物理上已经布好了晶体管,你只需要在网表里把它们「调用」出来,连上线就行。

我个人习惯把标准单元库分成三类:

  • 组合逻辑单元:AND、OR、NAND、NOR、XOR、AOI(与或非)、OAI(或与非)等。这些单元的输出只取决于当前输入。
  • 时序逻辑单元:DFF(D触发器)、LAT(锁存器)、SDFF(带扫描的D触发器)等。这些单元有记忆功能,输出还取决于时钟边沿。
  • 特殊功能单元:时钟缓冲器、延迟单元、电平转换器、ISO(隔离单元)等。这些单元不改变逻辑功能,但影响时序和功耗。

重点提醒:逆向分析时,你看到的网表里每个实例(instance)都会引用一个标准单元。比如 U1 INV_X1,意思就是实例U1是一个驱动能力为1倍的反相器。这个「X1」代表驱动强度,在时序分析里非常关键。

我在项目中遇到过一件事:有个团队逆向一个老芯片,发现所有反相器都标的是INV_X4。他们以为芯片设计者故意用大驱动单元,后来才发现——是因为标准单元库版本不同,X4在老库里就是最小尺寸。你看,不了解库的细节,分析就会跑偏。

1.2 网表层级结构——从顶层到底层

一个真实的芯片网表,少则几百万门,多则上亿门。你不可能把所有门平铺开来看。所以,网表一定是分层的。

层级结构长什么样?我画个图你就明白了。

顶层 (TOP) 模块A (MOD_A) 模块B (MOD_B) U1 (INV_X1) U2 (NAND_X2) U3 (DFF_X1) U4 (BUF_X4) 顶层模块 子模块 标准单元实例

这张图展示了典型的网表层级:

  • 顶层(TOP):芯片的顶层模块,包含所有IO端口。这是你逆向分析的入口。
  • 模块(Module):功能子模块,比如一个SPI控制器、一个FIFO、一个加法器。模块可以嵌套。
  • 实例(Instance):最底层的标准单元调用。每个实例对应一个具体的逻辑门或触发器。

实战技巧:拿到一个陌生网表,我习惯先看顶层有多少个IO端口。如果IO数量很少(比如几十个),那大概率是个小规模数字模块。如果IO有几百个,那可能是SoC级别的芯片。这个判断能帮你快速定位分析重点。

1.3 网表连接关系——线网、端口、引脚

网表的核心就三样东西:线网(net)、端口(port)、引脚(pin)。它们之间的关系,说白了就是「谁和谁连在一起」。

我举个例子,你一看就懂:

// 一个简单的网表片段
module TOP (clk, rst_n, data_in, data_out);
  input  clk, rst_n;
  input  [7:0] data_in;
  output [7:0] data_out;

  // 线网声明
  wire [7:0] internal_bus;
  wire       clk_buf;

  // 实例化
  BUF_X1 U_clk_buf (.A(clk), .Z(clk_buf));
  DFF_X1 U_reg[7:0] (.D(data_in), .Q(internal_bus), .CK(clk_buf), .RN(rst_n));
  INV_X1 U_inv[7:0] (.A(internal_bus), .ZN(data_out));
endmodule

这里面包含了三种连接元素:

元素 含义 在代码中的体现
端口(Port) 模块的对外接口 input clkoutput [7:0] data_out
线网(Net) 连接各实例的「导线」 wire clk_bufwire [7:0] internal_bus
引脚(Pin) 实例的输入输出接口 .A(clk).Z(clk_buf).D(data_in)

这里有个关键点,我当年踩过坑:线网名和引脚名是两码事。线网是物理连线,引脚是实例的接口。同一个线网可以连到多个实例的引脚上,但一个引脚只能连一个线网。

避坑指南:我曾经逆向一个网表,发现某个线网叫「n1234」,它同时连了10个DFF的时钟引脚。我一开始以为这是个普通信号,后来一查——它其实是时钟树上的一个缓冲输出。如果我没注意到这个线网扇出很大,时序分析就会完全错误。

1.4 连接关系的三种基本模式

在网表里,连接关系其实就三种模式。你记住这三种,后面分析路径就轻松了:

  1. 一对一连接:一个输出引脚连到一个输入引脚。比如反相器的输出直接连到下一个门的输入。这种最简单,路径清晰。
  2. 一对多连接(扇出):一个输出引脚连到多个输入引脚。比如时钟信号要驱动几百个触发器。这种在时序分析里要特别关注,因为负载大,延迟也大。
  3. 多对一连接(扇入):多个输出引脚连到同一个线网。这种情况在标准数字设计中很少见(因为会短路),但在三态总线里会出现。逆向分析时看到这种结构,要小心处理。

我个人习惯,拿到网表后先跑一个「扇出分析」。把所有扇出大于10的线网标出来,这些往往是时钟、复位、使能信号。它们就是关键路径的「嫌疑犯」。

1.5 小结

好了,这一章的内容就这些。总结一下:

  • 标准单元库是网表的「字母表」,你得认识每个单元的符号和功能。
  • 网表是分层的:顶层→模块→实例。逆向分析时,从顶层往下看,先抓大结构,再抠细节。
  • 连接关系就三种元素:端口、线网、引脚。搞清楚谁连谁,路径就出来了。

下一章,咱们会正式进入关键路径提取。但在此之前,我建议你找个简单的网表,自己动手画一画它的层级树和连接图。纸上得来终觉浅,绝知此事要躬行。


公众号:蓝海资料掘金营,微信deep3321