qqqzj@Crane
Back to home / 返回首页

Notes 笔记

计算机系统1

系统 作者 qqqzj-crane 约 43 分钟

计算机系统一#

0. 总体主线#

数字逻辑与计算机组成可以从两条线一起理解:一条是“硬件从门电路长成 CPU”,另一条是“程序从高级语言落到机器指令并在硬件上运行”。

二进制编码
-> 数字逻辑基础
-> 组合逻辑电路
-> 时序逻辑电路
-> FPGA / Verilog HDL
-> 运算方法和功能部件
-> 指令系统 ISA
-> CPU 微体系结构
-> 存储器层次结构
-> 系统互连与输入/输出
-> 程序编译、链接、加载和运行
抽象层关系#
抽象层关注点典型内容
ISA 层软件和硬件之间的接口指令、寄存器、寻址方式、异常/中断
微体系结构层如何实现 ISACPU 数据通路、控制器、流水线
RTL / 功能部件层寄存器传送和功能部件ALU、寄存器堆、存储器、总线
数字逻辑层用门电路实现功能组合逻辑、时序逻辑、FSM
器件层门电路的物理实现CMOS、FPGA、存储单元
章节之间的连接#
前面知识后面用在哪里
补码ALU 加减法、signed comparison、branch compare
移位shifter、乘除法优化、RISC-V immediate 对齐
布尔代数组合逻辑化简、control signal 生成
decoder / muxregister file、datapath 选择、instruction decode
flip-flopregister、PC、FSM、pipeline register
FSMcontrol unit、多周期 CPU、串口/协议控制
timing最高频率、critical path、同步电路可靠性
ISAdatapath 需要哪些硬件、control 需要哪些信号
ELF / linking汇编代码如何成为操作系统能运行的程序

1. 二进制编码与计算机系统抽象#

冯·诺依曼结构和程序执行#
Von-Neumann 模型#

Von-Neumann 模型把计算机抽象成:

部件作用
Memory存放指令和数据,每个地址对应一个内容
CPU取指、译码、执行运算和控制
I/O与外部设备交换数据
System将硬件、软件、运行环境组合成完整系统

核心思想:

  • Stored program:程序也作为二进制数据存放在内存中。
  • Binary:指令、数据最后都编码为 0/1。
  • CPU 自动执行指令序列,而不是人工设置每一步。
程序表示#

程序语言的层次:

层次例子转换工具
高级语言C, Javacompiler, interpreter
汇编语言RISC-V assembly, MIPS assemblyassembler
机器语言0/1 bit patternCPU 直接执行

程序执行的典型阶段:

  1. Instruction Fetch:从 PC 指向的内存地址取指令。
  2. Instruction Decode:解释 opcode 和 operand 字段。
  3. Execute:ALU 或控制逻辑执行操作。
  4. Memory Access:按需读写数据内存。
  5. Write Back:把结果写回寄存器或状态。
计算机系统抽象层和 ISA 位置#

从应用问题到硬件电路,中间有多个抽象层:

应用问题
-> 算法
-> 高级语言程序
-> 操作系统 / 虚拟机
-> 指令集体系结构 ISA
-> 微体系结构
-> RTL / 功能部件
-> 数字逻辑电路
-> 器件

ISA 是软件和硬件之间的桥梁。它规定“机器能执行什么”,例如:

  • 有哪些指令。
  • 指令如何编码。
  • 有哪些寄存器。
  • 操作数如何寻址。
  • 异常和中断如何表现给软件。

微体系结构关注“如何实现 ISA”。例如,ISA 规定是否有乘法指令;乘法指令到底用移位加法实现,还是用专用乘法器实现,是微体系结构问题。

二进制数、数据类型、整数和补码#

计算机内部处理的所有信息都以 0 和 1 编码,原因包括:

  • 二进制只有两个稳定状态,物理实现可靠。
  • 二进制计数和运算规则简单。
  • 0/1 与逻辑真假自然对应,便于用逻辑门实现计算。

机器级程序中常见基本数据类型:

类型说明
无符号整数表示非负整数
带符号整数常用补码表示
浮点数表示实数近似值,常用 IEEE 754
字符如 ASCII、Unicode、汉字编码
逻辑值true / false,通常用 1 / 0 表示
进制表示与转换#

位置计数法的核心是“每一位的权重不同”。十进制:

$$ 123.456 = 1\cdot10^2+2\cdot10^1+3\cdot10^0+4\cdot10^{-1}+5\cdot10^{-2}+6\cdot10^{-3} $$

二进制同理,只是基数从 10 换成 2:

$$ (100101.01)_2 = 1\cdot2^5+1\cdot2^2+1\cdot2^0+1\cdot2^{-2} $$

整数从十进制转二进制:

  1. 不断除以 2。
  2. 记录每一步余数。
  3. 从最后一个余数向前读。

例:

135 / 2 = 67 ... 1
 67 / 2 = 33 ... 1
 33 / 2 = 16 ... 1
 16 / 2 =  8 ... 0
  8 / 2 =  4 ... 0
  4 / 2 =  2 ... 0
  2 / 2 =  1 ... 0
  1 / 2 =  0 ... 1

(135)_10 = (10000111)_2

小数从十进制转二进制:

  1. 不断乘以 2。
  2. 每次取整数部分作为下一位。
  3. 剩余小数继续乘。

例:

0.6875 x 2 = 1.375  -> 1
0.375  x 2 = 0.75   -> 0
0.75   x 2 = 1.5    -> 1
0.5    x 2 = 1.0    -> 1

(0.6875)_10 = (0.1011)_2
二进制基础运算#

单 bit 加法:

XYCarry inSumCarry out
00000
01010
10010
11001
11111

单 bit 减法可以看成带 borrow in 的运算:

XYBorrow inDifferenceBorrow out
00000
01011
10010
11000
00111

二进制乘法和十进制竖式类似:

  • multiplier 当前位为 1,就加上 shifted multiplicand。
  • multiplier 当前位为 0,就跳过该部分积。
  • 固定位宽机器会截断超出位数的高位。

二进制除法的直觉是反复比较 remainder 和 divisor:

  • 如果 remainder 足够大,商位写 1,并减 divisor。
  • 如果 remainder 不够大,商位写 0。
  • 硬件实现可发展为 restoring / non-restoring division。
C 中位运算与逻辑运算#

C 的 Bit-Level Operations 把操作数看成 bit vector,逐位运算:

运算含义例子
&bitwise AND\(0x_{69} & 0x_{55} = 0x_{41}\)
\(|\)bitwise OR\(0x_{69} | 0x_{55} = 0x_{7}D\)
\(^\)bitwise XOR不同位为 1
~bitwise NOT\(~0x_{00} = 0xFF\),按当前类型宽度取反

logical operations 把 0 看成 false,把任何非 0 看成 true,结果只会是 0 或 1:

运算含义特点
&&logical AND支持短路求值
\(||\)logical OR支持短路求值
!logical NOT\(!0 = 1\),!非0 = 0

易错对比:

0x69 & 0x55   // 0x41,逐位计算
0x69 && 0x55  // 1,只判断二者是否非 0

p && *p       // 若 p 为 NULL,右侧不会被求值
固定宽度与机器数#

计算机内部的数是固定宽度的 bit pattern。这里要区分:

  • machine number:机器内部编码。
  • true value:该编码按某种解释方式得到的数学值。

对 $n$ 位无符号整数:

$$ 0 \le X \le 2^n - 1 $$

对 $n$ 位二进制补码整数:

$$ -2^{n-1} \le X \le 2^{n-1}-1 $$
常见有符号编码#
编码英文特点
原码sign-and-magnitude最高位为符号位,存在 \(+0\) 和 -0
反码one's complement负数按位取反,也存在两种 0
补码two's complement负数为模 $2^n$ 意义下的补数,硬件加减法统一
移码biased / frameshift code常用于浮点数阶码

补码的定义:

$$ [X]_C = 2^n + X \pmod {2^n} $$

补码负数转换快捷法:

  1. 对绝对值的二进制按位取反。
  2. 加 1。

补码取负也满足:

$$ \sim x + 1 = -x $$
补码手算完整流程#

例:用 8 bit 表示 -13。

  1. 先写 13 的二进制:
13 = 0000 1101
  1. 按位取反:
1111 0010
  1. 加 1:
1111 0011

所以:

-13 的 8-bit two's complement = 1111 0011

反过来,看到 1111 0011:

  1. 最高位是 1,所以按补码解释为负数。
  2. 取反加 1 得绝对值:
1111 0011
0000 1100   // invert
0000 1101   // +1

所以它表示 -13。

补码的一个直观理解是“模环”:

8-bit 下模数是 256
-13 ≡ 256 - 13 = 243
243 = 1111 0011

这也是为什么同一个 bit pattern:

1111 0011

按 unsigned 看是 243,按 signed two's complement 看是 -13。

模运算与溢出#

固定 $w$ 位机器会丢弃超出的高位,因此本质是在模 $2^w$ 下计算。

无符号加法:

$$ UAdd_w(u,v) = (u+v) \bmod 2^w $$

无符号乘法:

$$ UMult_w(u,v) = (u \cdot v) \bmod 2^w $$

有符号补码加法和无符号加法在 bit-level 上完全相同,区别只是解释结果的方式。

signed 与 unsigned 的映射#

signed 和 unsigned 互相转换时:

  • bit pattern 不变。
  • 解释方式改变。

若 $w$ 位补码值 $x < 0$,转为 unsigned 时会变成:

$$ T2U(x) = x + 2^w $$

这解释了 C 中很多“看起来奇怪”的比较:

-1 < 0U     // false, 因为 -1 被转换成 unsigned 后是很大的数
(unsigned)-1 > -2  // true

易错点:

  • C 表达式中若 signed 和 unsigned 混用,signed 通常会隐式转换为 unsigned。
  • 不要因为变量“应该非负”就随便用 unsigned,循环倒着写时很容易下溢。
signed / unsigned 转换例题#

以 4 bit 为例:

bit patternunsignedsigned two's complement
000000
000111
011177
10008-8
10019-7
111115-1

规律:

  • 最高位为 0 时,signed 和 unsigned 值相同。
  • 最高位为 1 时,signed 值 = unsigned 值 $-2^w$。

例如 $w=4$:

1001 unsigned = 9
1001 signed   = 9 - 16 = -7

C 语言比较例:

int x = -1;
unsigned y = 1;
printf("%d\n", x < y);

这里 \(x\) 会被转换成 unsigned:

-1 的 32-bit pattern = 0xffffffff
按 unsigned 解释 = 4294967295

所以:

4294967295 < 1  // false
扩展与截断#

扩展:

类型规则
unsigned 扩展高位补 0
signed 扩展复制符号位

截断:

  • 直接丢掉高位。
  • 对 unsigned 相当于取模。
  • 对 signed 会先得到截断后的 bit pattern,再按补码解释。
截断和扩展例题#

例:把 8-bit signed 1111 0011 扩展到 16 bit。

最高位是 1,所以符号扩展:

1111 0011
1111 1111 1111 0011

值仍然是 -13。

如果按 unsigned 扩展,则高位补 0:

1111 0011
0000 0000 1111 0011

值变成 243。

截断例子:

int x = 53191;        // 十六进制 0xCFC7
short y = (short)x;   // 保留低 16 bit

如果 short 是 16-bit signed,则 0xCFC7 最高位为 1,所以 y 是负数:

0xCFC7 unsigned = 53191
0xCFC7 signed   = 53191 - 65536 = -12345

这类题的稳定做法:

  1. 先写目标宽度的 bit pattern。
  2. 再决定按 signed 还是 unsigned 解释。
移位#
操作作用注意
\(x << k\)左移,低位补 0常等价于乘 $2^k$,但可能溢出
unsigned \(x >> k\)逻辑右移,高位补 0等价于向下取整除以 $2^k$
signed \(x >> k\)通常为算术右移,高位补符号位负数会向 $-\infty$ 方向取整

负数想实现 C 整数除法那种“向 0 截断”,右移前要加 bias:

