为什么要自己写RAM而不用vivado IP?
FIFO在项目中用的很多,自己写一个ram提高了代码的可重用性,不用一个一个手动例化IP核;
再有verilog形式的代码更容易移植。
RAM设计需求(用的最多的):
1、简单双口ram:一端写入、一端读取;
2、自定义地址深度、数据位宽(读写数据位宽一致,常用情况)
3、可选择调用分布式或者块RAM(自主调用FPGA资源)
代码展示:
module simp_dual_ram #(
parameter A_WIDTH = 4 ,//address width
parameter R_DEPTH = 16 ,//ram depth
parameter D_WIDTH = 8 ,//data width
parameter DELAY = 3 ,//read data output delay
parameter TYPE ="distributed" //block,distributed
)(
//port a
clka ,//clock a
ena ,//write enable
w_addr ,//write address
w_data ,//write data
//port b
clkb ,//clock b
enb ,//read enable
r_addr ,//read address
r_data //read data
);
//port a
input clka ;
input ena ;
input [A_WIDTH-1:0] w_addr ;
input [D_WIDTH-1:0] w_data ;
//port b
input clkb ;
input enb ;
input [A_WIDTH-1:0] r_addr ;
output [D_WIDTH-1:0] r_data ;
(*ram_style=TYPE*)reg [D_WIDTH-1:0] ram [0:R_DEPTH-1];
//=================================write=================================//
always@(posedge clka) begin
if(ena) begin
ram[w_addr] <= w_data;
end
end
//=================================read==================================//
reg [D_WIDTH-1:0] buffer [0:DELAY];
always@(posedge clkb) begin
if(enb) begin
buffer[0] <= ram[r_addr];
end
else begin
buffer[0] <= buffer[0];
end
end
integer i;
always@(posedge clkb) begin
for(i=1;i<=DELAY;i=i+1) begin
buffer[i] <= buffer[i-1];
end
end
assign r_data = buffer[DELAY];
endmodule
测试文件:
`timescale 1ns/1ps
module simp_dual_ram_tb;
reg clka ;
reg ena ;
reg [3:0] w_addr ;
reg [7:0] w_data ;
reg clkb ;
reg enb ;
reg [3:0] r_addr ;
wire [7:0] r_data ;
//wire [7:0] r_data_my;
//wire [7:0] r_data_IP;
initial begin
clka <= 0;
clkb <= 0;
end
always #5 clka <= ~clka;
always #5 clkb <= ~clkb;
initial begin
ena <= 0;
w_addr <= 0;
w_data <= 0;
enb <= 0;
r_addr <= 0;
#10;
#5;//write the first data; not read
ena <= 1;
w_addr <= 'd0;
w_data <= 8'd10;
enb <= 0;
r_addr <= 0;
#10;//write the second data; read the first data
ena <= 1;
w_addr <= 'd1;
w_data <= 8'd20;
enb <= 1;
r_addr <= 'd0;
#10;//write the third data;read the second data
ena <= 1;
w_addr <= 'd2;
w_data <= 8'd30;
enb <= 1;
r_addr <= 'd1;
#10;//write the fourth data and read the fourth data at the same time
ena <= 1;
w_addr <= 'd3;
w_data <= 8'd40;
enb <= 1;
r_addr <= 'd3;
#10;//not write data, read the fourth data
ena <= 0;
w_addr <= 'd0;
w_data <= 8'd0;
enb <= 1;
r_addr <= 'd3;
#10;
ena <= 0;
w_addr <= 'd0;
w_data <= 8'd0;
enb <= 0;
r_addr <= 'd0;
#20;
$finish;
end
simp_dual_ram #(
.A_WIDTH(4),//address width
.R_DEPTH(16),//ram depth
.D_WIDTH(8),//data width
.DELAY (1),//read data output delay
.TYPE ("block") //block,distributed
)u_simp_dual_ram(
//port a
.clka (clka ),//clock a
.ena (ena ),//write enable
.w_addr (w_addr),//write address
.w_data (w_data),//write data
//port b
.clkb (clkb ),//clock b
.enb (enb ),//read enable
.r_addr (r_addr),//read address
.r_data (r_data)//read data
);
endmodule
运行结果:
没有回复内容