数字电路知识点记录

TL;DR

最近太无聊,重新拾起cs61c课程,开始有些痛苦的数字电路学习。

我的仓库

这个博客就用来记录一下各种硬件的引脚和电路设计等知识。


Warm up Basic

在更高抽象的程序中,一般情况下都是串行的。

但是在硬件视角中,都是并行的。(电路很快,所以要有负反馈/回授等概念)

在硬件中,这些都是一瞬间发生的,所以是并行

Boolean Expression

布尔表达式,数字电路中的基础内容,通过TrueFalse构成的逻辑语句。

在绘制电路图前,需要先根据算法来构建对应的布尔表达式。

真值构建法

在数字电路中,通常需要先构建一个真值表,主要采用下面几种方式

① 积之和形式(SOP - Sum of Products / 主析取范式)

  • 核心原则:关注输出为 1 的行。
  • 构建步骤
    1. 找出使输出 Y = 1 的所有输入组合。
    2. 为每一行写出一个最小项(Minterm):变量为 1 写原变量,为 0 写反变量,中间用 AND 链接。
    3. 将所有最小项用 OR连接起来。

② 和之积形式(POS - Product of Sums / 主合取范式)

  • 核心原则:关注输出为 0 的行。
  • 构建步骤
    1. 找出使输出 Y = 0 的所有输入组合。
    2. 为每一行写出一个最大项(Maxterm):变量为 0 写原变量($A$),为 1 写反变量($\bar{A}$),中间用 OR 链接。
    3. 将所有最大项用AND连接起来。

Register 寄存器

Register

Register如图所示包含4个引脚,D,Q,WE,R

引脚名称全称含义与作用信号类型
DData In (数据输入端)待写入的数据。在时钟上升沿到来时,如果允许写入,输入到 D 的数值就会被存入寄存器内部。数据线 (多位)
QOutput / Queue (数据输出端)当前保存的状态值。时刻对外输出当前存储在寄存器里的数据(即上一周期写入的内容)。数据线 (多位)
WEWrite Enable (写使能端)写入控制信号。只有当 WE 处于高电平 (1) 时,寄存器才会在时钟触发时更新数据;若为 0,数据保持不变。控制线 (1 位)
RReset (复位/清零端)强制清零信号。当 R 输入高电平 (1) 时,无论输入 D 是什么,寄存器内部的值都会被立刻清零。控制线 (1 位)

寄存器是靠时钟驱动存储,寄存器内部采用Edge-Triggered Flip-Flops构建,不会随时随地接收D端数值并且改变

在两个时钟沿之间(平稳期):寄存器内部的值不变

在时钟上升沿到达的瞬间:寄存器把此时刻输入端 D 上的电平锁存到内部,并更新输出端Q

如果寄存器不按周期存储,而是输入 D 一变就立刻存入内部,电路中包含很多负反馈

会导致不可控的竞争和Dead Lock

在这期间,Setup TimeHold Time是两个核心条件

  • 建立时间 (Setup Time)

    在时钟上升沿到达之前,输入端 D 上的数据信号必须提前保持稳定的最短时间。

  • 保持时间 (Hold Time)

    在时钟上升沿到达之后,输入端 D 上的数据信号必须继续维持稳定的最短时间。

两者共同在时钟沿前后构成了一个稳定的数据有效窗口


Multi-Bit Adder 多位加法器

Adder

引脚名称缩写/标识方向/类型功能与作用说明
Data AData A输入 (Input)加数 A 输入端,位宽与组件属性的 Data Bits 相同(默认为 8 位)。
Data BData B输入 (Input)加数 B 输入端,位宽与组件属性的 Data Bits 相同(默认为 8 位)。
Carry Inc in输入 (Input)进位输入端,1 位信号。用于多位加法器级联,若输入为 1,计算结果将额外加 1。若不连接,默认为 0
OutputSum / 无输出 (Output)加法和计算结果输出端,位宽与 Data Bits 相同(计算结果:(A + B + c_in) mod 2^N)。
Carry Outc out输出 (Output)进位输出端,1 位信号。当无符号加法运算发生溢出(计算结果大于最高位可表达范围 2^N - 1)时输出 1,否则输出 0

