如何用Verilog设计一个RAM?

如何用Verilog设计一个RAM?

SRAM

Verilog设计一个sram,供仿真使用,实际工程中,FPGA直接例化工具自带的IP Core,ASIC由后端做专门的memory。 csen_n为低,wren_n为高写数据 csen_n为低,wren_n为高读数据 csen_n为高,memory不工作 。

1
2
3
4
5
6
7
8
9
10
11
reg     [DATA_WIDTH-1:0]   register[2**ADDR_WIDTH-1:0];

always @(posedge clk)begin
if(!wren_n && !csen_n)
register[addr] <= data_i;
end

always @(posedge clk)begin
if(wren_n && !csen_n)
data_o <= register[addr];
end

双口RAM

双口ram是单一时钟,支持一个读地址和一个写地址。本设计是同步读数ram,异步读数ram去掉时钟即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
reg     [DATA_WIDTH-1:0]   register[2**ADDR_WIDTH-1:0];
reg [ADDR_WIDTH-1:0] addrb_r;

always @(posedge clk)begin
if(!wrena_n && !csen_n)
register[addra] <= data_a;
end

always @(posedge clk)begin
if(!rdenb_n && !csen_n)
data_b <= register[addrb];//read old data
//addrb_r <= addrb//read new data
end

//assign data_b = register[addrb_r];//read new data

真双口RAM

真双口ram是两个时钟,支持两套独立完整的读写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
reg     [DATA_WIDTH-1:0]   register[2**ADDR_WIDTH-1:0];

always @(posedge clka)begin
if(!wrena_n && !csen_n)begin
register[addra] <= dina;
douta <= dina;
end
else if(!csen_n)
douta <= register[addra];
end

always @(posedge clkb)begin
if(!wrenb_n && !csen_n)begin
register[addrb] <= dinb;
doutb <= dinb;
end
else if (!csen_n)begin
doutb <= register[addrb];
end
end

Register File

在我的认知中Register File的写法其实和上述大同小异,在FPGA中写成Register File,工具貌似会综合成BRAM资源,在ASIC设计中RAM Memory需要专门去做存储块。本文大致了解RAM的原理,只可供仿真使用。

使用Reg File在存储为小规模使用时有优势,面积小速度快,当存储的规模大于256个单元时,提倡使用sram的标准单元库。

SRAM和DRAM

SRAM:Static Random-Access Memory,静态随机存取存储器,只要供电数据就会保持,但断电数据就会消失,也被称为Volatile Memory

DRAM:Dynamic Random Access Memory,动态随机存储器,主要原理是利用电容存储电荷的多少来代表一个bit是0还是1,由于晶体管的漏电电流现象,电容会放电,所以要周期性的给电容充电,叫刷新。SRAM不需要刷新也会保持数据丢失,但是两者断电后数据都会消失,称为Volatile Memory

SDRAM和DDR

SDRAM:Synchronous Dynamic Random Access Memory,同步动态随机存储器,同步写入和读出数据的DRAM。

DDR:Double Data Synchronous Dynamic Random Access Memory,双倍速率同步动态随机存储器,就是DDR SDRAM双倍速率传输的SDRAM,在时钟的上升沿和下降沿都可以进行数据传输。我们电脑的内存条都是DDR芯片。

留一个练习

设计一个双口RAM,要求可读可写,可以同时读写,两种处理方式

  • 将输入输出参数化,可重复调用
  • 读取原来存储的值,然后立即写入新值
  • 不能读取原来的值,而是直接获得正在写入的值

将设计电路参数化可重复使用,构建自己的代码库,搭建起你的数字积木,本设计博主放在了GitHub上,可以在订阅号后台回复 “ip_lib”得到GitHub路径进行交流。

NingHeChuan wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!