以下内容摘自:《正点原子逻辑设计指南》
一、单端口RAM
单端口 RAM 指的是只有一个读写口,就是只有一组数据线和地址线,就是读和写都是通过这个口来访问 RAM,但是同一个时刻只能访问一个,要么是读,要么是写。
单端口 RAM 读写要控制的主要信号就是写使能、总使能、写数据、写地址和读数据。
RAM 还有一个重要的特性是 RAM 读延迟,就是 RAM 发起读,然后读数据有效的周期数。这个延迟一般是 1,如果 RAM 输出再因为改善时序寄存一拍,那么 RAM 的读延迟就是 2。如下所示,在读使能为 1且地址有效的情况下(WEA 为 0,ENA 为 1),下一拍 DOUTA 即为读到的数据,一般来说,读使能和读地址不发生变化,DOUTA 不会发生变化。
另外 RAM 读数据我们建议只使用 RAM 读有效时的读数据,没有发起读的时候,读数据一般不建议使用,因此此时的读数据依赖于 RAM 模型的特性,有可能是不确定的值。
RAM 模型主要有一个二维的 RAM 存储,写入数据处理和读出数据处理,读出数据在读使能无效时,输出“X”态,那么为什么输出“X”态呢,输出“X”态是为了避免使用无效的读数据,防止逻辑使用错误。RAM 读无效时的数据我们不建议使用,我们一般只使用 RAM 读有效时的RAM 读数据。
module sp_ram (
input clock , //ram clk
input wen , //ram 写使能
input en , //ram 总使能
input [4:0] address , //ram 读写地址
input [7:0] data , //ram 写数据
output reg [7:0] q //ram 读数据
);
//reg define
reg [7:0] ram [15:0] ; //ram 数据
//*****************************************************
//** main code
//*****************************************************
always @(posedge clock ) begin
if(wen && en)
ram[address] <= data;
end
always @(posedge clock ) begin
if(( wen == 1'b0) && en)
q <= ram[address];
else
q <= 8'hx ;
end
endmodule
二、伪双端口RAM
伪双端口 RAM 指的是有两个读写端口,但是一个端口只能读,一个端口只能写,伪双端口 RAM 一般叫 TP RAM。一般 FIFO 内部例化的都是伪双端口 RAM。
下面我们来看下伪双端口 RAM,伪双端口 RAM 指的是有两个读写口,就是有两组数据线和地址线,一组是写数据线,一组是读数据线,同一个时刻写和读可以同时访问。
伪双端口 RAM 读写要控制的主要的端口都是写使能、读使能、写数据、写地址、读地址和读数据。
TP RAM 还有一个重要的特性是 RAM 读延迟,就是 RAM 发起读,然后读数据有效的周期数。这个延迟一般是 1,如果 RAM 输出再因为改善时序寄存一拍,那么 RAM 的读延迟就是 2。如下所示,在读使能为 1 且地址有效的情况下(ENB 为 1),下一拍 DOUTB 即为读到的数据,一般来说,读使能和读地址不发生变化,DOUTB 不会发生变化。
RAM 模型主要有一个二维的 RAM 存储,写入数据处理和读出数据处理,读出数据在读使能无效时,输出“X”态,那么为什么输出“X”态呢,输出“X”态是为了避免使用无效的读数据,防止逻辑使用错误。RAM 读无效时的数据我们不建议使用,我们一般只使用 RAM 读有效时的 RAM 读数据。
module tp_ram (
input clocka , //ram clk
input clockb , //ram clk
input wren , //ram 写使能
input rden , //ram 读使能
input [4:0] wr_address , //ram 写地址
input [4:0] rd_address , //ram 写地址
input [7:0] data , //ram 写数据
output reg [7:0] q //ram 读数据
);
//reg define
reg [7:0] ram [31:0] ; //ram 数据
//*****************************************************
//** main code
//*****************************************************
always @(posedge clocka ) begin
if(wren)
ram[wr_address] <= data;
end
always @(posedge clockb ) begin
if(rden)
q <= ram[rd_address];
else
q <= 8'hx ;
end
endmodule
三、真双端口RAM
真双端口 RAM 指的是有两个读写端口,每个端口都可以独立发起读或者写。下面我们来看下真双端口 RAM,真双端口 RAM 指的是有两个独立的读写口,就是有两组数据线和地址线,一组是读或者写数据线,另外一组也是读或者写数据线,同一个时刻两个端口可以同时访问,两个端口可以是读和读,也可以是写和读,还可以是写和写。
真双端口 RAM 读写要控制的端口是端口 A 和端口 B 的写使能、读使能、写数据、写地址、读地址和读数据。
module dp_ram (
input clocka , //ram clk
input clockb , //ram clk
input wren_a , //ram 写使能
input rden_a , //ram 读使能
input wren_b , //ram 写使能
input rden_b , //ram 读使能
input [4:0] address_a , //ram 写地址
input [4:0] address_b , //ram 写地址
input [7:0] data_a , //ram 写数据
input [7:0] data_b , //ram 写数据
output reg [7:0] q_a , //ram 读数据
output reg [7:0] q_b //ram 读数据
);
//reg define
reg [7:0] ram [31:0] ; //ram 数据
//*****************************************************
//** main code
//*****************************************************
always @(posedge clocka ) begin
if(wren_a)
ram[address_a] <= data_a;
if(wren_b)
ram[address_b] <= data_b;
end
always @(posedge clocka ) begin
if(rden_a)
q_a <= ram[address_a];
else
q_a <= 8'hx ;
end
always @(posedge clockb ) begin
if(rden_b)
q_b <= ram[address_b];
else
q_b <= 8'hx ;
end
endmodule