上文对BMG ip的基本情况进行了简单的描述,本文通过例化仿真来实际使用功能一下这个IP。
首先使用简单双端口BRAM实现一个简单的跨时钟域操作:将16bit的a时钟域的数据跨到b时钟域,b时钟频率是a时钟频率的一半,为了操作方便,直接将b数据位宽扩展到32bit(这样就不用增加控制信息,数据流是满的)。BMG IP输入输出位宽比支持:1:32, 1:16, 1:8, 1:4, 1:2, 1:1, 2:1, 4:1, 8:1, 16:1, 32:1.位宽变换时BMG的AB端口数据映射关系如下:

例化一个简单的ip,设置如下。这里选择简单双端口模式的本地接口,采用面积最小原则,端口A为16bit,深度为16,ram大小就是16*16bit,控制信号就使用ENA。对于端口B,将位宽设置为32bit,此时深度自动变换为8,使用写优先模式,同样使能ENB端口作为控制端口。



这里对续写模式再做一个简单的说明,支持WRITE_FIRST, READ_FIRST或NO_CHANGE三种模式,这三种模式的读写时序如下图所示。



WRITE_FIRST模式下,写优先级最高,同一地址,一旦写入,数据直接会透传到输出端。READ_FIRST模式,数据输出端口会锁存输出数据,有数据写入时,输出数据是上一次的数据。NO_CHANGE模式下,在写使能拉高后,输出将保持开始拉高时刻的数据,保持不变。注意这三种模式针对的是单端口,即端口A或者B。
编写一个简单的仿真测试代码如下:
// ============================================================
// File Name: tb_blk_mem_gen_sdp
// VERSION : V1.0
// DATA : 2023/8/5
// Author : FPGA干货分享
// ============================================================
// 功能:xilinx blk_mem_gen_sdp ip 代码仿真
// 使用简单双端口实现一个简单的跨时钟域
// delay :
// ============================================================
`timescale 1ns/100ps
module tb_blk_mem_gen_sdp ;
reg clka = 'd0 ;
reg ena = 'd1 ;
reg [0 : 0] wea = 'd1 ;
reg [3 : 0] addra = 'd0 ;
reg [15 : 0] dina = 'd0 ;
reg clkb = 'd0 ;
reg enb = 'd1 ;
reg [2 : 0] addrb = 'd0 ;
wire [31 : 0] doutb ;
reg [2:0] S_addr_a_flag ='d0 ;
reg S_a_flag ='d0 ;
reg [2:0] S_a_flag_2_b ='d0 ;
reg S_b_flag ='d0 ;
reg [2:0] S_clk_cnt8 ='d3 ;
always #1 clka = ~clka;
always #2 clkb = ~clkb;
//----------- clk_a ---//
always @(posedge clka)
if(ena && wea)
begin
addra <= addra + 'd1;
dina <= dina + 'd1;
end
always @(posedge clka)
S_addr_a_flag[0] <= (addra == 4'd10);
always @(posedge clka)
S_addr_a_flag[2:1] <= S_addr_a_flag[1:0] ;
always @(posedge clka)
S_a_flag <= |S_addr_a_flag ;
//----------- clk_b ---//
always @(posedge clkb)
S_a_flag_2_b <= {S_a_flag_2_b[1:0],S_a_flag} ;
always @(posedge clkb)
S_b_flag <= (!S_a_flag_2_b[2])&& S_a_flag_2_b[1] ;
always @(posedge clkb)
if((S_clk_cnt8 > 3'd2)&&S_b_flag)
S_clk_cnt8 <= 3'd2;
else
S_clk_cnt8 <= S_clk_cnt8 + 'd1;
always @(posedge clkb)
if(S_clk_cnt8 == 3'd1)
addrb <= 'd0;
else
addrb <= addrb + 'd1;
//----------- Begin Cut here for INSTANTIATION Template ---//
blk_mem_gen_sdp blk_mem_gen_sdp (
.clka (clka ), // input wire clka
.ena (ena ), // input wire ena
.wea (wea ), // input wire [0 : 0] wea
.addra (addra ), // input wire [3 : 0] addra
.dina (dina ), // input wire [15 : 0] dina
.clkb (clkb ), // input wire clkb
.enb (enb ), // input wire enb
.addrb (addrb ), // input wire [2 : 0] addrb
.doutb (doutb ) // output wire [31 : 0] doutb
);
endmodule
仿真结果如下:clkb时钟频率是clka时钟频率的一半,dataa数据位宽16bit,datab数据位宽32bit,输入输出均为满速率,同时在代码中增加了防抖保护措施,防止跨时钟域中因为出现时钟抖动而产生的数据异常问题。

以上就是Xilinx Block Memory Generator(BMG) IP的仿真。
-
FPGA
+关注
关注
1656文章
22288浏览量
630394 -
Xilinx
+关注
关注
73文章
2192浏览量
129969 -
仿真
+关注
关注
53文章
4408浏览量
137677 -
时钟
+关注
关注
11文章
1953浏览量
134561
发布评论请先 登录
XILINX FPGA IP之Clocking Wizard详解
XILINX FPGA IP之MMCM PLL DRP时钟动态重配详解
Xilinx FPGA IP之Block Memory Generator AXI接口说明
Distributed Memory Generator IP核简介
XILINX FPGA IP之AXI Traffic Generator

Xilinx FPGA IP之Block Memory Generator仿真
评论