搜索
bottom↓
回复: 0

《ATK-DFPGL22G之FPGA开发指南_V1.0》第十八章 IP核之单端口RAM实验

[复制链接]

出0入234汤圆

发表于 2023-1-29 14:49:45 | 显示全部楼层 |阅读模式
1)实验平台:正点原子紫光PGL22G开发板
2)购买链接:https://item.taobao.com/item.htm?&id=692368045899
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-340253-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子FPGA交流群:435699340 lQLPJxaFi2zaB4UWWrDAMgIsFEW2pwLb3abnwDMA_90_22.png
lQDPJxaFi2nfFizMjM0CbLCPlxn_FVheIQLb3aGrwFQA_620_140.jpg

lQLPJxaFi2nfFhLMkM0BXrDNvOUyeU_FPgLb3aGvQNIA_350_144.png


第十八章 IP核之单端口RAM实验

RAM的英文全称是Random Access Memory,即随机存取存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。本章我们将对PDS软件生成的单口RAM IP核进行读写测试,并向大家介绍Pango 单口RAM IP核的使用方法。
本章包括以下几个部分:
18.1RAM IP核简介
18.2实验任务
18.3硬件设计
18.4程序设计
18.5下载验证


18.1RAM IP核简介

Memory IP分为“Distributed RAM”与“DRM”。
DRM   
DRM(Dedicated RAM Module)既专用RAM模块,DRM Based RAM/FIFO IP是基于DRM设计的IP,通过对DRM的级联调用实现RAM/ROM/FIFO等IP设计。这里主要说明如何用深圳市紫光同创电子有限公司的Pango Design Suite套件(后文简称PDS)中IP Compiler工具(后文简称IPC)生成并配置此类IP。DRM Based RAM/FIFO IP的分类为:
DRM Based Dual Port RAM:基于DRM的双端口RAM
 DRM Based Simple Dual Port RAM:基于DRM的简单双端口RAM
 DRM Based Single Port RAM:基于DRM的单端口RAM
 DRM Based ROM:基于DRM的ROM
 DRM Based FIFO:基于DRM的FIFO
Logos系列FPGA的DRM有高达18K bits的存储单元并且容量可被独立配置为2个9K bits或者1个
18K bits。每个DRM都能支持DP(True Dual Port,双口)RAM模式,同时也以被配置为SP(Single Port,单口)RAM模式,SDP(Simple Dual Port,简单双口)RAM模式,ROM模式,以及可选丢包重发的同步\异步FIFO模式。DRM资源还支持输入寄存器(IR)、输出寄存器(OR)以及Core Latch,这使得DRM级联使用时拥有更加出色的性能表现。DRM的总数取决于Logos系列器件类型。
Logos系列FPGA DRM的原语是各种模式的基础,其原语有两种:GTP_DRM9K和GTP_DRM18K,
其支持类型如表 18.1.1所示:
表 18.1.1 Logos系列FPGA DRM原语
lQLPJxS51xf1kfQ_zQKFsGJWNpmC6MeCA9Cu1xQA2gA_645_63.png

注:1.所有原语模块在软件安装路径..\arch\vendor\pango\verilog\simulation可找出。
Distributed RAM
Distributed RAM IP是紫光同创基于FPGA片内资源设计的IP,适用于全系列FPGA产品,用户可以通过公司PDS(Pango Design Suite)套件中的IPC(IP Compiler)工具完成IP模块的配置和生成。Distributed RAM IP包含5个子IP:
 Distributed ROM:分布式ROM
 Distributed Single Port RAM:分布式单口RAM
 Distributed Simple Dual Port RAM:分布式简单双端口RAM
 Distributed Shift Register:分布式移位寄存器
 Distributed FIFO:分布式FIFO
