【计算机系统架构】从0开始构建一台现代计算机|时序逻辑、主存储器|第2章

在这里插入图片描述

  • 博主简介:努力学习的22级计算机科学与技术本科生一枚🌸
  • 博主主页: @Yaoyao2024
  • 往期回顾: 【计算机系统架构】从0开始构建一台现代计算机|二进制、布尔运算和ALU|第2章
  • 每日一言🌼: 孤独和喧嚣都令人难以忍受。如果一定要忍受,我宁可选择孤独。
    —— 周国平

0、前言

  • 一言以蔽之: 在构建了计算机的 ALU 之后,本 Modulation 将转向构建计算机的主存储器单元,也称为随机存取存储器或RAM。这项工作将自下而上逐步完成,从初级触发器门到一位寄存器,再到 n 位寄存器,直至一系列 RAM 芯片。与基于组合逻辑的计算机处理芯片不同,计算机的存储逻辑需要基于时钟的顺序逻辑(时序逻辑电路)。我们将首先概述这一理论背景,然后构建我们的内存芯片组
  • 关键概念:组合逻辑与时序逻辑、时钟与周期、触发器、寄存器、RAM 单元、计数器。

1、时序逻辑(Sequential Logic)

1.0 前言

在前面两章中,我们学习到一些逻辑门,他们代表着输入和输出的映射关系。但是我们并没有“时间”的概念,更通俗来说,我们的概念中,并不是先有输入,然后才有了输出;而是在输入的同一时间即刻得到的输出,我们并没有“One thing after an other”的概念。

但是现实生活中我们必须关注“时间”,因为我们就是生活在时间当中的,我们的任何行动和行为都是具有时间概念的,计算机也必须拥有时间,也才能更好地像人一样工作,否则则是混乱的。

