【verilog】 Vivado-Simple Dual-Port RAM IP的使用(Xilinx FPGA,双口RAM,IP使用)

本文档介绍了如何在Vivado 2019.2中配置一个双口RAM的IP核,详细阐述了IP核的A端口和B端口功能,以及它们的时钟独立特性。同时,给出了IP的例化顶层模块代码,并展示了针对A端口写入和B端口读出的测试用例,通过两个always块分别控制写入和读取操作。测试中模拟了不同的地址和数据写入读出过程,以验证双口RAM的正确功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单双口RAM的IP核

在这里插入图片描述
分A端口和B端口
A为输入端口,负责数据的写入
B端口为输出端口,负责数据的读出
两端的时钟可以不同,还允许在写入A的同时读B。

配置IP

vivado 2019.2
IP catalog -> Memories & Storage Elements -> RAMs & ROMs & BRAM -> …
在这里插入图片描述

例化顶层

module top(
  input clka,
  input wea,
  input [9:0]addra,
  input [15:0]dina, 

 input clkb,
 input [9:0] addrb,
 output [15:0] doutb
    );
    
blk_mem_gen_0 u1 (  
  .clka(clka),
  .wea(wea), 
  .addra(addra), 
  .dina(dina), 

  .clkb(clkb), 
  .addrb(addrb),
  .doutb(doutb) 
); 
endmodule

测试

主要内容为两个alwas块,一个负责操作Aport,另一个负责操作Bport

`timescale 1ns / 1ps
module tb_dram(); 

reg clk; //cha/chb common clk
reg rst_n;

//chnl a
reg cha_write_en;  
reg[15:0] cha_data;  
reg[9:0] sdpram_addr_cha;  
//chnl b
wire[15:0] chb_data;  
reg[9:0] sdpram_addr_chb;  
reg [15:0] data1;
reg [15:0] data2;
reg [15:0] data3;

//state chicken
reg[10:0] cnta_state;
reg[10:0] cntb_state;


//cha:data input chnl
//对ram进行写操作,在选择地址的同时给予数据。
always @ (posedge clk or negedge rst_n)  
begin
    if(!rst_n)begin
    	cnta_state <= 1'b0;
	cha_write_en <=1'b0;  
	sdpram_addr_cha <= 10'd0;
	cha_data <= 16'd0;
    end
    else begin
	case(cnta_state)
	0,1,2,3,4,5,6,7,8,9:cnta_state <= cnta_state + 1'b1;
	10:begin cha_write_en <= 1'b1;sdpram_addr_cha <= 10'd1;cha_data <= 16'h5555;
	         cnta_state <= cnta_state + 1'b1;
	   end	
	11:begin cha_write_en <= 1'b1;sdpram_addr_cha <= 10'd2;cha_data <= 16'haaaa;
	         cnta_state <= cnta_state + 1'b1;
           end
	12:begin cha_write_en <= 1'b1;sdpram_addr_cha <= 10'd3;cha_data <= 16'hcccc;
	         cnta_state <= cnta_state + 1'b1;
           end
	default:begin
    		 cnta_state <= 10'd13;
		 cha_write_en <=1'b0;  
		 sdpram_addr_cha <= 10'd0;
		 cha_data <= 16'd0;
    	   end
        endcase	
   end
end

//chb:data output chnl
//对ram做读操作,与写操作不同。
//读操作需要等2个clk才能在dout上输出选定地址的有效数据
//配置地址 -> 时序逻辑延迟经过一个clk才成功写入 -> 再过一个clk ->有效数据
always @ (posedge clk or negedge rst_n)  
begin
    if(!rst_n)begin
    	cntb_state <= 1'b0;
	data1 <= 1'b0;
	data2 <= 1'b0;
	data3 <= 1'b0;
	sdpram_addr_chb <= 10'd0;
    end
    else begin
	case(cntb_state)
	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19:
		 cntb_state <= cntb_state + 1'b1;
	20:begin sdpram_addr_chb <= 10'd1;        //选择地址1
	         cntb_state <= cntb_state + 1'b1;
	   end	
	21:begin  sdpram_addr_chb <= 10'd2;        //选择地址2
	          cntb_state <= cntb_state + 1'b1;
           end
	22:begin data1 <= chb_data;          //寄存地址1上吐出的数据
		 sdpram_addr_chb <= 10'd3;        //选择地址3
	         cntb_state <= cntb_state + 1'b1;
           end
	23:begin data2 <= chb_data;          //寄存地址2上吐出的数据
	         cntb_state <= cntb_state + 1'b1;
           end
	24:begin data3 <= chb_data;          //寄存地址3上吐出的数据
	         cntb_state <= cntb_state + 1'b1;
           end
	default:begin
    		 cntb_state <= 10'd24;
		 sdpram_addr_chb <= 10'd0;
    	   end
        endcase	
   end
end


initial begin clk = 0; rst_n = 0; #50; rst_n = 1'b1; end
initial begin #600; $stop(); end
always # 10 clk = ~clk;


top u2 (  
  .clka(clk), // input clka  
  .wea(cha_write_en), // input [3 : 0] wea  
  .addra(sdpram_addr_cha), // input [31 : 0] addra  
  .dina(cha_data), // input [31 : 0] dina  
    
  .clkb(clk), // input clkb  
  .addrb(sdpram_addr_chb), // input [31 : 0] addrb  
  .doutb(chb_data) // output [31 : 0] doutb  
); 
endmodule

波形

在这里插入图片描述

### Vivado IPRAM 使用详解 #### 单端口 RAM 配置 在 Vivado 中创建单端口 RAM (Single Port RAM),可以通过 IP Catalog 完成配置。选择合适的参数,如存储深度、数据宽度等,完成这些设置后生成 IP 核并将其加入到项目中[^1]。 ```verilog // Verilog 代码片段展示如何实例化单端口 RAM 模块 module single_port_ram ( input wire clk, input wire we, // Write enable signal input wire [7:0] din,// Data input bus width of 8 bits output reg [7:0] dout,// Data output bus width matches the data input input wire [9:0] addr // Address line with a suitable bit-width to cover all addresses ); always @(posedge clk) begin if(we) ram[addr] <= din; dout <= ram[addr]; end reg [7:0] ram [(2**10)-1:0]; // Define an array representing memory cells endmodule ``` #### 双端口 RAM 设置 对于简单双端口 RAM (Simple Dual Port RAM),除了将 `Memory Type` 设定为 “Simple Dual Port RAM”,其他选项基本保持一致。这种类型的 RAM 支持两个独立的数据访问通道,在同一时间可以从不同端口执行读/写操作而不发生冲突[^2]。 #### 处理读写冲突 当存在潜在的读写竞争条件时——即尝试在同一周期内向相同位置既读又写的场景下,默认情况下返回的是先前已存入该地址处的内容;然而具体行为可能依赖于所选器件及其内部实现细节[^4]。 #### 测试与验证 为了确保集成后的 RAM 功能正常工作,建议编写测试平台来进行仿真测试。这有助于确认设计满足预期性能指标,并能及时发现任何逻辑错误或不兼容之处[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞IC的那些年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值