您的位置 首页 编程

双口RAM概述及Vivado RAM IP核使用

双口RAM概述及Vivado RAM IP核应用-双口RAM概述 双口RAM(dual port RAM)在异构系统中应用广泛,通过双口RAM,不同硬件架构的芯片可以实现数据的交互,从而实现通信。

1.双口RAM概述

双口RAM(dual port RAM)在异构体系中运用广泛,经过双口RAM,不同硬件架构的芯片能够完成数据的交互,然后完成通讯。例如,一般情况下,ARM与DSP之间的通讯,能够运用双口RAM完成,ARM经过EBI总线连接到双口RAM的A口,DSP经过EMIF总线(也能够是uPP总线,取决于速度需求)连接到双口RAM的B口,两者对同一块存储区域进行操作,即可完成两者的数据交互。

可是,由于双口RAM的A口和B口都能够对相同的内存地址进行操作,这就引出了一个问题——假设通讯两边在两个端口对同一地址一起读写,就会引发抵触。要处理这个问题,办法有二。一是通讯两边在时序上确保不会一起读写同一地址,将ARM和DSP可写地址规模进行分区,不管任何一方写完数据后都经过IO发送中止告诉对方,对方进行数据读取(乒乓RAM操作),这样是比较牢靠的;别的一个办法就是在fpga里设置写busy信号,完成两头写同步[]。在FPGA中,构建双口RAM能够经过两种办法,一种是运用distributed RAM构建,另一种是运用Block RAM构建,关于两者的详细差异,能够参阅这两篇文章[][]。简而言之,Block RAM是是运用FPGA中的整块双口RAM资源,而distributed RAM则是用FPGA中的逻辑资源凑集构成的。一般的原则是,较大的存储运用,主张用bram;零散的小ram,一般就用dram。

在Vivado中,RAM IP核在Memories & Strorage Elements\RAM & ROMs和RAM & ROMs & BRAM文件夹下,如图所示,下面扼要介绍一下Vivado的双口RAM IP核。

双口RAM概述及Vivado RAM IP核运用

(图1.1)

2.Vivado 双口RAM IP核

2.1 Block Memory Generator概述

点击图1.1的Block Memory Generator项,运用BRAM来构建双口RAM。Block Memory Generator窗口如图2.1所示。

图中,第1部分,在IP symbol选项卡,点击“+”号能够打开端口详细信号,如图2.2所示。第2部分,Component Name能够设置IP核的姓名。第3部分,Basic选项卡,在Memory Type下拉列表中,能够设置内存的类型,如图2.3所示。Block Memory Gnerator总共能够发生5种不同类型的内存空间,其间block RAM有三种:单口RAM、简化双口RAM和真双口RAM[]。单口RAM只要一个端口(A端口),能够对A端口进行读写。简化双口RAM有两个端口(A和B端口),可是A端口只能进行写入操作,不能进行读出操作,而B端口则只能进行读出操作,不能进行写入操作。真双口RAM有两个端口(A和B端口),A和B端口都能进行读写操作[]。

双口RAM概述及Vivado RAM IP核运用

(图2.1)

双口RAM概述及Vivado RAM IP核运用

(图2.2)

双口RAM概述及Vivado RAM IP核运用

(图2.3)

2.2 真双口RAM的设置

2.2.1 Basic设置

在Basic选项卡的Memory type选项中挑选真双口RAM,IP Symbol如图2.4所示。ECC OpTIons为默许设置,Write Enable中也挑选默许设置,不使能字节写,Algorithm OpTIons挑选默许设置。

双口RAM概述及Vivado RAM IP核运用

(图2.4)

2.2.2 Port设置

点击Port A OpTIons选项卡,对A端口进行设置, 设置Write Width为16(即RAM单元为16位),Write Width为1024(即内存深度为1024,该端口可读写的RAM单元有1024个),OperaTIng Mode(操作形式)总共有三种:Write First,Read First,No Change。在Write First形式中,在一个时钟周期里,写入内存单元的数据被同步输出到输出数据总线上;在Read First形式中,在一个时钟周期里,写入到内存单元的数据是当时输入数据总线上的数据,而输出到输出数据总线上的数据则是上一个时钟周期存储在内存单元中的数据。细节可参阅PG058的49到50页4。Enable Port Type设置为Always Enabled,一向使能端口A。其它设置运用默许设置。如图2.5所示。

双口RAM概述及Vivado RAM IP核运用

(图2.5)