💁🏻‍♀️其实在本节学习计算机中的"时间"这个概念的时候,老师说我们之前几节学的组合逻辑,并不是先有输入,然后才有了输出(one after another);我其实比较纳闷,哪电流信号从输入信号流入,通过组合逻辑电路得到输出,肯定有时间的呀!!
但其实我这种想法是比较错误的,对于我们人来说,的确是有时间的,但是对于计算机来说,其实是没有时间的,因为你没有给它这个概念,时间也无法度量,对于它来说其实并不是`one thing after another"的。

要想计算机拥有时间的概念之前,我们再来深入地分析一下,时间的作用。

1.1 时间的作用

  • Use the same hardware over time(硬件的复用性)

    组合逻辑电路是可以复用的,但它的复用方式和时间的关系不同。我们先来理解组合逻辑电路和时间之间的关系。

    组合逻辑电路是一种不涉及存储的电路。它根据输入直接产生输出,输出完全由当前输入决定,和时间无关。所以,对于同样的输入,组合逻辑电路总是会立即产生相同的输出,不管什么时候输入是一样的,它都能立刻给出结果。

    但是,当我们说到需要“复用硬件”时,指的是计算机需要处理连续的、不同的计算任务,而这些任务不可能在同一时间内同时完成。时间在这里的作用是让计算机能够依次处理这些任务。例如,如果你有多个加法操作要进行,虽然组合逻辑电路可以同时处理多个加法,但硬件资源有限(例如一块特定的加法电路),计算机会按顺序利用这块电路来完成不同的加法任务。

    所以,组合逻辑电路本身是可以复用的,但复用它时依然需要时间。因为我们希望通过一个硬件单元(例如加法器)来处理不同的输入和任务,而不是为每个任务都配备独立的硬件。时间允许我们复用同一块硬件去完成多个操作,这样就可以节约资源。

    总的来说,复用硬件是指在不增加额外硬件的情况下,通过时间的控制,让一块硬件能够连续完成多个任务。

  • Remember state
    记录中间状态

    比如我们要计算一个数累加100次,如果不能记录每次中间得到的结果,就不可能得到正确答案

  • Deal with speed

    这段话主要讲了一个我们不想特别关心,但又必须考虑的关于时间的因素:计算机的速度有限

    具体来说,计算机处理任务的速度并不是无限的,它有一个固定的、有限的运行速度。因此,我们在设计程序或系统时,必须考虑到计算机的这个限制。我们不能要求计算机超出它的能力去完成任务,或者至少要知道计算机的运行速度是多少,这样才能合理地安排任务的执行。

    打个比方,就像我们不可能要求一个人每秒钟完成100件事一样,计算机也有它的极限。即使我们希望计算机能尽快完成任务,但实际上它的速度是受限的。因此,我们需要确保我们的程序不会让计算机超负荷工作,或者根据它的速度合理地安排计算任务,以避免程序崩溃或运行不稳定。

    总结一下:虽然我们更关注如何复用硬件和处理连续任务,但我们也必须注意到计算机的运行速度有限,不能让它超出能力范围工作。因为计算机不能超出其最大速度去处理任务,所以我们需要合理安排任务的顺序和执行时间。这也就是为什么我们说计算机的有限速度让时间变得重要。时间在这里的作用是分配和协调任务,确保计算机有足够的时间去完成每一项操作

1.2 时钟

时钟是计算机里来衡量和表示时间的方法。和现实世界中的时钟一样, 它的作用就算将连续的时间信号离散化,变为一个一个单位进行时间的衡量。

在这里插入图片描述

如上图,物理世界中的时间是连续的,而时钟的作用就是将时间离散化、量化,变成一个时间序列:time=1、time=2、time=3...。一个周期就是一个时间单位;在一个整数时间单位内,我们认为电路中不会有信号的改变。

在把时间量化后,输入输出的时间先后顺序是这样表示的:在t-1这个时间单位输出做出的改变,会在t时刻输出。这就完全不同于之前没有先后顺序的组合逻辑电路:在t-1这个时间单位输出做出的改变,会在t-1时刻l立刻输出。

👧🏻所以我个人认为拥有时钟来表示时间,就是量化时间,从而更好地更清晰的表示先后顺序,从而保证系统的稳定性,这点可以在下一节讲信号的延迟中可以看出。

1.3 信号的延迟

这点也进一步解释了我们为什么希望使用clock来将时间离散化,目的也是为了忽略不计这些信号的延迟!避免延迟带来的影响。对时钟时间周期选择的目的(不能太快,当然也不能太慢)的目的就是为了让硬件运行地更加稳定。

上面我们提到,虽然在组合电路中,对于计算里来说,是没有时间概念的;但是我们知道,在电路中,输入的物理信号用电信号表示,从输入到输出,是电子流动和聚集的过程,这在现实的物理世界中肯定是需要时间的,且在这段时间内的电信号变化是连续的而非条约的。即:从输入信号到输出信号存在延迟。
在这里插入图片描述
而在计算机内部建立起这种离散化的数字时间,其实也是为了避免信号的延迟!

为什么这么说呢?如下图,只要我们的时钟的速度不是太快,在连续的延迟之间流出足够多的时间等待信号达到稳定(即灰色区域后),当周期结束时,即可取得最终稳定的信号:

在这里插入图片描述
事实上,在选取时钟周期的前提也是确保所有的硬件都能稳定下来。

1.4 组合逻辑和时序逻辑的区别

∙ Combinatorial:  o u t [ t ] = f u n c t i o n ( i n [ t ] ) ∙ Sequential:  o u t [ t ] = f u n c t i o n ( i n [ t − 1 ] ) \bullet\text{Combinatorial: }out[t]=function(\:in[t]\:)\\\bullet\text{ Sequential: }out[t]=function(\:in[t-1]\:) Combinatorial: out[t]=function(in[t]) Sequential: out[t]=function(in[t1])

其实在上面的1.2小节已经讲到过了:

下面这个例子也是对组合逻辑和时序逻辑的比较:

  • 组合逻辑:
    在这里插入图片描述

  • 时序逻辑:
    在这里插入图片描述

2、时序逻辑的基本单元:D触发器 (D Flip-Flop)

D触发器是时序逻辑电路的基础,它可以保存一个bit的信息,这也为之后保存大量的字节内容奠定了基础

2.0 前言

在前面一小节我们讲解了时序逻辑电路,它的核心就是数字化和离散化了时间,让先后顺序更加量化和明确。这一小节,我们将从硬件实现 的角度出发,实现 s t a t e [ t ] = f u n c t i o n ( s t a t e [ t − 1 ] ) state[t]=function(state[t-1]) state[t]=function(state[t1]) 的时序逻辑。

2.1 状态的记忆:Remembering State

  • 首先,实现时序逻辑的关键就是记忆状态: 记住时刻的信息直到t时刻使用。Missing ingredient:remember one bit of information from time t-1 so it can be used at timet
  • 那么我们知道,这个记忆状态的元件肯定有两种状态:1 or 0; 并且根据t-1时刻的信号进行翻转flip01之间进行转换

上述实现这种在单位时间内进行信号状态记忆的元素称为 触发器(Clocked Data Flip Flop).

2.2 Clocked Data Flip Flop:D触发器

💜介绍:

如下图,D触发器有一个输入in和一个输出out;作用是记录上一个单位时间的输入,然后在下一个单位时间输出: o u t [ t ] = i n [ t − 1 ] out[t]=in[t-1] out[t]=in[t1]
在这里插入图片描述

注意:图中的正三角形🔺是【时钟脉冲沿】的意思,表示这个器件是时序逻辑下的芯片,与时钟有关;触发器输出的状态由该脉冲沿的状态来决定,三角符号下边有圆圈的表示时钟脉冲下降沿触发有效,无圆圈的则表示时钟脉冲上升沿触发有效。即,理解如下: 下一个周期的输出信号由上一个周期末尾结束的上升沿采样值确定。
在这里插入图片描述

🥗D触发器的实现:

  • 在这门课中,我们不会去关系它的内部地层实现,而是默认它是有记忆功能的原始器件即可。In this course:it is a primitive

  • In many physical implementations,it may be built from actual Nand gates:
    Step 1:create a"loop”achieving an“un-clocked”flip-flip
    Step 2:Isolation across time steps using a "master-slave"setup

  • Our Hardware Simulator forbids “combinatorial loops”

    • A cycle in the hardware connections is allowed only if it passesthrough a sequential gate

2.5 时序逻辑的实现

在这里插入图片描述

上图展示了我们将在计算机中构建的所有逻辑的架构:A combination of remembering information via this basic D Flip-Flops, and the manipulating them using combinational logics.

我们可以看到,在上述架构中可以看到,该芯片的输出状态不仅取决于当前时刻的输入,还取决于上一时刻的输出: s t a t e [ t ] = f ( i n p u t , s t a t e [ t − 1 ] ) state[t]=f(input,state[t-1]) state[t]=f(input,state[t1])

2.4 一位寄存器

💜目标(Goal):“永远”记住输入的1bit信息,直到被要求记住一个新的输入(remember an input bit “forever”:until requested to load a new value.)

`
在这里插入图片描述
在这里插入图片描述

