FPGA逻辑设计回顾(13)RAM以及ROM的IP核定制以及关键参数
前言
在后面讲解DDR IP的定制之前,这里先介绍下Xilinx的RAM以及ROM IP比较合适,因为都甚为存储性质的东西,有些东西还是可以作为比较的。
RAM中也有一些参数,也有一些延迟,需要注意!因为有时它的特性并非如我们想象的那样,正确的流程应该是先看数据手册,再使用,但是对于很多设计者来说,总感觉这玩意太简单,但越是这样可能越会用错,不注意延迟,可能会导致时序问题,进而导致功能性问题,最后是整个设计的失败。
好了,我们开始吧。
RAM IP的定制
Xilinx的IP定制位置
关于IP的这个最基础的内容,我们在这里只讲一次,可能没用过Xilinx的朋友以及新手朋友们可能需要:
Xilinx的IP核定制均在IP Catalog内:
Xilinx的RAM IP位于存储元素一类内部,如下图:
继续将小分类打开,可见:
我们的存储老朋友都在,第一个是DDR的控制接口,第二个是使用分布式资源的存储资源,第三个是Block资源的存储元素。
第一个放在后面的文章来讲解,我们先看第三个,Block资源的存储元素,以RAM为例,即BRAM。
Block RAM的定制过程
第一页
双击RAM,进入定制的第一页,第一页我们需要关注的内容如下:
定制的IP的名字只能在定制的时候更改,定制完成之后,不能再次更改,除非你删除自己定制的IP核,再次定制一个新的,那样比较麻烦,因此这里名字要按一个的规则写名字,一般而言,名字易懂即可,例如BRAM_16x1024,表示定制的是一个Block RAM,且位宽为16bit,深度为1024,关键信息一目了然。当然了,如果你的工程里用到了多个这种参数的RAM,你可以在后缀中加入更多的信息,例如功能性的信息,或者标号,即第几个这种RAM。
之后,我们在这一页需要关注的内容就是我们选用什么样的RAM,单端口还是双端口,这看你设计的需求。单端口适合先存储,之后过一段时间再取出,要分时使用,且最重要的是只能使用一个时钟,因为只有一个时钟端口。
对于双端口RAM而言,两边的端口都可以进行读写或存取,但在时序上也要求不能同时操作,例如对同一个地址同时进行读写,双端口的目的在于使用灵活,一端用于写,另一端可以用于读,且可以是不同的时钟域,功能划分清晰。
至于这一页的算法选择,可以关注也可以不关注,每一种选择都各有利弊,看你个人的选择,但我相信在你使用的时候,你可能想不到这一层面,到底我需要哪一种呢?自己也不清楚,还是暂时默认吧,无伤大雅。
第二页
定制第二页,是整个存储器定制的精华,也是我们最需要关注的内容,一般简单选择下就好了,选择满足我们功能的几个选项。
例如宽度与深度,操作模式呢?
可能不太需要吧,我们的使用场景尽量是分时使用,不能说一边写同时读那种吧。(如果你真的需要这种,那就不需要来看这篇博文了)
读写位宽可以不一致,这主要为位宽转换提供了方便,例如存两个数,取一次,就可以将两个数拼接在一起读出,这可以说是一种形式的串并转换了。
使能要不要选呢?
多一个选择多一条路,且这个选择不会对人造成困惑,如果没有特别需求,将其赋值为1即可。
至于输出寄存器放在哪一个位置,这个可以都选择,也可以只选择一个,带来的问题肯定是输出的延迟比较大。
例如我只选择了一个输出寄存器,看看延迟为多少?
延迟为2;
选择两个寄存器:
延迟为3。
但是好处在于选了后时序不会比不选差,原语处的寄存器位于原语内,IP核的寄存器位于FPGA的Fabric内。
该页最终的定制:
输出都是有延迟的,这一点后面的DDR也会有,需要当做常识。
第三页
第三页和第二页是同样的,只不过是定制B端口的内容,没有特别需求,建议保持一致。
第四页
上一页结束其实关键信息都已经选择,这一页对于RAM来说不太重要了,对于ROM来说可能很重要,因为ROM需要初始化内容, 后面就不写入了。
第五页
这一页是总结内容,告诉你的定制耗费了多少资源,输出相对于使能延迟了多少时钟,地址位宽是多少等。
到这里,我们就定制完了一个简单的真双端口BRAM IP核。
点击OK生成IP,之后复制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 = 1'd1;
wea = 1'd0;
dina = 32'd0;
addra = 10'd0;
web = 1'd1;
dinb = 32'd0;
addrb = 10'd0;
enb = 1'd0;
//写6个时钟的数据
#(15*PERIOD_CLK) rst = #(0.1) 1'd0;
#(6*PERIOD_CLK);
@(posedge clk);
wea = #(0.1*PERIOD_CLK) 1'd1;
dina = #(0.1*PERIOD_CLK) 32'h66;
#(5 * PERIOD_CLK) begin
wea = #(0.1*PERIOD_CLK) 1'd0;
end
//b端口读取6个数据
#(15*PERIOD_CLK);
@(posedge clk);
enb = #(0.1*PERIOD_CLK) 1'd1;
web = #(0.1 * PERIOD_CLK) 1'd0;
repeat(5) begin
@(posedge clk);
addrb = #( 0.1*PERIOD_CLK )addrb + 10'd1;
end
end
always @(posedge clk or posedge rst) begin
if(rst) begin
dina <= #(0.1) 32'd0;
addra <= #(0.1) 10'd0;
end
else if(wea)begin
dina <= #(0.1) dina + 32'd1;
addra <= #(0.1) addra + 10'd1;
end
end
bram_delay u_bram_delay(
.clka ( clk ),
.rsta ( rst ),
.ena ( 1'd1 ),
.wea ( wea ),
.addra ( addra ),
.dina ( dina ),
.douta ( douta ),
.clkb ( clk ),
.rstb ( rst ),
.enb ( enb ),
.web ( web ),
.addrb ( addrb ),
.dinb ( dinb ),
.doutb ( doutb )
);
endmodule
可见,我们的写使能持续了6个时钟:
这个效果靠的是下面这段测试代码实现:
//写6个时钟的数据
#(15*PERIOD_CLK) rst = #(0.1) 1'd0;
#(6*PERIOD_CLK);
@(posedge clk); //wea的第一个有效周期
wea = #(0.1*PERIOD_CLK) 1'd1;
dina = #(0.1*PERIOD_CLK) 32'h66;
repeat(5) begin //wea的后5个有效周期
@(posedge clk);
wea = #(0.1*PERIOD_CLK) 1'd1;
end
@(posedge clk);
wea = #(0.1*PERIOD_CLK)1'd0;
读6个数据:
从给地址开始,延迟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
总结
以上就是这篇文章的所有内容,很简单,主要是提供一个清晰地认识,为以后类似的存储器件作为对比,同时理解参数的延迟很重要,这对逻辑设计的时序十分关键。
- 分享
- 举报
-
浏览量:6877次2021-01-31 01:07:50
-
浏览量:5691次2021-01-31 04:24:47
-
浏览量:6172次2021-01-30 01:09:16
-
浏览量:10372次2020-12-13 19:59:59
-
浏览量:6863次2021-03-15 23:18:36
-
浏览量:6952次2021-01-30 23:18:56
-
浏览量:18994次2020-12-06 18:59:36
-
浏览量:8103次2020-12-27 18:30:21
-
浏览量:8485次2021-01-09 02:07:52
-
浏览量:10625次2021-01-17 00:16:33
-
浏览量:13143次2021-01-01 02:53:29
-
浏览量:6831次2021-01-23 18:45:14
-
浏览量:12163次2021-01-02 00:02:19
-
浏览量:6571次2021-03-14 02:34:44
-
浏览量:7639次2021-02-07 00:59:28
-
浏览量:4135次2021-03-12 23:39:20
-
浏览量:4808次2021-03-18 22:57:24
-
浏览量:5371次2021-03-17 23:24:53
-
浏览量:10842次2021-03-20 13:22:58
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
李锐博恩
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明