Pango PGL22G系列的Memory存储单元可以实现各种存储器的功能,PDS软件自带的IP Compiler(IP编译器)已经生成了各种存储器,例如RAM、移位寄存器、ROM以及FIFO缓冲器。
RAM与ROM这两者的区别是RAM是一种随机存取存储器,不仅仅可以存储数据,同时支持对存储的数据进行修改;而ROM是一种只读存储器,也就是说,在正常工作时只能读出数据,而不能写入数据。需要注意的是,配置成RAM或者ROM使用的资源都是FPGA内部的Distributed RAM,只不过配置成ROM时只用到了嵌入式Distributed RAM的读数据端口。本章我们主要介绍使用IPC(IP Compiler)工具生成的单口RAM实现读写的功能。
单端口RAM(DRM Based Single Port RAM)只有一个端口,读/写只能通过这一个端口来进行。单端口RAM只有一组数据总线、地址总线、时钟信号以及其他控制信号。有关DRM的更详细的介绍,请读者参阅Pango官方的手册文档“Logos系列FPGA专用RAM模块(DRM)用户指南(UG020002,Version1.1)”。
DRM Base Single Port RAM的单端口RAM的框图如下图所示。
IP核之单端口RAM实验2183.png
图 18.1.1 单端口RAM框图

各个端口的功能描述如下:
addr:写地址信号。
addr_strobe:写地址选锁存号,高电平对应地址无效,上一个地址被保持,低电平对应地址有效。
wr_data:写数据信号。
rd_data:读数据信号。
wr_en:写使能信号,高电平表示向RAM中写入数据,低电平表示从RAM中读出数据。
clk:RAM的时钟信号。
clk_en:时钟使能信号,高电平对应地址有效,低电平对应地址无效。
rst:复位信号,高有效
wr_byte_en:Byte Write使能信号,当配置“Enable Byte Write”选项勾选时有效,位宽范围1~128。高电平对应Byte值有效,低电平对应Byte值无效。
rd_oce:输出寄存使能信号,高电平对应地址有效,读数据寄存输出,低电平对应地址无效,读数据保持。
18.2实验任务
本节实验任务是使用PDS的IP Compiler配置一个单口RAM IP并对该单口RAM进行读写操作,通过PDS与Modelsim联合仿真观察波形是否正确,最后将设计下载到ATK-DFPGL22G开发板中,并使用Inserter对其进行在线调试观察。
18.3硬件设计
本章实验只用到了输入的时钟信号和按键复位信号,没有用到其它硬件外设,各端口信号的管脚分配如下表所示:
表 18.3.1 IP核之单口RAM实验管脚分配
lQLPJwhKm-H5ZvRczQJxsPXNJu1Lz7zMA9CuxYnA3gA_625_92.png

对应的FDC约束语句如下所示:
define_attribute {p:sys_clk} {PAP_IO_DIRECTION} {INPUT}
define_attribute {p:sys_clk} {PAP_IO_LOC} {B5}
define_attribute {p:sys_clk} {PAP_IO_VCCIO} {3.3}
define_attribute {p:sys_clk} {PAP_IO_STANDARD} {LVCMOS12}
define_attribute {p:sys_clk} {PAP_IO_NONE} {TRUE}
define_attribute {p:sys_rst_n} {PAP_IO_DIRECTION} {INPUT}
define_attribute {p:sys_rst_n} {PAP_IO_LOC} {G5}
define_attribute {p:sys_rst_n} {PAP_IO_VCCIO} {1.5}
define_attribute {p:sys_rst_n} {PAP_IO_STANDARD} {LVCMOS12}
define_attribute {p:sys_rst_n} {PAP_IO_NONE} {TRUE}
18.4程序设计
首先在PDS软件中创建一个名为ip_1port_ram的工程,工程创建完成后,在PDS软件的上方的菜单栏中“Tools”栏中单击“IP Compiler”按钮后弹出的“IP Compiler”窗口如图 18.4.2所示。
IP核之单端口RAM实验3644.png
图 18.4.1 点击“IP Compiler”