🌺实现(Implementation):

寄存器和触发器的逻辑并不完全相同:

  • 触发器永远保存上一个单位时间的输入;如果上一个单位时间的输入改变,则该单位时间的输出也随之改变;
  • 寄存器:只有在load = 1时,才会不断加载上一个单位时间的输入,直至load = 0则会永远保存load = 0之前那个单位时间的输入。即: if load(t-1) then out(t)=in(t-1) else out(t)=out(t-1) \begin{aligned}&\text{if load(t-1) then out(t)=in(t-1)}\\&\text{else out(t)=out(t-1)}\end{aligned} if load(t-1) then out(t)=in(t-1)else out(t)=out(t-1)

要想实现上述1bit寄存器的功能,只需在DFF之前加上一个选择器即可,根据load进行选择如何输出:
在这里插入图片描述

3、内存单元:RAM

3.0 前言

如下图,当我们讲到存储器Memory时,它是冯诺依曼体系结构的五大组成部分之一。

在这里插入图片描述
同时存储器有按照在计算机中的作用or层次可以分为以下两种:

  • Main memory(主存储器or内存储器): 随机存储器(RAM)…
    主存储器是存储在计算机内部的并连接到主板上的,CPU可以直接访问。作用是用来存储计算机运行器件所需要的数据和指令(指令本身就是程序的组成部分)。
  • Secondary memory(辅助存储器):磁盘disks,…

按照信息的可保存性分类为:

  • Volatile(易失性存储器)
    eg: RAM
  • non-volatile(非易失性存储器)
    eg: ROM

在本门课课程中我们只关心打✔的以下几项:
在这里插入图片描述

3.1 RAM的基础存储元素:寄存器

在这里插入图片描述

2.4,我们学习了一位寄存器,我们不难想到可以将其扩展为多位寄存器;其中w表示位宽,可以为:16-bit, 32-bit...

