后端基础——rom,ram,memory compiler

发布时间 2023-03-31 16:56:21作者: Haowen_Zhao

一,memory基础

1,导览

Memory用来存储和读写的大量的二进制数据。按功能上分类,基本可以分为两大类:只读存储器(ROM)和随机存取存储器(RAM)。ROM只能读,不能写;RAM既能读又能写。RAM具有易失性。断电以后,RAM中保存的数据将全部丢失;而ROM中的数据则可以长久保存。

RAM可以分为常用的SRAM和DRAM。SRAM是静态的存储器,存储单元是一个触发器,有0,1两个稳态;DRAM是动态的存储器,比SRAM要复杂一些,因为它会利用电容器存储电荷来保存0或1,需要在存储数据的过程中需要对于存储的信息不停的刷新。 另一种常用的存储器,我们称为Register File。 它是由多个寄存器堆组成的阵列,内部结构功能上和SRAM完全类似。只是Register File去除了bist电路,容量较小,速度也比较快,经常用于前端仿真,Register file速度快,面积小,容量小。小容量下,我们也应该优先选择Register file。

2,结构

一般由存储阵列,地址译码器和输出控制电路组成。我们把存储阵列以外的电路都称为外围电路(Periphery)。存储阵列是memory的核心区域,它有许多存储单元组成,每个存储单元存放一位二值数据。每次读出一组数据,称为一组字。一个字中所含的位数称为字长(Bit)。为了区别各个不同的字,给每个字赋予一个编号,称为地址,由译码器将地址代码转译。地址单元个数就是字数(Depth),用N表示,数值为2n,n为地址码的位数。
3,ROM,RAM的verilog实现

ROM

`include "../core/defines.v"  //包含一些常量和宏定义,如WriteEnable、RstEnable、ZeroWord等

module rom(

    input wire clk,  //时钟
    input wire rst,  //复位

    input wire we_i,                   // write enable使能信号
    input wire[`MemAddrBus] addr_i,    // addr地址
    input wire[`MemBus] data_i,  //数据

    output reg[`MemBus] data_o         // read data读出的数据

    );

    reg[`MemBus] _rom[0:`RomNum - 1];  //定义了一个内部的只读存储器_rom,存储的数据位宽为MemBus,ROM的大小为RomNum。直接用reg[]a[]寄存器堆实现

//当为写使能时,将data_i写入_rom中的addr_i[31:2]位置
    always @ (posedge clk) begin
        if (we_i == `WriteEnable) begin
            _rom[addr_i[31:2]] <= data_i;
        end
    end
//读使能,当rst为RstEnable时,将data_o的值设为ZeroWord;否则将data_o的值设为_rom中addr_i[31:2]位置的值
    always @ (*) begin
        if (rst == `RstEnable) begin
            data_o = `ZeroWord;
        end else begin
            data_o = _rom[addr_i[31:2]];
        end
    end

endmodule

RAM的verilog逻辑与之相同,均例化为寄存器堆。

在进行仿真测试时,利用系统函数$readmemh和$readmemb分别用来读取十六进制文件和二进制文件,将需要写的数据读进rom里,利用display将rom数据读出。

 

二,Memory macro配置

1,参数指标

一般foundry提供的memory databook上,会有以下参数指标:

WL: Physical Word Lines 字线 假设16

BL:Physical Bit Lines 位线 假设16

WD: Word Depth (WL * MUX)字数 16*16 =256

BIT: I/O Data Width (BL/MUX)字长 16/16 =1

Granularity:步长,WD或者BIT间隔的大小,只能按步长整数倍增加

BANK:分块,在Memory中,如果Bit line很长,会造成它的充放电速度很慢,导致memory的频率很低,这时,我们会将存储阵列分成N个bank来降低Bit line的长度

SEG: 分段,在Memory中,如果Word line很长,会影响它的性能,所以按Word line方向,把存储阵列分成N个segment.
bank和seg如下图所示:

 

 C64,C128,C256: Cell per bit line:每条bit line上挂的存储单元个数,经常有64,128,256等不同数字,该数值越大,表示配置的memory速度越慢,但是面积会越小;数值越小,表示配置的memory速度越快,但是面积会越大。

通常,大家还会看到类型HD,HC,HP等缩写,这些都是表征不同类型Bitcell和外围电路(Periphery)组成的:

HD:High Density Bitcell ,面积较小

HC:High Current Bitcell 高工作电流,access time较小

HP:High Performance Periphery ,速度快

LP:Low-Power Periphery ,功耗较小

ULP:Ultra-Low Power Periphery,超低功耗

ULL:Ultra-Low Leakage Periphery,超低漏电流

2,memory端口

(1)Register file

通常分为单口和双口,可以分为以下三种:

Single port(1RW): 一个端口,只能执行读或者写操作

Two port(1R/1W):2个端口,一个端口读,另一个端口写,可以独立不同的时钟频率

Pseudo two port(1R/1W):2个端口,一个端口读,另一个端口写,只有一个时钟

 

 (2)SRAM包含更多的模块,容量可以做得更大,可以拥有更多的bank,速度较慢,面积更大。大容量需求时,可以优先考虑SRAM。

Single port(1RW): 一个端口,只能执行读或者写操作

Dual port(2RW):2个端口,两个端口可以同时读写,可以独立不同的时钟频率

Pseudo two port(1R/1RW):2个端口,一个端口读,另一个端口可以读可以写,只有一个时钟。

即类型与(1)一致

三,Memory compiler使用

通常使用ARM Artisan Physical IP,能够给SoC提供物理IP,这其中就包括嵌入式的存储器。它包含了从250nm到3nm的每个foundry的IP,而且包含单、双口SRAM、Register File、eMRAM和ROM多种Memory。

 

 参数设定:

  • Number of Words:SRAM的深度,有范围限制。
  • Number of bits:SRAM数据宽度,有范围限制。
  • Multiplexer Width:根据官方PDF内设置即可,这个设定与SRAM的形状,有关,有范围限制
  • Frequency:根据系统工作频率设定,个人认为,不同频率,生成的SRAM硬件单元密度,形状,布线是不同的。

  • Word-write Mask:掩码,根据需要开启即可。
  • Corners:工艺角,一般跟整个系统需要的工艺角相同即可,一般只勾选一个就可以,否则会生成好多文件。ss为slow,tt为标准,ff为fast;一般SRAM工艺角与标准单元工艺角参数相同。

生成文件:

  • .lib文件:lib库文件转为db库,用于DC综合和ICC后端导入的库文件。
  • .lef文件:用于生成物理库MW
  • .v文件:生成verilog模型,用于前端仿真。在综合时,不要包括进来,否则会提是无法综合的错误。后端也不会用到。

其中lib可能需要转换。

参考文献:

(10条消息) 数字芯片后端设计——Memory Complier使用及库导入_数字后端怎样用lef文件生成mv库_Kimho-emo的博客-CSDN博客

(10条消息) 记忆深处有尘埃——Memory Compiler_Tao_ZT的博客-CSDN博客

使用Memory Compiler生成ASIC Embedded Memory - 知乎 (zhihu.com)