IP核之单端口RAM实验3714.png
图 18.4.2 “IP Compiler”窗口

本实验使用的IP核路径是Module→Memory→DRM→DRM Base Single Port RAM IP核,如下图所示。
IP核之单端口RAM实验3850.png
图 18.4.3DRM Based Single Port RAM

点击上图中红框中的IP后如下图所示:
IP核之单端口RAM实验3948.png
图 18.4.4 DRM Based Single Port RAM IP详情页面

Pathname:新建IP核在工程所在路径,这里保持默认即可。
Instance Name:在这里给新建的RAM IP命名,我们这里命名为“ram_1port”。
接下来的IP框里面的内容是该IP的基础信息,例如名称、版本号与所属公司(Pango)。Part框中的信息为工程所使用的芯片的详细信息“PGL22G-6CMBG324”。
点击上图中的“Customize”按钮进入“Customize IP”窗口对RAM IP的参数进行配置,“Customize IP”窗口界面如下图所示:图中的“Add IP”弹窗点击“Yes”后进入“Customize IP”界面进行单口RAM的参数配置,“Customize IP”界面如图 18.4.6所示。
IP核之单端口RAM实验4384.png
图 18.4.5 “Add IP”弹窗


CF01CAA5-997F-490d-901D-FB225F4E5B0B.png
图 18.4.6 Customize IP界面

本实验我们主要进行如下配置:
IP核之单端口RAM实验4533.png
图 18.4.7 “DRM Based Single Port RAM”参数配置界面

Customize IP界面主要包括如下选项:
DRM Resource Usage:选项主要说明DRM资源使用情况。该选项下的“DRM Resource Type”是
DRM资源类型,可以设置“AUTO”、“DRM9K”、“DRM18K”三种模式。三种模式可以根据你需要地址宽度与数据宽度来来设置,一般我们设置为“AUTO”模式。
表 18.4.1 9Kb DRM模式Single Port RAM模式和ROM模式列表
IP核之单端口RAM实验4875.png

表 18.4.2 18Kb DRM模式Single Port RAM模式和ROM模式列表
IP核之单端口RAM实验4965.png

Enable Byte Write:配置是否使能Byte Write功能,其含义是Byte写使能,也就是以字节为单位写入数据;Byte Write使能时,同时需要配置字节(Byte)的位宽(Byte Size)与字节个数(Byte Numbers),Byte Size可选择8或者9;Byte Numbers即配置所使用的Byte个数(注:Byte Write使能时,关闭Address Strobe功能。)举例说明:输入数据为32-bit,字节的位宽(Byte Size)设置为8bit,那么就需要4-bit Byte写使能信号,这个使能信号与输入数据各位的对应关系如下图所示。从图中不难看出,当we[3]有效时,只会将输入数据的高8-bit写入到目标地址;当we[0]有效时,只会将输入数据的低8-bit写入到目标地址。其实,也就是根据写使能来更新指定地址上原始数据的某些位,本实验不需要使能Byte Write功能即不需要勾选该配置。
lQLPJw64y2MXQzQszQI5sImXm83gxBlrA9CuSJYA2gA_569_44.png
图 18.4.8 Byte写使能与输入数据的对应关系