16-bit的寄存器逻辑和输入输出接口如下:

/*** 16-bit register:* If load is asserted, the register's value is set to in;* Otherwise, the register maintains its current value:* if (load(t)) out(t+1) = int(t), else out(t+1) = out(t)*/
CHIP Register {IN in[16], load;OUT out[16];PARTS: Replace this comment with your code.
}

3.2 RAM unit

RAM的体系架构如下:

在这里插入图片描述

  • RAM的抽象概念:(RAM abstraction): 是一系列(n个)可寻址的寄存器组成,地址为 0~1(A sequence ofn addressable registers,with addresses 0 to n-1)
  • 在任意给定时间单位内: 只有一个寄存器可以被选中。(At any given point of time,only oneregister in the RAM is selected)
  • k(输入地址的位宽): k = l o g 2 n \mathrm{k=log_2n} k=log2n
  • w(输入数据的位宽)在本门课所构建的Hack计算机中,w = 16

RAM的逻辑如下:

//Let M stand for the state of
//the selected register
if load then {M = in//from the next cycle onward:out = M
}
else out = M
  • RAM的读取逻辑:
    在这里插入图片描述

  • RAM的写入逻辑:
    在这里插入图片描述

3.3 16输入位宽的RAM系列

在这里插入图片描述

如上图可以看到RAM nn表示这个内存有n个寄存器,且每个寄存器的输入位宽这里默认是16

到这里我们也知道RAM的含义: Ramdom Access Memory,因为我们只用确定好要访问的寄存器地址,就能在同等的时间内快速选取到该寄存器对其进行处理。

4、程序计数器PC: Program Counter

4.0 前言

CPU是由ALU+控制器组成:
在这里插入图片描述

其中控制器是整个系统的 指挥中枢,基本功能就是执行指令

其中程序计数器PC控制器的组成部分。用于指出将要执行的指令在主程序中存放的地址,CPU再根据地址去取出指令;由于指令在内存中通常都是顺序存放,它有自增 的功能。