A和B的传入位宽必须相同


FSM logic

FSM Logic(有限状态机逻辑,Finite State Machine Logic),它是数字电路中最核心的控制单元。

递增器就是一个简单的有限状态机,状态随着加法器逐渐递增。

CPU 执行一条指令分为 Fetch -> decode -> Execute -> Writeback,这本质上就是 CPU 内部的状态机在按照时钟节拍不断进行状态切换和信号控制

FSM核心要素

任何一个有限状态机逻辑,都可以拆解为以下 3 个要素:

  1. 状态(States):系统当前所处的模式或阶段(例如:等待读取写入报错)。必须是有限个。
  2. 输入(Inputs):触发状态改变或控制输出的外部信号。
  3. 状态转移与输出(Transitions & Outputs):在什么条件下从“状态 A”切换到“状态 B”,以及在此过程中产生什么控制信号。

所以在硬件系统中的FSM的基础结构就是:

fsm

状态机类别

类型输出取决于什么?特点
Moore 型状态机仅取决于“当前状态” ($Output = f(State)$)输出非常稳定,只在状态改变时变化。响应相对延迟一个周期。
Mealy 型状态机取决于“当前状态”+“当前输入” ($Output = f(State, Input)$)外部输入一变,输出立刻响应(无需等下一个时钟),但容易产生毛刺(Glitch)。

MUX

多路选择器,作用是从多个输入中选择一个,输出到唯一输出端

用简单的二选一MUX举例演示原理

$$Y = (\bar{S} \cdot I_0) + (S \cdot I_1)$$

这个公式就展示了它的基本原理


时钟

这个需要在两个层面上来讲,硬件层面和抽象层面

在过去学习操作系统时,还有一个更高级的时钟抽象,但两者完全不在一个层面上

电路视角

在 RTL 和数字逻辑设计中,时钟是一个硬件物理信号。时钟树将方波送到每一个触发器的 CLK 引脚,仅此而已

存在的目的是为了保证数据在下一个上升沿到来前建立完毕(满足 Setup Time),从而稳定锁存状态。

用于在硬件电路中推进流水线

OS视角

在 OS 视角下,硬件的连续方波被封装成了抽象的“时间概念”

硬件定时器(如 APIC TimerHPETRISC-V mtime)按设定频率产生中断,OS 在中断处理函数中递增全局计数器(如 Linux 的 jiffies),并更新 xtime(POSIX 真实时间)

他们的存在主要是为了驱动任务调度

OS时钟抽象实现方案

  • 操作系统算好下一个 Tick 或高精度定时事件需要在 T next 时刻触发,把T next写入 Compare 寄存器

  • 电路内部有一个组合逻辑比较器,输入端分别接 Counter 和 Compare

  • 当 Counter 递增到 大于等于 Compare 的值时,比较器输出高电平,拉高 CPU 的时钟中断引脚

  • CPU 暂停当前任务进入 OS 中断处理函数,OS 完成调度或定时任务后,重新计算下一次触发时间,修改 Compare 寄存器的值为一个新的更大数值,中断信号自动清零,等待下一次匹配

有些方案采用的是递减到0的寄存器方案,但是有一些弊端

Reference:

recent-work

Rust的内存模型

TL;DR 最近在尝试rCore这个内核实验 这本教程旨在一步一步展示如何 从零开始 用 Rust 语言写一个基于 RISC-V 架构的 类 Unix 内核 。 所以只是理解Rust的各种语言特性就不够了,需要学习Rust的内存模型,理解它是如何在内存空间中组织各个实例 基于 …

Read more →

数字电路知识点记录

TL;DR 最近太无聊,重新拾起cs61c课程,开始有些痛苦的数字电路学习。 我的仓库 这个博客就用来记录一下各种硬件的引脚和电路设计等知识。 Warm up Basic 在更高抽象的程序中,一般情况下都是串行的。 但是在硬件视角中,都是并行的。(电路很快,所以要有负反馈/回授等 …

Read more →