赞
踩
双口 RAM IP 核有两个端口,它又分为伪双端口 RAM 和真双端口 RAM,伪双端口 RAM 一个端口只能读,另一个端口只能
写,真双端口 RAM 两个端口都可以进行读写操作。同时对存储器进行读写操作时就会用到双端口 RAM,例如有一个 FIFO 存储器,需要同时对其进行数据的写入和读出,这时候就需要一个写端口和一个读端口。
BMG IP 核配置成简单双端口 RAM 的框图如下图所示:
它有两组独立的端口 A 和 B,其中 A 端口只能提供了 DINA 数据总线,只能进行写操作,B 端口只提供了 DOUTB 数据总线,只能进行读操作,此外它相当于单口 RAM 还多出了以下信号线(在常规使用中一般不会关注这些信号线):
BMG IP 核配置成真双端口RAM 的框图如下图所示:
它有两组独立的端口 A 和 B,且每组端口都可进行读写操作。
通过对比可以发现无论是哪种双端口 RAM,其地址线、时钟线、使能线都有两组,所以双端口 RAM 可以实现在不同时钟域下的读/写,且可以同时对不同的地址进行读/写,这便大大提高了我们数据处理的灵活性。
写-写冲突:当两个端口都试图向同一个地址写数据(即两个端口写使能同时有效且写地址相同)时则会产生写-写冲突,发生写-写冲突后对应内存地址的数据为未知。
读-写冲突:一个端口进行读取数据操作,另一个端口进行写入数据操作,当同时操作到同一地址时就会发生读-写冲突,此时如果:
Block Memory Generator IP核的 IP Catalog 窗口如下,主要包括一个IP名称输入框核5个选项卡,下面依次进行介绍。
本次实验的用 Xilinx BMG IP 核配置成一个伪装双口 RAM 并对其进行读写操作,系统框图如下:
大多数情况下伪双口 RAM 都已经满足使用需求,入跨时钟域传输数据、存储数据、FIFO等,所以这里以伪双口 RAM 为例。
伪双口 RAM IP 核的配置如下:
在伪双口 RAM IP读写代码先例化一个伪双口 RAM IP核,在复位完成后开始通过 Port A 周期写入数据,当第一次写入到一半时启动 Port B 进行周期读数据,波形图如下:
module ram_ip_rw( input sys_clk, input sys_rst_n ); //端口 A 时钟 wire clka; //端口 A 使能,高电平使能 reg ena; //端口 A 写使能,高电平写入 reg wea; //端口 A 地址 reg [5:0]addra; //写入端口 A 的数据 wire [7:0]dina; //端口 B 时钟 wire clkb; //端口 B 使能,高电平使能 reg enb; //端口 B 地址 reg [5:0]addrb; //端口 B 读出的数据 wire [7:0]doutb; //端口 A 时钟 assign clka = sys_clk; //端口 A 使能 always @(posedge sys_clk) begin if(!sys_rst_n) ena <= 0; else ena <= 1; end //端口 A 写使能 always @(posedge sys_clk) begin if(!sys_rst_n) wea <= 0; else wea <= 1; end //端口 A 地址,0~63 always @(posedge sys_clk) begin if(!sys_rst_n) addra <= 0; else if((addra < 63) && (wea == 1)) addra <= addra + 1; else addra <= 0; end //端口 A 写入数据,从地址0~63依次写入如0~63 assign dina = (wea == 1) ? addra : 0; //端口 B 时钟 assign clkb = sys_clk; //端口 B 使能 always @(posedge sys_clk) begin if(!sys_rst_n) enb <= 0; else if(addra == 31) enb <= 1; end //端口 B 地址,0~63 always @(posedge sys_clk) begin if(!sys_rst_n) addrb <= 0; else if((addrb < 63) && (enb == 1)) addrb <= addrb + 1; else addrb <= 0; end //例化伪双口RAM IP核 blk_mem_gen_0 u_blk_mem_gen_0_inst0( .clka(clka), .ena(ena), .wea(wea), .addra(addra), .dina(dina), .clkb(clkb), .enb(enb), .addrb(addrb), .doutb(doutb) ); endmodule
仿真激励代码非常简单,只需要例化 单口 RAM IP读写模块 ,然后产生一个周期时钟即可,完整的代码如下:
module tb_ram_ip_rw( ); reg sys_clk; //系统时钟 reg sys_rst_n; //系统复位,低电平有效 //信号初始化 initial begin sys_clk = 1'b0; sys_rst_n = 1'b0; #200 sys_rst_n = 1'b1; end //产生时钟 always #20 sys_clk = ~sys_clk; //例化需要仿真的IP核 ram_ip_rw tb_u_ram_ip_rw_inst0( .sys_clk(sys_clk), //系统时钟 .sys_rst_n(sys_rst_n) //系统复位,低电平有效 ); endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。