Vivado 简单双端RAM verilog实现-Xilinx-AMD社区-FPGA CPLD-ChipDebug

Vivado 简单双端RAM verilog实现

 

为什么要自己写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

 

运行结果:

图片[1]-Vivado 简单双端RAM verilog实现-Xilinx-AMD社区-FPGA CPLD-ChipDebug

 

请登录后发表评论

    没有回复内容