Address and Data Width Config:选项即地址与位宽配置,Address Width配置地址位宽,Data Width配置数据位宽。地址位宽合法配置范围为1~20,数据位宽合法配置范围为1~1152,但是所占用的DRM9K或者DRM18K个数必须小于总资源个数。本实验我们配置的地址位宽为5,数据位宽为8位。
Enable clk_en Signal:配置是否使能clk_en信号(注:Clock Enable与Address Strobe功能互斥),本实验未使用保持默认不用勾选。
Enable Address Strobe Signal:配置是否使能addr_strobe信号(注:1.Byte Write使能时,关闭Address Strobe功能2.Clock Enable与Address Strobe功能互斥), 本实验未使用保持默认不用勾选。
Write Mode:配置写模式。共分为三种模式,分别是NORMAL_WRITE(正常模式)、TRANSPARENT_WRITE(写优先模式)和READ_BEFORE_WRITE(读优先模式)。正常模式指读写分开操作,不能同时进行读写,本实验选择NORMAL_WRITE模式;写优先模式指数据先写入RAM中,然后在下一个时钟输出该数据;读优先模式指数据先写入RAM中,同时输出RAM中同地址的上一次数据。
Enable rd_oce Signal:配置是否使能rd_oce(输出寄存器选项)信号,使能rd_oce信号时,默认且必须使能读端口输出寄存“Enable Output Register”,本实验不需要使能读信号,所以不勾选该选项。
Enable Output Register:输出寄存器选项。如果勾选了“Enable rd_oce Signal”信号,输出寄存器默认是选中状态,作用是打开DRM内部位于输出数据总线之后的输出流水线寄存器,虽然在一般设计中为了改善时序性能会保持此选项的默认勾选状态,但是这会使得DRM输出的数据延迟一拍,这不利于我们在调试窗口中直观清晰地观察信号;而且在本实验中我们仅仅是把DRM的数据输出总线连接到了调试的探针端口上来进行观察,除此之外数据输出总线没有别的负载,不会带来难以满足的时序路径,因此这里取消勾选。
Enable Clock Polarity Invert for Output Register:配置是否使能读端口输出时钟极性反向,使能读端口输出时钟极性反向时,默认且必须使能读端口输出寄存(Enable Output Register),这里不需要使能读端口输出时钟极即不需要勾选该配置。
Enable Low Power Mode:配置是否使能低功耗模式,本实验不需要配置成低功耗模式,即不勾选使能低功耗模式。
Reset Type:配置复位方式:"ASYNC"异步复位,"SYNC"同步复位,"Sync_Internally "异步复位同步释放,本实验选择异步复位。
Enable Init:配置是否使能对当前RAM进行初始化,这里不需要该配置即不用勾选使能初始化选项。
Init File:配置使能对当前RAM进行初始化,指定初始化文件路径,若不指定,则生成初始值为全“0”的初始化文件.v文件。
File Type:配置初始化文件数据格式:"BIN"二进制,"HEX"十六进制。
至此本实验所需要的单口RAM IP已配置完成,接下来点击“Customize IP”窗口左上角的“Generate”在弹出的“Question”对话框选择“OK”即可,如下图所示。
IP核之单端口RAM实验7030.png
图 18.4.9 点击“Generate”按钮

IP核之单端口RAM实验7099.png
图 18.4.10点击“OK”

点击“OK”后打印如下左图信息,至此单口RAM IP核配置成功,并生成ram_1port_tmpl.v文件。例化单口RAM IP时可以使用下图中ram_1port_tmpl.v文件红框中的代码。
IP核之单端口RAM实验7259.png
图 18.4.11 单口RAM IP创建成功

然后如下图所示,关闭“Customize IP”页面与“IP Compiler”页面。
IP核之单端口RAM实验7371.png
图 18.4.12 关闭创建IP的窗口

之后我们就可以在“Sources”窗口的“Designs”一栏中出现了该IP核“ram_1port”如下图所示。
IP核之单端口RAM实验7493.png
图 18.4.13 ram_1port IP核