🐣eg: 比如我写了一个程序给机器人如何做蛋糕,这个程序由49条指令组成,顺序存放。那么机器人做蛋糕就从第1条指令出发,顺次往下自增得到指令并执行即可;同时,可以随意从一个指令跳到另一个指令(比如完成了一个蛋糕后,再重新做一个蛋糕时不必从指令1开始,或许可以从指令17开始,因为前面的准备工作都已完成。

4.1 PC的作用

  • 首先,计算机必须要跟踪当前指令的执行以及即将执行的指令(The computer must keep track of which instruction should be fetched and executed next)
  • 上述这种控制可以被PC,即程序计数器实现。
  • 程序计数器包含下一个将要被取得和执行的指令地址(The PC contains the address of the instruction that will befetched and executed next)

同时,PC必须包含以下三个基本设置:

  1. Reset: fetch the first instruction (PC = 0)
  2. Next: fetch the next instruction (PC++)
  3. Goto: fetch instruction n (PC = n)

4.2 深入PC

PC的结构如下:
在这里插入图片描述

PC的逻辑如下:

/*** A 16-bit counter.* if      reset(t): out(t+1) = 0* else if load(t):  out(t+1) = in(t)* else if inc(t):   out(t+1) = out(t) + 1* else              out(t+1) = out(t)*/
CHIP PC {IN in[16], reset, load, inc;OUT out[16];PARTS: Replace this comment with your code.
}

5、Project 3

在这里插入图片描述

5.1 一位存储器

在这里插入图片描述

  • 🐣分析:1 bit寄存器的结构如下,由一个数据选择器mux和一个DFF组成:

在这里插入图片描述

  • 🪴HDL代码:

    /*** 1-bit register:* If load is asserted, the register's value is set to in;* Otherwise, the register maintains its current value:* if (load(t)) out(t+1) = in(t), else out(t+1) = out(t)*/
    CHIP Bit {IN in, load;OUT out;PARTS: Replace this comment with your code.Mux(a= outDFF, b= in, sel= load, out= o1);DFF(in= o1,  out = outDFF,out = out);
    }
    

    Tips:注意到DFFout有两个赋值,这是正确的,因为其输出确实连接了两个引脚,HDL本身也就是描述硬件的连接的。

5.2 16位寄存器

在这里插入图片描述

  • 🐣分析:16bit的寄存器本身就是将16个1bit的寄存器并接即可,load都由一位控制即可。

  • 🪴HDL代码:

    /*** 16-bit register:* If load is asserted, the register's value is set to in;* Otherwise, the register maintains its current value:* if (load(t)) out(t+1) = int(t), else out(t+1) = out(t)*/
    CHIP Register {IN in[16], load;OUT out[16];PARTS: Replace this comment with your code.// Put your code here:Bit(in= in[0],load=load ,out=out[0] );Bit(in= in[1],load=load ,out=out[1] );Bit(in= in[2],load=load ,out=out[2] );Bit(in= in[3],load=load ,out=out[3] );Bit(in= in[4],load=load ,out=out[4] );Bit(in= in[5],load=load ,out=out[5] );Bit(in= in[6],load=load ,out=out[6] );Bit(in= in[7],load=load ,out=out[7] );Bit(in= in[8],load=load ,out=out[8] );Bit(in= in[9],load=load ,out=out[9] );Bit(in= in[10],load=load ,out=out[10] );Bit(in= in[11],load=load ,out=out[11] );Bit(in= in[12],load=load ,out=out[12] );Bit(in= in[13],load=load ,out=out[13] );Bit(in= in[14],load=load ,out=out[14] );Bit(in= in[15],load=load ,out=out[15] );
    }
    

5.3 RAM8

在这里插入图片描述

  • 🐣分析:

    • 让输入in[16]与所有的寄存器连接
    • 反向选择器连接load,用address来选择判断让哪个寄存器来进行加载数据
    • 数据输出部分很简单,利用多路选择器并用address来判断读取哪个寄存器的数据
      在这里插入图片描述
  • 🪴HDL代码:

    /*** Memory of eight 16-bit registers.* If load is asserted, the value of the register selected by* address is set to in; Otherwise, the value does not change.* The value of the selected register is emitted by out.*/
    CHIP RAM8 {IN in[16], load, address[3];OUT out[16];PARTS: Replace this comment with your code.进行数据读取的判断,选择哪个寄存器来加载数据DMux8Way(in= load, sel= address, a= load0, b= load1, c= load2, d= load3, e= load4, f= load5, g= load6, h= load7);将输入与每个寄存器相连Register(in= in, load= load0, out= o0);Register(in= in, load= load1, out= o1);Register(in= in, load= load2, out= o2);Register(in= in, load= load3, out= o3);Register(in= in, load= load4, out= o4);Register(in= in, load= load5, out= o5);Register(in= in, load= load6, out= o6);Register(in= in, load= load7, out= o7);使用多路选择器来判断将哪个寄存器的结果输出Mux8Way16(a= o0, b= o1, c= o2, d= o3, e= o4, f= o5, g= o6, h= o7, sel= address, out= out);
    }
    

5.4 …->RAM16

在这里插入图片描述

现在我们要完成RAM64~RAM512,但这也是基于之前的RAM8RAM64…逐渐抽象的过程:

1 RAM64

  • 🐣分析:RAM64的本质是8RAM8
    其中address[3~5]负责选择哪一个RAM进行输入和输出。,address[0~2]负责选择这个RAM里面的哪个寄存器
    在这里插入图片描述

  • 🪴HDL代码:

    /*** Memory of sixty four 16-bit registers.* If load is asserted, the value of the register selected by* address is set to in; Otherwise, the value does not change.* The value of the selected register is emitted by out.*/
    CHIP RAM64 {IN in[16], load, address[6];OUT out[16];PARTS: Replace this comment with your code.DMux8Way(in= load, sel= address[3..5], a= load0, b= load1, c= load2, d= load3, e= load4, f= load5, g= load6, h= load7);RAM8(in= in, load= load0, address= address[0..2], out= o0);RAM8(in= in, load= load1, address= address[0..2], out= o1);RAM8(in= in, load= load2, address= address[0..2], out= o2);RAM8(in= in, load= load3, address= address[0..2], out= o3);RAM8(in= in, load= load4, address= address[0..2], out= o4);RAM8(in= in, load= load5, address= address[0..2], out= o5);RAM8(in= in, load= load6, address= address[0..2], out= o6);RAM8(in= in, load= load7, address= address[0..2], out= o7);Mux8Way16(a= o0, b= o1, c= o2, d= o3, e= o4, f= o5, g= o6, h= o7, sel= address[3..5], out= out);
    }
    

2 RAM512

在这里插入图片描述

这个和RAM64的思路完全一样:

/*** Memory of 512 16-bit registers.* If load is asserted, the value of the register selected by* address is set to in; Otherwise, the value does not change.* The value of the selected register is emitted by out.*/
CHIP RAM512 {IN in[16], load, address[9];OUT out[16];PARTS: Replace this comment with your code.DMux8Way(in= load, sel= address[6..8], a= load0, b= load1, c= load2, d= load3, e= load4, f= load5, g= load6, h= load7);RAM64(in= in, load= load0, address= address[0..5], out= o0);RAM64(in= in, load= load1, address= address[0..5], out= o1);RAM64(in= in, load= load2, address= address[0..5], out= o2);RAM64(in= in, load= load3, address= address[0..5], out= o3);RAM64(in= in, load= load4, address= address[0..5], out= o4);RAM64(in= in, load= load5, address= address[0..5], out= o5);RAM64(in= in, load= load6, address= address[0..5], out= o6);RAM64(in= in, load= load7, address= address[0..5], out= o7);Mux8Way16(a= o0, b= o1, c= o2, d= o3, e= o4, f= o5, g= o6, h= o7, sel= address[6..8], out= out);
}

3 RAM4k

/*** Memory of 4K 16-bit registers.* If load is asserted, the value of the register selected by* address is set to in; Otherwise, the value does not change.* The value of the selected register is emitted by out.*/
CHIP RAM4K {IN in[16], load, address[12];OUT out[16];PARTS: Replace this comment with your code.// Put your code here:DMux8Way(in=load ,sel=address[9..11] ,a=load0 ,b=load1 ,c=load2 ,d=load3 ,e=load4 ,f=load5 ,g=load6 ,h=load7 );RAM512(in=in ,load=load0 ,address=address[0..8] ,out=out0 );RAM512(in=in ,load=load1 ,address=address[0..8] ,out=out1 );RAM512(in=in ,load=load2 ,address=address[0..8] ,out=out2 );RAM512(in=in ,load=load3 ,address=address[0..8] ,out=out3 );RAM512(in=in ,load=load4 ,address=address[0..8] ,out=out4 );RAM512(in=in ,load=load5 ,address=address[0..8] ,out=out5 );RAM512(in=in ,load=load6 ,address=address[0..8] ,out=out6 );RAM512(in=in ,load=load7 ,address=address[0..8] ,out=out7 );Mux8Way16(a=out0 ,b=out1 ,c=out2 ,d=out3 ,e=out4 ,f=out5 ,g=out6 ,h=out7 ,sel=address[9..11] ,out=out );
}

4 RAM16k

/*** Memory of 16K 16-bit registers.* If load is asserted, the value of the register selected by* address is set to in; Otherwise, the value does not change.* The value of the selected register is emitted by out.*/
CHIP RAM16K {IN in[16], load, address[14];OUT out[16];PARTS:// Put your code here:DMux4Way(in=load ,sel=address[12..13] ,a=load0 ,b=load1 ,c=load2 ,d=load3);RAM4K(in=in ,load=load0 ,address=address[0..11] ,out=out0 );RAM4K(in=in ,load=load1 ,address=address[0..11] ,out=out1 );RAM4K(in=in ,load=load2 ,address=address[0..11] ,out=out2 );RAM4K(in=in ,load=load3 ,address=address[0..11] ,out=out3 );Mux4Way16(a=out0 ,b=out1 ,c=out2 ,d=out3 ,sel=address[12..13] ,out=out );
}

5.5 PC

在这里插入图片描述

  • 🐣分析:

    • 首先,这是一个时序电路,那么它的结构肯定是复合2.5 时序逻辑的实现那样,如下图:
      在这里插入图片描述
    • 由上图我们可以确定,组合逻辑在左边,而时序逻辑(寄存器)在右半部分。
    • 那么难点其实是组合逻辑的书写

    这里直接看最终代码:

/*** A 16-bit counter with load and reset control bits.* if      (reset[t] == 1) out[t+1] = 0* else if (load[t] == 1)  out[t+1] = in[t]* else if (inc[t] == 1)   out[t+1] = out[t] + 1  (integer addition)* else                    out[t+1] = out[t]*/CHIP PC {IN in[16],load,inc,reset;OUT out[16];PARTS:// Put your code here:Inc16(in=state,out=inc16);Mux16(a=state ,b=inc16 ,sel=inc ,out=tmp1 );Mux16(a=tmp1 ,b=in ,sel=load ,out=tmp2 );Mux16(a=tmp2 ,b=false ,sel=reset ,out=newstate );Register(in=newstate ,load=true ,out=out,out=state );
}

可以看到,它其实是从几个多层if判断有里往外写的,这个是很难理解的一点,因为拿到这个输入,我们很自然而然的就会想到它是由外往里进行逻辑判断的。但实际上并不是这样,因为其实越靠外面越会直接得到最终结果,就应该更靠逻辑图的右边(距离输出更近)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/410969.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

参会投稿 | 第三届先进传感与智能制造国际学术会议(ASIM 2024)

第三届先进传感与智能制造国际会议(The 3rd International Conference on Advanced Sensing, Intelligent Manufacturing),由江汉大学、西安交通大学和山东大学主办,由江西省机械工程学会、东华理工大学机械与电子工程学院等联合协…

iPhone突然黑屏?别慌,这里有你的自救指南

在日常使用iPhone的过程中,不少用户可能会遇到手机突然黑屏的情况,这往往让人措手不及。别担心,今天我们就来详细探讨一下iPhone突然黑屏的可能原因及解决方法,帮助你快速恢复手机的正常使用。 一、iPhone突然黑屏的可能原因 1. …

IPD+敏捷高级训战盛典(上海站)圆满落幕,引领创新管理新纪元

在金秋送爽的八月末,翰德恩咨询精心筹备的为期两日的“IPD敏捷高级训战盛典(上海站)”于24日至25日璀璨落幕,标志着一场汇聚行业精英、融合前沿管理智慧的盛宴圆满收官。此次盛典不仅是知识的碰撞与交融,更是企业转型升…

序列化组件对比

1、msgpack介绍 1.MsgPack产生的数据更小,从而在数据传输过程中网络压力更小 2.MsgPack兼容性差,必须按照顺序保存字段 3.MsgPack是二进制序列化格式,兼容跨语言 官网地址: https://msgpack.org/ 官方介绍:Its lik…

ST表(区间查询

解决的问题&#xff1a; 数组区间查询最大值和最小值对于解决数组的树状数组的区间修改 ------- 线段树倍增思想 核心代码&#xff1a; #include<bits/stdc.h> using namespace std; const int N1e5; int num[N]; int f[N][N]; int main(){int n;cin>>n;//输入默…

Vue 2.x时间转换为北京时间(+8)

文章目录 当前时间格式效果图理想时间格式效果图转换方法总结 当前时间格式效果图 非中国常用时间格式&#xff0c;在上图中给可以看到&#xff0c;选择的时间为&#xff1a;2024-8-26 ~ 2024-8-27&#xff0c;返回结果却是&#xff1a;2024-08-25TXX:XX:XXZ&#xff0c;明显不…

最大噪音值甚至受法规限制,如何基于LBM算法有效控制风扇气动噪音

风扇的气动噪声 在工业设备行业&#xff0c;最大噪音值受法规限制。在很多使用风扇冷却的设备上&#xff0c;风扇噪声通常是这些设备工作噪声的最大贡献量。而在家电民用行业&#xff0c;例如空调、空气净化器、油烟机等&#xff0c;其噪音大小直接关系到用户的体验感受&#x…

实现并发网络服务器

一&#xff0c;网络服务器 1.单循环网络服务器 —— 同一时刻只能处理一个客户端任务 2.并发服务器 —— 同一时刻能处理多个客户端任务 二&#xff0c;并发服务器 1.多线程 2.IO多路复用 3.多进程 三&#xff0c;IO模型 1.阻塞IO 阻塞IO&#xff08;Blocking IO&…

SQLi-LABS通关攻略【41-45】

SQLi-LABS 41关 这一关是堆叠注入 测试闭合 ?id1 //回显错误 ?id1-- //回显错误 ?id1-- //回显正确 所以是数字型的注入 测试堆叠注入&#xff0c;更改Dumb的密码 ?id1;update users set password123456 where usernameDumb-- SQLi-…

不会PS怎么快速抠图?试试这3种方法,抠图干净又高效!

我就不信每个人都会用PS抠图&#xff01;&#xff01; 关于抠图技巧&#xff0c;前面高赞已经分享了好多&#xff0c;但&#xff0c;我还是忍不住想向所有小白推荐更“傻瓜式”抠图。 就是那种根本不需要学习就能抠干净的抠图工具&#xff0c;适用于99%的抠图需求&#xff0c…

【数字时序】时钟树延迟偏差——CPPR adjustment

接上一篇文章Innovus的时序报告解读&#xff0c;新版的貌似多了一些信息&#xff0c;比如CPPR Adjustment和Derate。不太清楚这两个是什么概念&#xff0c;搜索之后转载2篇后端工程师的博客如下&#xff1a; 搜到个这个网站好像有很多后端相关的知识点分享一哈&#xff1a; Co…

springboot+vue+mybatis计算机毕业设计电子产品交易系统+PPT+论文+讲解+售后

系统根据现有的管理模块进行开发和扩展&#xff0c;采用面向对象的开发的思想和结构化的开发方法对电子产品交易管理的现状进行系统调查。采用结构化的分析设计&#xff0c;该方法要求结合一定的图表&#xff0c;在模块化的基础上进行系统的开发工作。在设计中采用“自下而上”…

书店销售内部后台管理系统员工信息部门图书入库账目集成分析销售客户

本系统的设计实施为书店管理系统的运行做基础&#xff0c;为书店的管理提供良好的条件。系统主要实现了&#xff1a;员工信息管理、部门管理、图书管理、入库管理、账目集成分析、销售管理、客户管理。 2.1系统开发工具 本系统主要使用JSP技术对系统进行设计和开发。JSP拥有Jav…

上书房信息咨询:医疗满意度调研

随着人们生活水平的不断提高&#xff0c;医疗服务的需求日益增长。近期&#xff0c;上书房信息咨询受托完成了某市医疗市场的满意度调研&#xff0c;旨在深入了解市民对医疗服务的评价和需求&#xff0c;为提升医疗服务质量提供有力支持。 近年来&#xff0c;某市致力于推进医…

本地生活本地推软件有哪些?手把手教你从零开始提升转化率!

当前&#xff0c;多家互联网大厂在本地生活版块的布局不断深入&#xff0c;让本地生活市场不断焕发新活力的同时&#xff0c;也使得竞争态势日益激烈。在此背景下&#xff0c;对于本地生活服务商而言&#xff0c;无论是想要拓展品牌商家资源&#xff0c;还是想要改善交付效果&a…

Java毕业设计 基于SpringBoot vue药店管理系统

Java毕业设计 基于SpringBoot vue药店管理系统 SpringBoot 药店管理系统 功能介绍 管理员 登录 修改个人资料 密码修改 门店管理 销售业绩 药品管理 进货管理 库存管理 会员管理 员工管理 店长 登录 修改个人资料 密码修改 销售业绩 药品管理 进货管理 库存管…

【设计模式-策略】

定义 策略模式是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以互相替换&#xff0c;且算法的变化不会影响到使用算法的客户。通过使用策略模式&#xff0c;算法可以在运行时根据需要动态地进行更换&#xff0c;从…

Golang | Leetcode Golang题解之第372题超级次方

题目&#xff1a; 题解&#xff1a; const mod 1337func pow(x, n int) int {res : 1for ; n > 0; n / 2 {if n&1 > 0 {res res * x % mod}x x * x % mod}return res }func superPow(a int, b []int) int {ans : 1for _, e : range b {ans pow(ans, 10) * pow(a…

前端页面调用本地exe,打开exe主界面

一、文件配置 在桌面新建文件Start.txt 复制以下内容&#xff0c;保存后修改后缀名.txt为 .reg。 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Start] "URL Protocol""D:\\Task\\app.exe" "Start Protocol" [HKEY_CLASSES_ROOT\…

第20讲 动画讲解轻松学会STM32的PWM

来源&#xff1a;【STM32】动画讲解轻松学会STM32的PWM_哔哩哔哩_bilibili 基本概念 周期/频率 计算公式&#xff1a;PWM周期1个高电平用时1个低电平用时 PWM的频率1/周期 如图所示此时周期为1ms&#xff0c;即1s内存在1000组这样的高低电平&#xff0c;PWM的频率为1000hz。…