OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4149|回复: 0

[ALTERA] 《新起点之FPGA开发指南 V2.1》第十九章 IP核之双端口RAM实验

[复制链接]

1118

主题

1129

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4671
金钱
4671
注册时间
2019-5-8
在线时间
1224 小时
发表于 2021-10-12 17:05:27 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2021-10-30 10:09 编辑

1)实验平台:正点原子新起点V2FPGA开发板
2)  章节摘自【正点原子】《新起点之FPGA开发指南 V2.1》
3)购买链接:https://detail.tmall.com/item.htm?id=609758951113
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_xinqidian(V2).html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)正点原子FPGA技术交流QQ群:712557122 QQ群.png

原子哥.jpg

微信公众号.png





第十九章 IP核之双端口RAM实验


在“IP核之单端口RAM实验”中,我们成功实现了对单端口RAM IP核的读写操作,本章我们将通过Quartus II软件生成一个双端口的RAM IP核,并对其进行读写操作。
本章包括以下几个部分:
1919.1简介
19.2实验任务
19.3硬件设计
19.4程序设计
19.5下载验证

19.1简介
我们知道,RAM IP核分为单端口RAM和双端口RAM,即表示RAM IP核有几个读写端口。对于单端口RAM来说,由于读写共用一对地址线,所以没有办法同时读写不同地址的数据;而对于双端口RAM来说,由于读写地址线是分开的,所以可以同时读写不同地址的数据。
双端口RAM又分为简单双端口RAM和真双端口RAM,顾名思义,简单双端口RAM虽然有两个端口,但是一个端口只能用来写,另一个端口只能用来读,所以简单双端口RAM也称为伪双端口RAM。而真双端口RAM是指两个端口都可以用来写或者读,可以理解成具有两个独立的单端口的RAM,一般用于需要多路写入和读出的情况,而不用例化两个单端口的RAM,在使用上更为方便。
在实际开发应用中,对于单端口RAM、伪双端口RAM和真双端口RAM的选择,需要根据项目需求来选择合适的RAM。对于不需要同时读写RAM的情况,可以选择单端口RAM;对于需要同时读写RAM,但是只需要一路数据写入,一路数据读出的情况,可以选择简单双端口RAM;而对于需要同时读写RAM,有又两个写入或者读出的情况,可以选择真双端口RAM。双端口RAM一般对于异步数据的缓存使用较多,因此本章使用的是简单双端口RAM IP。
下图为简单双单端口RAM的端口框图。
第十九章 IP核之双端口RAM实验695.png
图 19.1.1 简单双端口RAM端口框图
单端口RAM的端口描述如下:
data:RAM写数据端口;
wraddress:RAM写地址端口;
wren:写使能信号,高电平有效;
byteena:字节使能控制,该功能屏蔽了输入数据,这样仅写入数据中指定字节,未被写入的字节保留之前写入的值。当写入数据的位宽为16位、18位、32位和36位时,M9K模块将支持字节使能,wren信号以及字节byteena信号一起控制RAM模块的写操作。byteena信号在RAM IP核创建过程中是可选的,可选择是否使用字节使能控制功能。
wr_addressstall:写地址时钟使能控制,当wr_addressstall信号为高电平时,有效地址时钟使能就会保持之前的地址。wr_addressstall信号在RAM IP核创建过程中是可选的,可选择是否使用地址使能控制功能。
wrclock:写时钟;
wrclocken:写时钟使能信号,高电平有效;
aclr:异步复位信号,高电平有效;
rdaddress:RAM读地址端口;
rden:读使能信号,高电平有效;
q:从RAM中读出的数据;
rd_addressstall:读地址时钟使能控制,当rd_addressstall信号为高电平时,有效地址时钟使能就会保持之前的地址。rd_addressstall信号在RAM IP核创建过程中是可选的,可选择是否使用地址使能控制功能。
rdclock:读时钟;
rdclocken:读时钟使能信号,高电平有效;
19.2实验任务
本节实验任务是使用Altera RAM IP核生成一个简单双端口的RAM,然后对RAM进行读写操作,并通过Modelsim软件进行仿真及SignalTap软件进行在线调试。
19.3硬件设计
本章实验只用到了输入的时钟信号和按键复位信号,没有用到其它硬件外设。
本实验中,各端口信号的管脚分配如下表所示。
表 19.3.1 IP核之RAM实验管脚分配
信号名        方向        管脚        端口说明
sys_clk        input        M2        系统时钟,50Mhz
sys_rst_n        input        M1        系统复位,低有效
因为引脚数极少这里就不再给出TCL管脚约束语句了。
19.4程序设计
根据实验任务要求和模块化设计的思想,我们需要如下5个模块:简单双端口RAM模块、写RAM模块、读RAM模块、PLL IP核模块以及顶层模块,顶层模块例化其余模块实现前四个模块的数据交互。由于双端口RAM多用于跨时钟域信号的处理,所以本实验我们使用两个不同的时钟分别作为RAM的写时钟和读时钟,这两个时钟由PLL IP核生成,输出的时钟分别是50Mhz和25Mhz。系统的功能框图如下所示:
第十九章 IP核之双端口RAM实验1908.png
图 19.4.1 IP核之双端口RAM IP核系统框图
由上图可知,PLL IP核输出两个时钟,分别作为写RAM模块和读RAM模块的时钟;写RAM模块负责向RAM中写入数据,而读RAM模块负责从RAM中读出数据。和“IP核之单端口RAM实验”不同的是,本次试验只在上电后写入一次,然后不断地从RAM中读出数据。
首先创建一个名为ip_2port_ram的工程,在这里我们就不再给出Quartus II软件创建工程的详细过程,如果大家对Quartus II软件的创建过程还不熟悉的话,可以参考“第四章 Quartus II软件的安装和使用”章节中的Quartus II软件的使用部分。新建后的工程如下图所示:
第十九章 IP核之双端口RAM实验2257.png
图 19.4.2工程新建完成页面
创建好了工程以后,接下来我们创建RAM IP核。我们在Quartus II软件的菜单栏中找到【Tools】→【MegaWizard Plug-In Manager】按钮并点击打开,Tool工具栏打开页面及打开后弹出的页面如图 18.4.2和图 18.4.3所示。
第十九章 IP核之双端口RAM实验2533.png
图 19.4.3 工具栏打开IP核页面
第十九章 IP核之双端口RAM实验2598.png
图 19.4.4 创建IP核向导页面
在该页面中,可以看到有三个选项,第一个是创建一个新的IP核,第二个是编辑一个已经创建好的IP核,第三个是复制一个已经创建好的IP核。因为我们这里是首次创建IP核,因此直接选择默认的第一个选项,然后点击【Next>】,进入下图所示页面。
第十九章 IP核之双端口RAM实验2780.png
图 19.4.5 选择RAM:2-PORT IP核页面
在该页面中,我们在Memory Compiler下找到RAM:2-PORT,单击选中它,然后我们需要为RAM IP核选择保存的路径及名称。首先大家在工程所在路径par文件夹下创建一个文件夹ipcore,由于本次实验会用到多个IP核,为了方便管理IP核,我们在ipcore文件夹下创建一个ram_2port文件夹,用于存放RAM IP核(如果之前没有创建ipcore和ram_2port文件夹的话)。
然后在“What name do you want for the output file”一栏中输入IP存放的路径及名称,这里我们命名为ram_2port并且选择创建的IP核代码为Verilog HDL。完成这些设置以后,我们点击【Next>】,进入下图所示页面。
第十九章 IP核之双端口RAM实验3187.png
图 19.4.6 RAM IP核参数配置页面
“How will you be using the dual port RAM?”:用于指定双端口RAM的类型,第一个选项选择简单双端口RAM,第二个选项选择真双端口RAM,此处选择第一个(With one read prot and one write port)。
“How do you want to specify the memory size?”:用于指定存储器大小,第一个选项以“word”为单位,第二个选项以“bit”为单位,此处选择第一个(As a number of words);
然后我们直接点击【Next>】,进入下图所示页面。
第十九章 IP核之双端口RAM实验3535.png
图 19.4.7 RAM存储深度、位宽配置页面
“How many 8-bit words of memory?”:用于设置RAM的存储深度,此处设置为32。
“How wide should the ‘data_a’ input bus be?”:用于RAM的数据位宽,此处设置为8;
其余设置保持默认即可,配置完成后,我们就可以点击【Next】,进入下图所示页面。
第十九章 IP核之双端口RAM实验3765.png
图 19.4.8 RAM时钟、读使能配置页面
“What clocking method do you want to use?”:用于设置双端口RAM的时钟,此处选择第二个(Dual clock:use separate ‘read’ and ‘write’ clocks),即写端口和读端口选择独立的时钟。
“Create a ‘rden’ read enable signal”:选择是否勾选读使能信号,如果不勾选则一直在读,此处勾中这个选项。
配置完成后,我们就可以点击【Next】,进入下图所示页面。
第十九章 IP核之双端口RAM实验4066.png
图 19.4.9 RAM 输出寄存器配置
Read output port(s) ‘q’:选择是否寄存输出信号q,如果选中的话,从RAM中读到的q会多延时一个时钟周期输出,此处不勾选。
其余设置保持默认即可,配置完成后,我们就可以点击【Next】,进入下图所示页面。
第十九章 IP核之双端口RAM实验4245.png
图 19.4.10 RAM初始化配置
从该页面中,我们可以看出,该页面就是对RAM初始化页面。需要注意的是,后面我们还会学习ROM IP核的创建过程,这里和ROM IP核不同的是,ROM IP核不能设置为 No,只能设置为Yes,而我们的 RAM IP 核,我们可以设置为空,也可以进行初始化。在这里我们保持默认设置即可,直接点击【Next】,进入下图所示页面。
第十九章 IP核之双端口RAM实验4472.png
图 19.4.11 EDA的配置页面
从该页面中,我们可以看出,如果我们想要仿真RAM IP核,那么我们需要添加altera_mf仿真库。如果我们想要将此RAM IP核用在其他的EDA工具上,我们可以通过选择Generate netlist这个选项来生成IP_syn.v文件,用于其他的EDA工具中。这里需要注意的是,并不是所有的第三方 EDA工具都支持。在这里直接点击【Next】,进入下图所示页面。
第十九章 IP核之双端口RAM实验4719.png
图 19.4.12 Summary 的配置页面
此处勾选ram_2port_inst.v和ram_2port_bb.v,方便对IP核的例化,然后我们点击【Finish】完成整个IP核的创建。接下来Quartus II软件会在ipcore文件夹下创建RAM IP核生成的文件,然后询问我们是否添加至工程,点击“YES”按钮将生成的IP核添加至工程,如下图所示页面。
第十九章 IP核之双端口RAM实验4946.png
图 19.4.13 IP核添加至工程确认界面
接下来返回到工程界面,在File界面里,我们可以看到生成的ram_2port.qip和ram_2port.v已经添加到工程中。qip是Quartus IP的缩写,我们打开qip的文件可以看到如下图所示的脚本代码。
第十九章 IP核之双端口RAM实验5121.png
图 19.4.14 ram_2port.qip文件内容
上图中红色框标注的意思是把ram_2port.v文件添加到工程,如果大家在添加IP核后工程里面只有ram_2port.qip文件,而没有ram_2port.v的话也没有关系,工程中只添加ram_2port.qip文件也是可以的。
添加完RAM IP核后,可以在IP核所在的路径下打开ram_2port.v代码,如下图所示。
第十九章 IP核之双端口RAM实验5356.png
图 19.4.15 RAM IP核添加至工程界面
上图中我们可以看到,ram_2port模块的端口分别为:data(ram写数据)、rdaddress(ram读地址)、rdclock(ram读时钟)、rden(ram读使能信号)、wraddress(ram写地址)、wrclock(ram写时钟)、wren(ram写使能信号)和q(ram读出的数据)。当我们需要写入数据时,把wren信号拉高的同时,给出写地址(wraddress)和写数据(data),数据就会按照指定的地址写入对应的存储单元;当我们需要读数据时,把rden信号拉高,给出读地址(rdaddress),q(ram读出的数据)就会根据指定的地址输出对应存储单元的数据。
至此,RAM IP核的创建已经全部完成,如果需要修改IP核的话,点击在Quartus II软件的菜单栏中找到【Tools】→【MegaWizard Plug-In Manager】按钮并点击打开,下图为打开后的页面。
第十九章 IP核之双端口RAM实验5828.png
图 19.4.16 修改IP核页面
和我们第一次创建IP核不同的是,这一次我们选择第二个选项,修改已经存在的IP核,然后点击【Next>】,进入选择IP核路径页面,双击ipcore文件夹,进入下图所示页面。然后双击ram_2port.v文件或者选中ram_2port.v文件,点击【Next>】开始重新配置RAM IP核。
第十九章 IP核之双端口RAM实验6035.png
图 19.4.17 选择需要修改的IP核路径页面
除此之外,我们再创建一个PLL IP核(命名为pll_clk),共输出两路时钟,时钟频率分别是50Mhz和25Mhz,存放路径为par/ipcore/pll_clk,如下图所示,创建过程此处不再赘述。
接下来我们设计一个verilog文件对ram进行写入数据,文件名为ram_wr.v,编写的verilog代码如下。
  1. 1  module ram_wr(
  2. 2      input            clk,           //时钟信号
  3. 3      input            rst_n,         //复位信号,低电平有效
  4. 4                                      
  5. 5      //RAM写端口操作                 
  6. 6      output           ram_wr_en,     //ram写使能
  7. 7      output reg [4:0] ram_wr_addr,   //ram写地址        
  8. 8      output reg [7:0] ram_wr_data    //ram写数据
  9. 9  );
  10. 10
  11. 11 //reg define
  12. 12 reg  [5:0]  wr_cnt;                 //写计数器
  13. 13
  14. 14 //*****************************************************
  15. 15 //**                    main code
  16. 16 //*****************************************************
  17. 17
  18. 18 //wr_cnt计数范围在0~31,ram_wr_en为高电平
  19. 19 assign ram_wr_en = ((wr_cnt>=6'd0) && (wr_cnt<=6'd31) && rst_n) ? 1'b1 : 1'b0;
  20. 20
  21. 21 //写计数器,计数器范围0~63
  22. 22 always @(posedge clk or negedge rst_n) begin
  23. 23     if(!rst_n)
  24. 24         wr_cnt <= 6'd0;
  25. 25     else if(wr_cnt == 6'd63)
  26. 26         wr_cnt <= wr_cnt;
  27. 27     else   
  28. 28         wr_cnt <= wr_cnt + 1'b1;
  29. 29 end
  30. 30
  31. 31 //写计数器范围:0~31,产生ram写数据信号
  32. 32 always @(posedge clk or negedge rst_n) begin
  33. 33     if(!rst_n)
  34. 34         ram_wr_data <= 8'd0;
  35. 35     else if(wr_cnt >= 6'd0 && wr_cnt <= 6'd31)  
  36. 36         ram_wr_data <= ram_wr_data + 1'b1;
  37. 37     else
  38. 38         ram_wr_data <= 8'd0;
  39. 39 end        
  40. 40
  41. 41 //写地址信号 范围:0~31        
  42. 42 always @(posedge clk or negedge rst_n) begin
  43. 43     if(!rst_n)        
  44. 44         ram_wr_addr <= 5'd0;
  45. 45     else if(wr_cnt >= 6'd0 && wr_cnt <= 6'd31)
  46. 46         ram_wr_addr <= ram_wr_addr + 1'b1;
  47. 47     else
  48. 48         ram_wr_addr <= 5'd0;
  49. 49 end        
  50. 50
  51. 51 endmodule
复制代码


模块中定义了一个写计数器(wr_cnt),从0累加至63,此后一直保持在数值63。当计数范围在0~31之间时,向ram中写入数据,而其它计数值时停止写入。实现的功能是向RAM的地址0写入数据0,地址1写入数据1,一直到地址31写入数据31,只在上电后写入一次。
接下来我们设计一个verilog文件来从RAM中读出数据,文件名为ram_rd.v,编写的verilog代码如下。
  1. 1  module ram_rd(
  2. 2      input            clk,           //时钟信号
  3. 3      input            rst_n,         //复位信号,低电平有效
  4. 4                                      
  5. 5      //RAM读端口操作                 //ram读使能
  6. 6      output           ram_rd_en,     //ram读地址
  7. 7      output reg [4:0] ram_rd_addr,   //ram读数据        
  8. 8      input      [7:0] ram_rd_data
  9. 9  );
  10. 10
  11. 11 reg  [5:0]  rd_cnt;                 //读控制计数器
  12. 12
  13. 13 //*****************************************************
  14. 14 //**                    main code
  15. 15 //*****************************************************
  16. 16
  17. 17 //rd_cnt计数范围在0~31,ram_rd_en为高电平
  18. 18 assign ram_rd_en = ((rd_cnt>=6'd0) && (rd_cnt<=6'd31) && rst_n) ? 1'b1 : 1'b0;
  19. 19
  20. 20 //读控制计数器,计数器范围0~63
  21. 21 always @(posedge clk or negedge rst_n) begin
  22. 22     if(!rst_n)
  23. 23         rd_cnt <= 6'd0;
  24. 24     else if(rd_cnt == 6'd63)
  25. 25         rd_cnt <= 6'd0;
  26. 26     else   
  27. 27         rd_cnt <= rd_cnt + 1'b1;
  28. 28 end      
  29. 29
  30. 30 //写地址信号 范围:0~31        
  31. 31 always @(posedge clk or negedge rst_n) begin
  32. 32     if(!rst_n)        
  33. 33         ram_rd_addr <= 5'd0;
  34. 34     else if(rd_cnt >= 6'd0 && rd_cnt <= 6'd31)
  35. 35         ram_rd_addr <= ram_rd_addr + 1'b1;
  36. 36     else
  37. 37         ram_rd_addr <= 5'd0;
  38. 38 end        
  39. 39
  40. 40 endmodule
复制代码


模块中定义了一个读计数器(rd_cnt),循环的从0累加至63。当计数范围在0~31之间时,从ram中读出数据,而其它计数值时停止读数据。
接下来我们设计一个verilog文件来例化创建的PLL IP核、RAM IP核、RAM写模块和RAM读模块,文件名为ip_2port_ram.v,编写的verilog代码如下。
  1. 1  module ip_2port_ram(
  2. 2      input               sys_clk        ,  //系统时钟
  3. 3      input               sys_rst_n         //系统复位,低电平有效
  4. 4      );
  5. 5  
  6. 6  //wire define
  7. 7  wire             clk_50m ;
  8. 8  wire             clk_25m ;
  9. 9  wire             locked  ;
  10. 10 wire             rst_n   ;
  11. 11   
  12. 12 wire             ram_wr_en  ; //ram写使能
  13. 13 wire    [4:0]    ram_wr_addr; //ram写地址
  14. 14 wire    [7:0]    ram_wr_data; //ram写数据
  15. 15 wire             ram_rd_en  ; //ram读使能
  16. 16 wire    [4:0]    ram_rd_addr; //ram读地址
  17. 17 wire    [7:0]    ram_rd_data; //ram读数据
  18. 18   
  19. 19 //*****************************************************
  20. 20 //**                    main code
  21. 21 //*****************************************************
  22. 22
  23. 23 assign rst_n = sys_rst_n & locked;
  24. 24
  25. 25 //锁相环模块
  26. 26 pll_clk u_pll_clk(
  27. 27     .areset   (~sys_rst_n),
  28. 28     .inclk0   (sys_clk),
  29. 29     .c0       (clk_50m),
  30. 30     .c1       (clk_25m),
  31. 31     .locked   (locked)
  32. 32     );
  33. 33
  34. 34 //RAM写模块
  35. 35 ram_wr u_ram_wr(
  36. 36     .clk           (clk_50m),
  37. 37     .rst_n         (rst_n),
  38. 38      
  39. 39     .ram_wr_en     (ram_wr_en  ),
  40. 40     .ram_wr_addr   (ram_wr_addr),
  41. 41     .ram_wr_data   (ram_wr_data)
  42. 42     );
  43. 43
  44. 44 //简单双端口RAM   
  45. 45 ram_2port   ram_2port_inst (
  46. 46     .data         (ram_wr_data),
  47. 47     .rdaddress    (ram_rd_addr ),
  48. 48     .rdclock      (clk_25m ),
  49. 49     .rden         (ram_rd_en ),
  50. 50     .wraddress    (ram_wr_addr),
  51. 51     .wrclock      (clk_50m ),
  52. 52     .wren         (ram_wr_en ),  
  53. 53     .q            (ram_rd_data )
  54. 54     );
  55. 55
  56. 56 //RAM读模块   
  57. 57 ram_rd u_ram_rd(
  58. 58     .clk           (clk_25m),
  59. 59     .rst_n         (rst_n),
  60. 60                  
  61. 61     .ram_rd_en     (ram_rd_en  ),
  62. 62     .ram_rd_addr   (ram_rd_addr),
  63. 63     .ram_rd_data   (ram_rd_data)
  64. 64     );   
  65. 65
  66. 66 endmodule
复制代码


我们将PLL IP核输出的50Mhz作为写时钟,25Mhz作为读时钟,将RAM IP核写操作相关端口连接至RAM写模块,RAM IP核读操作相关端口连接至读模块。
ip_2port_ram模块添加至工程后,如果工程名字和ip_2port_ram模块名字不一致的话,必须先将ip_2port_ram模块设置为顶层模块,设置方法是右键选择ip_2port_ram.v文件,点击Set as Top-Level Entity。
第十九章 IP核之双端口RAM实验11361.png
图 19.4.18 ip_2port_ram设置为顶层文件
接下来点击分析和综合图标编译工程。
第十九章 IP核之双端口RAM实验11454.png
图 19.4.19 开始编译工程界面
工程编译成功后,打开Pin Planner配置FPGA的管脚,管脚按照本章硬件设计中的列表来分配,分配完成后重新编译工程。
接下来我们对RAM IP核进行仿真,来验证对RAM的读写操作是否正确。首先在Modelsim软件中创建一个名为tb_ip_2port_ram的工程,在这里我们就不再给出软件创建工程的详细过程,如果大家对Modelsim软件的创建过程还不熟悉的话,可以参考“第五章 Modelsim软件的安装和使用”章节中的Modelsim的使用部分。
tb_ip_2port_ram仿真文件源代码如下:
  1. 1  `timescale  1ns/1ns   //仿真的单位/仿真的精度
  2. 2  
  3. 3  module ip_2port_ram_tb();
  4. 4  
  5. 5  parameter T = 20;
  6. 6  
  7. 7  reg          sys_clk;
  8. 8  reg          sys_rst_n;   
  9. 9  
  10. 10 initial begin
  11. 11     sys_clk = 1'b0;
  12. 12     sys_rst_n = 1'b0;
  13. 13     #(T+1)
  14. 14     sys_rst_n = 1'b1;
  15. 15 end
  16. 16
  17. 17 always #(T/2) sys_clk = ~sys_clk;
  18. 18
  19. 19 ip_2port_ram u_ip_2port_ram(
  20. 20     .sys_clk            (sys_clk  ),
  21. 21     .sys_rst_n          (sys_rst_n)
  22. 22     );
  23. 23     
  24. 24 endmodule
复制代码


需要注意的是,对IP核的仿真需要在Modeslim工程中添加altera_mf文件仿真库,仿真库的路径在Quartus II软件的安装路径下,路径为:D:\altera\13.1\quartus\eda\sim_lib\altera_mf.v(如果大家把Quartus安装在其它磁盘,可在对应的安装路径下找到仿真库文件)。建议大家把alerta_mf文件拷贝到工程的sim\tb文件夹下,方便添加至工程。工程创建完成后,把ip_2port_ram_tb.v文件、ip_2port_ram.v文件、ram_wr.v文件、ram_rd.v文件、ram_2port.v文件和altera_mf文件添加至工程,然后编译各个文件(注意altera_mf文件编译时间较长),编译后的工程界面如下图所示:
第十九章 IP核之双端口RAM实验12580.png
图 19.4.20 Modelsim工程界面
接下来就可以开始仿真了,仿真过程这里不再赘述,下图为Modelsim仿真的波形图。
第十九章 IP核之双端口RAM实验12690.png
图 19.4.21 Modelsim写数据仿真波形
由上图可以看到,ram_wr_en信号拉高,说明此时是对ram进行写操作。ram_wr_en信号拉高之后,地址和数据都是从0开始累加,也就说当ram地址为0时,写入的数据也是0;当ram地址为1时,写入的数据也是1,我们总共向ram中写入32个数据。
下图为读ram数据时Modelsim仿真的波形图。
第十九章 IP核之双端口RAM实验12914.png
图 19.4.22 Modelsim读数据仿真波形
由上图可以看到,ram_rd_en信号拉高,说明此时是对ram进行读操作。ram_rd_en(读使能)信号拉高之后,ram_addr从0开始增加,也就是说从ram的地址0开始读数据;ram中读出的数据ram_rd_data在延时一个时钟周期之后,开始输出数据,输出的数据为0,1,2……,和我们写入的值是相等的,也就是说,我们创建的RAM IP核从仿真结果上来看是正确的。
接下来再看一张整体的仿真运行图。
第十九章 IP核之双端口RAM实验13189.png
图 19.4.23 整体仿真运行图
由上图可知,我们只在开始时写入一次,随后不再写入,而是每隔一段时间读取一次。
19.5下载验证
首先将下载器一端连接电脑,另一端与开发板上的JTAG下载口相连,最后连接电源线并打开电源开关。
接下来我们使用SignalTap II软件对RAM IP核进行调试,首先我们在Quartus II软件中创建一个SignalTap II调试文件,我们将ram_wr_addr、ram_wr_data和ram_wr_en这三个信号添加至SignalTap II调试文件中,下图为SignalTap软件采集到的波形图。
第十九章 IP核之双端口RAM实验13503.png
图 19.5.1写ram数据SignalTap波形图
ram_wr_en信号拉高之后,地址和数据都是从0开始累加,也就说当ram地址为0时,写入的数据也是0;当ram地址为1时,写入的数据也是1。我们可以发现,上图中的数据变化和Modelsim仿真软件仿真的波形是一致的。需要注意的是,由于写操作在上电后只运行一次,需要设置ram_wr_en的上升沿为触发条件,并按下电源复位按键即可捕获到波形。
下图为读ram数据时SignalTap采集的波形图。
第十九章 IP核之双端口RAM实验13774.png
图 19.5.2 读ram数据SignalTap波形图
ram_rd_en(读使能)信号拉高之后,ram_addr从0开始增加,也就是说从ram的地址0开始读数据;ram中读出的数据ram_rd_data在延时一个时钟周期之后,开始输出数据,输出的数据为0,1,2……,和我们写入的值是相等的。我们可以发现,上图中的数据变化同样和Modelsim仿真软件仿真的波形是一致的。本次实验的IP核之RAM读写实验验证成功。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 19:54

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表