计算机各类存储浅析
引论
我有一种预感,在今天的知乎上,这篇文章可能并没有人会感兴趣。就好像夏洛克在博客里写的《辨识灰烬的50种方法》。但这一部分毕竟是我觉得相对杂乱的地方。如果这篇文章能够帮助一些困惑的初学者理清思路,我将感到万分荣幸。特别说明一下有些中文专业词汇可能是我自己凭感觉翻译的,不代表官方名词。计算机各种存储示意图
计算机中的存储主要分为两类:non-volatile memory(非挥发性记忆体)和volatile memory(挥发性记忆体)。non-volatile memory是指即使对计算机停止供电,所有的数据依然能够保存下来的memory。volatile memory是指必须无时无刻给计算机供电才能保存数据的memory。
由上述性质我们可以感觉到,non-volatile memory是通过更改物理结构或材料性质来保存信息的,因此它并不依赖于电源的保持。volatile memory是通过维持高电位低点位来储存信息的,它不会改变储存介质的物理性质和结构,因此它依赖于电源来保持电位以储存信息。
由于non-volatile memory总是需要读取或改变存储介质的物理结构,因此它在绝大多数情况下比volatile memory慢(不少)。所以在电脑中,我们常用volitale memory (一般来说常用DRAM) 作为内存,non-volatile memory (比如SSD, HDD)作为存储。
在这个浅析中,我会整理:
non-volatile memory: ROM, NAND Flash, NOR Flash和SSD(机械硬盘HDD也是,但是这里暂时不包括,如果有机会我会加上)
volatile memory: SRAM, DRAM
ROM(Read Only Memory, 唯读记忆体)
理论上,ROM只能写入一次,然后就只能读取。这种memory一般被在硬件中,固定下来最底层的硬件执行逻辑或驱动,然后无法更改。这就是我们常说的“刻在电路板上的程序”。用户无法更改内部的特性,一定程度上保证了硬件不会被破坏。开机程序和BIOS就是写在这种memory里的。
但是完全只能写一次的ROM容错率太低。于是发展出了几个版本:
PROM(Programmable Read Only Memory, 可程式唯读记忆体)
又名OTP(One-Time Programmable) ROM(一次编程唯读记忆体)。操作者能够对其进行一次修改,然后所有的性质都与ROM相同。
EPROM (Erasable Programmable Read Only Memory, 可擦可程式唯读记忆体)
当该记忆体中的IC package暴露在特定的紫外线下一定时间后,memory中的所有数据就会被擦除。然后它的所有性质都和PROM相同。
EEPROM (Electrically Erasable Programmable Read-Only Memory,带电可擦可程式唯读记忆体)
不需要像EPROM一样用紫外线进行擦除,EEPROM可以用电进行数据清除并重写。这大大简化了重构的过程。现在大多数电脑中使用的ROM是EEPROM。
EEPROM清除和重写的次数十分有限,并不适合做需要不断修改的存储。
Flash Memory(闪存)
Flash memory是根据Floating Gate Technology(FGT)制作的memory。它可以直接以电子的方式进行写入和修改。相比较EEPROM而言有着更多的写入次数且更廉价。
Flash 的存储结构一般是 block->page->byte。每次擦除必须要擦除整个block。读取的大小视类别而定,如果闪存类型是NAND,则每次读取一个page。如果类型是NOR,则每次读取一个block。
从数电课上我们知道,对于多个电子元件,我们可以用不同的逻辑门将其连接。工程师们在设计闪存的时候发现有两种可行的连接存储单元的方式:与非门(NOR),或非门(NAND)
NOR Flash有着更快的读取速度,相对而言更不容易出错,而且支持随机地址读取和写入(random access)。随机地址读取指的是给定一个地址,我们可以直接得知这个地址上存储单元的数据(你没有看错,这个性质并不是所有memory都应该有的基本素养)。这一点是由NOR Gate的性质决定的:只有bit line和word line都是0的时候才会assert当前地址的存储单元,从而读取数据。感兴趣的同学可以自行查阅电路图。
NAND Flash的写入速度则比NOR Flash快很多,而且价格较低。
随机地址读取和写入给了NOR Flash一个重要的性质:execute in place(XIP,在当前位置直接运行)。如果你继续往下读的话,就会看到很多种memory比如是不能直接在存储器上运行程序的,因为它们的设计不支持代码的随即跳转(NAND Flash只支持同一page上的跳转,往后看就懂了)。因此各种驱动等需要直接在memory上运行的程序需要写在支持XIP的memory里,一般都是ROM和NOR Flash。
Flash 的物理原理(非常非常浅显的解读)
MOSFET
如图为Flash的基本单元MOSFET(Metal-Oxide-Semiconductor Field Effect Transistor金属-氧化物半导体场效应晶体管),图中灰白色的部分是氧化层,棕色的部分是电流主要通过的半导体。
在工作时,电流从S进入,从D流出。G和B之间会施加一个电压来改变半导体的性质。
我们大家都知道半导体是介于导体与绝缘体之间的材料,这是因为我们比较容易控制半导体的导电性。在G和B之间没有电压的时候,整个元件呈现为绝缘体。当G和B之间达到某个电压阈值的时候(我不知道这算不算击穿电压),这个半导体就呈现出导电性。
MOSFET的精妙之处就在于对这个电压阈值的控制。它有两种形态:Erased state和Programmed state。在Erased state中这个电压阈值低,在Programmed state中阈值高。电压阈值示意图
因此当G处电压到达绿线的时候,处于Erased state的元件就会呈导电性,也就是1;处于Programmed state的元件就会呈绝缘性,也就是0。于是我们对一块Flash通电的时候,处于不同形态的单元就会给出它储存的的信息。
两种形态的相互转变来源于金属氧化层。当氧化层中电子多的时候就会消除一部分半导体上的电压,导致我们在G必须有更高的电压才能在半导体处达到电压阈值。反之亦然,当电子少的时候就不需要那么高的电压。
为了改变氧化层中的电子数量,我们需要给G提供相对较高的电压或者负电压来吸引/排斥电子。由于金属氧化层过度插入或消除电子会导致老化,最终无法完全释放电子,Flash的写入是有次数限制的。固态硬盘主要由NAND Flash构成,所以建议用固态硬盘的同学们不要过于频繁的大量下载和删除哦(虽然大多数情况下人们远远用不到它写入次数的极限)。
排出电子所需要的负电压并不容易直接对某个单元施加,因此对MOSFET写入的时候必须先擦除(即把电子排出金属氧化层,使得Flash逻辑变为1)整个block,然后再写入(将电子插入氧化层,使得Flash逻辑变为0)。这就是为什么NAND Flash和NOR Flash写入的时候必须先擦除整个block。
Multi-level Cell(多层单元)
随着技术的进步,存储单元逐渐由单层变为多层。这就意味着在同一个单元中我们我们可以读取两个甚至三个bit。
这无疑极大的增加了信息存储的密度。但是有得必有失,增加信息密度所带来的是降低传输速度和增加错误率。
NOR Flash 的读写
NOR Flash逻辑电路图
NOR Flash总是被分为很多个block,每个block都可以单独擦除。就像下图一样。NOR Flash 的 block 划分
观察这张图,我们就会发现并不是每一个block都是一样大的。在低端(或顶端)的block可能偏小。这是因为这些block中存着启动代码(boot loader)等常年不变的代码。还记得之前我们提到过的每次擦除必须擦除整个block吗?假如我们把boot loader放到正常大小的block中去,这个block中没有用到的区域不能写别的东西,因为别的东西一旦要更改就会擦除boot loader,这就会导致整个计算机的基础程序出问题。处于不浪费空间的原则,我们把boot loader等放进相对较小的block中去。NOR Flash 接口信息
上图显示的是一种常见的NOR Flash接口,但是开发商不同,接口也不尽相同,同学们开发的时候还是要参考官方说明啊。
NOR Flash和SRAM非常像(SRAM以后我们会介绍到),他们都是支持XIP(还记得吗,可以直接从存储位置执行代码的那个性质)的。最显著的不同点就是NOR Flash有一个WP#。这就是我们前面说的写入保护。
NOR Flash的读取过程如下:NOR Flash读取
该图表示的是时间线。在读取过程中,通过地址线传入要读取的地址,然后激活CE#和OE#(这个#代表的是active low,也就是低电位的时候激活)
我们注意到图上有两个时间区间: 和 。这两个都是延迟时间, 是指从output enable开始到数据开始输出所需要的延迟的时间, 是指从关闭output enable到数据结束输出所需要的时间。需要注意的是不同的开发商对于这个时间可能会有不同的标识,所以小伙伴们在开发的时候请阅读说明书。一般这两个时间都是开发商所给定的常数(最大延迟),根据这个数据开发者就可以更好的设计自己的产品。
事实上除了上面提到的这几种pin(引脚,这东西就是芯片上面凸出来的小铁针,用来接收信号和传输信号的),NOR Flash可能还需要其他的pin,比如说这个flash既支持8位,也支持16位,那么就需要有一个pin来辨别什么时候用支持8位的模式,什么时候用支持16位的模式。还有的Flash有一个Ready/Busy pin,当Flash在处理某些内部指令比如读写的时候,激活这个pin使得Flash暂时停止接收其它的信号的数据。
NOR Flash的写入过程如下:NOR Flash的写入过程
与读取不同,NOR Flash的写入更麻烦一些。而且由于NOR Flash每次写入之前必须擦除整个block,就使得它的写入速度相当慢(3s)。
首先NOR Flash 要从bus上传输一个指令(其实地址线和数据线上都要传,但图上只画了数据线),这个指令告诉Flash接下来要开始写入了。然后写入地址和写入的数据就会依次传入到buffer里。然后Flash就会开始擦除和写入的工作(如果这个Flash有Ready/Busy pin的话,此时就会被设定为busy状态)。
示例:NOR Flash 写入的例子
该例子中写入指令需要3个写入周期,每个周期的命令具体是什么已经用红色圈在了图上。第四个写入周期就是具体的数据和地址。我们注意到,这里的数据线是16位的,但是给数据线的指令只有八位(0xAA,十六进制,8个bit)。所以这八位是处于数据线的低位上。
NAND Flash 的读写
我们全程使用Micron来举例子(谷歌一搜第一个就是它)https://www.micron.com/-/media/client/global/documents/products/data-sheet/nand-flash/20-series/2gb_nand_m29b.pdfNAND Flash 的结构
如图所示,是NAND Flash 的结构。和NOR Flash相比,NAND Flash多了一层结构:page。一个NAND Flash会被分为很多个block,一个block又会被分成很多个page。每一个page都会有一些多余的bit,这些多余的空间可以用来存放纠错码。
在图上我们还看到,NAND Flash还有和page一样大的cache(缓存区)和register(寄存器)。
NAND Flash存储信息比较紧凑,信息密度大,所以相对而言容易出错于是我们需要多余的空间放纠错码。而且NAND Flash并不支持全局XIP,但是他有random data read指令能够让我们快速查找同一page中的数据,所以我们也说NAND Flash支持同一页面的XIP。
NAND Flash只有一个I/O bus。这个数据线既需要传送地址,又需要传送数据,还要传输指令。为了区分什么时候传数据,什么时候传地址,什么时候传指令,NAND Flash专门设计了两个pin:CLE(Command Latch Enable)和ALE(Address Latch Enable)。当激活CLE的时候,I/O bus上面传的就是指令,当激活ALE的时候,I/O bus上面传的就是地址,其余时间传的是数据。
其它的控制接口和NOR Flash相同。MICRO的NOR Flash指令集
图中所示是指令集的一种。不同的生产商会有不同的指令集,同样的,开发的小伙伴需要参考说明书哦(上图这个指令集来源于MICRO生产的NAND Flash)。
由于NAND Flash并不支持全局的XIP,所以无论是读取还是写入都需要有一个输入指令-传送地址-/写入数据的过程。这个过程有两种常见的实现方式:两种NAND Flash的读写顺序实现方式
由指令集我们可以看到,一般每个指令都需要两个周期。所以我们既可以把这两个周期集中在最开头,也可以把他们分散在读取地址的两端。由于我们在这里主要会拿Micron举例子,Micron又是用的第一种方式,所以我们也暂且使用第一种实现方式。NAND Flash 读取
读取数据的时候首先开启CLE读取第一个clock cycle的指令,然后传入地址,然后传入第二个指令。中间的 是数据从Flash memory传到寄存器所用的时间。所有的数据都需要先传进register(寄存器),然后才能进行下一步操作处理,在这段时间内R/B#会将memory设置为busy,其它的指令和数据没有办法干扰它。
接下来需要的数据就都会存在register里,RE#不断地产生脉冲来读取register中的数据。random data read
每次外部设备读取的时候只能读取当前register中的数据。random date read
指令集中的random data read可以省掉传输row的时间,更快的在同一page中查找想要的数据。如上图所示。NAND Flash 写入过程
写入过程依然遵循着我们之前提到的顺序。但是需要注意的一点是传完地址之后并没有直接传指令,而是传了想要传的数据进register。然后NAND Flash并不会直接将这些数据写入,而是需要用另外一种指令来辅助数据写入memory。
Flash还需要注意设置纠错码和预防超过读写次数限制。
设置纠错码这里就简单列几个相关算法,感兴趣的同学可以自行查阅:Hamming, Reed Solomon, Bose-Chaudhuri-Hocquenghem(BCH), Low-Density Parity Check(LDPC)
预防超过读写次数Wear Leveling,可以 创建一个RAM作为buffer。对于写入次数非常多的数据现在RAM中完成,如果确认不需要大规模更改了再写入Flash。除此之外,还有两种算法可以缓解wear leveling,我们将之分为static和dynamic。两种算法的核心都是努力让每个单位都有接近的擦除次数,
dynamic的方法就是每当移动一个数据的时候,就找Flash中被擦除次数最少的单位。但是这个方法有着它的局限性:有些单位从开始到最后都没有被擦除过。这样一来这些不被擦除的存储单位就会导致整个Flash的擦除次数不平衡。
static的方法就是按照一定的时间长度或写入周期来移动那些擦除次数非常少的单位中的数据。这样一来被这些数据所占用的位置就可以更大化利用了。(感觉dynamic更像静态,static更像动态有没有。。。)两种算法的优缺点
固态硬盘(SSD)简介
主要由NAND Flash构成,有着写入次数的限制。
为了缓解写入次数限制,它有一个non-volatile memory的buffer用来存放当前经常更改的数据。所以我们拔掉固态硬盘之前,要先“弹出设备”,这样才能够保证buffer里的数据安全更新到Flash里。如果直接拔会导致数据丢失。
额,这个好像并没有什么需要讲的。
SRAM(Static Random Access Memory 静态随机存取存储器)
再次回顾一下,SRAM是拔掉电源就会丢失数据的存储类型。它的读写速度远快于上面描述的那几种存储设备,而且没有读写次数限制。是做buffer和register的良好选择!
SRAM比DRAM快,但是也更贵。
一般来说,CPU等运算核心的速度是远快于各种存储设备的读写的。为了能够更好的和CPU进行匹配,越靠近核心的内存零件就需要有越快的速度。当然了鱼和熊掌不可兼得,有着更快的速度往往意味着昂贵的价格,所以大规模使用靠近核心的存储设备是不现实的。于是各种存储设备之间就会出现“分层”的现象。SRAM就是那几乎最靠近CPU的一层。SRAM原理
SRAM的原理如上图,它是由两个inverter组成的。单个单位的读写原理在数电中有讲过,这里不会过多叙述。我们主要考虑它的应用以及读写。
SRAM非常稳定,只需要通电,不需要任何额外操作就能存储信息。由于DRAM还需要通电给电容充能,所以SRAM比DRAM要快一些。
SRAM常用于嵌入式设备的main memory(也就是我们常说的内存。但是PC的一般不用SRAM,手机上用的多),微处理器上的存储,register寄存器,buffer缓存器,cache memory缓冲器。
我们用IDT的2K x8做例子。https://www.renesas.com/sg/en/document/dst/6116sala-data-sheetSRAM接口信息
SRAM的接口如图所示。它与NOR Flash很像,有数据线,地址线,和一系列控制接口。图中这个是2Kx8 SRAM。x8指的是数据线宽度(data bus width)。SRAM 读取过程
如图所示为IDT生产的SRAM的读取过程。我们看到图中和NOR Flash一样,有着 和 的延迟。SRAM写入过程
首先address bus需要一直保持着地址的数据,然后用WE来控制具体信息的读写。当WE进入低电位的时候,要写入的信息需要保留在data bus上,然后当WE rising edge的时候,bus上的信息就会同步保存到SRAM里面。
DRAM(Dynamic Random Access Memory 动态随机存取存储器)
DRAM 原理
和SRAM不同,DRAM使用的是一个个小电容来存储相应的信息。当电容中有电荷的时候,它所代表的信息就是1,当电容中没有电荷的时候,它所代表的信息就是0。电容和bit line之间有一个MOS晶体管,能够控制通路和断路。DRAM接口信息
在读取数据的时候,整个行的信息都会被复制到buffer里面。然后会有相应的列地址来导出我们想要的数据。在写入数据的时候,我们也会先允许整行数据的写入,然后再需要改变的列上更改它的0或1。DRAM单元写入原理
在写入的时候,bit line中先加载上我们想要写入的数据,然后word line将MOS元件变成通路。这样一来,如果bit line中的数据是0,那么电容中的电荷也就会被导出,自身也变成0,如果bit line中的数据是1,电容中也会被插入电荷,于是自身也变成1。DRAM单元读取过程
在读取的时候,首先会把bit line调成 。然后bit line会接一个信号放大器。接下来word line打开MOS。如果电容中本身就是0,那么bit line中会有一个向0的扰动,然后信号放大器就会把这个扰动迅速放大,然后bit line中的信息很快就会变成0。同理,如果电容本身是1,那么信号放大器就会迅速将bit line上的信息退化为1。具体原理大家可以复习一下模电。
读取过程会不会影响电容器中的数据呢?并不会。因为读取时,电容器随时是和bit line相连的。虽然刚开始的时候电容器需要用自己的电位来影响bit line,但是bit line在放大器的影响下退化为0或1的时候就会将电位反哺给电容器。于是乎电容器相当于自动pre-charge了。
在没有写入或读取的时候,电容会不断地自动流失电荷。所以我们需要定期的给它补充电荷。这也是DRAM比SRAM慢的主要原因。补充电荷(refresh)的流程一般包括读取信息并锁住,然后再把这个信息返还给电容。
Refresh的手段一般被分为两种:Auto-Refresh和Self-Refresh
Auto-Refresh就是主动的使用refresh指令,给所有的行一轮一轮的补充电荷。每一轮所用的时间都要求在电荷耗尽的时间之内。但是这样一来有些长期不用却需要保持信息的行,就会占用refresh的资源。我们希望能够不管这些长时间不会更改却要保持信息的单位,让他们能够自己给自己补充电荷。
Self-Refresh就是解决上述问题的。他会根据自己内部的clock,不断地给自己补充电荷。在需要用到它的时候在把它调成auto-refresh模式。
如图所示,正常逻辑下DRAM应该是左边这张图的样子,是一个相对比较大的板子。但是我们每次读取的时候都需要将整行读取到buffer里,如果一行过大,读取的时候可能会降低速度,也可能会precharge的速度赶不上电荷流失的速度导致信息丢失。
为了解决这个问题,我们使用多个板子。每一个板子称为一个bank,每个bank有着自己单独的电荷补充周期和输入输出接口。在读取的时候,我们也不会从只从一个板子里读取,我们会将地址分给所有的bank,每个bank贡献一个bit,然后这些数据拼在一起构成一个byte或4 bit之类。因此,一般来说如果一个DRAM有4个bank,则它是x4,如果有8个,则它是x8。以此类推。实际情况中的DRAM
SDRAM(Synchronous DRAM 同步动态随机存取存储器)
SDRAM是DRAM的进化版。现在市面上已经很难找到单纯的DRAM了,用的一般都是SDRAM。
我们在这里举例子还是使用Micron 的 SDRAMhttps://www.micron.com/-/media/client/global/documents/products/data-sheet/dram/64mb_x4x8x16_sdram.pdf?rev=e1748f6ffbb443edbc5465a55d7f3153SDRAM结构图
SDRAM的结构如图所示。我们发现它的基础结构和DRAM是相似的,也是有很多个bank构成。
和DRAM不同的是,SDRAM内部有一个很快的同步时钟,它用pipeline的方式提供高速操作。它能够让同一行中的信息访问变得非常快,而且可以在访问一个bank的时候高速无缝隙的给其它的bank补充电荷。于是不同bank读取的时候可以大大的减少补充电荷所需要的单独的时间开销。
如果想你要开始一段读取或写入的操作,就需要先激活SDRAM。在指令线中传入激活指令。然后SDRAM会读取BA0和BA1中的输入来选取bank(假设这里有4个bank)。然后address bus上会给出需要读取的行地址,然后SDRAM就会在这一行中进行操作直到precharge指令开始执行。
如果SDRAM需要在同一个bank中对不同的行进行操作,则它必须在这两个操作之间进行一次precharge。所以每一次的操作SDRAM都只能对同一行进行。
事实上当某一行的读写指令正在进行的时候,其他bank就可以进行active了,这样利用pipeline可以大量的缩减所需要用到的时间。SDRAM连续读取过程SDRAM随机读取过程
在active的时候相应的bank和row就已经传到了读取控制器里面,剩下的随机读取步骤只需要不断传输需要读取的列地址就可以了。每一个cycle都只能够读取一个数据,这些数据会传到相应的buffer里,再通过各种通信接口传出去。
SDRAM有两种读取方式:连续读取和随机读取。连续读取就是先给定一个列地址,然后设备就会连续的依次将这个列地址后面的数据读出来。随机读取就是每次clock都会传入一个新的列地址,然后设备就会按照传入的列地址读取相应的信息。具体方式如上图所示。
细心观察不难发现,图中的column address和output data并不对应。其中相差了 CL 个clock cycle。CL是给定的设备参数。中间相差几个周期往往是因为pipeline的时候会有资源冲突。开启auto-precharge的读取过程关闭auto-precharge的读取过程
如果我们开启了auto-precharge,就不需要在传输完所有信息以后使用precharge指令。如果我们没有开始,就需要使用precharge指令进行补充电荷。auto-precharge的开启在A10上,如图所示。SDRAM写入过程
和读取过程非常相似,只不过是把读取指令变成了写入指令。同样也有两种方式:连续写入和随机写入。具体方式与读取相同,上图中是连续写入。
SDRAM支持多个bank 进行pipeline来节约时间:
同一bank同一row的合并运行,在中间的空隙中插入其它bank的active,然后运行相同bank不同row。这样能够最大化利用资源缩短时间。
在使用SDRAM的最最开始的地方,我们还需要配置mode register。mode register
对register进行编辑,设置我们所需要用的参数从而选取SDRAM的某种模式,然后SDRAM开始运行的时候会自动读取这个register并配置自己的模式。
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/91457.html