端口B设置为与A共同。在Other Options选项卡中,保存默许设置。Load Init File设置是否用Coe文件对内存区域初始化,这个在初始化ROM的时分会用到,这儿不勾选,坚持默许。最终,在Summary选项卡会显现耗费的资源。

3.双口RAM例程

例程1,该例程是Altera官方例程[],选用寄存器构建双口RAM,代码如下:

moduletrue_dpram_sclk

input [7:0] data_a, data_b,

input [5:0] addr_a, addr_b,

input we_a, we_b, clk,

outputreg [7:0] q_a, q_b

);

// Declare the RAM variable

reg [7:0] ram[63:0];

// Port A

always @ (posedge clk)

begin

if (we_a)

begin

ram[addr_a] 《= data_a;

q_a 《= data_a;

end

else

begin

q_a 《= ram[addr_a];

end

end

// Port B

always @ (posedge clk)

begin

if (we_b)

begin

ram[addr_b] 《= data_b;

q_b 《= data_b;

end

else

begin

q_b 《= ram[addr_b];

end

end

endmodule

例程2,该例程是Xilinx官方例程[],选用寄存器构建真双口RAM,代码如下:

// Dual-Port Block RAM with Two Write Ports

// File: rams_16.v

modulev_rams_16 (clka,clkb,ena,enb,wea,web,addra,addrb,dia,dib,doa,dob);

input clka,clkb,ena,enb,wea,web;

input [9:0] addra,addrb;

input [15:0] dia,dib;

output [15:0] doa,dob;

reg[15:0] ram [1023:0];

reg[15:0] doa,dob;

always @(posedge clka) beginif (ena)

begin

if (wea)

ram[addra] 《= dia;

doa 《= ram[addra];

end

end

always @(posedge clkb) beginif (enb)

begin

if (web)

ram[addrb] 《= dib;

dob 《= ram[addrb];

end

end

endmodule

例程3,该例程是网友博客中的例程[],代码如下:

moduleTOP(

input USER_CLK

);

`define DLY #1

reg FPGA_Enable=0;

reg[3:0] FPGA_Write_Enable=4‘h0;

reg[31:0] FPGA_Address=0;

reg[31:0] FPGA_Write_Data=0;

reg[31:0] FPGA_Read_Data_reg=0;

wire[31:0] FPGA_Read_Data;

reg[10:0] count=0;

always @ (posedge USER_CLK)

begin

count 《= count +1;

if(count《=100)

begin

FPGA_Enable 《=0;

FPGA_Write_Enable 《=4’h0;

end

elseif((count 《=105)&&(count 》100))

begin

FPGA_Enable 《=1;

FPGA_Write_Enable 《=4‘hf;

FPGA_Address 《= FPGA_Address +4;

FPGA_Write_Data 《= FPGA_Write_Data +1;

end

elseif((count 《=110)&&(count 》105))

begin

FPGA_Enable 《=0;

FPGA_Write_Enable 《=4’h0;

FPGA_Address 《=0;

FPGA_Write_Data 《=0;

end

elseif((count 《=117)&&(count 》110))

begin

FPGA_Enable 《=1;

FPGA_Write_Enable 《=4‘h0;

FPGA_Read_Data_reg 《= FPGA_Read_Data;

FPGA_Address 《= FPGA_Address +4;

end

elseif(count ==118)

begin

FPGA_Enable 《=0;

count 《= count;

end

end

BBBByour_instance_name (

.clka(USER_CLK), // input clka

.ena(FPGA_Enable), // input ena

.wea(FPGA_Write_Enable), // input [3 : 0] wea

.addra(FPGA_Address), // input [31 : 0] addra

.dina(FPGA_Write_Data), // input [31 : 0] dina

.douta(FPGA_Read_Data), // output [31 : 0] douta

.clkb(clkb), // input clkb

.enb(enb), // input enb

.web(web), // input [3 : 0] web

.addrb(addrb), // input [31 : 0] addrb

.dinb(dinb), // input [31 : 0] dinb

.doutb(doutb) // output [31 : 0] doutb

);

endmodule

该例程中,在count为101(》100)后开端往地址4到20写入1-5,然后在count为111(》110)的时分读出写入的数据。

4.仿真

下面运用Modelsim和Vivado进行联合仿真,关于vivado怎么与modelsim进行联合仿真能够参阅这篇文章:

vivado与modelsim的相关以及器材库编译

有一点要留意的是,我用的是Vivado2017.1版别,这个版别只支撑Modelsim10.5及以上的版别,假如是低版别的Modelsim,在用Vivado2017.1编译Modelsim的仿真库时,会犯错。Modelsim10.5版别能够在这儿下载:

modelsim 10.5 适用vivado 2017.1

用Modelsim仿真时,会在sim_1/behav文件夹下发生3个.do文件,分别是xx_compile.do,xx_simulate.do,xx _wave.do文件。在规划的verilog文件修正之后,假如在Modelsim中直接restart,仿真的其实仍是没有修正前的文件,要使修正的.v文件在Modelsim中收效,能够在Modelsim的指令窗口输入do xx_compile.do文件,对仿真的库文件以及规划文件(.v文件)从头编译,然后在输入do xx_simulate.do文件,才干仿真修正后的文件。输入do xx_compile.do指令对规划文件从头编译的时分,Modelsim会强制退出,这时由最终一句force quit指令引起的,只要把它删掉就行了。假如要保存波形文件,能够save format,另存为xx_wave.do文件。

参阅上面双口RAM的例程3进行功用仿真,RAM IP运用Write First形式,规划文件代码如下:

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

// Company:

// Engineer:

//

// Create Date: 2017/12/09 22:36:48

// Design Name:

// Module Name: dual_port_ram_demo

// Project Name:

// Target Devices:

// Tool Versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 – File Created

// Additional Comments:

//

//////////////////////////////////////////////////////////////////////////////////

moduledual_port_ram_demo(

input USER_CLK

);

`define DLY #1

