FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

前言

在后面讲解DDR IP的定制之前,这里先介绍下Xilinx的RAM以及ROM IP比较合适,因为都甚为存储性质的东西,有些东西还是可以作为比较的。

RAM中也有一些参数,也有一些延迟,需要注意!因为有时它的特性并非如我们想象的那样,正确的流程应该是先看数据手册,再使用,但是对于很多设计者来说,总感觉这玩意太简单,但越是这样可能越会用错,不注意延迟,可能会导致时序问题,进而导致功能性问题,最后是整个设计的失败。

好了,我们开始吧。

RAM IP的定制

Xilinx的IP定制位置

关于IP的这个最基础的内容,我们在这里只讲一次,可能没用过Xilinx的朋友以及新手朋友们可能需要:

Xilinx的IP核定制均在IP Catalog内:

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

Xilinx的RAM IP位于存储元素一类内部,如下图: FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数 继续将小分类打开,可见:

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

我们的存储老朋友都在,第一个是DDR的控制接口,第二个是使用分布式资源的存储资源,第三个是Block资源的存储元素。

第一个放在后面的文章来讲解,我们先看第三个,Block资源的存储元素,以RAM为例,即BRAM。

Block RAM的定制过程

第一页

双击RAM,进入定制的第一页,第一页我们需要关注的内容如下:

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

定制的IP的名字只能在定制的时候更改,定制完成之后,不能再次更改,除非你删除自己定制的IP核,再次定制一个新的,那样比较麻烦,因此这里名字要按一个的规则写名字,一般而言,名字易懂即可,例如BRAM_16x1024,表示定制的是一个Block RAM,且位宽为16bit,深度为1024,关键信息一目了然。当然了,如果你的工程里用到了多个这种参数的RAM,你可以在后缀中加入更多的信息,例如功能性的信息,或者标号,即第几个这种RAM。

之后,我们在这一页需要关注的内容就是我们选用什么样的RAM,单端口还是双端口,这看你设计的需求。单端口适合先存储,之后过一段时间再取出,要分时使用,且最重要的是只能使用一个时钟,因为只有一个时钟端口。 对于双端口RAM而言,两边的端口都可以进行读写或存取,但在时序上也要求不能同时操作,例如对同一个地址同时进行读写,双端口的目的在于使用灵活,一端用于写,另一端可以用于读,且可以是不同的时钟域,功能划分清晰。

至于这一页的算法选择,可以关注也可以不关注,每一种选择都各有利弊,看你个人的选择,但我相信在你使用的时候,你可能想不到这一层面,到底我需要哪一种呢?自己也不清楚,还是暂时默认吧,无伤大雅。

第二页

定制第二页,是整个存储器定制的精华,也是我们最需要关注的内容,一般简单选择下就好了,选择满足我们功能的几个选项。 例如宽度与深度,操作模式呢? 可能不太需要吧,我们的使用场景尽量是分时使用,不能说一边写同时读那种吧。(如果你真的需要这种,那就不需要来看这篇博文了)

读写位宽可以不一致,这主要为位宽转换提供了方便,例如存两个数,取一次,就可以将两个数拼接在一起读出,这可以说是一种形式的串并转换了。 使能要不要选呢? 多一个选择多一条路,且这个选择不会对人造成困惑,如果没有特别需求,将其赋值为1即可。 FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

至于输出寄存器放在哪一个位置,这个可以都选择,也可以只选择一个,带来的问题肯定是输出的延迟比较大。 例如我只选择了一个输出寄存器,看看延迟为多少?

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数 延迟为2;

选择两个寄存器:

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数 延迟为3。

但是好处在于选了后时序不会比不选差,原语处的寄存器位于原语内,IP核的寄存器位于FPGA的Fabric内。

该页最终的定制:

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数 输出都是有延迟的,这一点后面的DDR也会有,需要当做常识。

第三页

第三页和第二页是同样的,只不过是定制B端口的内容,没有特别需求,建议保持一致。 FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

第四页

上一页结束其实关键信息都已经选择,这一页对于RAM来说不太重要了,对于ROM来说可能很重要,因为ROM需要初始化内容, 后面就不写入了。 FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

第五页

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数

这一页是总结内容,告诉你的定制耗费了多少资源,输出相对于使能延迟了多少时钟,地址位宽是多少等。

到这里,我们就定制完了一个简单的真双端口BRAM IP核。

点击OK生成IP,之后复制IP核自带的例化模板使用即可。

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数 双击Veo文件,即可得到IP模板:

//———– Begin Cut here for INSTANTIATION Template —// INST_TAG bram_16x1024 your_instance_name ( .clka(clka), // input wire clka .rsta(rsta), // input wire rsta .ena(ena), // input wire ena .wea(wea), // input wire [0 : 0] wea .addra(addra), // input wire [9 : 0] addra .dina(dina), // input wire [31 : 0] dina .douta(douta), // output wire [31 : 0] douta .clkb(clkb), // input wire clkb .rstb(rstb), // input wire rstb .enb(enb), // input wire enb .web(web), // input wire [0 : 0] web .addrb(addrb), // input wire [9 : 0] addrb .dinb(dinb), // input wire [31 : 0] dinb .doutb(doutb) // output wire [31 : 0] doutb ); // INST_TAG_END —— End INSTANTIATION Template ———

加入到你的设计即可。

Block RAM的延迟讨论