$$ (x + (1 \ll k) - 1) \gg k $$

这里适用于 $x<0$ 的情况。

有符号溢出判断#

二进制补码加法中:

  • 正数 + 正数 = 负数,则正溢出。
  • 负数 + 负数 = 正数,则负溢出。
  • 一正一负相加不会溢出。

等价判断:

  • 操作数符号相同,结果符号不同,则 overflow。
  • 最高有效值位进位和符号位进位不同,则 overflow。

常见 flags:

Flag含义主要用于
ZFZero Flag,结果为 0signed 和 unsigned
SF/NFSign Flag,结果符号位signed
CFCarry Flag,加法进位或减法借位unsigned
OFOverflow Flag,有符号溢出signed
溢出判断例题#

4-bit signed two's complement 范围:

-8 ~ +7

例 1:\(4 + 5\)

  0100   // 4
+ 0101   // 5
------
  1001

1001 按 signed 是 -7。两个正数相加得到负数,所以正溢出。

例 2:\(-4 + -5\)

  1100   // -4
+ 1011   // -5
------
1 0111

丢弃第 5 位后得到 0111,即 \(+7\)。两个负数相加得到正数,所以负溢出。

例 3:\(-4 + 5\)

  1100   // -4
+ 0101   // 5
------
1 0001

丢弃高位后是 0001,即 1。一正一负相加不会 signed overflow。

硬件中常用判断:

OF = carry into sign bit XOR carry out of sign bit

或者从符号看:

OF = (a_sign == b_sign) && (sum_sign != a_sign)
浮点数和数据存储顺序#
基本形式#

IEEE 浮点数的数值形式:

$$ (-1)^s \times M \times 2^E $$

字段:

字段含义
\(s\)sign bit
\(\exp\)指数字段,不直接等于 $E$
frac尾数字段,不直接等于 $M$

单精度:

字段位数
sign1
exp8
frac23

双精度:

字段位数
sign1
exp11
frac52
规格化数#

条件:

exp != 000...0 且 exp != 111...1

指数:

$$ E = Exp - Bias $$

其中:

$$ Bias = 2^{k-1}-1 $$

尾数:

$$ M = 1.xxx... $$

这个隐含的前导 1 是规格化数的关键。

非规格化数#

条件:

exp = 000...0

指数:

$$ E = -Bias + 1 $$

尾数:

$$ M = 0.xxx... $$

作用:

  • 表示非常接近 0 的数。
  • 实现 gradual underflow。
  • \(\exp=0, frac=0\) 表示 \(+0\) 或 -0。
特殊值#
expfrac含义
全 1全 0$\pm \infty$
全 1非 0NaN
全 0全 0$\pm 0$
浮点数编码例题#

例:把 13.25 表示成 IEEE 754 单精度的结构。

先转二进制:

13 = 1101
0.25 = 0.01
13.25 = 1101.01

规格化:

1101.01 = 1.10101 x 2^3

所以:

s = 0
E = 3
Bias = 127
Exp = E + Bias = 130 = 10000010
frac = 10101000000000000000000

最终结构:

0 10000010 10101000000000000000000

这类题不一定要求写完整 32 位十六进制,但必须能判断:

  • sign bit。
  • exponent 是否要加 bias。
  • frac 是去掉规格化前导 1. 后的小数部分。

非规格化数的识别题:

exp = 00000000, frac != 0

此时:

M = 0.frac
E = -126   // single precision

特殊值识别题:

exp = 11111111, frac = 0      -> infinity
exp = 11111111, frac != 0     -> NaN
浮点运算的核心#

浮点加法:

  1. 对阶:把较小指数的尾数右移。
  2. 尾数相加或相减。
  3. 规格化结果。
  4. 舍入。
  5. 检查 overflow / underflow。

浮点乘法:

  1. 符号:$s = s_1 \oplus s_2$。
  2. 尾数:$M = M_1 \times M_2$。
  3. 指数:$E = E_1 + E_2$。
  4. 规格化和舍入。

重要性质:

  • 浮点加法通常不满足结合律。
  • 浮点乘法也通常不满足结合律和分配律。
  • 默认舍入通常是 round-to-nearest-even。
浮点舍入为什么会出问题#

二进制浮点只能保存有限个 frac bit。若精确结果不能放进 frac,就必须舍入。

例:

float a = 1e20;
float b = -1e20;
float c = 3.14;

比较:

(a + b) + c
a + (b + c)

第一种:

a + b = 0
0 + c = 3.14

第二种:

b + c ≈ b   // c 太小,在对阶时被舍掉
a + b = 0

所以浮点加法不满足结合律。考试或调试时看到浮点比较,不要默认它像数学实数那样精确。

数据宽度常用单位:

单位含义
bit二进制位
byte字节,通常 8 bit
word字,具体宽度由机器约定

大端和小端:

方式含义
大端最高有效字节放在低地址
小端最低有效字节放在低地址

大小端只影响多字节数据在内存中的字节排列,不改变数据本身的数值。

本章英文术语#
English中文复习提示
bit pattern位模式同一串 0/1 可按 signed 或 unsigned 解释
binary number二进制数基数为 2
decimal number十进制数基数为 10
conversion进制转换整数除 2 取余,小数乘 2 取整
unsigned integer无符号整数范围 $0$ 到 $2^w-1$
signed integer有符号整数本课通常指 two's complement
sign bit符号位最高位表示符号
sign extension符号扩展复制最高位
zero extension零扩展高位补 0
truncation截断丢弃高位
overflow溢出数学结果超出固定位宽范围
carry进位unsigned 加法关注
borrow借位unsigned 减法关注
two's complement补码负数按位取反加 1
one's complement反码负数按位取反
sign-and-magnitude原码符号位加绝对值
biased notation移码 / 偏置表示浮点 exponent 常用
bitwise operation位运算&、\(|\)、\(^\)、~
logical operation逻辑运算&&、\(||\)、!,返回 0/1
short-circuit evaluation短路求值左侧已决定结果时不算右侧
left shift左移低位补 0
logical right shift逻辑右移高位补 0
arithmetic right shift算术右移高位补符号位
floating point浮点数近似表示实数
normalized number规格化数隐含前导 1
denormalized number非规格化数也叫 subnormal
subnormal number次正规数接近 0 的小数
significand尾数 / 有效数$M$
exponent指数$E$ 或 exp field
bias偏置single precision 为 127
fraction小数字段frac,不含规格化隐藏 1
rounding舍入默认常为 nearest even
nearest even最近偶数舍入tie 时选偶数
infinity无穷exp 全 1、frac 全 0
NaN非数exp 全 1、frac 非 0
endian字节序byte order
big endian大端高有效字节在低地址
little endian小端低有效字节在低地址

2. 数字逻辑基础#

逻辑门和数字抽象#

基本逻辑门:

门表达式含义
NOT$Y=\overline{A}$取反
AND$Y=AB$全 1 才为 1
OR$Y=A+B$至少一个为 1
NAND$Y=\overline{AB}$AND 后取反
NOR$Y=\overline{A+B}$OR 后取反
XOR$Y=A\oplus B$不同为 1
XNOR$Y=\overline{A\oplus B}$相同为 1

数字信号来自连续物理量,例如电压。数字抽象把电压划分为低电平 0、高电平 1,并在中间留下 threshold region / forbidden zone,避免噪声把 0 和 1 混淆。合法输入必须产生合法输出,这就是 static discipline。

Noise Margin / 噪声容限:

$$ NM_H=V_{OH}-V_{IH} $$
$$ NM_L=V_{IL}-V_{OL} $$

理想 buffer 可近似理解为阈值在中间、噪声容限接近 $V_{DD}/2$;真实 buffer 会有非理想转换区,因此 $NM_H$ 和 $NM_L$ 都小于理想值。

CMOS 晶体管和门电路#

CMOS 中常见两类晶体管:

晶体管Gate=0Gate=1适合传递
nMOSOFFONgood 0
pMOSONOFFgood 1

CMOS 门电路用 pMOS 上拉网络和 nMOS 下拉网络互补实现逻辑函数。NAND、NOR、NOT 是常见基础结构。

电路参数:

参数含义复习抓手
propagation delay输入变化到输出稳定的时间$T_{pd}$,且 $T_{plh}$ 和 $T_{phl}$ 可能不同
transition time输出电压真正上升/下降所需时间常受电容、负载、fan-out 影响
fan-in一个逻辑门可接受的输入数量输入太多会增加复杂度和延迟
fan-out一个输出能驱动的后级输入数量超过数据手册限制可能无法提供足够电流
static power输出不切换时的功耗$P_S=I_{DD}\cdot V_{CC}$,CMOS 通常很低
dynamic power信号切换时的功耗与开关活动、电容和频率有关

Power Dissipation / power consumption 复习时要分清 static power 和 dynamic power:前者来自静态漏电或静态电流,后者主要来自节点电容充放电和信号切换。

布尔代数#

基本逻辑优先级:

  1. Parentheses
  2. NOT
  3. AND
  4. OR

常用定理:

名称公式
恒等律$A+0=A,\ A\cdot1=A$
零一律$A+1=1,\ A\cdot0=0$
幂等律$A+A=A,\ AA=A$
互补律$A+\overline A=1,\ A\overline A=0$
交换律$A+B=B+A,\ AB=BA$
结合律$(A+B)+C=A+(B+C)$
分配律$A(B+C)=AB+AC$,$A+BC=(A+B)(A+C)$
吸收律$A+AB=A$,$A(A+B)=A$
德摩根律$\overline{AB}=\overline A+\overline B$,$\overline{A+B}=\overline A\overline B$

Shannon expansion 把一个函数按某个变量拆成两种情况,是理解 mux、递归化简和 BDD 的基础:

$$ F(X_1,\ldots,X_n)=X_1F(1,X_2,\ldots,X_n)+\overline{X_1}F(0,X_2,\ldots,X_n) $$

对偶形式可写为:

$$ F=(X_1+F(0,X_2,\ldots,X_n))(\overline{X_1}+F(1,X_2,\ldots,X_n)) $$
真值表、表达式与标准形式#

描述逻辑函数的常见方式:

方式特点
真值表唯一描述函数,变量多时规模指数增长
波形图适合描述信号随时间变化
逻辑表达式不唯一,便于化简和实现
标准形式便于系统化设计

术语:

名称含义
literal变量或变量的反
product term若干 literal 的 AND
sum term若干 literal 的 OR
minterm所有变量都出现一次的 product term
maxterm所有变量都出现一次的 sum term
SOPsum of products
POSproduct of sums

Canonical SOP 使用输出为 1 的 minterms:

$$ F = \sum m(\text{rows where }F=1) $$

Canonical POS 使用输出为 0 的 maxterms:

$$ F = \prod M(\text{rows where }F=0) $$

canonical form 在固定变量顺序下唯一;standard SOP/POS 不要求每个项都包含所有变量,因此不唯一。把 standard SOP 变成 canonical SOP 时,可对缺失变量乘以 $(x+\overline{x})$ 后展开;把 standard POS 变成 canonical POS 时,可对缺失变量加上 $x\overline{x}$ 后用分配律展开。

例:三输入函数 $F(x,y,z)$ 在编号 1, 2, 4, 7 时输出 1。

$$ F(x,y,z)=\sum m(1,2,4,7) $$

按变量顺序 x y z:

编号xyzminterm
1001$x'y'z$
2010$x'yz'$
4100$xy'z'$
7111$xyz$

所以:

$$ F=x'y'z+x'yz'+xy'z'+xyz $$

如果用 decoder 实现,一个 3-to-8 decoder 的每根输出线天然对应一个 minterm,把 1,2,4,7 输出线接到 OR gate 即可。

K-map 化简#

K-map 的本质是把只差一个变量的 minterms 放在相邻格子。相邻项可以合并,因为:

$$ AB + AB' = A $$

化简步骤:

  1. 把输出为 1 的格子填入 K-map。
  2. 按 $1,2,4,8,\ldots$ 个格子分组。
  3. 每组必须是矩形,且可跨边界。
  4. 每组越大,消去变量越多。
  5. 每个 1 至少覆盖一次。
  6. 得到每组中保持不变的变量,组成 product term。
  7. 所有 product term 相加得到 SOP。