接下来我们创建一个新的设计文件,命名为ram_rw.v,代码如下:
1  module ram_rw(
2      input               clk        ,  //时钟信号
3      input               rst_n      ,  //复位信号,低电平有效
4  
5      output              ram_en     ,  //ram使能信号
6      output              ram_wea    ,  //ram读写选择
7      output  reg  [4:0]  ram_addr   ,  //ram读写地址
8      output  reg  [7:0]  ram_wr_data   //ram写数据  
9      );
10
11 //reg define
12 reg  [5:0]  rw_cnt;        //读写控制计数器
13
14 //*****************************************************
15 //**                    main code
16 //*****************************************************
17
18 //控制RAM使能信号
19 assign ram_en = rst_n;
20 //rw_cnt计数范围在0~31,写入数据;32~63时,读出数据
21 assign ram_wea = (rw_cnt <= 6'd31 && ram_en == 1'b1) ? 1'b1 : 1'b0;
22
23 //读写控制计数器,计数器范围0~63
24 always @(posedge clk or negedge rst_n) begin
25     if(rst_n == 1'b0)
26         rw_cnt <= 1'b0;   
27     else if(rw_cnt == 6'd63)
28         rw_cnt <= 1'b0;
29     else
30         rw_cnt <= rw_cnt + 1'b1;
31 end  
32
33 //产生RAM写数据
34 always @(posedge clk or negedge rst_n) begin
35     if(rst_n == 1'b0)
36         ram_wr_data <= 1'b0;
37     else if(rw_cnt <= 6'd31)  //在计数器的0-31范围内,RAM写地址累加
38         ram_wr_data <= ram_wr_data + 1'b1;
39     else
40         ram_wr_data <= 1'b0 ;
41 end  
42
43 //读写地址信号 范围:0~31
44 always @(posedge clk or negedge rst_n) begin
45     if(rst_n == 1'b0)
46         ram_addr <= 1'b0;
47     else if(ram_addr == 5'd31)
48         ram_addr <= 1'b0;
49     else   
50         ram_addr <= ram_addr + 1'b1;
51 end
52
53 endmodule
模块中定义了一个读写控制计数器(rw_cnt),当计数范围在0~31之间时,向ram中写入数据;当计数范围在32~63之间时,从ram中读出数据。
接下来我们设计一个verilog文件来实例化创建的单口RAM IP核以及ram_rw模块,文件名为ip_1port_ram.v,编写的verilog代码如下。
1  module ip_1port_ram(
2      input          sys_clk   ,
3      input          sys_rst_n ,
4      
5  //冗余逻辑,仅仅是为了将端口拉出去,方便观察信号
6      output         ena  ,
7      output         wea  ,
8      output [4 : 0] addra,
9      output [7 : 0] dina ,
10     output [7 : 0] douta
11     );
12
13 //*****************************************************
14 //**                    main code
15 //*****************************************************
16
17 ram_1port u_ram_1port (
18   .wr_data    (dina      ),    // input [7:0]
19   .addr       (addra     ),    // input [4:0]
20   .wr_en      (wea       ),    // input
21   .clk        (sys_clk   ),    // input
22   .rst        (~sys_rst_n),    // input
23   .rd_data    (douta     )     // output [7:0]
24 );
25
26 ram_rw u_ram_rw (
27     .clk            (sys_clk  ),
28     .rst_n          (sys_rst_n),
29     .ram_en         (ena      ),
30     .ram_wea        (wea      ),
31     .ram_addr       (addra    ),
32     .ram_wr_data    (dina     )
33     );
34     
35 endmodule
程序中例化了ram_rw模块和单口ram IP核,其中ram_rw模块负责产生对ram IP核读/写所需的所有数据、地址以和读写使能信号,同时从ram IP读出的数据也连接至ram_rw模块。
接下来对单口RAM IP核进行仿真,来验证对单口RAM的读写操作是否正确。ip_1port_ram_tb仿真文件源代码如下:
1  `timescale 1ns / 1ps
2  module ip_1port_ram_tb;
3  
4  reg  grs_n;
5  //GTP_GRS I_GTP_GRS(
6      GTP_GRS GRS_INST(
7      .GRS_N (grs_n)
8      );
9      
10     initial begin
11     grs_n = 1'b0;
12     #5000 grs_n = 1'b1;
13     end
14
15     // Inputs
16     reg sys_clk;
17     reg sys_rst_n;
18     
19     // Outputs
20     wire ena_tb;
21     wire wea_tb;
22     wire [4:0] addra_tb;
23     wire [7:0] dina_tb;
24     wire [7:0] douta_tb;
25     // Instantiate the Unit Under Test (UUT)
26     ip_1port_ram uut (
27     .sys_clk      (sys_clk  ),
28     .sys_rst_n    (sys_rst_n),
29     .ena          (ena_tb   ),
30     .wea          (wea_tb   ),
31     .addra        (addra_tb ),
32     .dina         (dina_tb  ),
33     .douta        (douta_tb )
34     );
35     
36     initial begin
37     // Initialize Inputs
38     sys_clk = 0;
39     sys_rst_n = 0;
40     
41     // Wait 100 ns for global reset to finish
42     #100;
43     sys_rst_n=1;
44     // Add stimulus here
45     end
46     
47     always #10 sys_clk=~sys_clk;
48     
49 endmodule
代码第4行到第13行例化了一个GTP_GRS模块 ,GTP_GRS是一个全局复位,在FIFO或者RAM IP中使用了这个全局复位,所以使用了FIFO或者RAM IP的文件的仿真代码里面就需要对GTP_GRS模块进行例化,不然联合仿真会报错。
接下来就可以开始仿真了,仿真过程这里不再赘述,仿真波形图如下图所示。
IP核之单端口RAM实验11666.png
图 18.4.14 单口RAM写操作波形图

图 18.4.14为单口RAM的写操作仿真波形图,由上图可知,地址和数据初始化赋值为0,当wea_tb信号拉高,说明此时是对ram进行写操作。wea_tb信号拉高之后,地址和数据都是从0开始累加,也就说当ram地址为0时,写入的数据也是0;当ram地址为1时,写入的数据也是1,我们总共向ram中写入32个数据。
单口RAM读操作仿真波形图如下图所示:
IP核之单端口RAM实验11935.png
图 18.4.15 单口RAM读操作波形图

由上图可知,ram_wea信号拉低,说明此时是对ram进行读操作。ram_wea信号拉低之后,ram_addr从0开始增加,也就是说从ram的地址0开始读数据;ram中读出的数据ram_rd_data在延时1个时钟周期之后,开始输出数据,输出的数据为0,1,2……,和我们写入的值是相等的,也就是说,我们创建的单口RAM IP核从仿真结果上来看是正确的。
接下来新建DebugCore,将ena、wea、addra、dina和dout信号添加至观察列表中,新建DebugCore核的方法这里不再赘述。
18.5下载验证
编译工程并生成比特流.sbit文件后,此时将下载器一端连接电脑,另一端与开发板上的JTAG下载口连接,连接电源线,并打开开发板的电源开关。
点击PDS工具栏的下载按钮,在弹出的Fabric Configuration界面中双击“Boundary Scan”,我们将生成好的sbit流文件下载到开发板中去。
单口RAM写操作在Fabric Debugger中观察的波形如下图所示:
IP核之单端口RAM实验12448.png
图 18.5.1 RAM写操作波形图

wea信号拉高之后,地址和数据都是从0开始累加,也就说当ram地址为0时,写入的数据也是0;当ram地址为1时,写入的数据也是1。我们可以发现,上图中的数据变化和在PDS仿真的波形是一致的。
单口RAM读操作在Fabric Debugger中观察的波形如下图所示:
IP核之单端口RAM实验12645.png
图 18.5.2 RAM读操作波形图

wea(写使能)信号拉低之后进行读使能,addr从0开始增加,也就是说从ram的地址0开始读数据;ram中读出的数据douta在延时1个时钟周期之后,开始输出数据,输出的数据为0,1,2……,和我们写入的值是相等的。我们可以发现,上图中的数据变化同样和PDS仿真的波形是一致的。本次实验的IP核之单口RAM读写实验验证成功。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 23:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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