我们熟知的NAND闪存,还有个“双胞胎兄弟”
【IT168 评论】无论消费者还是企业机构,大多数人在谈到闪存时,首先想到的就是NAND闪存。从一定的现实意义上来讲,NAND闪存可以说已经成为固态硬盘的代名词。基于块寻址结构和高密度,使其成为磁盘的完美替代品。
NOR闪存是另一种与NAND不同的闪存类型,它具有不同的设计拓扑结构,某些特定的应用场景下更为适合。在比较NAND和NOR闪存在不同应用中的相对优势和适用性之前,检查其结构差异是很重要的。
NAND闪存产品是当今已经达到高水准的存储芯片,是当前市面上嵌入式以及独立式SSD的主要原材料。多层单元(MLC)技术和3D制造工艺的结合,将NAND存储单元垂直蚀刻到硅衬底上,使存储密度和NAND芯片容量呈几何级增长。
NAND与NOR电路基础
尽管NAND闪存是这两种非易失性内存技术中相对流行的一种,但NAND和NOR都是由同一名东芝公司的工程师在上世纪80年代中期发明的。要理解这两个种类的区别和命名,需要简要回顾一下逻辑门的基础知识。
NAND和NOR分别涉及到布尔逻辑函数中的逻辑“和”(and)以及“或”(or)。如下所示,NAND和NOR都生成响应两个二进制输入的输出。
响应两个二进制输入的NAND和NOR输出
NAND和NOR逻辑门仅仅为它们各自的功能实现了上面这个真值表。
NAND门在概念上是作为AND门实现的——当两个输入都是1时输出1——后面跟着一个NOT门,这是一个逻辑反转。相应的,NOR门在概念上是一个OR门——有任何一个输入是1时输出1,然后是NOT门,这是一个逻辑倒装。
布尔逻辑的背景对于理解NAND和NOR闪存至关重要,因为闪存单元被连接到一个行和列的数组中。在NAND闪存中,一组中的所有单元(通常是一个字节的倍数,取决于芯片的大小)共享一条位线,并以串行方式连接每个单元,每个单元连接到一个单独的字行。同一字行连接一个内存块中的多个字节,通常为4 KB到16 KB。因此,只有当所有的字线都是高或单状态时,位线才会降低或变为零状态,这实际上将内存组转换为一个多输入NAND门。
与此相反,NOR闪存并行组织位线的方式是,当位线和字线都处于低或零状态时,内存单元只保持高或单状态。
NAND单元的串联结构使得它们可以通过导电层(或掺杂层)连接在衬底上,而不需要外部接触,从而显著减少了其横截面积。
NAND闪存单元的串联连接意味着它们不需要单元之间通过金属层进行外部接触——而这正是NOR拓扑结构所需的。使用导电层连接硅衬底上的单元意味着NAND闪存的密度通常比NOR高两个数量级,或100倍。此外,组内单元的串联连接使它们可以垂直地堆积在3D数组中,位线类似于垂直管道。
相反,由于NOR闪存单元不能单独寻址,因此它们对于随机访问应用程序更快。
NAND与NOR产品类型
这两种类型的闪存具有明显的特性和性能差异,它们有各自最适合的应用程序类型。除了容量外,NAND和NOR闪存还具有不同的运行、性能和成本特性,如下图所示。
这两种闪存中也有几种不同的产品类型,它们在I/O接口、写入持久性、可靠性和嵌入式控制功能方面有所不同。
NAND闪存产品类型
NAND闪存以单层(SLC)、多层(MLC)、三层(TLC)或四层(QLC)的形式在每个单元(cell)中存储bit,分别为1 bit/cell、2 bit/cell、3 bit/cell、4 bit/cell。要确定哪种类型的NAND最适合于工作负载,简单来说,每个单元的位数越高,其容量就越大——当然,是以数据持久性和稳定性为代价的。
NAND设备只是没有任何外围电路的存储芯片,这些外围电路使NAND闪存可以在SSD、U盘或其他存储设备中使用。相比之下,托管型NAND产品嵌入了一个内存控制器来处理必要的功能,比如磨损调平、坏块管理(从使用中消除非功能性内存块)和数据冗余。
NOR闪存产品类型
串行设备通过只暴露少量(通常是1到8个)I/O信号来减少包的pin数。对于需要快速连续读取的应用程序来说,这是理想的选择。NOR闪存通常用于瘦客户机、机顶盒、打印机和驱动器控制器。
并行NOR产品暴露多个字节,而且通常使用内存页而不是单独的字节进行操作,更适用于启动代码和高容量应用程序,包括数码单反相机、存储卡和电话。
两种闪存都是不可或缺的
NAND是闪存的主力,广泛用于嵌入式系统和SSD等存储设备的大容量数据存储。不过,NOR 闪存在存储可执行的启动代码和需要频繁随机读取小数据集的应用程序方面起着关键作用。显然,这两种类型的闪存将继续在计算机、网络和存储系统的设计中发挥作用。
原文作者:Kurt Marko
System C的模块和过程
模块和过程
本节包含一个完整的简单设计,以演示SystemC中模块和过程的使用。为了简单起见,它是非常低的级别-而不是您通常期望的系统级别设计语言中的编码样式!
展示的要点是
建立阶层
所述sc_signal原始信道
(专用)端口
进程(SC_METHOD,SC_THREAD,SC_CTHREAD)
一个简单的测试台
SystemC背景
为什么要查看模块和流程?原因是SystemC旨在应付硬件和软件,并允许对大型系统进行建模。
进程是与其他进程同时运行的一小段代码。几乎所有已开发的高级系统级设计(SLD)工具都使用流程网络的基础模型。SystemC提供了支持独立(并行/并行)代码段网络构建的过程。
SLD需要处理大型设计。为了解决这个问题,通常使用层次结构。层次结构是通过使用模块在SystemC中实现的,该模块可以使用端口链接到其他模块。模块允许单独进行一项设计。模块可以包含进程和其他模块的实例。
实例设计
该设计包括一个EXOR门和四个NAND门。同样,必须注意,这不是典型的设计风格-很好理解。设计看起来像这样
第一步是对“与非”门建模。NAND门是组合电路;它的输出纯粹是输入值的函数。它没有内存,并且不需要时钟。因此,模型可以使用最简单的SystemC进程SC_METHOD。
SC_METHOD只是C ++函数。因此,SystemC类库必须使它们的行为像进程一样。尤其是
SystemC类库包含一个仿真内核,这是一段代码,用于模拟时间的流逝,并在函数的输入发生更改时调用函数以计算其输出。
该函数必须声明为SC_METHOD,并且对其输入敏感。
这是一个与非门的代码,位于一个文件nand.h中
#include“ systemc.h”SC_MODULE(nand2)//声明nand2 sc_module{
sc_in <布尔> A,B; //输入信号端口
sc_out <布尔> F; //输出信号端口
void do_nand2()//一个C ++函数
{
F.write(!(A.read()&& B.read()));
}
SC_CTOR(nand2)// nand2的构造函数
{
SC_METHOD(do_nand2); //向内核注册do_nand2
敏感<< A << B; //敏感度列表
}};
SystemC中的层次结构是使用类sc_module创建的。sc_module可以直接使用,也可以使用宏SC_MODULE “隐藏” 。上面的示例SC_MODULE创建了一个名为nand2的sc_module类对象。
接下来是声明的输入和输出端口。通常,使用类sc_port声明端口。例如,将声明 使用sc_signal的输入端口
sc_port <sc_signal_in_if <bool>,1> A,B;
但正如您所看到的,这是很多输入。为了方便起见,还可以创建和使用专用端口。sc_in是sc_signal类的专用端口的示例。
端口可以是任何C ++或SystemC类型-该示例使用内置的C ++类型bool。
接下来,声明完成工作的函数。输入和输出(专用)端口包括方法read()和write(),以允许读写端口。读取A和B,计算NAND函数,然后使用write()方法将结果写入F。
请注意,由于=运算符和类型转换运算符已被重载,因此您通常可以不使用read()和write()方法而逃脱。所以你可以写
F =!(A && B);
但是使用read()和write()是一个好习惯,因为它有助于C ++编译器消除表达式的歧义。
编写函数do_nand2()之后,将为sc_module实例nand2提供一个构造函数。SystemC使用宏SC_CTOR提供了一种简便的方法。构造函数执行以下操作
创建层次结构(在这种情况下为无)
将功能注册为模拟内核中的进程
声明流程的敏感度列表
也可以在此处初始化需要初始化的任何内容,例如,可以初始化类数据成员。
在上面的示例中,构造函数声明do_nand2是SC_METHOD,并说端口A和B上的任何事件都必须使内核运行该函数(从而为F计算一个新值)。
层次结构
EXOR门由NAND门的四个副本(或实例)组成。这是通过使用EXOR门构造器连接NAND门实例来实现的。这是EXOR门的代码
#include“ systemc.h”#include“ nand2.h”SC_MODULE(exor2){
sc_in <布尔> A,B;
sc_out <布尔> F;
nand2 n1,n2,n3,n4;
sc_signal <布尔> S1,S2,S3;
SC_CTOR(exor2):n1(“ N1”),n2(“ N2”),n3(“ N3”),n4(“ N4”)
{
n1.A(A);
n1.B(B);
n1.F(S1);
n2.A(A);
n2.B(S1);
n2.F(S2);
n3.A(S1);
n3.B(B);
n3.F(S3);
n4.A(S2);
n4.B(S3);
n4.F(F);
}};
该开始看起来与NAND门非常相似,但请注意,它包括文件nand2.h。这允许访问包含与非门的模块。
创建模块exor2,并声明端口。请注意,由于这是层次结构的不同级别,因此允许重复使用名称A,B 和F。
原始图显示了一些“线段”以连接NAND门。这些通过声明创建 sc_signal小号S1, S2和S3。 sc_signal是带有模板参数的类,该模板参数指定信号可以保存的数据类型- 在此示例中为bool。sc_signal是基本通道的一个示例,它是SystemC类库中的内置通道。它的行为类似于VHDL中的信号。
EXOR门的构造函数比NAND门的构造函数复杂,因为它必须具有nand2的四个实例。在端口声明之后,声明了nand2的四个实例:n1,n2,n3和n4。必须为每个实例赋予标签。通过使用exor2构造函数上的初始化器列表,将四个标签“ N1”,“ N2”,“ N3”和“ N4”传递给nand2实例的构造函数。
最后,将端口连接起来。如图所示,这是在构造函数中完成的。
试验台
为了测试设计,有一个激励发生器。这是另一个模块,与上面的非常相似。唯一重要的一点是,它使用线程(SC_THREAD),这是一种可以挂起的进程。这是stim.h的代码
#include“ systemc.h”SC_MODULE(刺激){
sc_out <bool> A,B;
sc_in <bool> Clk;
无效StimGen()
{
A.write(false);
B.write(false);
等待();
A.write(false);
B.write(true);
等待();
A.write(true);
B.write(false);
等待();
A.write(true);
B.write(true);
等待();
sc_stop();
}
SC_CTOR(刺激)
{
SC_THREAD(StimGen);
敏感<< Clk.pos();
}};
请注意对sc_stop()的最终调用,这将使模拟停止。监视代码看起来非常相似,因此被省略了-它位于mon.h文件中。
这是顶层-位于文件main.cpp中,该文件包含上述所有子模块
#include“ systemc.h”#include“ stim.h”#include“ exor2.h”#include“ mon.h”int sc_main(int argc,char * argv []){
sc_signal <bool> ASig,BSig,FSig;
sc_clock TestClk(“ TestClock”,10,SC_NS,0.5);
刺激Stim1(“ Stimulus”);
Stim1.A(ASig);
Stim1.B(BSig);
Stim1.Clk(TestClk);
exor2 DUT(“ exor2”);
DUT.A(ASig);
DUT.B(BSig);
DUT.F(FSig);
mon Monitor1(“ Monitor”);
Monitor1.A(ASig);
Monitor1.B(BSig);
Monitor1.F(FSig);
Monitor1.Clk(TestClk);
sc_start(); //永远运行
返回0;}
包含模块的头文件,声明进行连接的顶级信号以及使用sc_clock创建的时钟;然后每个模块都被实例化并连接。
此后,调用sc_start()将启动模拟,并且模拟将永久运行(或者直到遇到刺激模块中对sc_stop()的调用)。
这是此示例的输出
时间ABF
0秒0 0 1
10 ns 0 0 0
20 ns 0 1 1
30 ns 1 0 1
40 ns 1 1 0
如果您看一下,您会发现一些很奇怪的东西-时间0的第一行说F为1(真),而A和B为0-这不是一个非常有说服力的EXOR门!到10 ns时,一切都应达到预期。在时间0发生了什么事?
模拟
SystemC库包含一个仿真内核。这决定了要运行的进程(软件线程)。在时间0,所有SC_METHOD和SC_THREAD将以不确定的顺序运行,直到它们暂停。然后,当出现时钟沿时,SC_CTHREAD将运行。
上面的问题是由于多种情况造成的
所述sc_clock语句结果在上升沿在时间0,因此监视器和刺激的过程将运行(在未定义的顺序,它不知道其将第一运行)
C ++中的变量并不总是具有定义的初始值(除非将其声明为静态)。因此,F持有的数据值恰好是从1开始(真)
所述do_nand2 SC_METHOD运行在时间0,和时间表˚F更新,但˚F是一个信号,它不能立即更新,因此该值1是仍然存在的监视处理运行时。
为了证明是这种情况,可以修改sc_clock语句以延迟时钟的第一个边沿,如下所示
sc_clock TestClk(“ TestClock”,10,SC_NS,0.5,1,SC_NS);
最后的1个SC_NS参数指定在第一个时钟沿出现之前的1 ns延迟。现在时间已经过去,所以F将被更新。这是对应的输出
时间ABF
1 ns 0 0 0
11 ns 0 0 0
21 ns 0 1 1
31 ns 1 0 1
41 ns 1 1 0
现在您可以看到F总是正确的。
结论
总结了模块和流程的快速浏览。您已经了解了了解SystemC仿真内核的并发本质以及sc_signal基本通道的行为的重要性。
您还看到了一些在顶层模块中实例化底层模块的基本示例,以及如何使用sc_main。
相关问答
xor是什么门?xor是异或门。该门是在不同类型的计算电路中使用的一种特殊类型的门。除了AND,OR,NOT,NAND和NOR门外,还有两个特殊的门,即Ex-OR和Ex-NOR。这些门本身并不是...
布尔运算原理?是逻辑学中描述和操作布尔代数的基本规则。它基于布尔代数的两个基本元素,即真(1)和假(0),并定义了一组基本的逻辑操作符,包括与(AND)、或(OR)和非(N...是逻...
谁帮我写个简单的通信达公式,求选出昨日收阴今日低...- 汇...[回答]选股公式存在吗?通达信选股小公式:1,30个交易日内,股价跌幅达到一半的股票:xghhv(c,30)-c)/hhv(c,30)>0.5;2,今天的量是5天平均的2倍以上xg:v>ma(v...
通达信公式中怎样加入指定个股或大盘的KDJ数据- 汇财吧专业问...[回答]大盘KDJA3:="999999$HIGH";A4:="999999$LOW";DP:=(CLOSE-LLV(A4,9))/(HHV(A3,9)-LLV(A4,...