K-map 术语:

名称含义
implicant覆盖若干输出为 1 的 minterm 的 product term
prime implicant不能再扩大分组的 implicant,对应 K-map 中最大可能圈
essential prime implicant至少覆盖某个只被它覆盖的 minterm,因此必须选

don't care 的使用:

  • 可以当 1 用来扩大分组。
  • 也可以不用。
  • 目标是让表达式更简单,而不是机械地包含所有 don't care。
本章英文术语#
English中文复习提示
digital abstraction数字抽象用 0/1 抽象连续电压
threshold region阈值区0 和 1 之间的中间区域
forbidden zone禁止区非合法电平区间
static discipline静态纪律合法输入产生合法输出
noise margin噪声容限$NM_H$、$NM_L$
propagation delay传播延迟输入变化到输出稳定
contamination delay污染延迟输入变化到输出开始变化
transition time转换时间上升/下降不瞬时
rise time上升时间输出从低到高
fall time下降时间输出从高到低
fan-in扇入一个门的输入数量
fan-out扇出一个输出能驱动多少输入
power dissipation功耗static + dynamic
static power静态功耗不切换时的功耗
dynamic power动态功耗切换时的功耗
CMOS互补金属氧化物半导体pMOS + nMOS
pull-up network上拉网络把输出拉到 $V_{DD}$
pull-down network下拉网络把输出拉到 GND
Boolean algebra布尔代数逻辑化简基础
De Morgan's theorem德摩根定律取反分配到 AND/OR
Shannon expansion香农展开按变量拆函数
truth table真值表唯一描述函数
Boolean expression布尔表达式不唯一
literal文字 / 变量或反变量product/sum term 的元素
minterm最小项所有变量都出现的乘积项
maxterm最大项所有变量都出现的和项
canonical form规范形式固定变量顺序下唯一
standard form标准形式不要求每项含所有变量
SOP与或式sum of products
POS或与式product of sums
Karnaugh map / K-map卡诺图相邻项合并化简
implicant蕴含项覆盖若干 1 的 product term
prime implicant主蕴含项不能再扩大的圈
essential prime implicant必要主蕴含项覆盖独有 minterm,必须选
don't care无关项可当 1 也可不用

3. 组合逻辑电路#

组合逻辑电路概述#

组合逻辑电路满足:

  • 输出只由当前输入决定。
  • 不含存储状态。
  • 不允许形成无意义反馈环。

设计流程:

  1. 确定输入、输出和逻辑关系。
  2. 写 truth table。
  3. 得到逻辑函数并化简。
  4. 画电路图或写 HDL。
  5. 画 timing diagram。
  6. 做 timing analysis。

HDL-based design flow 常见顺序:

logic design with HDL -> simulation -> synthesis -> physical design / FPGA implementation

simulation 验证功能是否符合预期;synthesis 把 HDL 转成门级结构;FPGA flow 的最后一步通常是生成并下载 bitstream。

典型组合逻辑部件#

Decoder:

  • $n$ 位输入,最多 $2^n$ 个 one-hot 输出。
  • 可用多个小 decoder 和 AND gate 扩展,例如用 1-to-2 结构扩成 2-to-4、3-to-8。
  • 常用于地址译码、minterm 生成和控制信号生成。

Encoder:

  • 把 one-hot 或 priority input 编成二进制输出。
  • 普通 encoder 的两个问题:多个输入同时为 1 时不明确;全 0 和 $I_0=1$ 容易混淆。
  • priority encoder 通过优先级解决冲突,并常带 valid bit 表示至少有一个输入有效。

Multiplexer:

  • 用选择信号从多个输入中选一个输出。
  • $n$ 个 select bit 可以选择 $2^n$ 路输入。
  • 逻辑上可看成 decoder 加若干 AND-OR 结构。

Demultiplexer:

  • 一个输入分发到多个输出。
  • 本质上可看成带 enable/data input 的 decoder。

Half Adder:

$$ S=A\oplus B $$
$$ C=AB $$

Full Adder:

$$ S=A\oplus B\oplus C_{in} $$
$$ C_{out}=AB+AC_{in}+BC_{in} $$
组合逻辑时序分析#

传播延迟:

$$ T_{pd} = \text{input 到 output 的最大延迟} $$

污染延迟:

$$ T_{cd} = \text{input 到 output 的最小延迟} $$

critical path:

  • 总传播延迟由最长路径决定。
  • 如果路径上有多个门,总 $T_{pd}$ 是该路径上各门 $T_{pd}$ 之和。

shortest path:

  • 总污染延迟由最短路径决定。
  • 常用于分析 hold constraint。

race hazard / glitch:

  • 单个输入变化可能沿多条不同延迟路径影响输出。
  • 如果输出发生短暂错误跳变,就是 glitch。
  • 即使最终逻辑值正确,glitch 也可能被后级时序元件采样到。
本章英文术语#
English中文复习提示
combinational circuit组合逻辑电路输出只依赖当前输入
HDL design flowHDL 设计流程design, simulation, synthesis, implementation
simulation仿真检查逻辑行为
synthesis综合HDL 转门级结构
decoder译码器输入编码到 one-hot 输出
encoder编码器one-hot 输入到二进制编码
priority encoder优先编码器多个输入有效时按优先级
multiplexer / MUX多路选择器选一路输入
demultiplexer / DEMUX多路分配器一路输入分到多路
half adder半加器无 carry in
full adder全加器有 carry in
timing analysis时序分析分析延迟和路径
critical path关键路径最长延迟路径
shortest path最短路径污染延迟相关
propagation delay传播延迟最大延迟
contamination delay污染延迟最小延迟
glitch毛刺短暂错误跳变
race hazard竞争冒险不同路径延迟导致 glitch

4. 时序逻辑电路#

时序逻辑与有限状态机#

时序逻辑电路由组合逻辑和存储元件组成,输出不仅依赖当前输入,还依赖过去状态:

$$ S_{next}=f(S_{current},X) $$
$$ Y=g(S_{current},X) $$

有限状态机两种模型:

模型输出依赖特点
Moore只依赖状态输出稳定,状态数可能较多
Mealy依赖状态和输入状态数可能较少,输出可能更快变化

一般规律:

  • Mealy 输出标在边上,常用 input/output。
  • Moore 输出标在状态上,通常状态数更多。
组合逻辑与时序逻辑的判断题#

看到题目时可以这样判断:

现象可能类型
输出只由当前输入决定combinational
输出还依赖过去发生过什么sequential
电路里有 flip-flop / registersequential
有 posedge clksequential
有 feedback 但没有明确存储元件需要谨慎,可能是 latch 或非法组合环

典型组合逻辑:

  • decoder
  • encoder
  • mux
  • adder
  • ALU
  • barrel shifter

典型时序逻辑:

  • register
  • counter
  • shift register
  • FSM
  • PC
  • register file 的写入部分
Latch 与 Flip-Flop#
元件触发方式特点
latchlevel-sensitive时钟有效电平期间透明
flip-flopedge-triggered只在边沿采样

双稳态电路能保存 1 bit 状态。Latch 通常由交叉耦合门构成,flip-flop 可由多个 latch 组合而成。

SR latch:

  • 有 Set / Reset 输入。
  • NOR 型 SR latch 中,\(S=R=1\) 是非法组合。
  • NAND 型 SR latch 通常输入低有效,非法组合对应 \(S'=R'=0\)。

D latch:

  • \(C=1\) 时,\(D\) 传到 \(Q\)。
  • \(C=0\) 时,保持旧值。
  • 用一个 data input 避免 SR latch 的非法输入组合。

Pulse-triggered / master-slave flip-flop:

  • 用两个 latch 串联,并让两级在不同 clock phase 打开。
  • SR / JK pulse-triggered 结构可能出现 1's catching:输入端短暂出现的 1 被 master latch 捕获,即使后来消失,也会传到 slave。

Edge-triggered D flip-flop:

  • 只在上升沿或下降沿采样 \(D\)。
  • D 输入消除了 SR / JK 中一些输入组合问题。
  • 是同步时序电路最常用的存储元件。

常见扩展:

  • enabled D flip-flop:\(EN=1\) 时更新,\(EN=0\) 时保持。
  • resettable D flip-flop:可以同步或异步 reset。
  • JK flip-flop:\(J=K=1\) 时翻转。
  • T flip-flop:\(T=1\) 时翻转,\(T=0\) 保持。
触发器描述表#

Characteristic table 描述“当前输入和当前状态会得到什么下一状态”;excitation table 反过来描述“想从当前状态变到目标下一状态,需要什么输入”。

SR flip-flop:

SR$Q(t+1)$操作
00$Q(t)$hold
010reset
101set
11undefinedinvalid

约束下的特征方程:

$$ Q(t+1)=S+\overline{R}Q(t),\quad SR=0 $$

D flip-flop:

D$Q(t+1)$操作
00reset
11set
$$ Q(t+1)=D $$

JK flip-flop:

JK$Q(t+1)$操作
00$Q(t)$hold
010reset
101set
11$\overline{Q(t)}$complement

常见写法:

$$ Q(t+1)=J\overline{Q(t)}+\overline{K}Q(t) $$

T flip-flop:

T$Q(t+1)$操作
0$Q(t)$hold
1$\overline{Q(t)}$complement
$$ Q(t+1)=T\oplus Q(t) $$

常用 excitation table:

当前 $Q(t)$目标 $Q(t+1)$SR 输入D 输入JK 输入T 输入
00\(S=0, R=X\)0\(J=0, K=X\)0
01\(S=1, R=0\)1\(J=1, K=X\)1
10\(S=0, R=1\)0\(J=X, K=1\)1
11\(S=X, R=0\)1\(J=X, K=0\)0
Verilog 时序逻辑模板#

同步寄存器:

always @(posedge clk) begin
    q <= d;
end

带同步 reset:

always @(posedge clk) begin
    if (rst)
        q <= 1'b0;
    else
        q <= d;
end

带异步 reset:

always @(posedge clk or posedge rst) begin
    if (rst)
        q <= 1'b0;
    else
        q <= d;
end

时序逻辑经验:

  • 时序逻辑用 nonblocking assignment:\(\le \)。
  • 组合逻辑常用 blocking assignment:\(=\)。
  • 一个寄存器最好只在一个 always block 里赋值。
  • reset 是同步还是异步,要和题目或实验框架一致。
FSM 分析与设计流程#

分析一个时序电路:

  1. 找状态变量。
  2. 写 next-state equation。
  3. 写 output equation。
  4. 列 state table。
  5. 画 state diagram。

设计一个 FSM:

  1. Specification:明确功能。
  2. Formulation:得到 state diagram 或 state table。
  3. State assignment:给状态分配二进制编码。
  4. Flip-flop input equation:根据触发器类型推输入方程。
  5. Output equation:推输出方程。
  6. Optimization:化简。
  7. Technology mapping:映射到门和触发器。
  8. Verification:验证。

状态化简的依据是状态等价:如果两个状态对所有输入产生相同输出,并转向相同或等价的下一状态,则可以合并。

两个状态等价的条件:

  • 对每个可能输入,输出完全相同。
  • 对每个可能输入,next state 相同或等价。
序列检测器例子:识别 1101#

Mealy 设计思路:

状态含义
A还没有匹配到有效前缀
B已看到 1
C已看到 11
D已看到 110

当在 D 状态读到 1 时,识别到 1101,输出 1。由于最后一个 1 也可能是下一次匹配的起点,所以转回 B。

Moore 版本需要额外状态 E 来输出 1,因此通常“Moore is more”。

对应状态表可以从状态图直接读出:每个 present state 在输入为 0 和 1 时分别写 next state 和 output。状态表也可用于发现等价状态并合并。

FSM 的 Verilog 写法#

推荐三段式写法:

localparam S_IDLE = 2'b00;
localparam S_1    = 2'b01;
localparam S_11   = 2'b10;
localparam S_110  = 2'b11;

reg [1:0] state, next_state;