//Port A declaration

reg FPGA_Enable=0;

reg FPGA_Write_Enable=0;

reg[31:0] FPGA_Address=0;

reg[31:0] FPGA_Write_Data=0;

reg[31:0] FPGA_Read_Data_reg=0;

wire[31:0] FPGA_Read_Data;

//Port B declaration

reg enb=0;

reg[3:0] web=4’h0;

reg[31:0] addrb=0;

reg[31:0] dinb=0;

reg[31:0] doutb_reg=0;

wire[31:0] doutb=0;

reg[10:0] count=0;

always @ (posedge USER_CLK)

begin

count 《= count +1;

if(count《=100)

begin

FPGA_Enable 《=1;

FPGA_Write_Enable 《=0;

end

elseif((count 《=105)&&(count 》100))

begin

FPGA_Enable 《=1;

FPGA_Write_Enable 《=1;

FPGA_Address 《= FPGA_Address +4;

FPGA_Write_Data 《= FPGA_Write_Data +1;

end

elseif((count 《=110)&&(count 》105))

begin

FPGA_Enable 《=1;

FPGA_Write_Enable 《=0;

FPGA_Address 《=0;

FPGA_Write_Data 《=0;

end

elseif((count 《=117)&&(count 》110))

begin

FPGA_Enable 《=1;

FPGA_Write_Enable 《=1;

FPGA_Read_Data_reg 《= FPGA_Read_Data;

FPGA_Address 《= FPGA_Address +4;

end

elseif(count ==118)

begin

FPGA_Enable 《=0;

count 《= count;

end

end

dpRAMu1 (

.clka(USER_CLK), // input clka

.ena(FPGA_Enable), // input ena

.wea(FPGA_Write_Enable), // input [3 : 0] wea

.addra(FPGA_Address), // input [31 : 0] addra

.dina(FPGA_Write_Data), // input [31 : 0] dina

.douta(FPGA_Read_Data), // output [31 : 0] douta

.clkb(USER_CLK), // input clkb

.enb(enb), // input enb

.web(web), // input [3 : 0] web

.addrb(addrb), // input [31 : 0] addrb

.dinb(dinb), // input [31 : 0] dinb

.doutb(doutb) // output [31 : 0] doutb

);

endmodule

testbench文件如下:

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

// Company:

// Engineer:

//

// Create Date: 2017/12/09 22:47:26

// Design Name:

// Module Name: simu

// Project Name:

// Target Devices:

// Tool Versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 – File Created

// Additional Comments:

//

//////////////////////////////////////////////////////////////////////////////////

modulesimu(

);

//testbench 时钟信号

reg clk =0;

always # 10 clk 《=~clk;

//调用dual_port_ram_demo模块

dual_port_ram_demodemo1(clk);

endmodule

仿真成果如下:

双口RAM概述及Vivado RAM IP核运用

(图4.1)

程序在1时间准备好地址和要写入RAM的数据,在2时间写入RAM中,在3时间端口才会输出2时间写入RAM的数据,留意与PG058的图稍有不同。

双口RAM概述及Vivado RAM IP核运用

(图4.2)

4.跋文

关于BRAM,引荐一个youtube视频,里边讲的十分明晰易懂。

What is a Block RAM in an FPGA?

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/biancheng/340964.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部