Distributed Memory Generator IP核简介

描述

Distributed Memory Generator IP 核采用 LUT RAM 资源创建各种不同的存储器结构。IP可用来创建只读存储器 (ROM)、单端口随机存取存储器 (RAM) 和简单双/双端口 RAM 以及基于 SRL16 的 RAM。该IP的灵活的特性配置方式,使用户能针对存储器类型、数据宽度、存储器大小、输入/输出选项和复位选项进行定制。

Distributed Memory Generator IP GUI界面如下:

FPGA

该IP的主要特性为:

  • 生成只读存储器 (ROM)、单、简单双和双端口随机存取存储器 (RAM)以及基于SRL16 的 RAM;
  • 支持 16 到 65536 的数据深度;
  • 支持1 到 1024 之间的数据宽度;
  • 可选的寄存输入和输出;

这个IP的端口如下图所示:

FPGA

输入:

a:地址输入;

Dpra:双端口时的读地址;

d:数据输入;

Clk:时钟

Qdpo_clk:双端口模式下的第二个时钟

We:写使能

i_ce:输入时钟使能;

Qspo_ce:输出时钟使能;

Qdpo_ce:第二个端口的输出时钟使能;

输出:

Spo:非寄存器模式下第一个端口的输出数据

Dpo:非寄存器模式下第二个端口的输出数据

Qspo:寄存器模式下第一个端口的输出数据

Qdpo:寄存器模式下第二个端口的输出数据

复位:

qspo_rst :寄存器模式下第一个端口的异步复位

qdpo_rst :寄存器模式下第二个端口的异步复位

qspo_srst:寄存器模式下第一个端口的同步复位

qdpo_srst :寄存器模式下第二个端口的同步复位

Distributed Memory在不同工作模式下的内部情况如下图所示:

ROM模式:

FPGA

单端口RAM模式:

FPGA

双端口RAM模式:

FPGA

简单双端口模式:

FPGA

一般情况下常用简单双端口模式进行跨时钟域,简单缓存的操作。用简单双端口实现一个简单的跨时钟域代码如下:

// ============================================================
// File Name: tb_dist_mem_gen
// VERSION  : V1.0
// DATA     : 2023/8/18
// Author   : FPGA干货分享
// ============================================================
// 功能:xilinx Distributed Memory Generator ip 代码仿真
//       使用简单双端口实现一个简单的跨时钟域
// delay : 
// ============================================================




`timescale 1ns/100ps
module tb_dist_mem_gen ;


reg             clka   = 'd0 ;
reg             ena    = 'd1 ; 
reg  [0 : 0]    wea    = 'd1 ; 
reg  [5 : 0]    addra  = 'd0 ;
reg  [15 : 0]   dina   = 'd0 ;
reg             clkb   = 'd1 ;
reg             enb    = 'd1 ; 
reg  [5 : 0]    addrb  = 'd0 ;
wire [15 : 0]   doutb        ;




reg [2:0]   S_addr_a_flag   ='d0 ;
reg         S_a_flag        ='d0 ;
reg [2:0]   S_a_flag_2_b    ='d0 ;
reg         S_b_flag        ='d0 ;


reg [2:0]   S_clk_cnt8      ='d3   ;


always #1 clka = ~clka;
always #1 clkb = ~clkb;




//----------- clk_a  ---// 
always @(posedge clka)
    if(ena && wea)
        begin
            addra <= addra + 'd1;
            dina  <= dina + 'd1;
        end


always @(posedge clka)
    S_addr_a_flag[0] <= (addra == 6'd10);

always @(posedge clka)
    S_addr_a_flag[2:1] <= S_addr_a_flag[1:0] ; 


always @(posedge clka)
    S_a_flag <= |S_addr_a_flag ;


//----------- clk_b  ---// 
always @(posedge clkb)
    S_a_flag_2_b <= {S_a_flag_2_b[1:0],S_a_flag} ;


always @(posedge clkb)
    S_b_flag <= (!S_a_flag_2_b[2])&& S_a_flag_2_b[1] ;

always @(posedge clkb)
    if((S_clk_cnt8 > 3'd2)&&S_b_flag)
        S_clk_cnt8 <= 3'd2;
    else 
        S_clk_cnt8 <= S_clk_cnt8 + 'd1;




always @(posedge clkb)
    if(S_clk_cnt8 == 3'd1)
        addrb <= 'd0;
    else 
        addrb <= addrb + 'd1;




dist_mem_gen_0 dist_mem_gen_0 (
  .a        (addra      ), // input wire [5 : 0] a
  .d        (dina       ), // input wire [15 : 0] d
  .dpra     (addrb      ), // input wire [5 : 0] dpra
  .clk      (clka       ), // input wire clk
  .we       (wea        ), // input wire we
  .qdpo_clk (clkb       ), // input wire qdpo_clk
  .qdpo     (doutb      )  // output wire [15 : 0] dpo
);


endmodule
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分