always @(posedge clk) begin
    if (rst)
        state <= S_IDLE;
    else
        state <= next_state;
end

always @(*) begin
    next_state = state;
    case (state)
        S_IDLE: next_state = x ? S_1 : S_IDLE;
        S_1:    next_state = x ? S_11 : S_IDLE;
        S_11:   next_state = x ? S_11 : S_110;
        S_110:  next_state = x ? S_1 : S_IDLE;
        default: next_state = S_IDLE;
    endcase
end

always @(*) begin
    y = 1'b0;
    if (state == S_110 && x)
        y = 1'b1;   // Mealy: output depends on state and input
end

对应的是 Mealy 版本 1101 序列检测器。输出在读到最后一个 1 的那个周期产生。

若改成 Moore,通常要增加一个 \(S_{1101}\) 状态,并在该状态输出 1:

assign y = (state == S_1101);

Moore 输出更稳定,但可能晚一个周期,并且状态数可能更多。

状态编码#

若有 $m$ 个状态,至少需要 $n$ 位:

$$ n \ge \lceil \log_2 m \rceil $$

状态编码会影响逻辑化简成本。经验规则:

  • 对某输入有相同 next state 的状态,尽量编码相邻。
  • 同一个状态的多个 next states,尽量编码相邻。
  • 输出相同的状态,尽量编码相邻。

Gray code assignment 可减少相邻状态切换时改变的位数,常能降低两级逻辑优化后的 gate input cost。状态编码不同,不改变 FSM 功能,但会改变 next-state equation 和 output equation 的复杂度。

时序约束#

对 D flip-flop:

  • $t_{setup}$:时钟沿前输入必须稳定的时间。
  • $t_{hold}$:时钟沿后输入必须继续稳定的时间。
  • $t_{ffpd}$:clock-to-Q 延迟。

时钟周期约束:

$$ t_{clk} \ge t_{ffpd} + t_{comb} + t_{setup} $$

hold 约束:

$$ t_{hold} \le t_{ffpd} + t_{comb} $$
Setup / Hold 约束例题#

假设:

t_ffpd = 2 ns
t_comb = 7 ns
t_setup = 1 ns

则时钟周期至少:

$$ t_{clk} \ge 2 + 7 + 1 = 10\text{ ns} $$

最大频率:

$$ f_{max} = 1 / t_{clk} = 100\text{ MHz} $$

如果组合逻辑太长,解决方向:

  • 优化组合逻辑。
  • 插入 pipeline register,把长路径切短。
  • 降低 clock frequency。

hold violation 和 setup violation 的直觉不同:

  • setup violation:数据来得太晚。
  • hold violation:数据变得太早。

setup 可通过降频缓解,hold 通常不能单靠降频解决。

Register、Bus 与 Datapath#

寄存器是多个触发器组成的多 bit 存储单元。

用途:

  • 临时保存数据。
  • 构建 datapath。
  • 支持 register transfer operation。

微操作 microoperation:

类型例子
transfer\(R_{2} <- R_{1}\)
arithmeticadd, subtract, increment
logicAND, OR, XOR
shiftleft shift, right shift

数字系统常分成:

部分作用
datapath执行数据处理,包含寄存器、ALU、bus、mux
control unit决定何时执行哪些微操作

寄存器传输结构:

结构特点
dedicated multiplexer每个目的端用 mux 选择来源,控制明确但 mux 多
shared bus多个寄存器共享数据通路,节省连线
three-state bus同一时刻只允许一个 driver 使能,否则 bus contention
multiple buses支持更多并行传输,硬件成本更高

Multiplexer bus 用 mux 保证只选一路;3-state bus 通过 high-Z 状态断开未选 driver,设计时必须确保 enable 互斥。

Shift Register#

移位寄存器可以把数据向 MSB 或 LSB 方向移动。

常见功能:

  • shift right
  • shift left
  • parallel load
  • hold

如果每个 D flip-flop 前放一个 4-input MUX,就可以统一支持这几种操作。

基本 serial shift register:

  • Data input 是 serial input。
  • 每个 clock 把数据向一侧移动一位。
  • 所有触发器输出一起看时,就是 parallel output。

并行装入 parallel load 允许一次性写入所有位,之后再进行移位;带可变 shift amount 的移位器可用多级 mux 组成。

Counter#

计数器是按固定状态序列运行的时序电路。

用途:

  • 计时。
  • 计数事件。
  • 记录发送或接收了多少 bit。
  • CPU 中的 Program Counter。

Ripple counter:

  • 只有最低位直接接全局时钟。
  • 高位时钟来自低位输出。
  • 变化逐级 ripple。
  • 最坏延迟约为 $n \cdot t_{PHL}$。
  • 严格说不是完全同步结构,因为各位不是同一 clock edge 同时更新。

Synchronous counter:

  • 所有触发器共享同一个 clock。
  • 组合逻辑计算 next state。
  • 更适合高速设计。
  • up-counter 可用 incrementer 产生下一状态。
  • count enable 让 counter 在 \(EN=0\) 时保持不变。
  • carry out 可接到更高位 counter 的 enable,用于级联。

同步计数器内部常见 carry chain:

  • serial gating:carry 逐级通过 AND 链,路径较长。
  • parallel gating:并行生成部分 carry,类似 carry lookahead,可减少大计数器延迟。
本章英文术语#
English中文复习提示
sequential circuit时序逻辑电路输出依赖状态
latch锁存器电平敏感
flip-flop触发器边沿敏感
bistable circuit双稳态电路可保存 1 bit
SR latchSR 锁存器Set / Reset
D latchD 锁存器data input
edge-triggered flip-flop边沿触发触发器时钟边沿采样
pulse-triggered flip-flop脉冲触发触发器可能有 1's catching
1's catching1 捕获短暂的 1 被 master 捕获
JK flip-flopJK 触发器\(J=K=1\) 时翻转
T flip-flopT 触发器\(T=1\) 时翻转
characteristic table特征表输入和现态推下一状态
excitation table激励表状态转移反推输入
finite state machine / FSM有限状态机state + transition
Mealy machineMealy 型状态机输出依赖状态和输入
Moore machineMoore 型状态机输出只依赖状态
state diagram状态图图形表示状态转移
state table状态表表格表示状态转移
state assignment状态编码给状态分配 bit pattern
setup time建立时间时钟沿前需稳定
hold time保持时间时钟沿后需稳定
clock-to-Q delay时钟到 Q 延迟$t_{ffpd}$
register寄存器多个 flip-flop
register file寄存器堆多读/写端口寄存器集合
datapath数据通路ALU、寄存器、mux、bus 等
control unit控制单元产生控制信号
three-state bus三态总线high-Z 共享连线
bus contention总线冲突多个 driver 同时驱动
shift register移位寄存器逐拍移动数据
parallel load并行装入一次写入所有位
ripple counter异步 / 行波计数器变化逐级 ripple
synchronous counter同步计数器所有触发器共享 clock
count enable计数使能控制是否计数
carry out进位输出可级联计数器

5. FPGA 设计和 Verilog HDL#

可编程逻辑器件和 FPGA#

FPGA 是可编程逻辑器件的一类。使用者通过配置文件改变内部逻辑连接,从而实现不同数字电路。它适合教学和实验,因为可以在硬件上验证 CPU、控制器、数据通路等设计。

相关概念:

概念含义
PLD可编程逻辑器件
PLA可编程逻辑阵列
FPGA现场可编程门阵列
ASIC专用集成电路
HDL 设计流程#

基于 HDL 的数字电路设计通常按下面的链路推进:

  1. Logic design with HDL:用 HDL 描述电路结构和行为。
  2. Simulation:编写 testbench 验证功能是否正确。
  3. Synthesis:把 HDL 综合为门级网表。
  4. Physical design:布局布线,确定实际硬件连接。
  5. ASIC tape-out 或 FPGA bitstream download:生成版图或下载到 FPGA。

仿真检查的是“逻辑行为是否符合预期”,综合关注的是“这些写法能不能变成实际硬件”。所以 Verilog 不是普通软件语言,写代码时要一直想它对应的电路是什么。

Verilog 基础语法#

模块结构:

module top(
    input a,
    input b,
    output c
);
    assign c = a & b;
endmodule

关键点:

  • Verilog 区分大小写。
  • 关键字小写。
  • // 表示单行注释,\(/* ... */\) 表示多行注释。
  • assign 常用于组合逻辑的连续赋值。

数字常量格式:

<位宽>'<进制><数值>

例:

4'b1010
8'hff
16'd255

常见进制:

base含义
\(b\)binary
\(o\)octal
\(d\)decimal
\(h\)hexadecimal

特殊值:

  • \(x\):unknown。
  • \(z\):high impedance。
  • ?:在数字常量中等价于 \(z\)。

负数写法要注意位宽归属:

-6'd3   // 正确
4'd-2   // 错误

常见数据类型:

类型用途
wire连线型,常用于连续赋值
reg过程赋值变量,不一定综合成寄存器
vector多 bit 信号,如 [7:0]
array多元素存储结构

端口常见规则:

  • input 端口定义一般是 wire。
  • output 可为 wire 或 reg,取决于赋值方式。
  • 实例化时 output 接到外部 wire。
Verilog 建模方式和模板#
建模方式说明
结构建模实例化模块或门并连接
数据流建模使用 assign 描述组合逻辑
行为建模使用 always、if、case 描述行为

assign 适合简单组合逻辑:

assign y = sel ? a : b;
assign sum = a + b;

\(always @(*)\) 适合较复杂的组合逻辑:

always @(*) begin
    y = 1'b0;          // 默认值,避免 latch
    case (op)
        2'b00: y = a & b;
        2'b01: y = a | b;
        2'b10: y = a ^ b;
        2'b11: y = ~a;
        default: y = 1'b0;
    endcase
end

组合逻辑最重要的检查:

  • 每条路径都给输出赋值。
  • case 最好有 default,或者在前面给默认值。
  • 不要在组合逻辑里使用 clock edge。
  • 分支不全会让综合工具推导 latch。

错误例子:

always @(*) begin
    if (en)
        y = a;
end

当 \(en=0\) 时,\(y\) 没被赋值,综合工具会认为它必须“记住原值”,于是推导出 latch。

时序逻辑通常由触发器实现,模板是:

always @(posedge clk) begin
    if (rst)
        q <= 1'b0;
    else
        q <= d;
end

注意:

  • 时序逻辑通常用非阻塞赋值 \(\le \)。
  • 组合逻辑常用阻塞赋值 \(=\)。
本章英文术语#
English中文复习提示
FPGA现场可编程门阵列可下载 bitstream 重新配置
programmable logic device / PLD可编程逻辑器件FPGA 属于其中一类
LUT查找表FPGA 中实现组合逻辑
flip-flop触发器FPGA 逻辑单元中的存储元件
HDL硬件描述语言描述电路,不是普通软件语言
hardware description language硬件描述语言Verilog / VHDL
design flow设计流程design, simulation, synthesis, implementation
simulation仿真检查逻辑行为
synthesis综合HDL 转门级结构
physical design物理设计布局布线
bitstream位流FPGA 下载文件
module模块Verilog 基本设计单元
port端口input / output / inout
wire线网型连续赋值常用
reg过程赋值变量不一定综合为寄存器
vector向量多 bit 信号
array数组多元素存储结构
high impedance高阻态\(z\)
structural modeling结构建模实例化模块/门
dataflow modeling数据流建模assign 连续赋值
behavioral modeling行为建模always、if、case
blocking assignment阻塞赋值\(=\),组合逻辑常用
nonblocking assignment非阻塞赋值\(\le \),时序逻辑常用

6. 运算方法和运算部件#

基本运算部件#

串行进位加法器 RCA:

  • 由多个全加器串接。
  • 低位进位逐级传到高位。
  • 硬件简单,但延迟较大。

并行进位加法器 CLA:

定义:

$$ G_i=A_iB_i $$
$$ P_i=A_i+B_i $$

进位:

$$ C_{i+1}=G_i+P_iC_i $$

CLA 通过并行生成进位减少串行等待。

