RAM学习笔记(SRAM,DRAM,同步,异步)

SRAM和DRAM区别与联系

从基本的cell结构上划分,RAM分为SRAM和DRAM,二者在性能,成本,使用场景上都有所不同。

器件结构

SRAM

SRAM(Static Random-Access Memory),静态随机存取存储器,其基本的cell电路图如下:
SRAM cell

SRAM的cell中共有六个晶体管(transistor)组成,其结构相当于一个SR锁存器:
在这里插入图片描述
  WL(word line),字线,连接在三极管的栅极,字线用来控制,相当于写使能,当字线接通时,M5,M6打开,位线(Bit Line,图中的BL)才可以进行读写操作,图中有两条位线,互相取反,虽然不是必须两条取反的位线,但是这种取反的位线有助于改善噪声容限。
  当栅极电压超过阈值之后,源极的电子才会流通到漏极,使得源极和漏极的电压相等。因此,三极管可以看作一个阀门,阀门打开,阀门两端电压相等,阀门关闭,两端会存在稳定的电势差。
  其中,M1与M2,M3与M4分别构成了两个与非门。这里可以验证,以M3和M4组成的与非门为例,在写状态下,BL端输入到Q,因此 Q Q Q Q ‾ \overline{Q} Q为与非门的输入,与非门的输出为 Q Q Q。锁存器状态具体的细节请参见SR锁存器_个人整理_JauWang,SRAM具体的读写操作讲解请参见SRAM工作原理图解

DRAM

DRAM cell主要由电容构成,其结构如下:
在这里插入图片描述
结构明显简单于SRAM,一个cell只需要一个晶体管和电容,因此其cell面积小于SRAM,集成度可以做得很高。当字线选通时,位线上的电压得以通过晶体管,加在电容上,需要注意的是,电容具有漏电的特性,因此,即使不更新数据,每隔一段时间,DRAM也需要进行刷新一次,保证数据不丢失。同时,电容的充电需要时间,因此,DRAM的读写速度是不如SRAM的。

性能差异

SRAMDRAM
基本元件锁存器电容
破坏性读出
刷新不需要需要
读写速度
集成度
发热量
存储成本

使用场景

SRAM用于 极高速度信息传送且较小信息量(因为成本问题)场景中,一般CPU的cache使用的就是SRAM,而DRAM则用于大量信息但是速度要求中等情境下,比如内存。

SRAM类别与实现

同步双端口实现

sram共有两个端口,一个为写端口,一个为读端口,代码如下:

