关注、星标公众号,直达精彩内容
内存是我们平常嵌入式系统中接触的比较频繁的硬件之一,但是我们对这个器件的了解却知之甚少。主要的原因是作为嵌入式工程师的我们,这部分主要是配置参数,而这些参数都是由芯片厂商已经提供好了,硬件工程师都会基于厂商认证的DDR选型,减少开发周期。其实对于内存,有很多的细节和知识点可以深挖,本章的内容包括如下内容:
-通过由浅入深的学习内存的基本原理
-通过由浅入深的学习内存的软硬件特性
-从软件的角度来学习下,我们该如何尝试去配置一块处理器上的DDR
1
情景
小张有一定的计算机背景知识,最近他在京东上买了两条DDR3的内存,打算把笔记本升级成8G。可是一拆开包装到就傻眼了:
4GB看起来很好,两根刚好8GB。2Rx8是啥,PC3又是啥,10600似乎和他想买的1333的差好远,后面那串数字又代表什么呢?于是乎对于这些细节,我们越看越傻眼。后面将会详细的介绍这些细节。
2
DDR的前世今生
2.1 ROM和RAM的概念
在回归DDR的发展过程之前,我们先来了解下储存器的主要功能,其主要是储存程序和各种数据,并能在计算机运行过程中高速、自动完成程序或数据的出存取。
首先,要了解下储存的基本部分,ROM和RAM。
从上面的可以看出,其主要的区别有两点:
-ROM是可读可写,并且速度很快,而ROM只能事先写,然后就只能读取,所以程序在运行过程中必须读写,就必须要有RAM存在
-ROM只作为储存用途,断电不会丢失数据;而RAM在断电的时候会丢失数据
而对于RAM,可分为SRAM(静态随机存储器)和DRAM(动态随机存储器)
2.2 发展历程
但回顾内存容量的发展,从最初KB到GB的跃进,从单条1GB到如今单条16GB或者32GB的进化,经历了漫长的过程。
从最初的时候,个人电脑和嵌入式系统对于功能的实现都比较简单,内存的容量和储存容量都比较小,只有64K到256KB,对于嵌入式系统上甚至更小。
-对于个人电脑,个人电脑上是没有内存条的,内存是直接以DIP芯片的形式安装在主板的DRAM插座上面,需要安装8到9颗这样的芯片,容量只有64KB到256KB,要扩展相当困难,但这对于当时的处理器以及程序来说这已经足够了,直到80286的出现硬件与软件都在渴求更大的内存,只靠主板上的内存已经不能满足需求了,于是内存条就诞生了。
-对于嵌入式设备,例如我最早开始接触的51单片机,内部就集成了ROM和RAM,空间很小。后来又接触到了MTK的芯片,像山寨时期比较流程的53系列的芯片,就使用到了nor flash,可以片上执行,随着时代的发展,35系列就引入了SDRAM,慢慢随着CPU的主频越来越高和对于RAM的容量要求越来越大,就慢慢的开始使用DDR。
那我们以PC的过程来讲解发展过程,由于第一代DIP的芯片难以扩展,而随着CPU的数据总线的宽度达到64bit,一根DDR就难以满足处理需要,所以就需要两根、4根,内存容量也有所增加,它的出现很快就替代了30pin SIMM内存,386、486以及后来的奔腾、奔腾Pro、早期的奔腾II处理器多数会用这种内存。
EDO DRAM【扩展数据输出内存】
它拥有更大的容量和更先进的寻址方式,这内存简化了数据访问的流畅,读取速度DRAM快不少,主要用在486、奔腾,奔腾Pro、早期的奔腾II处理器的电脑上面。
在1991到1995年EDO内存盛行的时候,凭借着制造工艺的飞速发展,EDO内存在成本和容量上都有了很大的突破,单条EDO内存容量从4MB到16MB不等,数据总线依然是32位,所以搭配拥有64位数据总线的奔腾CPU时基本都成对的使用。
SDR SDRAM【同步型动态存储器】
然而随着CPU的升级EDO内存已经不能满足系统的需求了,内存技术也发生了大革命,插座从原来的SIMM升级为DIMM(Dual In-line Memory Module),两边的金手指传输不同的数据,SDR SDRAM内存插座的接口是168Pin,单边针脚数是84,进入到了经典的SDR SDRAM(Single Data Rate SDRAM)时代。
SDRAM其实就是同步DRAM的意思,“同步”是指内存工作需要同步时钟,内部命令的发送与数据的传输都以它为基准。内存频率与CPU外频同步,这大幅提升了数据传输效率,再加上64bit的数据位宽与当时CPU的总线一致,只需要一根内存就能让电脑正常工作了,这降低了采购内存的成本。
DDR
SDRAM从发展到现在已经经历了四代,分别是:第一代SDR SDRAM,第二代DDR SDRAM,第三代DDR2 SDRAM,第四代DDR3 SDRAM,现在已经发展到DDR5 SDRAM。
·DDR SDRAM是Double Data Rate Synchronous Dynamic Random Access Memory(双数据率同步动态随机存储器)的简称,是由VIA等公司为了与RDRAM相抗衡而提出的内存标准,为第二代SDRAM标准。其常见标准有DDR 266、DDR 333和DDR 400。其对于SDRAM,主要它允许在时钟脉冲的上升沿和下降沿传输数据,这样不需要提高时钟的频率就能实现双倍的SDRAM速度,例如DDR266内存与PC133 SDRAM内存相比,工作频率同样是133MHz,但在内存带宽上前者比后者高一倍。这种做法相当于把单车道更换为双车道,内存的数据传输性能自然可以翻倍。
·DDR2(Double Data Rate 2)SDRAM是由JEDEC(电子设备工程联合委员会)开发的第三代SDRAM内存技术标准,1.8v工作电压,240线接口,提供了相较于DDR SDRAM更高的运行效能与更低的电压,同样采用在时钟的上升/下降延同时进行数据传输的基本方式,但拥有两倍于上一代DDR内存预读取能力(即4bit数据读预取能力),其常见的频率规范有DDR2 400\533\667\800\1066\1333等,总线频率553MHz的DDR2内存只需133MHz的工作频率。
·DDR3 SDRAM相比起DDR2具备更低的工作电压(1.5v),240线接口,支持8bit预读,只需133MHz的工作频率便可实现1066MHz的总线频率。其频率从800MHz起跳,常见频率有DDR3 800\1066\1333\1600\1866\2133等。DDR3是当前流行的内存标准,Intel酷睿i系列(如LGA1156处理器平台)、AMD AM3主板及处理器的平台都是其“支持者”。
·DDR4相比DDR3最大的区别有三点:16bit预取机制(DDR3为8bit),同样内核频率下理论速度是DDR3的两倍;更可靠的传输规范,数据可靠性进一步提升;工作电压降为1.2V,更节能。
在80286时代,内存颗粒(Chip)是直接插在主板上的,叫做DIP(Dual In-line Package)。到了80386时代,换成1片焊有内存颗粒的电路板,叫做SIMM(Single-Inline Memory Module)。那么这样又带来哪些好处呢?
由阵脚形态变化成电路板带来了很多好处:模块化,安装便利等等,造就了我们现在的DIY市场的产生,我们就可以针对我们现在的PC进行内存的升级工作。
当时SIMM的位宽是32bit,即一个周期读取4个字节,到了奔腾时,位宽变为64bit,即8个字节,于是SIMM就顺势变为DIMM(Double-Inline Memory Module)。这种形态一直延续至今,也是内存条的基本形态。现在的DIMM分为很多种:
·RDIMM: 全称(Registered DIMM),寄存型模组,主要用在服务器上,为了增加内存的容量和稳定性分有ECC和无ECC两种,但市场上几乎都是ECC的。
·UDIMM:全称(Unbuffered DIMM),无缓冲型模组,这是我们平时所用到的标准台式电脑DIMM,分有ECC和无ECC两种,一般是无ECC的。
·SO-DIMM:全称(Small Outline DIMM),小外型DIMM,笔记本电脑中所使用的DIMM,分ECC和无ECC两种。
·Mini-DIMM:DDR2时代新出现的模组类型,它是Registered DIMM的缩小版本,用于刀片式服务器等对体积要求苛刻的高端领域。
从DDR到DDR4主要的区别是在于传输速率的不同,随着时钟周期的不断降低,传输率也不断提高。还有电压也越来越低。有趣的是命名规则,大部分台式机DIMM厂商都会标注DDRx-yyy,x代表第几代,yyy代表数据传输率。而大部分的SO-DIMM和RDIMM等则标注PCx-zzzz,x还代表第几代,zzzz则代表最大带宽。因为DDR位宽为64位,8个字节,所以zzzz=yyy * 8,而yyy又是时钟的两倍。
所以小张的内存条上的PC3-10600S代表DDR3,1333MHz的SO-DIMM。小张又问,那2R*8啥意思呢?
2.3 DDR区别
DDR到DDR5的主要变化,我们可以看到,为了配合整体行业对于性能,容量和省电的不断追求,规范的工作电压越来越低,芯片容量越来越大, IO的速率也越来越高。
除了电压,容量和IO的速率变化之外,还列出了Bank, Bank Group,Prefetch和Burst Length的演进,bank数越来越多,到DDR4出现bank group,prefetch也从2n增加到4n,8n。虽然我们说现在DDR4的最大速率是3200MT/s, 但是这是指的DDR4的IO频率,即DDR4和memroy controller之间的接口数据传输速率。那么DRAM是怎么实现用比较低的核心传输频率来满足日益高涨的高速IO传输速率的需求呢?这就是靠prefetch来实现的。
从DDR开始到DDR3很好理解,Prefetch相当于DRAM core同时修了多条高速公路连到外面的IO口,来解决IO速率比内部核心速率快的问题,IO数据速率跟核心频率的倍数关系就是prefetch。
burst length的长度跟CPU的cache line大小有关。Burst length的长度有可能大于或者等于prefetch。但是如果prefetch的长度大于burst length的长度,就有可能造成数据浪费,因为CPU一次用不了那么多。所以从DDR3到DDR4,如果在保持DDR4内存data lane还是64的前提下,继续采用增加prefetch的方式来提高IO速率的话,一次prefetch取到的数据就会大于一个cache line的大小 (512bits),对于目前的CPU系统,反而会带来性能问题。
DDR4出现了Bank Group,这就是DDR4在不改变prefetch的情况下,能继续提升IO速率的秘密武器。DDR4利用Bank group的interleave,实现IO速率在DDR3基础上进一步提升。
3
内存原理
其实从外观上就可以看出来小张的内存条由很多海力士的内存颗粒组成。从内存控制器到内存颗粒内部逻辑,笼统上讲从大到小为:channel>DIMM>rank>chip>bank>row/column,如下图:
一个现实的例子是:
在这个例子中,一个i7 CPU支持两个Channel(双通道),每个Channel上可以插俩个DIMM,而每个DIMM由两个rank构成,8个chip组成一个rank。由于现在多数内存颗粒的位宽是8bit,而CPU带宽是64bit,所以经常是8个颗粒可以组成一个rank。所以小张的内存条2R X 8的意思是由2个rank组成,每个rank八个内存颗粒(为啥我们以后讲)。由于整个内存是4GB,我们可以算出单个内存颗粒是256MB。
这次我们来看看rank和Chip里面有什么,如下图:
这是个DDR3一个Rank的示意图。我们把左边128MB Chip拆开来看,它是由8个Bank组成,每个Bank核心是个一个存储矩阵,就像一个大方格子阵。这个格子阵有很多列(Column)和很多行(Row),这样我们想存取某个格子,只需要告知是哪一行哪一列就行了,这也是为什么内存可以随机存取而硬盘等则是按块存取的原因。
实际上每个格子的存储宽度是内存颗粒(Chip)的位宽,在这里由8个Chip组成一个Rank,而CPU寻址宽度是64bit,所以64/8=8bit,即每个格子是1个字节。选择每个格子也不是简单的两组信号,是由一系列信号组成,以这个2GB DDR3为例:
其引脚按照功能可以分为7类:前3类为电源、地、配置
后4类为:控制信号、时钟信号、地址信号、数据信号
电源、地、配置信号的功能很简单,在此不赘述。控制信号主要是用来完成DDR4与DDR4 Controller之间的状态切换。DDR4中最重要的信号就是地址信号和数据信号。
如上DDR4芯片有20根地址线(17根Address、2根BA、1根BG),16根数据线。在搞清楚这些信号线的作用以及地址信号为何还有复用功能之前,我们先抛出1个问题。假如我们用20根地址线,16根数据线,设计一款DDR,我们能设计出的DDR寻址容量有多大?
Size(max)=(2^20) * 16=1048576 *16=16777216bit=2097152B=2048KB=2MB。
但是事实上,该DDR最大容量可以做到1GB,比传统的单线编码寻址容量大了整整512倍,它是如何做到的呢?答案很简单,分时复用。我们把DDR存储空间可以设计成如下样式:
首先将存储空间分成两个大块,分别为BANK GROUP0和BANK GROUP1,再用1根地址线(还剩19根),命名为BG,进行编码。若BG拉高选择BANK GROUP0,拉低选择BANK GROUP1。(当然你也可以划分成4个大块,用2根线进行编码)
再将1个BANK GROUP区域分成4个BANK小区域,分别命名为BANK0、BANK1、BANK2、BANK3。然后我们挑出2根地址线(还剩余17根)命名为BA0和BA1,为4个小BANK进行地址编码。
此时,我们将DDR内存颗粒划分成了2个BANK GROUP,每个BANK GROUP又分成了4个BANK,共8个BANK区域,分配了3根地址线,分别命名为BG0,BA0,BA1。然后我们还剩余17根信号线,每个BANK又该怎么设计呢?这时候,就要用到分时复用的设计理念了。
剩下的17根线,第一次用来表示行地址,第二次用来表示列地址。现在修改为传输2次地址,在传输1次数据,寻址范围最多被扩展为2GB。虽然数据传输速度降低了一半,但是存储空间被扩展了很多倍。这就是改善空间。
所以,剩下的17根地址线,留1根用来表示传输地址是否为行地址。
·在第1次传输时,行地址选择使能,剩下16根地址线,可以表示行地址范围,可以轻松算出行地址范围为2^16=65536个=64K个。
·在第2次传输时,行地址选择禁用,剩下16根地址线,留10根列地址线表示列地址范围,可以轻松表示的列地址范围为2^10=1024个=1K个,剩下6根用来表示读写状态/刷新状态/行使能、等等复用功能。
·这样,我们可以把1个BANK划分成67108864个=64M个地址编号。如下所示
·所以1个BANK可以分成65536行,每行1024列,每个存储单元16bit。
所以1个BANK可以分成65536行,每行1024列,每个存储单元16bit。
-每行可以存储1024*16bit=2048bit=2KB。每行的存储的容量,称为Page Size。
-单个BANK共65536行,所以每个BANK存储容量为65536*2KB=128MB。
-单个BANK GROUP共4个BANK,每个BANK GROUP存储容量为512MB。
-单个DDR4芯片有2个BANK GROUP,故单个DDR4芯片的存储容量为1024MB=1GB。
至此,20根地址线和16根数据线全部分配完成,我们用正向设计的思维方式,为大家讲解了DDR4的存储原理以及接口定义和寻址方式。
但是细心的同学发现一个问题,对于每一个bank,按照正常的10位数据,那么col应该是1024,而现在是128,是什么原因呢?
那么问题又来了,为什么Column Address的寻址能力只有128呢?请继续看下图:
在上图中,可以清晰地发现,10bits的Column Address只有7bits用于列地址译码!列地址0,1,2并没有用!!!列地址0,1,2,这3bits被用于什么功能了?或者是DDR的设计者脑残,故意浪费了这三个bits?在JESD79-3规范中有如下的这个表格:
可以发现,Column Address的A2,A1,A0三位被用于Burst Order功能,并且A3也被用于Burst Type功能。由于一般情况,我们采用的都是顺序读写模式(即{A2,A1,A0}={0,0,0}),所以此时的A3的取值并无直接影响,这个后面章节中重点介绍。
CA[2:0]的值决定了一次Burst sequence的读写地址顺序。
比如一次Burst Read的时候如果CA[2:0]=3’b001表示低三位从地址1开始读取,CA3=0的时候按顺序读取1,2,3,0,5,6,7,4,CA3=1的时候交错读取1,0,3,2,5,4,7,6。
·对于Prefetch而言,正好是8N Prefetch,对于Burst而言对应BL8。
·BC4其实也是一次BL8的操作,只是丢弃了后一半的数据。
更形象地理解就是对于一个Bank里面的Memory Array,每个Memory Cell可以看作是一个Byte的集合体。CA[9:3]选中一行中的一个特定Byte,再由CA[2:0]选择从这个Byte的哪个位置开始操作。CA3既参与了列地址译码,也决定Burst是连续读取还是交错读取。Prefetch也决定了I/O Frequency和SDRAM Core Frequency之间的关系。
4
总结
本章主要是针对DDR的发展和原理进行了学习,主要集中在硬件的组成原理,其中涉及到Channel > DIMM > Rank > Chip > Bank > Row/Column,其组成如下图所示:
·Channel:一个主板上可能有多个插槽,用来插多根内存。这些槽位分成两组或多组,组内共享物理信号线。这样的一组数据信号线、对应几个槽位(内存条)称为一个channel(通道)。简单理解就是DDRC(DDR控制器),一个通道对应一个DDRC。CPU外核或北桥有两个内存控制器,每个控制器控制一个内存通道。内存带宽增加一倍。(理论上)
·DIMM(dual inline memory module)是主板上的一个内存插槽。一个Channel可以包括多个DIMM。
·Rank是一组内存芯片的集合,当芯片位宽x芯片数=64bits(内存总位宽)时,这些芯片就组成一个Rank。一般是一个芯片位宽8bit,然后内存每面8个芯片,那么这一面就构成一个Rank(为了提高容量,有些双面内存条就有两个rank。在DDR总线上可以用一根地址线来区分当前要访问的是哪一组)。同一个Rank中的所有芯片协作来共同读取同一个Address(一个Rank8个芯片 * 8bit = 64bit),这个Address的数据分散在这个Rank的不同芯片上。设计Rank的原因是这样可以使每个芯片的位宽小一些,降低复杂度。
·Chip是内存条上的一个芯片。由图中是由8个bank组成了一个memory device。
·Bank:Bank是一个逻辑上的概念。一个Bank可以分散到多个Chip上,一个Chip也可以包含多个Bank。Bank和Chip的关系可以参考下面的图,每次读数据时,选定一个Rank,然后同时读取每个chip上的同一bank。
·Row/Column组成的Memeory Array:Bank可以理解为一个二维数组bool Array[Row][Column]。而Row/Column就是指示这个二维数组内的坐标。注意读取时每个Bank都读取相同的坐标。
5
参考文档
1.《内存的故事》外一篇–Rambus之战:https://zhuanlan.zhihu.com/p/69420038
2.从诞生到三足鼎立格局,DRAM到底经历了什么?:https://www.sohu.com/a/331550672_100246125
3.内存系列二:深入理解硬件原理:https://zhuanlan.zhihu.com/p/26327347
4.LPDDR4协议规范:https://blog.csdn.net/YJFeiii/article/details/105469366
本文转自:https://blog.csdn.net/u012489236
版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
关注我的微信公众号,回复“星球”加入知识星球,有问必答。
点击“阅读原文”查看知识星球详情,欢迎点分享、收藏、点赞、在看。