带标志加法器需要生成:

标志含义
ZF结果为 0
SF结果符号位
CF无符号进位/借位
OF有符号溢出

ALU 支持多种算术逻辑操作,是 CPU 运算器核心。

定点数运算#

补码加减法:

$$ A-B=A+\overline B+1 $$

所以加法和减法可以共用同一个加法器,只需控制 B 是否取反以及最低位进位输入是否为 1。

有符号溢出判断:

  • 两个正数相加得到负数,正溢出。
  • 两个负数相加得到正数,负溢出。
  • 一正一负相加不会溢出。

原码乘法:

  • 符号单独处理。
  • 数值部分按无符号乘法。

补码乘法:

  • 可用 Booth 编码等方法处理连续 1。
  • 核心思想是将连续 1 的部分积转换为少量加/减操作。

除法:

  • 恢复余数除法:减过头时加回除数。
  • 不恢复余数除法:不立即恢复,而在下一步改为加除数修正。
浮点数运算#

浮点加减:

  1. 对阶。
  2. 尾数相加或相减。
  3. 规格化。
  4. 舍入。
  5. 检查溢出、下溢和特殊值。

浮点乘除:

  • 符号由操作数符号决定。
  • 指数相加或相减。
  • 尾数相乘或相除。
  • 再规格化和舍入。

浮点运算的重点不是“精确实数运算”,而是“有限位宽下的近似运算”。

加法器、ALU 和乘除法硬件#
Carry Propagate Adder#

常见 CPA:

类型特点
Ripple-Carry Adder硬件简单,但 carry 逐级传播,慢
Carry-Lookahead Adder用 generate/propagate 提前计算 carry
Prefix Adder$O(\log N)$ 级计算 carry,更快但硬件更多

RCA 延迟:

$$ t_{ripple} = N t_{FA} $$
CLA generate 与 propagate#

第 $i$ 位:

$$ G_i = A_iB_i $$
$$ P_i = A_i + B_i $$

carry:

$$ C_{i+1} = G_i + P_i C_i $$

sum:

$$ S_i = A_i \oplus B_i \oplus C_i $$

CLA 的思想是先算每一位或每个 block 的 generate/propagate,减少 carry 串行传播。

Adder 设计细化#

RCA:

FA0 -> FA1 -> FA2 -> ... -> FAN-1

carry 必须一级一级传,所以最坏情况很慢。

CLA 的关键是把:

$$ C_{i+1}=G_i+P_iC_i $$

展开。例如:

$$ C_1 = G_0 + P_0C_0 $$
$$ C_2 = G_1 + P_1C_1 = G_1 + P_1G_0 + P_1P_0C_0 $$
$$ C_3 = G_2 + P_2G_1 + P_2P_1G_0 + P_2P_1P_0C_0 $$

这样 carry 可以由多级门并行算出,而不是等前一级 full adder 的 carry out。

Prefix adder 更进一步,把 generate/propagate 做成树形前缀运算:

1-bit group -> 2-bit group -> 4-bit group -> 8-bit group -> ...

所以延迟大致随 $\log N$ 增长,但布线和硬件成本更高。

CLA 可分层做成 block carry lookahead。4-bit block 常写成:

$$ C_4=G_{3:0}+P_{3:0}C_0 $$

其中:

$$ G_{3:0}=G_3+P_3G_2+P_3P_2G_1+P_3P_2P_1G_0 $$
$$ P_{3:0}=P_3P_2P_1P_0 $$

16-bit 或 32-bit CLA 可以用多个 4-bit block 级联,再对 block-level 的 $G$ 和 $P$ 做 lookahead。常见延迟估算:

$$ t_{CLA}=t_{pg}+t_{pg\_block}+(N/k-1)t_{AND\_OR}+kt_{FA} $$

这里 $k$ 是每个 CLA block 的位数。

减法器#

减法 $X-Y$ 可以两种实现:

  1. 串接 full subtractor,borrow ripple。
  2. 用加法器计算:
$$ X - Y = X + (\sim Y + 1) $$

因此 adder-subtractor 通常通过控制信号决定是否取反 B 并把最低位 carry-in 设为 1。

ALU#

ALU 是 processor datapath 的核心组合逻辑,用来执行:

  • arithmetic:add, subtract
  • logic:AND, OR, XOR
  • shift
  • comparison:SLT

典型 datapath:

registers -> ALU -> destination register

ALU 与寄存器配合时,一个 register transfer operation 通常在一个 clock cycle 内完成。

SLT#

SLT 即 set less than。常见做法:

  1. 计算 $A-B$。
  2. 根据符号位和 overflow 判断 $A<B$。
  3. 结果低位置 1,高位补 0。

不能只看减法结果符号位,因为 signed overflow 会影响符号位含义。

ALU 控制信号理解#

一个简单 ALU 可以把多个操作共用硬件:

ALUOp操作
000AND
001OR
010ADD
110SUB
111SLT

加法和减法可共用 adder:

SUB: A - B = A + ~B + 1

因此控制信号可以做:

Binvert = 1
Cin = 1

SLT 常基于 subtraction,但 signed SLT 要考虑 overflow:

less = sum_sign XOR overflow

因为 overflow 会让符号位“翻错方向”。

Flag 与简单 ALU 例子#

带 flags 的 adder / ALU 常输出:

Flag置位条件主要用途
ZFresult 全 0signed / unsigned 都可用
SF/NFresult 最高位为 1signed 符号
CF加法 carry out;减法常表示 borrowunsigned 比较/溢出
OFsigned overflowsigned 加减法

一个简化 ALU 的控制可以这样理解:

aluop输出
00a & b
01\(a | b\)
10\(a + b\)
11保留或其他操作

实际 CPU 的 ALU 通常把加法器、逻辑门、移位器和比较结果接到一个 mux,控制信号选择最终输出。

Barrel Shifter#

barrel shifter 用多级 mux 在一个组合逻辑路径里完成可变位移,不需要一位一位移动。

以 4-bit rotate-left 为例:

  • 第一级根据 shift amount 的 bit 0 决定是否左转 1 位。
  • 第二级根据 shift amount 的 bit 1 决定是否左转 2 位。
  • 两级组合后可实现左转 0、1、2、3 位。

普通 shift register 是时序部件,通常每个 clock 移一位;barrel shifter 是组合部件,可在一个周期内根据 shift amount 直接得到结果,但硬件 mux 更多。

乘法基本思想#

二进制乘法和十进制乘法类似:

  • multiplier 的某位为 1,则加入 shifted multiplicand。
  • multiplier 的某位为 0,则不加。
  • 部分积相加得到结果。

硬件实现会在 area 和 time 间折中:

  • 宽 ALU + 多寄存器:简单但硬件多。
  • 复用较窄 ALU:硬件少但多周期。
  • array multiplier:并行加部分积,快但面积大。

常见迭代乘法实现:

实现思路代价
Implementation 2multiplier 右移,product 右移,multiplicand 保持复用硬件,过程较慢
Implementation 3把 product 和 multiplier 合在一个寄存器中右移寄存器更紧凑,是常见硬件写法
Array multiplier并行生成并相加部分积快,但面积大
有符号乘法#

简单做法:

  1. 记录 operands 的符号。
  2. 转成正数做无符号乘法。
  3. 根据符号异或决定结果符号。

也可以通过符号扩展和 Booth encoding 直接处理补码。

Booth Encoding#

Booth 算法的核心:

  • 把连续的一串 1 变成“开始减一次,结束加一次”。
  • 对连续 1 很长的 multiplier,可以减少部分积数量。

1-bit Booth 规则:

当前位右侧前一位操作
00no op
01add multiplicand
10subtract multiplicand
11no op

直观理解:

$$ 01111000 = 10000000 - 00001000 $$
Booth 算法更直观的例子#

计算 M x 01111000。

普通乘法看到四个连续的 1,需要:

M<<3 + M<<4 + M<<5 + M<<6

Booth 把它看成:

01111000 = 10000000 - 00001000

所以:

M x 01111000 = (M << 7) - (M << 3)

从 4 次加法变成 1 次加法意义上的高位项和 1 次减法。连续 1 越长,Booth 越有优势。

判断边界:

0 -> 1 : run begins, subtract
1 -> 0 : run ends, add

从右往左扫描乘数时,本质就是检测这些连续 1 的边界。

除法#

无符号除法本质上反复判断:

$$ remainder \ge divisor $$

可以通过:

$$ remainder - divisor \ge 0 $$

来判断。

硬件除法常见状态:

寄存器作用
quotient保存逐步生成的商
divisor保存或移动除数
remainder保存当前余数

做题时可以把每一轮看成:移动、试减、根据余数符号写商位、必要时修正。

Restoring division:

  • 先减 divisor。
  • 如果 remainder 变负,恢复原值。
  • 每 bit 可能需要两次 ALU 操作。

Non-restoring division:

  • 如果上一步 remainder 为负,下一步改为加 divisor。
  • 避免立即 restore。
  • 可以做到约 1 bit per cycle。

有符号除法:

  • quotient 的符号由 operands 符号异或决定。
  • 非零 remainder 的符号应与 dividend 一致。
Restoring / Non-restoring Division 对比#

Restoring division 每一步:

  1. \(R = R - D\)
  2. 若 \(R \ge 0\),商位写 1。
  3. 若 \(R < 0\),商位写 0,并 \(R = R + D\) 恢复。

缺点:

  • 失败时要多做一次加法恢复。

Non-restoring division 的想法:

  • 如果上一步减过头导致 \(R < 0\),下一步不要先恢复。
  • 下一轮改成加 divisor,把效果补回来。

所以每轮根据 remainder 符号选择:

当前 remainder下一步
\(R \ge 0\)shift 后减 divisor
\(R < 0\)shift 后加 divisor

最后若 remainder 为负,再做一次修正。

本章英文术语#
English中文复习提示
ripple-carry adder / RCA串行进位加法器carry 逐级传播
carry-lookahead adder / CLA先行进位加法器generate / propagate
prefix adder前缀加法器树形计算 carry
generate生成信号$G_i=A_iB_i$
propagate传播信号$P_i=A_i+B_i$
subtractor减法器$A-B=A+\overline{B}+1$
adder-subtractor加减法器加法器复用做减法
ALU算术逻辑单元arithmetic + logic + shift + compare
arithmetic operation算术运算add, subtract 等
logic operation逻辑运算AND, OR, XOR 等
zero flag / ZF零标志结果为 0
sign flag / SF符号标志结果最高位
carry flag / CF进位标志unsigned
overflow flag / OF溢出标志signed
set less than / SLT小于置位signed 时要考虑 overflow
barrel shifter桶形移位器组合逻辑可变移位
multiplier乘法器生成并加部分积
multiplicand被乘数被移动和相加的一方
multiplier operand乘数决定哪些部分积出现
partial product部分积每一位乘数产生的 shifted multiplicand
Booth algorithmBooth 算法连续 1 转加/减边界
array multiplier阵列乘法器并行硬件,面积大
divisor除数division 中被减的一方
dividend被除数division 的输入
quotient商除法结果
remainder余数除法剩余
restoring division恢复余数除法减过头再加回
non-restoring division不恢复余数除法下一轮反向修正

7. 指令系统和 RISC-V#

指令系统概述#

指令系统是 ISA 的核心。每条指令规定:

  • 做什么操作。
  • 操作数从哪里来。
  • 结果写到哪里。
  • 下一条指令如何确定。

指令通常包含:

字段作用
操作码 opcode指定操作类型
源操作数字段指定输入数据位置
目的操作数字段指定结果位置
立即数字段指令中直接给出的常数
控制转移字段指定分支或跳转目标

常见操作类型:

类型例子
Arithmetic and LogicADD, SUB, AND, OR
ShiftSLL, SRL, SRA
Data TransferMOV, LOAD, STORE
String字符串移动、比较等
ControlBRANCH, JMP, CALL, RET
SystemHALT, interrupt control, privilege switch
Input/Output与外设或端口交换数据
指令系统设计#

