张裕 发表于 2024-8-9 14:51:50

FPGA开发——IP核的RAM调用(单端口)

一、简介

RAM(Random Access Memory),即随机存取存储器。可以随时吧数据写入任一订定的地址的 存储单元,可以随时从任一指定地址独处数据。时钟频率决定读写速率。 RAM 重要用来存放程序以及程序执行过程中产生的中间数据和运算效果。
1、RAM分类

           Altera FPGA 的 RAM IP 核分为两种类型:单端口 RAM 和双端口 RAM。
        单端口 RAM:只有一组地址线控制着写数据端口和读数据端口。
        双端口 RAM:具有两组地址线分别控制着写数据端口和读数据端口。
今天这篇文章我们来讲一下单端口RAM的相关使用。
2、 单端口的端口 

https://i-blog.csdnimg.cn/direct/c94f833a76844cbf921fa659578dd83d.png
二、单端口RAM的调用

1、单端口RAM选择

        如图所示,在 IP Catalog 的搜刮栏中搜刮 RAM,然后选择 RAM:1-PORT。(这里和前面调用的pll一样也是需要先辈行工程创建,不清楚的小伙伴可以在前面的文章看看)
https://i-blog.csdnimg.cn/direct/98c66416f0db46c8bfd8696a5382902b.png
2、RAM存放位置的选择,这里和pll操作完全同等。

https://i-blog.csdnimg.cn/direct/b51d6ba4c4fa473da929d2da33b91dd6.png
3、参数设置 

如下图所示,该界面设置的参数有:
方框①:IP 核的输出数据位宽 方框
②:IP 核的存储容量 方框
③:储存单元类型,默认即可 方框
④:选择时钟模式,单时钟或双时钟。单时钟用一个时钟信号控制存储,这里选择单时 钟。然后点击 Next 进入下一界面。
https://i-blog.csdnimg.cn/direct/42cca614e47c470688556f37501ef1c4.png
4、输出端口寄存和时钟使能信号的选择 

如图所示: 方框①:选择输出端口 q 是否寄存。
方框②:时钟使能信号,通常默认不勾选即可。
方框③:选择是否创建已补复位信号“aclr”和读使能信号“rden”。 点击“Next”进入下一界面。
https://i-blog.csdnimg.cn/direct/bf427445ac4c4a62b72e019f01a10bb0.png
 5、同读同写时读数据的选择

        如下图所示,该页面是设置某个地址写入数据同时读取数据的情况,是不关心,还是读出新 数据,或是读出旧数据。通常保持默认“New data”即可。
https://i-blog.csdnimg.cn/direct/e3571ce77eaf49f99c1f016367b5057d.png
6、RAM存储器初始化参数设置

如图所示,本页面重要是设置 RAM 存储器初始化参数。:
方框①:是否设置初始化文件,根据需要选择,这里默认不初始即可。
方框②:选择是否允许系统存储器内容编辑器收罗和更新内容在与系统时钟无关的情况下, 默认不勾选即可。 
https://i-blog.csdnimg.cn/direct/4edd4c045e834ee58687f3a83aa71f76.png
7、仿真库文件的选择

如下图所示,表现的是仿真库文件 altera_mf。无需其它操作,点击“Next”进入下一界面。
https://i-blog.csdnimg.cn/direct/a5118cea498c43ca8ddacddfcb5ec1d1.png
 
8、天生文件的选择

如下图所示,该页面为需要设置天生的文件。勾选 ram_1port_inst.v 即可。ram_1port_bb.v 可勾可不勾选。然后点击 finish。
https://i-blog.csdnimg.cn/direct/fd0cb19aaf6a4979ba3f87f045333978.png
 9、将文件添加到工程中

如下图所示,设置完成,点击“Yes”即可。
https://i-blog.csdnimg.cn/direct/72a89917dfeb4def85431d7e8ea5fbf9.png
 三、RAM的相关调用和仿真

1、设计文件的编写

在rtl文件夹中新建ip_ram.v文件,其中ram实例化代码可以从 ram_1port_inst.v 例化模板文件复制。如图:
module ip_ram(
    input                                clk                ,
    input                                rst_n        ,
    input                                rden    ,
    input               wden        ,
    input                   address        ,
    input                        din         ,
    output                        dout       
);                                                               
   
   
ram_1        ram_1_inst (
        .aclr ( ~rst_n ),
        .address ( address ),
        .clock ( clk ),
        .data ( din ),
        .rden ( rden ),
        .wren ( wden ),
        .q ( dout )
        );
   
endmodule 2、测试文件的编写

在tb文件夹中新建tb_ram。v文件。如图:
`timescale 1ns/1ns
   
module tb_ram();

//激励信号定义
    reg                                clk                  ;
    reg                                rst_n          ;
    reg                                rden             ;
    reg                                wden                  ;
    reg                                address          ;
    reg                                din                   ;

//输出信号定义       
wire                        dout    ;

//时钟周期参数定义       
    parameter                CLOCK_CYCLE = 20;   

//模块例化
    ip_ram   ip_ram_inst(
    /*input                                */.clk                (clk        ),
    /*input                                */.rst_n        (rst_n),
    /*input                                */.rden   (rden   ),
    /*input             */.wden          (wden          ),
    /*input                   */.address        (address),
    /*input                        */.din           (din           ),
    /*output                */.dout          (dout          )
);                       

//产生时钟
    initial                 clk = 1'b0;
    always #(CLOCK_CYCLE/2) clk = ~clk;

//产生激励
    integer i;
    initialbegin
   
      rst_n = 1'b0;
      wden = 1'b0;
      rden = 1'b0;
      din = 9'h00;
      #(CLOCK_CYCLE*20);
      rst_n = 1'b1;

      #10;
      //写入600个数据
      for (i = 0;i<600;i=i+1) begin
            wden = 1'b1;
            address = i;
            din = 8'($random);
            @(posedge clk);
            wden=1'b0;
            rden = 1'b1;
            address = i;
            @(posedge clk);
            rden =1'b0;
      end
      //复位,验证ram写入的数据是否清空
      #CLOCK_CYCLE;
      rst_n = 1'b0;
      #(CLOCK_CYCLE*20);
      rst_n = 1'b1;
      #10;

      //重新从地址0写入20个数据
      for (i = 0;i<20;i=i+1) begin
            wden = 1'b1;
            address = i;
            din = 8'($random);
            @(posedge clk);
            wden=1'b0;
      end

      #(CLOCK_CYCLE*20);
      #5;
      i=0;
      //从地址0开始,读20个数据
      repeat(20)begin
            rden = 1'b1;
            address = i;
            i = i + 1;
            @(posedge clk);
      end
      rden = 0;

      #(CLOCK_CYCLE*100);
      $stop;
    end   

endmodule 3、波形仿真

https://i-blog.csdnimg.cn/direct/f083496c79ea49e398c7f7e9e839a149.png
通过对比波形图中的写入和读出数据等的相关比较。我们可以看到RAM可以或许成功的举行调用,到这里单端口的RAM调用结束。 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: FPGA开发——IP核的RAM调用(单端口)