这里的讨论,最主要的还是讨论下什么时候数据可以使用存入的数据而已,以上述定制的IP为例,我们我们令写使能有效6个时钟,即可入6个数据,然后将这6个数据从另外一端读出。

首先将BRAM例化一下:

`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Engineer: 李锐博恩 // Create Date: 2021/02/06 18:57:57 // Module Name: bram_delay ////////////////////////////////////////////////////////////////////////////////// module bram_delay( input wire clka, input wire rsta, input wire ena, input wire [0 : 0] wea, input wire [9 : 0] addra, input wire [31 : 0] dina, output wire [31 : 0] douta, input wire clkb, input wire rstb, input wire enb, input wire [0 : 0] web, input wire [9 : 0] addrb, input wire [31 : 0] dinb, output wire [31 : 0] doutb ); bram_16x1024 inst_bram_16x1024 ( .clka(clka), // input wire clka .rsta(rsta), // input wire rsta .ena(ena), // input wire ena .wea(wea), // input wire [0 : 0] wea .addra(addra), // input wire [9 : 0] addra .dina(dina), // input wire [31 : 0] dina .douta(douta), // output wire [31 : 0] douta .clkb(clkb), // input wire clkb .rstb(rstb), // input wire rstb .enb(enb), // input wire enb .web(web), // input wire [0 : 0] web .addrb(addrb), // input wire [9 : 0] addrb .dinb(dinb), // input wire [31 : 0] dinb .doutb(doutb) // output wire [31 : 0] doutb ); endmodule
<

使能的控制放在测试文件里做:

`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Engineer: 李锐博恩 // Create Date: 2021/02/06 18:57:57 // Module Name: bram_tb ////////////////////////////////////////////////////////////////////////////////// module bram_tb( ); reg clk; reg rst; reg wea; reg [9 : 0] addra; reg [31 : 0] dina; wire [31 : 0] douta; reg enb; reg web; reg [9 : 0] addrb; reg [31 : 0] dinb; wire [31 : 0] doutb; localparam PERIOD_CLK = 5; initial begin clk = 0; forever begin #(PERIOD_CLK/2) clk = ~clk; end end initial begin rst = 1d1; wea = 1d0; dina = 32d0; addra = 10d0; web = 1d1; dinb = 32d0; addrb = 10d0; enb = 1d0; //写6个时钟的数据 #(15*PERIOD_CLK) rst = #(0.1) 1d0; #(6*PERIOD_CLK); @(posedge clk); wea = #(0.1*PERIOD_CLK) 1d1; dina = #(0.1*PERIOD_CLK) 32h66; #(5 * PERIOD_CLK) begin wea = #(0.1*PERIOD_CLK) 1d0; end //b端口读取6个数据 #(15*PERIOD_CLK); @(posedge clk); enb = #(0.1*PERIOD_CLK) 1d1; web = #(0.1 * PERIOD_CLK) 1d0; repeat(5) begin @(posedge clk); addrb = #( 0.1*PERIOD_CLK )addrb + 10d1; end end always @(posedge clk or posedge rst) begin if(rst) begin dina <= #(0.1) 32d0; addra <= #(0.1) 10d0; end else if(wea)begin dina <= #(0.1) dina + 32d1; addra <= #(0.1) addra + 10d1; end end bram_delay u_bram_delay( .clka ( clk ), .rsta ( rst ), .ena ( 1d1 ), .wea ( wea ), .addra ( addra ), .dina ( dina ), .douta ( douta ), .clkb ( clk ), .rstb ( rst ), .enb ( enb ), .web ( web ), .addrb ( addrb ), .dinb ( dinb ), .doutb ( doutb ) ); endmodule
<

可见,我们的写使能持续了6个时钟: FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数 这个效果靠的是下面这段测试代码实现:

//写6个时钟的数据 #(15*PERIOD_CLK) rst = #(0.1) 1d0; #(6*PERIOD_CLK); @(posedge clk); //wea的第一个有效周期 wea = #(0.1*PERIOD_CLK) 1d1; dina = #(0.1*PERIOD_CLK) 32h66; repeat(5) begin //wea的后5个有效周期 @(posedge clk); wea = #(0.1*PERIOD_CLK) 1d1; end @(posedge clk); wea = #(0.1*PERIOD_CLK)1d0;

读6个数据:

FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数 从给地址开始,延迟3拍出数据,这与定制的时候看到的延迟数为3一致。

ROM IP核的定制

关于ROM IP核的定制,没什么好说的,和RAM类似,但有一点就是需要进行初始化,初始化时初始化的数据使用COE文件来提供,而这个COE文件的格式为:

memory_initialization_radix = 16; memory_initialization_vector = 23f4 0721 11ff ABe1 0001 1 0A 0 23f4 0721 11ff ABe1 0001 1 0A 0

即正常的文件加上两个开头,一个表明初始化数据的进制:memory_initialization_radix; 另一个表明初始化数据:memory_initialization_vector; 提供一个例子:

memory_initialization_radix = 2; memory_initialization_vector = 00000000 00000001 00000010 00000011

总结

以上就是这篇文章的所有内容,很简单,主要是提供一个清晰地认识,为以后类似的存储器件作为对比,同时理解参数的延迟很重要,这对逻辑设计的时序十分关键。

免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数 https://www.yhzz.com.cn/a/13031.html

上一篇 2023-05-11 17:52:27
下一篇 2023-05-11 17:54:48

相关推荐

联系云恒

在线留言: 我要留言
客服热线:400-600-0310
工作时间:周一至周六,08:30-17:30,节假日休息。