设计 ISA 需要权衡:

  • 指令数量多少。
  • 指令格式固定还是可变。
  • 操作数个数。
  • 寻址方式多少。
  • 是否采用 load-store 风格。
  • 是否支持异常、中断和特权机制。

寻址方式:

方式含义
立即寻址操作数直接在指令中
寄存器寻址操作数在寄存器中
直接寻址地址字段给出内存地址
间接寻址地址字段指向一个保存有效地址的位置
基址/变址寻址基地址加偏移
PC 相对寻址目标地址由 PC 加偏移得到

指令系统风格:

风格特点
CISC指令复杂、格式多样、寻址方式丰富
RISC指令规整、load-store、易流水化
栈式操作数隐含在栈顶
累加器式一个操作数隐含在累加器
寄存器-寄存器式算术逻辑操作只在寄存器间进行
RISC-V 架构#

RISC-V 命名:

RV + 位宽 + 扩展

例:

名称含义
RV32I32 位基础整数指令集
RV32IMRV32I 加整数乘除扩展
RV32G常用通用扩展组合

RISC-V 常见指令格式:

格式用途
R-type寄存器-寄存器运算
I-type立即数运算、load、jalr
S-typestore
B-type条件分支
U-type高位立即数
J-type无条件跳转

RISC-V 设计特点:

  • 寄存器字段位置尽量固定。
  • 立即数符号位固定在指令最高位附近,便于符号扩展。
  • 无分支延迟槽。
  • 基础指令集小,扩展模块化。
ISA 设计、数据通路需求和 RISC-V 细节#
ISA 是什么#

ISA 是软件和硬件之间的契约:

  • instruction set
  • registers
  • memory organization
  • addressing modes
  • exception / interrupt behavior

ISA 不是具体微架构。同一个 ISA 可以有多个实现。

简化 MIPS 数据通路#

以简化 MIPS 为例,支持:

  • addu rd, rs, rt
  • subu rd, rs, rt
  • ori rt, rs, imm16
  • lw rt, imm16(rs)
  • sw rt, imm16(rs)
  • beq rs, rt, imm16

需要的硬件部件:

部件作用
PC保存下一条指令地址
Instruction Memory根据 PC 取指
Register File两读一写
ALU加、减、OR、比较
Extender立即数扩展,zero/sign extension
Data Memoryload/store
MUX在不同来源之间选择数据
Control生成 RegWr、ALUSrc、MemWr 等控制信号

PC 更新:

  • 顺序执行:\(PC <- PC + 4\)
  • branch taken:\(PC <- PC + 4 + (sign_{ext}(imm_{16}) << 2)\)
单周期数据通路信号怎么想#

以简化 MIPS / 类似单周期 CPU 为例,做题时按 instruction 分类。

R-type addu rd, rs, rt:

信号值
RegDst选 rd
ALUSrc选 register rt
MemToReg选 ALU result
RegWr1
MemWr0
ExtOpt不关心
ALUCtradd
nPC_selPC+4

ori rt, rs, imm16:

信号值
RegDst选 rt
ALUSrc选 immediate
ExtOptzero extension
MemToReg选 ALU result
RegWr1
MemWr0
ALUCtrOR

lw rt, imm16(rs):

信号值
RegDst选 rt
ALUSrc选 immediate
ExtOptsign extension
MemToReg选 memory data
RegWr1
MemWr0
ALUCtradd address

sw rt, imm16(rs):

信号值
ALUSrc选 immediate
ExtOptsign extension
RegWr0
MemWr1
ALUCtradd address

beq rs, rt, imm16:

信号值
ALUSrc选 register rt
RegWr0
MemWr0
ALUCtrsubtract / compare equal
nPC_sel取决于 zero flag 和 branch control

做数据通路题的顺序:

  1. 这条指令要不要写寄存器?
  2. 写哪个寄存器?
  3. ALU 第二个输入来自寄存器还是立即数?
  4. 立即数是 sign extend 还是 zero extend?
  5. 结果来自 ALU 还是 memory?
  6. 要不要写 memory?
  7. PC 是 \(PC+4\) 还是 branch/jump target?
ISA 设计原则#

Hennessy 和 Patterson 总结的原则:

  1. Simplicity favors regularity。
  2. Make the common case fast。
  3. Smaller is faster。
  4. Good design demands good compromises。

ISA 设计要考虑:

  • 支持哪些数据类型。
  • 提供多少操作。
  • 每条指令几个 operand。
  • operand 放在寄存器还是内存。
  • 地址模式如何设计。
  • 指令长度固定、可变还是混合。
操作数数量#
类型特点
3-address两个 source,一个 destination,灵活但指令长
2-addressdestination 常复用一个 source,可能破坏原值
1-address隐含 accumulator,硬件简单但程序繁琐
0-addressstack machine,操作数隐含在栈顶

以:

Y = (A - B) / (C + (D * E))

为例,2-address instruction 可能写成:

MOV R1, A
MOV R2, D
SUB R1, B
MUL R2, E
ADD R2, C
DIV R1, R2

1-address accumulator instruction 把一个操作数隐含在 accumulator 中:

LDA D
MUL E
ADD C
STO R1
LDA A
SUB B
DIV R1

0-address stack instruction 把操作数隐含在栈顶:

PUSH B
PUSH A
SUB
PUSH E
PUSH D
MUL
PUSH C
ADD
DIV

区别抓手:

  • 3-address:表达自然,但 instruction 需要更多字段。
  • 2-address:指令较短,但会覆盖一个源操作数,常要先 MOV 保存原值。
  • 1-address:CPU 简单,但 accumulator 成为隐含瓶颈。
  • 0-address:指令短,表达式求值依赖栈顺序。
典型指令架构风格#
架构操作数位置典型特点
Stack architecture栈顶指令短,硬件围绕栈组织
Accumulator architectureaccumulator + memory/register硬件简单,程序中 load/store accumulator 频繁
Memory-Memory architecture源和目的都可在 memory指令表达力强,但访存多、实现复杂
Register-Memory architecture一个 operand 可在 memory,一个在 register比 load-store 灵活,但流水化更复杂
Load-Store architecture算术只在 registers 间,访存只靠 load/storeRISC 常用,数据通路规整,易流水化
Addressing Modes#
模式例子含义
ImmediateADD #5operand 本身就是值
DirectADD 100operand 是内存地址
IndirectADD [100]operand 指向的内存中存放真正地址
Register DirectADD R5operand 在寄存器
Register IndirectADD [R3]R3 中保存内存地址
RelativePC + offset常用于 branch
Indexedbase address + index常用于数组
Basedbase register + displacement常用于栈帧、结构体

寻址例题可以这样读:

写法含义
Load #800immediate addressing,加载数值 800 本身
Load 800direct addressing,加载内存地址 800 中的内容
Load [800]indirect addressing,先读地址 800 中保存的地址,再去那个地址取数
Load R1register direct,加载寄存器 R1 的值
Load R1[800]base/indexed addressing,用 R1 和偏移 800 形成有效地址

考试时先问“instruction 字段给的是值,还是地址,还是装着地址的地方”。这能快速区分 immediate、direct、indirect。

CISC 与 RISC#

CISC:

  • variable length instructions。
  • 指令和寻址模式丰富。
  • 解码复杂。
  • 可能包含 memory-to-memory 操作。
  • 常使用 microcode。

RISC:

  • fixed length instructions。
  • load-store architecture。
  • 较少寻址模式。
  • 硬连线控制。
  • 寄存器数量较多。
  • 更容易 pipeline。

现代 x86 常见现象:

  • 外部 ISA 是 CISC。
  • 内部微架构会把复杂 x86 指令翻译成更类似 RISC 的 micro-ops。
基本特点#

RISC-V 是开放的 RISC ISA 标准。

命名方式:

RV + word width + extensions

例子:

  • RV32I:32-bit base integer ISA。
  • RV32IM:RV32I 加整数乘除扩展 M。
  • RV32G:通常表示 IMAFD。

标准扩展:

扩展含义
IInteger base
MInteger multiplication and division
AAtomic
FSingle-precision floating point
DDouble-precision floating point
CCompressed 16-bit instructions
RISC-V 处理器状态#

包括:

  • PC
  • 32 个整数寄存器 \(x_{0}-x_{31}\)
  • \(x_{0}\) 恒为 0
  • \(x_{1}\) 常作为 return address
  • 32 个浮点寄存器 \(f_{0}-f_{31}\)
  • floating-point status register
指令格式#

RISC-V base instruction 通常是 32-bit,低两位为 11。

核心格式:

格式用途
R-typeregister-register arithmetic
I-typeload, immediate arithmetic, jalr
S-typestore
B-typeconditional branch
U-typeupper immediate
J-typeunconditional jump

重要规则:

  • register fields 的位置固定,便于硬件解码。
  • immediate 的 sign bit 总在 instruction bit 31。
  • branch/jump offset 按 2-byte 粒度组织,以兼容 compressed instructions。
RISC-V 指令格式字段细节#

R-type:

funct7 | rs2 | rs1 | funct3 | rd | opcode

典型:

add rd, rs1, rs2
sub rd, rs1, rs2

I-type:

imm[11:0] | rs1 | funct3 | rd | opcode

典型:

addi rd, rs1, imm
lw   rd, imm(rs1)
jalr rd, imm(rs1)

S-type:

imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode

典型:

sw rs2, imm(rs1)

B-type:

imm[12,10:5] | rs2 | rs1 | funct3 | imm[4:1,11] | opcode

典型:

beq rs1, rs2, label

U-type:

imm[31:12] | rd | opcode

典型:

lui   rd, imm20
auipc rd, imm20

J-type:

imm[20,10:1,11,19:12] | rd | opcode

典型:

jal rd, label

设计上看起来 immediate 被“拆散”了,但好处是:

  • rd, rs1, rs2 位置尽量固定。
  • sign bit 固定在 bit 31。
  • 硬件解码和符号扩展更规整。
常见指令类别#

R-type:

  • ADD, SUB
  • SLT, SLTU
  • SLL, SRL, SRA

I-type:

  • ADDI
  • SLTI, SLTIU
  • ANDI, ORI, XORI
  • SLLI, SRLI, SRAI
  • load instructions

U-type:

  • LUI
  • AUIPC

Control transfer:

  • JAL
  • JALR
  • conditional branches
Calling Convention#

函数调用阶段:

  1. 把参数放到 callee 可访问的位置。
  2. 用 jal 跳转到函数。
  3. callee 分配局部资源,必要时保存寄存器。
  4. 执行函数体。
  5. 把返回值放到 caller 可访问的位置,恢复寄存器,释放栈帧。
  6. 用 ret 返回。

概念:

名称含义
caller调用者
callee被调用函数
prologue函数入口保存寄存器、分配栈帧
epilogue函数出口恢复寄存器、释放栈帧
stack frame函数私有栈空间
fpframe pointer,常为 \(x_{8}\)
RISC-V 函数调用小例子#

C 代码:

int add2(int a, int b) {
    return a + b;
}

RISC-V 中常见约定:

a0 = 第 1 个参数 / 返回值
a1 = 第 2 个参数
ra = return address
sp = stack pointer

可能的汇编:

add2:
    add a0, a0, a1
    ret

如果函数内部还要调用别的函数,就必须保护 ra,因为新的 jal 会覆盖它:

foo:
    addi sp, sp, -16
    sw   ra, 12(sp)

    jal  bar

    lw   ra, 12(sp)
    addi sp, sp, 16
    ret

理解 prologue / epilogue:

  • prologue:进入函数时开栈帧、保存该保存的寄存器。
  • epilogue:返回前恢复寄存器、释放栈帧。