`include "defines.v"

module sram_s # (
    parameter ADDR_WIDTH = 4,
    parameter DATA_WIDTH = 8,
    parameter DATA_DEPTH = 16
)(
    input wire                  clk,
    input wire                  rst,
    input wire                  ce,

    // port read
    input wire[ADDR_WIDTH-1:0]  raddr,
    input wire                  re,
    output reg[DATA_WIDTH-1:0]  rdata,

    // port write
    input wire[ADDR_WIDTH-1:0]  waddr,
    input wire                  we,
    input wire[DATA_WIDTH-1:0]  wdata
    );

    integer i;
    reg [DATA_WIDTH-1:0]        register [DATA_DEPTH-1:0];

always @ (posedge clk) begin
    if (rst == `RstEnable) begin
        for(i=0; i<DATA_DEPTH; i=i+1) begin
            register[i] <= {DATA_WIDTH{1'b0}};
        end
    end 
    else if ((we == `WriteEnable) && (ce == `ChipEnable)) begin
        register[waddr] <= wdata;
    end
end

always @ (posedge clk) begin
    if (rst == `RstEnable) begin
        rdata <= {DATA_WIDTH{1'b0}};
    end
    else if ((re == `ReadEnable) && (ce == `ChipEnable)) begin
        rdata <= register[raddr];
    end else begin
        rdata <= rdata;
    end
end

endmodule

其中,defines.v文件:

`define RstEnable 1'b1
`define RstDisable 1'b0
`define WriteEnable 1'b1
`define WriteDisable 1'b0
`define ReadEnable 1'b1
`define ReadDisable 1'b0
`define ChipEnable 1'b1
`define ChipDisable 1'b0

testbench文件:

`include "defines.v"

module tb_sram_s(

    );
`define CLK_PERIORD     10

parameter ADDR_WIDTH = 4;
parameter DATA_WIDTH = 8;
parameter DATA_DEPTH = 16;

integer i;

reg                     clk, rst, ce;

reg[ADDR_WIDTH-1:0]     raddr;
reg                     re;
wire[DATA_WIDTH-1:0]    rdata;

reg[ADDR_WIDTH-1:0]     waddr;
reg                     we;
reg[DATA_WIDTH-1:0]     wdata;

sram_s sram_s_0(
    .clk(clk),
    .rst(rst),
    .ce(ce),

    // port read
    .raddr(raddr),
    .re(re),
    .rdata(rdata),

    // port write
    .waddr(waddr),
    .we(we),
    .wdata(wdata)
);

initial begin
    clk = 0;
end
always #(`CLK_PERIORD/2)    clk = ~clk;

initial begin
    rst     =   `RstEnable;
    ce      =   `ChipDisable;
    we      =   `WriteDisable;
    re      =   `ReadDisable;
    raddr   =   {ADDR_WIDTH{1'b0}};
    #20
    rst     =   `RstDisable;
    ce      =   `ChipEnable;
    #5

    @(posedge clk)
    we      =   `WriteEnable;
    for (i=0;i<DATA_DEPTH;i=i+1) begin
        @(posedge clk) 
        begin
            waddr = i;
            wdata = {DATA_WIDTH{1'b0}}+i;
            we      =   `WriteDisable;
            re      =   `ReadEnable;
            raddr = i;
        end
    end

    #10
    ce      =   `ChipDisable;

    #100 $stop;
end

endmodule

注意其中的@(posedge clk)会阻塞之后的语句直到时钟上升沿到来。在进行仿真时,可能会出现 cannot open include file ‘defines.v’ 的报错,将defines.v文件复制到tb文件所在文件夹下就可以解决。
波形:
在这里插入图片描述
电路图中,读输出端口是一个寄存器,如果去掉这个寄存器(即读端口写成组合逻辑),那么读端口的输出随时可以根据读地址的改变而改变,而不是等时钟上升沿才会刷新。
在这里插入图片描述

异步双端口实现

不同于同步SRAM,异步双端口SRAM需要两个不同频率的时钟,分别用于两个端口的读写,代码如下:

`include "defines.v"

module sram_a # (
    parameter ADDR_WIDTH = 4,
    parameter DATA_WIDTH = 8,
    parameter DATA_DEPTH = 16
)(
    input wire                  clkr, clkw,
    input wire                  rst,
    input wire                  ce,

    // port read
    input wire[ADDR_WIDTH-1:0]  raddr,
    input wire                  re,
    output reg[DATA_WIDTH-1:0]  rdata,

    // port write
    input wire[ADDR_WIDTH-1:0]  waddr,
    input wire                  we,
    input wire[DATA_WIDTH-1:0]  wdata
    );

    integer i;
    reg [DATA_WIDTH-1:0]        register [DATA_DEPTH-1:0];

always @ (posedge clkw) begin
    if (rst == `RstEnable) begin
        for(i=0; i<DATA_DEPTH; i=i+1) begin
            register[i] <= {DATA_WIDTH{1'b0}};
        end
    end 
    else if ((we == `WriteEnable) && (ce == `ChipEnable)) begin
        register[waddr] <= wdata;
    end
end

always @ (posedge clkr) begin
    if (rst == `RstEnable) begin
        rdata <= {DATA_WIDTH{1'b0}};
    end
    else if ((re == `ReadEnable) && (ce == `ChipEnable)) begin
        rdata <= register[raddr];
    end else begin
        rdata <= rdata;
    end
end


endmodule

tb文件:

`include "defines.v"

module tb_sram_a(

    );
`define CLK_PERIORD_R       10
`define CLK_PERIORD_W       16

parameter ADDR_WIDTH = 4;
parameter DATA_WIDTH = 8;
parameter DATA_DEPTH = 16;

integer i;

reg                     clkr, clkw, rst, ce;

reg[ADDR_WIDTH-1:0]     raddr;
reg                     re;
wire[DATA_WIDTH-1:0]    rdata;

reg[ADDR_WIDTH-1:0]     waddr;
reg                     we;
reg[DATA_WIDTH-1:0]     wdata;

sram_a sram_a_0(
    .clkr(clkr),
    .clkw(clkw),
    .rst(rst),
    .ce(ce),

    // port read
    .raddr(raddr),
    .re(re),
    .rdata(rdata),

    // port write
    .waddr(waddr),
    .we(we),
    .wdata(wdata)
);

initial begin
    clkr = 0;
    clkw = 0;
end
always #(`CLK_PERIORD_R/2)      clkr = ~clkr;
always #(`CLK_PERIORD_W/2)      clkw = ~clkw;

initial begin
    rst     =   `RstEnable;
    ce      =   `ChipDisable;
    we      =   `WriteDisable;
    re      =   `ReadDisable;
    raddr   =   {ADDR_WIDTH{1'b0}};
    #20
    rst     =   `RstDisable;
    ce      =   `ChipEnable;
    #5

    @(posedge clkw)
    we      =   `WriteEnable;
    for (i=0;i<DATA_DEPTH;i=i+1) begin
        @(posedge clkw) 
        begin
            waddr = i;
            wdata = {DATA_WIDTH{1'b0}}+i;
        end
    end

    @(posedge clkr)
    we      =   `WriteDisable;
    re      =   `ReadEnable;
    for (i=0;i<DATA_DEPTH;i=i+1) begin
        @(posedge clkr) 
        begin
            raddr = i;
        end
    end

    #10
    ce      =   `ChipDisable;

    #100 $stop;
end

endmodule

仿真波形:
在这里插入图片描述

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值