背景
- 基于Xilinx的7系列FPGA,
在通过文档《ug474_7Series_CLB.pdf》学习CLB过程中,
对7系列CLB中的分布式RAM(Distributed RAM)进行展开学习,遂就有了此文。
系列目录与链接
基于Xilinx的7系列FPGA,笔者在对CLB进行学习、研究时,归纳并总结出了以下博文:
1、分篇1:《7系列 之 查找表(Look-Up Table,LUT)》
2、分篇2:《7系列 之 存储单元(Storage Elements)》
3、分篇3:《7系列 之 多路复用器(Multiplexers)》
4、分篇4:《7系列 之 进位逻辑(Carry Logic)》
5、分篇5:《7系列 之 分布式RAM(Distributed RAM)》
6、分篇6:《7系列 之 7系列 之 移位寄存器(Shift Registers)》
7、总纲 :《7系列 之 可配置逻辑块(7 Series Configurable Logic Block,CLB)》
说明1:本系列基于文档文档《ug474_7Series_CLB.pdf》而写,翻译和感悟,会出现中英文混合的情况。
说明2:虽然文中会出现一些原文的部分截图,但非常支持并推荐道友们去看原汁原味的官方文档
说明3:在查阅相关资料过程中,发现一些关于相关知识点的介绍零零散散,本系列会对其进行整合,力求详尽。
说明4:如果文章有误,欢迎道友们指出、讨论,笔者也会积极改正,希望一起进步!
文章目录
Ch.1: RAM相关的基本概念
1.1 ··· 随机存取存储器(RAM)
-
随机存取存储器(Random Access Memory,RAM),可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。RAM工作时可以随时从任何一个指定的地址写入(存入)或读出(取出)信息。它与ROM的最大区别是数据的易失性,即一旦断电所存储的数据将随之丢失。RAM在计算机和数字系统中用来暂时暂存程序、数据和中间结果。
-
RAM的一些基本特点:
1、易失性:RAM是一种易失性存储介质,这意味着当电源关闭时,存储在RAM中的数据会丢失。
2、读写速度:RAM的读写速度非常快,通常比硬盘驱动器(HDD)和固态驱动器(SSD)这类长期存储设备要快得多。
3、用作工作内存:计算机将RAM用作工作内存(或主存),用于暂时存储正在运行的程序和数据,以便CPU能够快速访问。
4、容量:RAM的容量通常以字节(B)为单位,常见的RAM大小从几GB到几十GB不等,取决于计算机系统的需求。
5、类型:RAM主要有两种类型,即静态RAM和动态RAM。静态RAM,速度快但成本高,通常用作高速缓存;动态RAM速度稍慢但成本较低,通常用作主存。
1.2 ··· FPGA中的RAM
在FPGA中,笔者目前接触到的RAM主要分为三类:
块RAM(Block RAM,BRAM),
分布式RAM(Distributed RAM),
和静态RAM(Static Random-Access Memory,SRAM)。
1.2.1 ··· BRAM
- 块RAM(BRAM,Block RAM),FPGA中专用RAM资源,固定分布在FPGA内部的特定位置。
- 性能优异但数量有限,每一个BRAM是36Kb大小,也可以配置成2个18Kb的BRAM,BRAM可以用来实现多种不同位宽和深度的RAM/ROM/FIFO,在FPGA中应用非常广泛和灵活。
- BRAM的输出需要时钟来驱动,具有较大的存储空间,在作为FIFO调用资源的基础下,支持不同位宽的读写(时序逻辑输出)。
1.2.2 ··· 分布式RAM
- 分布式RAM(Distributed RAM),使用是CLB中的SLICEM中的LUT,会占用一定的逻辑资源,使用时位宽和深度都可以随意配置。
1.2.3 ··· SRAM
- 静态RAM(Static Random-Access Memory,SRAM)
- 所谓的“静态”,是指这种存储器只要保持通电,里面储存的数据就可以恒常保持。相对之下,动态随机存取存储器里面所储存的数据就需要周期性地更新。
-当电力供应停止时,SRAM储存的数据还是会消失(被称为volatile memory),这与在断电后还能储存资料的ROM或闪存是不同的。
1.3 ··· BRAM与分布式RAM
那么,在BRAM和分布式RAM之间该怎么选择呢?
- 参考文献4,提及了BRAM与分布式RAM的选择方法:
1、小于或等于64bit容量的都用分布式RAM实现;
2、深度在64~128之间的,若无额外的block,可用分布式RAM;数据宽度大于16时,用BRAM。
3、分布式RAM有比BRAM更好的时序性能。分布式RAM在逻辑资源CLB中。而BRAM则在专门的存储器列中,会产生较大的布线延迟,布局也受制约。
4、分布式RAM可以是纯组合逻辑,即给出地址马上出数据,也可以加上register变成有时钟的RAM。而BRAM一定是有时钟的。
上述做个参考,建议道友还是转跳至 本文的第3.7章,有官方给的说明。
Ch.2: 7系列中的SLICEL & SLICEM
2.1 ··· Slice的构成
-
Slice是 Xilinx 公司定义的基本逻辑单位
-
每个Slice中都包含:
1、 4个 6输入查找表(6-inputs look-up tables,LUT6)
2、 8个 存储单元(storage elements )
3、 3个 数据选择器(wide-function multiplexers)
4、 1个 进位链(carry logic) -
每个Slice都使用这些单元来提供逻辑、算术和ROM功能。
-
一些Slices支持两个额外的功能:用分布式RAM来存储数据、用32位寄存器来进行数据移位(即,移位寄存器)。
支持这两个额外功能的Slices称为SLICEM,其它的Slices被称为SLICEL。
1、大约三分之二的Slices是SLICEL(L:Logic),剩余的是SLICEM(M:Memory)。
2、数量比:SLICEL :SLICEM = 2 :1
2.2 ··· SLICEL & SLICEM
- SLICEL结构:
- SLICEM结构:
由上述两个图可以看出,SLICEM和SLICEL的大体结构相同。但是,SLICEM中每个LUT6的输入多了一个DI信号,并且CE信号中引入了WE控制。(两者区别,笔者并未在图中标出,不过仔细对比下两者的结构示意图,还是可以看出来的。)
同时,继续放大 xc7a100tfgg676-2 (active) 在Vivado的Device视图并对比,可以发现SLICEM和SLICEL在Device视图上明显的区别就在于两者的LUT有所不同。
上图,是对 SLICE_X30Y78(SLICEM)的Device视图中的LUT6放大截图。
上图,是对 SLICE_X31Y78(SLICEL)的Device视图中的LUT6放大截图。
将上述两种LUT的结构进行对比,可得:
1、 相同点:都具有地址输入线(A1-A6),两个输出口(O5-O6)。
2、不同点:SLICEM的LUT6具有写地址输入线(WA1-WA8),写数据端(DI1 DI2),写使能端(WE),而SLICEL的LUT6没有。
这是由于以上的不同,才使得:
SliceL的LUT只具有存储数据的能力,只能作为ROM使用;
而SliceM的LUT还具备了数据写入的功能,可以作为分布式RAM或移位寄存器使用。
Ch.3: 7系列中的分布式RAM(Distributed RAM)
- 分布式RAM(Distributed RAM),仅在SLICEM中可用(Available in SLICEM Only)。
3.1 ··· 分布式RAM(Distributed RAM)
一个 SLICEM中的多个查找表可以不同方式组合来存储更多的数据。
分布式 RAM的主要特点是快速,本地化并且对于小数据缓存区、 先进出、以及寄存器文件有着理想的效果。
对于更大储需求,可考虑用 18K 分区 RAM来实现。
3.1.1 ··· 分布式RAM(Distributed RAM)
SLICEM中的LUT6s可以被用作为同步RAM资源,称为分布式RAM(Distributed RAM)。
SLICEM中的多个LUT可以用多种方式组合起来以存储更大的数据量。
表2-3,展示了SLICEM中每种分布式RAM配置所使用的LUT数量(每个 Slice中有4个LUT)。
分布式存储配置包括:
- Single port, 单端口
– 只有一个通用地址端口,用于同步写数据和异步读数据。即,读写地址共用同一个地址总线。 - Dual port,双端口
– 一个端口用于同步写数据和异步读数据。
– 一个端口用于异步读数据。 - Simple dual port,简单双端口
– 一个端口用于同步写数据(写数据端口没有数据输出或读取)。
– 一个端口用于异步读数据。 - Quad port,四端口
– 一个端口用于同步写数据和异步读数据。
– 三个端口用于异步读数据。
分布式RAM是同步写入,异步读取,在写使能信号WE为高电平时,并且处于时钟跳变沿时,数据写入到RAM中指定地址的空间中。数据读取则是异步操作,每次地址引脚的数据更新后,在经过LUT的时延后将指定地址的数据输出。
如图2-3所示,通用写数据端口 W6:W1( 即图中的WA[6:1] )是由D LUT的输入用D[6:1]进行的物理驱动。4个LUT的读数据端口都是独立的。因此,即使选择DPRAM64作为查找表配置,D查找表始终是有效的单端口;其他3个LUT实际上总是双端口的,尽管在读写地址连接在一起时可以选择SPRAM32。
图2-6至图2-14展示了占用一个Slice的各种分布式RAM配置示例。
3.1.2 ··· x2 配置时
当使用 x2 配置时(图2-6中32×2四端口),A6和WA6由软件驱动高电平,以保持O5和O6的独立性。
3.1.3 ··· Single-Port(单端口)
图2-8中D为输入的数据,WCLK为同步时钟,WE为使能信号,
A[5:0]为地址总线(读写共用),输出端可选是否使用寄存器实现同步读。
如果构建4个单端口64 × 1位模块,如图2-8所示,
4个RAM64x1单元要共用相同的时钟、write enable和共享读写端口地址输入,就可以占用一个Slice。这个配置相当于一个64 x 4位的单端口分布式RAM。
3.1.4 ··· Dual-Port(双端口)
如图2-9所示构建两个双端口64 × 1位模块,
两个RAM64X1D基元只要共用clock、write enable和读写端口地址输入,就可以占用一个Slice。
这个配置相当于一个64 x 2位的双端口分布式RAM。
一个端口(A[5:0]为地址输入)可同步写,异步读。
另一个端口(DPRA[5:0]为输入地址)只能异步读。
两个LUT6中存放着相同的数据,其实上面的LUT6就是一个单端口分布式RAM,
它的输出(SPO)取决于输入地址A[5:0]。
下面的LUT6的不同之处就是它的输入端口A[6:1]连的是DRPA[5:0],
因此它的输出取决于地址DPRA[5:0]。
3.1.5 ··· Quad-Port(四端口)
一个端口(ADDRD为地址输入)可同步写、异步读。
另外的三个端口(ADDRA、ADDRB、ADDRC为输入地址)只能异步读。
这四个端口,都可选同步读,但要加一个寄存器。
结构与双端口相似,4个LUT所存放相同的数据,但每个端口都可以单独读不同地址的内容。
3.1.6 ··· Simple Dual-Port(简单双端口)
一个端口用于同步写(不能输出数据,即不能进行读),
另一个端口用于异步读(可配置成同步读,加一个寄存器)。
64x3简单双端口分布式RAM,3个数据输入口DATA[3:1]并行输入,3个数据输出口O[3:1]并行输出。
3.1.7 ··· 更大深度的分布式RAM
实现深度大于64的分布式RAM配置,
需要使用wide-function multiplexers(F7AMUX、F7BMUX和F8MUX),如图2-12至图2-14所示。
如果构建两个单端口128 × 1位模块,如图2-12所示,
两个128x1单元可以占用一个SLICEM,
只要它们共享相同的时钟、write enable和共享读写端口地址输入。
这种配置相当于128x2位单端口分布式内存。
比提供的示例更大的分布式RAM配置需要多个Slice。
Slice之间没有直接的连接来在CLB内或Slice之间形成更大的分布式RAM配置。
3.2 ··· 分布式RAM的数据流
- 同步写操作:
同步写是带有使能信号的单时钟沿操作。
当写使能信号(WE)为高时,输入数据(D)被写入地址(address)对应的存储空间。 - 异步读操作:
当单端口时,输出由地址A决定,当双端口时,上面一个LUT(对应既可读又可写的)的输出SPO由地址A决定,下面一个LUT(只可读)的输出DPO由地址DPRA决定。每次地址变化,延迟访问LUT的时间后输出该地址的内存数据值。这个操作是异步的,可以独立于时钟信号(也可以配置成同步)。
3.4 ··· Read Only Memory (ROM)
SLICEMs 和 SLICELs 中的每个函数生成器(LUT)都可以实现64x1位的ROM,有三种配置:ROM64X1、ROM128X1和ROM256X1。ROM内容会在每个设备配置时加载。每个ROM配置大小占用的查找表数量,如表2-4所示。
3.5 ···SLICEM分布式RAM中的原语(primitive)
- RAM128X1D的原语:
RAM128X1D #(
.INIT(128'h00000000000000000000000000000000)
) RAM128X1D_inst (
.DPO(DPO), // Read port 1-bit output
.SPO(SPO), // Read/write port 1-bit output
.A(A), // Read/write port 7-bit address input
.D(D), // RAM data input
.DPRA(DPRA), // Read port 7-bit address input
.WCLK(WCLK), // Write clock input
.WE(WE) // Write enable input
);
- RAM64X16DP官方代码
// Dual-Port RAM with Asynchronous Read (Distributed RAM)
//
// File: HDL_Coding_Techniques/rams/rams_09.v
//
module v_rams_09 (clk, we, a, dpra, di, spo, dpo);
input clk; //时钟信号
input we; //写使能
input [5:0] a; //地址信号(读写共用)
input [5:0] dpra; //读地址信号
input [15:0] di; //输入数据
output [15:0] spo; //地址a对应的spo数据输出
output [15:0] dpo; //地址dpo对应的dpo数据输出
reg[15:0] ram [63:0]; //RAM定义,深度64,位宽16
always @(posedge clk) begin
if (we)
ram[a] <= di;
end
assign spo = ram[a]; //异步读
assign dpo = ram[dpra]; //异步读
endmodule
3.6 ··· 分布式RAM的应用
-
分布式RAM提供了一种权衡,
即:使用存储单元来处理非常小的阵列、使用BRAM来处理较大的阵列。
建议在可能的情况下评估内存,以提供最大的灵活性。
分布式RAM也可以通过实例化或通过使用Xilinx LogiCORE™ IP来实现。 -
一般来说,分布式RAM应该用于所有由64位或更少组成的存储器,
除非目标器件的SLICEM或逻辑资源短缺。分布式RAM在资源、性能和功率方面更高效。 -
对于深度大于64位但小于或等于128位的存储器,决定使用哪种最佳资源取决于以下因素:
1、额外RAM(BRAM)的可用性:如果没有,应该使用分布式RAM。
2、延迟的要求:如果需要异步读取能力,必须使用分布式RAM。
3、数据宽度:宽度大于16位的应使用BRAM,如果有BRAM的话。
4、必要的性能要求:与BRAM相比,分布式RAM具有更短的时钟到输出时间和更少的布局限制。
参考文献
1、《ug474_7Series_CLB.pdf》
2、《随机存取存储器》
3、《[FPGA IP系列] 2分钟了解FPGA中的BRAM》
4、《BRAM、DRAM和SRAM的区别》
5、《FPGA原理与结构(6)——分布式RAM(Distributed RAM,DRAM)》
6、《FPGA从入门到精通(3) - DRAM》