本章英文术语#
English中文复习提示
ISA指令集体系结构软件和硬件契约
microarchitecture微体系结构ISA 的具体实现
instruction set指令集机器可执行指令集合
opcode操作码指令做什么
operand操作数指令处理的数据
addressing mode寻址方式操作数在哪里
immediate addressing立即寻址操作数就是常数
direct addressing直接寻址字段给内存地址
indirect addressing间接寻址字段指向保存地址的位置
register direct寄存器直接寻址操作数在寄存器
register indirect寄存器间接寻址寄存器里保存内存地址
relative addressing相对寻址PC + offset
indexed addressing变址寻址base + index
based addressing基址寻址base register + displacement
stack architecture栈式架构操作数隐含在栈顶
accumulator architecture累加器架构一个操作数隐含在 accumulator
memory-memory architecture内存-内存架构操作数可都在内存
register-memory architecture寄存器-内存架构一个寄存器、一个内存
load-store architecture取存架构算术只访问寄存器
CISC复杂指令集指令复杂、寻址丰富
RISC精简指令集规整、load-store、易流水化
instruction format指令格式字段如何排列
R-typeR 型指令register-register arithmetic
I-typeI 型指令immediate, load, jalr
S-typeS 型指令store
B-typeB 型指令conditional branch
U-typeU 型指令upper immediate
J-typeJ 型指令jump
calling convention调用约定参数、返回值、寄存器保存规则
caller调用者发起调用的函数
callee被调用者被调用函数
stack frame栈帧函数私有栈空间
prologue函数序言保存寄存器、开栈帧
epilogue函数尾声恢复寄存器、释放栈帧

8. 中央处理器#

CPU 概述#

CPU 基本功能:

  • 取指令。
  • 译码。
  • 取操作数。
  • 执行运算或访存。
  • 写回结果。
  • 处理中断和异常。

CPU 基本组成:

部件作用
数据通路数据实际流动和处理的路径
控制器产生控制信号
ALU运算
寄存器堆保存临时数据
PC保存指令地址
指令存储器/数据存储器接口取指和访存
单周期 CPU#

单周期 CPU 中,每条指令在一个时钟周期内完成。设计步骤:

  1. 分析每条指令的功能。
  2. 确定需要哪些部件。
  3. 建立数据通路。
  4. 增加多路选择器以复用通路。
  5. 设计控制器产生控制信号。
  6. 根据最长指令路径确定时钟周期。

常见控制信号:

信号作用
RegWrite是否写寄存器
MemWrite是否写数据存储器
ALUSrcALU 第二操作数来自寄存器还是立即数
MemToReg写回数据来自 ALU 还是内存
Branch是否为分支指令
ALUOp指定 ALU 操作
多周期 CPU 和控制器#

多周期 CPU 把一条指令拆成多个阶段执行,每个阶段完成一部分操作。优点是:

  • 同一硬件可在不同周期复用。
  • 时钟周期可按较短阶段设置。
  • 控制器可用有限状态机描述。

控制器设计方式:

方式特点
硬连线控制器速度快,修改困难
微程序控制器控制逻辑像程序一样组织,灵活但可能较慢
流水线 CPU#

典型五级流水:

阶段含义
IF取指
ID译码/读寄存器
EX执行/地址计算
MEM访存
WB写回

流水线冒险:

冒险原因常见处理
结构冒险多条指令争用同一硬件增加硬件或暂停
数据冒险后续指令依赖前面结果forwarding 或 stall
控制冒险分支改变 PC分支预测、flush、stall

流水线提高吞吐率,但不一定降低单条指令延迟。

和前面章节的关系#

CPU 设计把前面几章的部件放到同一个时间结构中:组合逻辑负责“算出下一步”,触发器和寄存器负责“在时钟边沿保存状态”,控制器负责“根据指令产生选择信号”。单周期 CPU 的关键是连出完整数据通路,多周期 CPU 的关键是把每条指令拆成状态序列,流水线 CPU 的关键是把不同指令的不同阶段重叠执行并处理冒险。

做 CPU 数据通路题时,建议按以下顺序判断:

  1. 这条指令是否写寄存器。
  2. 写哪个寄存器。
  3. ALU 第二操作数来自寄存器还是立即数。
  4. 立即数需要 sign extension 还是 zero extension。
  5. 写回值来自 ALU、内存还是 PC+4。
  6. 是否写数据存储器。
  7. PC 下一值是顺序地址、branch target 还是 jump target。
本章英文术语#
English中文复习提示
CPU中央处理器fetch, decode, execute
datapath数据通路数据实际流动和处理
control unit控制器产生控制信号
control signal控制信号选择 mux、写寄存器、写内存等
program counter / PC程序计数器保存下一条指令地址
instruction memory指令存储器按 PC 取指
data memory数据存储器load/store 访问
register file寄存器堆两读一写等端口
single-cycle CPU单周期 CPU每条指令一个周期
multi-cycle CPU多周期 CPU一条指令拆多阶段
finite state controller有限状态控制器多周期控制常用
hardwired control硬连线控制组合逻辑产生控制
microprogrammed control微程序控制控制信号来自微指令
pipeline流水线不同指令阶段重叠
IF取指instruction fetch
ID译码instruction decode
EX执行execute / address calculation
MEM访存memory access
WB写回write back
hazard冒险pipeline 冲突
structural hazard结构冒险硬件资源冲突
data hazard数据冒险指令间数据依赖
control hazard控制冒险分支改变 PC
forwarding转发解决部分数据冒险
stall暂停插入等待
flush冲刷清除错误路径指令
branch prediction分支预测猜测分支方向

9. 存储器层次结构#

存储器概述#

存储器层次结构按速度、容量、成本组织:

寄存器
-> cache
-> 主存 DRAM
-> 外存 SSD/HDD

越靠近 CPU:

  • 速度越快。
  • 容量越小。
  • 单位成本越高。

局部性原理:

类型含义
时间局部性最近访问过的数据很可能再次访问
空间局部性访问某地址后,附近地址也可能被访问
主存储器#

SRAM:

  • 速度快。
  • 成本高。
  • 常用于 cache。

DRAM:

  • 密度高。
  • 成本低。
  • 需要刷新。
  • 常用于主存。

存储器扩展:

  • 位扩展:增加数据宽度。
  • 字扩展:增加地址空间容量。
  • 字位同时扩展:同时增加宽度和容量。
Cache#

cache 是主存的高速缓存。基本工作方式:

  1. CPU 发出地址。
  2. cache 判断是否命中。
  3. 命中则直接返回数据。
  4. 缺失则从主存取块并填入 cache。

映射方式:

方式特点
直接映射每个主存块只能放到固定 cache 行
全相联映射可放到任意 cache 行
组相联映射先选组,再在组内任意放置

替换算法:

  • 随机替换。
  • FIFO。
  • LRU 或近似 LRU。

写策略:

策略含义
write-through写 cache 同时写主存
write-back先只写 cache,替换时写回主存
write-allocate写缺失时把块调入 cache
no-write-allocate写缺失时直接写主存
虚拟存储器#

虚拟存储器把主存看作外存的缓存,为每个进程提供独立虚拟地址空间。

分页式虚拟存储:

  • 虚拟地址空间划分为虚拟页。
  • 物理内存划分为页框。
  • 页表记录虚拟页到物理页框的映射。
  • 访问未在主存中的页会发生缺页异常。

虚拟存储器的作用:

  • 扩大程序可用地址空间。
  • 实现进程隔离。
  • 支持按需调页。
  • 提供存储保护。
和 CPU 执行的关系#

存储层次结构的目标是在“容量、速度、成本”之间折中。寄存器和 cache 让 CPU 尽量少等主存,虚拟存储器让每个进程看到独立的地址空间。理解存储器时要抓住两个缓存关系:cache 是主存的缓存,主存又可以看作外存的缓存。

本章英文术语#
English中文复习提示
memory hierarchy存储器层次结构speed, capacity, cost 折中
SRAM静态随机访问存储器快、贵、常用于 cache
DRAM动态随机访问存储器密度高、需刷新、常用于主存
cache高速缓存主存缓存
cache hit缓存命中数据在 cache 中
cache miss缓存缺失需访问下一层
hit rate命中率命中次数比例
miss rate缺失率缺失次数比例
block / cache line块 / 缓存行cache 和 memory 之间传输单位
direct-mapped cache直接映射 cache每个内存块只到一个位置
set-associative cache组相联 cache每块映射到某组内任一路
fully associative cache全相联 cache可放任意位置
tag标记判断 cache line 是否匹配
valid bit有效位判断 cache line 是否有效
dirty bit脏位write-back 时表示被修改
replacement policy替换策略cache 满时换谁
LRU最近最少使用least recently used
write-through写直达写 cache 同时写主存
write-back写回替换时写回主存
write-allocate写分配写缺失时调入 cache
no-write-allocate非写分配写缺失时直接写主存
virtual memory虚拟存储器地址空间抽象
virtual address虚拟地址程序看到的地址
physical address物理地址实际内存地址
page页虚拟地址空间单位
page frame页框物理内存单位
page table页表虚拟页到物理页框映射
page fault缺页异常访问页不在主存

10. 系统互连与输入/输出#

外设与系统总线#

外设分为:

类型例子
输入设备键盘、鼠标、扫描仪
输出设备显示器、打印机
输入/输出设备磁盘、网卡、触摸屏

总线是部件之间传递信息的公共路径。系统总线通常包括:

  • 地址线。
  • 数据线。
  • 控制线。

总线性能指标:

指标含义
总线宽度一次并行传输的数据位数
工作频率数据传输频率
带宽单位时间最大传输数据量
寻址能力地址线决定可访问空间大小

带宽常用估算:

$$ B=\frac{W\times F}{N} $$

其中 $W$ 为一次传输数据量,$F$ 为时钟频率,$N$ 为一次传输所需周期数。

I/O 接口和端口#

I/O 接口也称设备控制器,位于外设和总线之间。功能包括:

  • 数据缓冲。
  • 状态检测。
  • 控制和定时。
  • 数据格式转换。

I/O 端口是 I/O 接口中 CPU 可访问的寄存器:

端口作用
数据端口传输数据
状态端口读取设备状态
控制端口写入控制命令

端口编址方式:

方式特点
独立编址I/O 地址空间和内存地址空间分离,需要专用 I/O 指令
统一编址I/O 端口像内存单元一样编址,也称 memory-mapped I/O
输入/输出控制方式#

程序直接控制:

  • CPU 主动查询设备状态。
  • 简单,但 CPU 可能长时间等待。

中断控制 I/O:

  • 设备完成或就绪后向 CPU 发中断。
  • CPU 可在等待期间执行其他程序。
  • 需要中断响应和中断服务程序。

DMA:

  • Direct Memory Access。
  • 外设和主存之间由 DMA 控制器直接传输数据。
  • CPU 只负责初始化和收尾。
  • 适合磁盘等高速块设备。

三种方式对比:

方式CPU 参与程度适用场景
程序查询高简单低速设备
中断中低速或中速异步设备
DMA低大批量高速数据传输
I/O 软件层次#

一次 I/O 请求通常经过多个软件层次:

用户程序 / C 库函数
-> 系统调用
-> 与设备无关的 I/O 软件
-> 设备驱动程序
-> 中断服务程序
-> I/O 控制器和外设

与设备无关软件负责:

  • 统一设备驱动接口。
  • 缓冲区管理。
  • 错误报告。
  • 文件打开关闭等通用操作。
  • 逻辑块大小处理。

设备驱动程序负责:

  • 操作具体设备控制器。
  • 读写控制/状态/数据端口。
  • 启动设备。
  • 处理中断或 DMA 完成事件。

中断服务程序包含:

  1. 准备阶段:保存断点和现场,设置屏蔽字。
  2. 处理阶段:执行具体中断服务。
  3. 恢复阶段:恢复现场并返回。
三种 I/O 方式的直觉#
方式谁等谁CPU 负担适合场景
程序查询CPU 等设备高简单低速设备
中断设备就绪后通知 CPU中异步低速/中速设备
DMADMA 控制器接管总线传块低磁盘、网卡等大批量高速传输

中断请求的是 CPU 时间,DMA 请求的是总线控制权。这个区别很重要。

