存储器
1.序言
本文详细讲解了单双端口ROM常见注意点,并以牛客网VL53/VL54单双端口ROM两个题为例进行了讲解。
2.思路及注意点
(1)存储空间配置
一般配置一个reg类型变量对数据进行存储,格式如下:
reg [存储器位宽] 存储空间名 [存储深度];
注意:存储器会给出存储深度和存储位宽,要会根据这两个值定义存储空间以及确定数据地址变量位宽。以存储深度为128,数据位宽为8为例:
定义存储空间:
reg [8-1:0] 存储空间名 [128-1:0];
定义读写数据的位宽:(即求128个数需要的地址位宽为**$clog2(128)**,即多少位二进制位宽)
reg [$clog2(128)-1:0] r_addr;
reg [$clog2(128)-1:0] w_addr;
(2)存储空间初值
如果存储空间要求复位时,清空,一般使用for循环实现:
);
//存储空间配置
reg [3:0] mem [255:0];
//存储空间操作
integer i;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
for(i = 0 ; i<8 ; i=i+1)
mem[i] <= 'd0;
else if(write_en)
mem[write_addr] <= write_data;
end
3.例题(牛客网VL53/VL54单双端口ROM)
(1)牛客网存储器,VL53单端口RAM
A)题目描述
注意,这个题缺了两个条件:
//在enb为1的时候写数据,在enb为0的时候读数据
//利用时钟的上升沿写数据,下降沿读数据
B)实现
`timescale 1ns/1ns
module RAM_1port(
input clk,
input rst,
input enb,
input [6:0]addr,
input [3:0]w_data,
output wire [3:0]r_data
);
//在enb为1的时候写数据,在enb为0的时候读数据
//利用时钟的上升沿写数据,下降沿读数据
//深度为10进制,变量后第一个为深度,第二个为位宽
reg [3:0] rem [0:128-1];
always@(posedge clk)begin
if(enb)
rem[addr] <= w_data;
end
reg [3:0] rdata_r;
always@(negedge clk or negedge rst)begin
if(!rst)
rdata_r <= 'd0;
else if(!enb)
rdata_r <= rem[addr];
else
rdata_r <= 'd0;
end
assign r_data = rdata_r;
endmodule
(2)牛客网存储器,VL54RAM简单实现
A)题目描述
B)实现
`timescale 1ns/1ns
module ram_mod(
input clk,
input rst_n,
input write_en,
input [7:0]write_addr,
input [3:0]write_data,
input read_en,
input [7:0]read_addr,
output reg [3:0]read_data
);
//存储空间配置
reg [3:0] mem [255:0];
//存储空间操作
integer i;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
for(i = 0 ; i<8 ; i=i+1)
mem[i] <= 'd0;
else if(write_en)
mem[write_addr] <= write_data;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
read_data <= 'd0;
else if(read_en)
read_data <= mem[read_addr];
else
read_data <= 'd0;
end
endmodule