一、储存单元简介
1.ROM
只读存储器,系统上电后数据就被写入ROM,运行过程中只能从ROM中读取数据,而不能改变ROM中的数值。
2.RAM
随机存取储存器,可以随时把数据写入任一指定地址的储存单元,也可以随时从任一指定地址中读取数据。其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。适合双向交换数据。
2.1RAM的分类
Altera FPGA的RAM IP核分为两种类型:单端口RAM和双端口RAM。单端口RAM只有一组地址线,这组地址线控制着写数据端口和读数据端口,而双端口RAM具有两组地址线,这两组地址线分别控制着写数据端口和读数据端口。单端口RAM类型和双端口RAM类型在操作上都是一样的。下面以单端口RAM IP核为例。
Data | RAM写数据端口 |
Address | 写使能信号,高电平有效,高电平时data口的数据才能被写入 |
Wren | 写使能信号,高电平有效,高电平时RAM中的数据才能被读出 |
rden | 读使能信号,高电平有效,高电平时RAM中的数据才能被读出 |
Clken | 时钟使能信号,用于控制时钟是否有效 |
aclr | 异步复位信号,高电平有效 |
Inclock outclock | 单口RAM端口支持双时钟模式和单时钟模式。在双时钟模式下,输入时钟控制存储器模块的输入寄存器,其中包括数据、地址、wren以及rden寄存器;输出时钟控制数据输出寄存器。在单时钟模式下,没有Inclock信号与outclock信号之分,只有一个clock信号,可以通过单时钟以及时钟使能来控制M9K存储器模块中的所有寄存器。 |
2.2双端口RAM介绍
分为简单双口RAM和真双口RAM两种:
简单双口RAM:一组读数据和读地址线,一组写数据和写地址线,能同时进行读和写操作,但不能同时对同一地址进行读和写操作。
真双口RAM:有两组读数据线线与地址线,两组写数据线与写地址线;能同时进行两个端口读,能同时进行两个端口写,也能一个端口读同时另一个端口写。这个真双口RAM其实就是两个单口RAM组合在一起构成的,只是真双口RAM里的两个单口RAM是操作的同一片存储空间。
3.FIFO
(不寻址,操作简单)适合数据缓冲、跨时钟域数据同步,数据位宽匹配处理。
3.1FIFO的基本介绍
FIFO的英文全称是First In First Out,即先进先出。FPGA使用的FIFO一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互,也即所谓的跨时钟域信号传递。
它与FPGA内部的RAM和ROM的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点是不能像RAM和ROM那样可以由地址线决定读取或写入某个指定的地址。
3.2FIFO的分类
FIFO从输入时钟的角度来分,有两种类型:单时钟FIFO(SCFIFO)和双时钟FIFO(DCFIFO);其中,双时钟FIFO又可从输出数据的位宽的角度,分为普通双时钟(DCFIFO)和混合宽度双时钟FIFO(DCFIFO_MIXED_WIDTHS)。
单时钟FIFO具有一个独立的时钟端口clock,因此,所有的输入输出信号都同步于clock信号。
双时钟FIFO结构中,写端口和读端口分别有独立的时钟,所有与写相关的信号都是同步于写时钟wrclk,所有与读相关的信号都是同步于读时钟rdclk。
3.3FIFO的参数
1.FIFO的宽度:FIFO一次读写操作的数据位N; |
2.FIFO的深度:FIFO可以储存多少个宽度位N位的数据; |
3.空标志:对于双时钟FIFO,又分为读空rdempty和写空标志wrempty;FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止继续从FIFO中读出数据而造成无效数据的读出。 |
4.满标志:对于双时钟FIFO,又分为读满标志rdfull和写满标志wrfull;FIFO已满或将要写满时由FIFO的状态电路送出的一个信号,以阻止继续向FIFO中写数据而造成溢出。 |
5.读时钟:读FIFO时所遵循的时钟,在每个时钟的上升沿触发。 |
6.写时钟:写FIFO时所遵循的时钟,在每个时钟的上升沿触发。 |
3.4单时钟FIFO和双时钟FIFO的应用场景
1.单时钟FIFO常用于同步时钟的数据缓冲;
2.双时钟FIFO常用于跨时钟域的数据信号的传递,例如时钟域A下的数据data传递给异步时钟域B,当data为连续变化信号时,如果直接传递给时钟域B则可能会导致收非所送的情况,即在采集过程中会出现包括亚稳态(数据采样失真)问题在内的一系列问题,使用双时钟FIFO能将不同时钟域中的数据同步到所需的时钟域中。
二、储存单元测试代码
1.RAM
`timescale 1ns/1ns
module tb_ram();
//激励信号
reg clk ;
reg rst_n ;
reg [07:00] address ;
reg [07:00] data ;
reg rden ;
reg wren ;
//观测信号
wire [07:00] data_out ;
//模块例化
s_ram_256_8 s_ram_256_8_inst (
.aclr ( ~rst_n ),
.address ( address ),
.clock ( clk ),
.data ( data ),
.rden ( rden ),
.wren ( wren ),
.q ( data_out)
);
//系统初始化
initial begin
clk = 1'b1;
forever begin
#10 clk = ~clk;
end
end
initial begin
rst_n =1'b0 ;
address = 8'd0 ;
data = 8'h33 ;
rden = 1'b0 ;
wren = 1'b0 ;
#203
rst_n = 1'b1 ;
//读取一遍储存空间所有数据
repeat(256)begin
rden = 1'b1;
#20
address = address + 8'd1;
end
rden = 1'b0;//读取使能关闭
//写入数据
repeat(256)begin
wren = 1'b1;
#20
data = data + 8'h2;
address = address + 8'd1;
end
wren = 1'b0;//写入使能关闭
#1000;
//再次读取
repeat(256)begin
rden = 1'b1;
#20
address = address + 8'd1;
end
#1000
$stop(2) ;
end
endmodule
2.FIFO
`timescale 1ns/1ps
module tb_fifo_test();
//激励信号
reg clk;
reg rst_n;
reg [07:00] data_in;
reg wrreq;
reg rdreq;
wire rdempty;
wire [07:00] rdusedw;
wire wrfull;
wire [08:00] wrusedw;
wire [15:00] data_out;
//模块例化
fifo_test U_fifo_test(
.clk (clk) ,
.rst_n (rst_n) ,
.data_in (data_in) ,
.wrreq (wrreq) ,
.rdreq (rdreq) ,
.rdempty (rdempty) ,
.rdusedw (rdusedw) ,
.wrfull (wrfull) ,
.wrusedw (wrusedw) ,
.data_out (data_out)
);
//系统初始化
initial begin
clk = 1'b1;
forever begin
#10 clk = ~clk;
end
end
initial begin
rst_n =1'b0 ;
data_in = 8'h0 ;
rdreq = 1'b0 ;
wrreq = 1'b0 ;
#203
rst_n = 1'b1 ;
//写入数据
repeat(512)begin
wrreq = 1'b1;
#20
data_in = data_in + 8'h2;
end
wrreq = 1'b0;//写入请求关闭
//读出数据
rdreq = 1'b1;
#10000
$stop(2) ;
end
endmodule