本章英文术语#
English中文复习提示
peripheral外设键盘、显示器、磁盘等
system bus系统总线address, data, control
address bus地址总线传地址
data bus数据总线传数据
control bus控制总线传控制信号
bus width总线宽度一次并行传输位数
bandwidth带宽单位时间传输量
latency延迟一次访问等待时间
I/O interfaceI/O 接口也叫设备控制器
device controller设备控制器外设和总线之间
data register数据寄存器存数据
status register状态寄存器存设备状态
control register控制寄存器接收 CPU 命令
port端口I/O 寄存器地址
isolated I/O独立编址 I/OI/O 地址空间独立
memory-mapped I/O存储器映射 I/OI/O 映射到内存地址
programmed I/O程序查询 I/OCPU 轮询设备
interrupt中断设备通知 CPU
interrupt service routine / ISR中断服务程序处理中断
device driver设备驱动程序操作具体设备控制器
system call系统调用用户程序进入内核
DMA直接内存访问设备接管总线传输
DMA controllerDMA 控制器控制块传输
polling轮询CPU 不断检查状态
buffering缓冲平衡速度差异

11. 程序从源代码到运行#

这一部分把“程序如何落到机器上运行”接到前面的 ISA、存储器和操作系统接口上,重点看编译、汇编、链接、加载之间的分工。

编译链路#

C 程序到运行的逻辑步骤:

.c -> .i -> .s -> .o -> executable -> running process
阶段输入输出作用
preprocessor.c.i展开宏、include
compiler.i.s生成汇编
assembler.s.o生成 relocatable object
linker多个 .o 和 librariesexecutable符号解析、重定位
loaderexecutableprocess加载到内存并跳转入口
ELF#

ELF 是 Unix-like 系统常见目标文件格式。

三类 object file:

类型含义
relocatable file可与其他 object 链接,如 .o
executable file可执行程序
shared object file动态库,如 .so

常见 section:

section内容
.textinstructions
.rodataread-only constants
.datainitialized global/static data
.bssuninitialized global/static data
symbol table符号定义和引用
relocation info需要链接器修补的位置
ELF 中符号放在哪里#

看 C 代码:

#define ITEM_NUM 16
static int item_size = 4;
int global_count;

int add(int x, int y) {
    return x + y;
}

int main() {
    char *p = malloc(64);
    return add(item_size, ITEM_NUM);
}

分类:

符号位置 / 类型原因
\(ITEM_{NUM}\)不一定进入 symbol table宏在预处理阶段直接替换
\(item_{size}\).data 中的 local symbolstatic 且已初始化
\(global_{count}\).bss 中的 global symbol全局未初始化
add.text 中的 global symbol函数定义
main.text 中的 global symbol函数定义
mallocimported / undefined symbol当前文件引用但未定义

这类题要分清:

  • 宏不是运行时对象。
  • initialized data 和 uninitialized data 放不同 section。
  • static 限制链接可见性,不代表一定在栈上。
  • 外部库函数在当前 .o 里通常是 unresolved external reference。
Assembler 与 Linker#

assembler 要处理:

  • pseudo-instructions。
  • local labels。
  • forward references。
  • 生成 object file。

linker 主要做:

  1. 合并各 object 的 text/data 等 segment。
  2. 符号解析:找到 undefined external symbol 的定义。
  3. 重定位:修正地址。
  4. 记录 entry point。

注意:C/C++ 程序真正入口通常不是 main,而是 _start 或 crt0 相关启动代码。启动代码初始化运行时环境后再调用 main。

Static Linking 与 Dynamic Linking#

Static linking:

  • 链接时把需要的库代码合入 executable。
  • 启动时简单。
  • 可执行文件可能更大。
  • 库更新后程序不自动使用新版库。

Dynamic linking:

  • 运行时加载并解析共享库。
  • 多个程序可共享同一份库代码。
  • 使用 GOT 和 PLT 支持延迟绑定。

PIC:

  • position-independent code。
  • 代码不依赖固定加载地址。
  • 常用于 shared libraries。
链接和加载的直观区别#

链接 linker 解决的是“文件之间怎么拼起来”:

  • 多个 .o 合并。
  • 找到函数和全局变量的定义。
  • 修补地址。
  • 生成 executable。

加载 loader 解决的是“executable 怎么变成进程”:

  • 创建地址空间。
  • 把 text/data 映射进内存。
  • 建 stack / heap 初始布局。
  • 设置参数、环境变量。
  • 跳到 entry point。

一句话:

linking makes a complete program file.
loading makes a running process.
Loader 与进程内存布局#

loader 的工作:

  1. 读取 executable header。
  2. 分配地址空间。
  3. 把 text/data segment 放入内存。
  4. 清零 .bss。
  5. 建立 stack。
  6. 设置参数和环境变量。
  7. 跳转到 entry point。

典型内存布局:

high address
stack      grows downward
...
heap       grows upward
static data
text
low address
本章英文术语#
English中文复习提示
preprocessing预处理宏展开、头文件包含
compilation编译C 转 assembly
assembly汇编assembly 转 object
linking链接object 合并成 executable
loading加载executable 变运行进程
preprocessor预处理器处理 #include、#define
compiler编译器生成汇编或机器代码
assembler汇编器assembly 转 object file
linker链接器合并 object、解析符号、重定位
loader加载器建地址空间并跳到入口
object file目标文件尚不可直接运行
executable file可执行文件可被 loader 加载运行
shared object共享对象 / 动态库.so
ELF可执行和可链接格式object/executable/shared object
section节.text、.data、.bss 等
text section代码节instructions
rodata section只读数据节read-only constants
data section数据节initialized global/static data
bss sectionBSS 节uninitialized global/static data
symbol table符号表记录定义和引用
undefined symbol未定义符号当前文件引用但未定义
relocation重定位修补地址
entry point入口点程序开始执行位置
static linking静态链接库代码合入 executable
dynamic linking动态链接运行时加载共享库
GOT全局偏移表global offset table
PLT过程链接表procedure linkage table
PIC位置无关代码shared library 常用
process address space进程地址空间text/data/heap/stack
heap堆动态分配区,通常向高地址增长
stack栈调用栈,通常向低地址增长

12. 统一复习表#

各章重点#
章重点
1冯·诺依曼结构、抽象层、进制转换、C 位/逻辑运算、补码、浮点、大小端
2逻辑门、数字抽象、CMOS、电气参数、布尔代数、Shannon、标准形式、K-map
3组合逻辑设计流程、HDL flow、译码器、编码器、MUX/DEMUX、加法器、时序分析
4FSM、锁存器、触发器描述表、同步时序设计、总线、移位寄存器、计数器
5FPGA、HDL 流程、Verilog 模块/数据类型/建模方式
6RCA/CLA、标志位、ALU、barrel shifter、补码加减、乘除法、浮点运算
7ISA、操作数数量、寻址方式、指令架构风格、RISC-V 指令集
8单周期 CPU、多周期 CPU、控制器、流水线和冒险
9SRAM/DRAM、cache、映射、替换、写策略、虚拟存储器
10总线、I/O 接口、端口编址、查询/中断/DMA、I/O 软件层次
11预处理、编译、汇编、链接、ELF、加载、进程内存布局
必须能解释#
  • 为什么 signed 和 unsigned 转换时 bit pattern 不变但值会变。
  • 为什么补码可以用同一个加法器实现加减法。
  • 为什么 signed overflow 不能只看 carry out。
  • IEEE 754 中 normalized、denormalized、infinity、NaN 的判定。
  • C 的 &/\(|\)/~/\(^\) 与 &&/\(||\)/! 为什么不是一类运算。
  • noise margin、propagation delay、transition time、fan-in/fan-out、static/dynamic power 分别看什么。
  • canonical SOP/POS 与 standard SOP/POS 的区别。
  • prime implicant 和 essential prime implicant 为什么影响 K-map 选圈。
  • Verilog 中 wire 和 reg 的使用语境。
  • 组合逻辑和时序逻辑的根本区别。
  • latch、pulse-triggered flip-flop、edge-triggered flip-flop 的触发差异。
  • characteristic table 和 excitation table 分别回答什么问题。
  • Mealy 和 Moore FSM 的输出区别。
  • setup/hold 约束的意义。
  • multiplexer bus 和 three-state bus 的核心差别。
  • RCA、CLA、prefix adder 的速度和硬件代价差异。
  • barrel shifter 为什么是组合逻辑,而 shift register 是时序逻辑。
  • Booth algorithm 为什么能减少部分积。
  • ISA 和 microarchitecture 的区别。
  • 0/1/2/3-address instruction 对硬件和程序长度的影响。
  • stack、accumulator、memory-memory、register-memory、load-store 架构的区别。
  • RISC-V R/I/S/B/U/J 格式分别服务什么指令。
  • .c 到进程运行的每个阶段在解决什么问题。
易错点清单#
  • 位运算的返回值是 bit pattern;逻辑运算返回 0 或 1,且可能短路。
  • unsigned 循环变量做 \(i \ge 0\) 这种条件时可能永远为真。
  • signed 和 unsigned 混合比较时,signed 会被转换成 unsigned。
  • signed 右移负数通常是算术右移,不等价于 C 除法的向 0 截断。
  • 浮点数不满足普通实数的结合律。
  • K-map 中 don't care 是可选工具,不是必须全部当作 1。
  • \(always @(*)\) 中组合逻辑分支不完整会推导出 latch。
  • SR latch / SR flip-flop 有非法输入组合,D latch 用一个数据输入规避它。
  • 3-state bus 同时使能多个 driver 会造成 bus contention。
  • Moore FSM 通常比 Mealy FSM 多状态。
  • ripple counter 不是严格同步电路。
  • signed SLT 不能只看减法结果符号位,要考虑 overflow。
  • load-store ISA 中,算术指令通常不直接访问内存。
  • RISC-V 的 \(x_{0}\) 不能被改写。
  • object file 不是 executable,必须链接后才可直接运行。
易混概念#
概念 A概念 B区别
ISA微体系结构ISA 定义机器接口;微体系结构实现 ISA
位运算逻辑运算前者逐 bit;后者按 true/false,结果 0/1
组合逻辑时序逻辑前者无状态;后者依赖历史状态
latchflip-flop前者电平敏感;后者边沿敏感
characteristic tableexcitation table前者由输入求下一状态;后者由状态转移反推输入
barrel shiftershift register前者组合逻辑一次得到结果;后者用触发器逐拍移位
mux busthree-state bus前者用 mux 选一路;后者靠 high-Z 和 enable 共享连线
SRAMDRAMSRAM 快且贵;DRAM 密度高但需刷新
cache虚拟存储器cache 缓存主存;虚拟存储器把主存作为外存缓存
中断DMA中断请求 CPU 时间;DMA 请求总线控制权
独立编址统一编址前者 I/O 地址空间独立;后者 I/O 映射到内存地址空间
CISCRISC前者指令/寻址复杂;后者规整、load-store、易流水化
常用公式#

无符号范围:

$$ 0 \le x \le 2^w-1 $$

补码范围:

$$ -2^{w-1} \le x \le 2^{w-1}-1 $$

补码取负:

$$ -x = \sim x + 1 $$

无符号加法:

$$ UAdd_w(u,v) = (u+v)\bmod 2^w $$

无符号乘法:

$$ UMult_w(u,v) = (uv)\bmod 2^w $$

CLA:

$$ G_i = A_iB_i,\quad P_i = A_i+B_i $$
$$ C_{i+1}=G_i+P_iC_i $$

Full adder:

$$ S = A \oplus B \oplus C_{in} $$
$$ C_{out}=AB+AC_{in}+BC_{in} $$

Noise margin:

$$ NM_H=V_{OH}-V_{IH},\quad NM_L=V_{IL}-V_{OL} $$

浮点数:

$$ V=(-1)^sM2^E $$

时钟周期:

$$ t_{clk} \ge t_{ffpd}+t_{comb}+t_{setup} $$

Hold 约束:

$$ t_{hold} \le t_{ffpd}+t_{comb} $$

简化 MIPS branch target:

$$ PC_{next}=PC+4+(sign\_ext(imm)\ll 2) $$

RISC-V branch target:

$$ PC_{next}=PC+sign\_ext(imm) $$

其中 B-type immediate 编码已经隐含最低位 0,因此目标地址按 2-byte 粒度对齐。

总线带宽估算:

$$ B=\frac{W\times F}{N} $$