IP - SRAM

1. 目的及意义

CPU、存储、总线、外设看起来很平常,但是在构建系统时,并非可以很容易获取;
IP:
组件标准化、复用很有意义;
IP需要一定的业界水准;
IP精心设计,需要能够支持不同设计需求,因而要具备一定的可配置性;;
需要配备完整的验证方案、集成流程和文档;
千层之台起于累土,本博将基于组件,构建一个完整系统,从RTL到GDS的例子。

2. 设计与实现

头文件:

// ============================================================================
//               Copy Right Chip, All Rights Reserved
//
// File: dp_sram_model_define.v
//
// Description:
//     top tb of dp_sram_model.v
//
// Relation:
//
// Revision:
//     v0.0: Initial version: debug memory?
//           Chip,2015/6/6.
//
// ============================================================================

// ----------------------------------------------------------------------------
// 1. for design
// ----------------------------------------------------------------------------

`define ADDR_WIDTH 4
`define DATA_WIDTH 8

// ----------------------------------------------------------------------------
// 2. for sim
// ----------------------------------------------------------------------------

// `timescale 1ns/1ps

`define CLK_CYC  20
`define SIM_TIME 3000

参数化有利于信息管理和设计可配置。

 

设计文件:

// ============================================================================
//               Copy Right Chip, All Rights Reserved
//
// File: dp_sram_model.v
//
// Description:
//     dual port sram sim model
//
// Relation:
//
// Revision:
//     v0.0: Initial version: function,format,parameter.
//            Chip,2015/6/6.
//     ToDo: 
//     	   1. sync/async;
//         2. rst;
//         3. initial for fastsim;
//         4. bit mask;
//         5. deal with r/w confilct;
//         6. single port/two port;
//         7. write through;
//         8. more real just like fundry IP does;          
//
// ============================================================================

// ----------------------------------------------------------------------------
// 1. include
// ----------------------------------------------------------------------------

`include "dp_sram_model_define.v"

// ----------------------------------------------------------------------------
// 2. port
// ----------------------------------------------------------------------------

module dp_sram_model
(   // glb sig
	input                    rst_n,
	input                    clk,

	// rd port
	input                    rd,	
	input  [`ADDR_WIDTH-1:0] rd_addr,
	output [`DATA_WIDTH-1:0] rd_data,
	
	// wr port
	input                    wr,
	input  [`ADDR_WIDTH-1:0] wr_addr,
	input  [`DATA_WIDTH-1:0] wr_data
);

// ----------------------------------------------------------------------------
// 3. wire/reg
// ----------------------------------------------------------------------------

parameter num_units = 2 << (`ADDR_WIDTH-1); // NOTEME: 2^`ADDR_WIDTH,  ^ is xor;

reg [`DATA_WIDTH-1:0] mem [num_units-1:0];// NOTEME: 1, unit width; 2,num of units;

// ----------------------------------------------------------------------------
// 4. main logic
// ----------------------------------------------------------------------------

// rd
assign rd_data = rd ? mem[rd_addr] : `DATA_WIDTH'bz; // FIXME: preserve? wr through?

// wr
always @( posedge clk )                              // FIXME: com logic?
if ( wr )
    mem[wr_addr] = wr_data;
else;

endmodule

// ============================================================================
// File End
// ============================================================================


3. 测试和验证

testbench:

// ============================================================================
//               Copy Right Chip, All Rights Reserved
//
// File: dp_ram_model_tb.v
//
// Description:
//     top tb of dp_sram_model.v
//
// Relation:
//
// Revision:
//     v0.0: Initial version;
//           Chip,2015/6/6.
//     ToDo: for gen test data and auto check
//
// ============================================================================

// ----------------------------------------------------------------------------
// 1. include
// ----------------------------------------------------------------------------

`include "dp_sram_model_define.v"

// ----------------------------------------------------------------------------
// 2. port
// ----------------------------------------------------------------------------

module dp_sram_model_tb;

// ----------------------------------------------------------------------------
// 3. wire/reg
// ----------------------------------------------------------------------------

// port connections
reg                    rst_n;
reg                    clk;

reg                    rd;
reg  [`ADDR_WIDTH-1:0] rd_addr;
wire [`DATA_WIDTH-1:0] rd_data;

reg                    wr;
reg  [`ADDR_WIDTH-1:0] wr_addr;
reg  [`DATA_WIDTH-1:0] wr_data;

// test data
//integer i;
parameter num_units = 2 << (`ADDR_WIDTH-1);
reg [`DATA_WIDTH-1:0] test_data [num_units-1:0];

// ----------------------------------------------------------------------------
// 4. DUT
// ----------------------------------------------------------------------------

dp_sram_model u_dp_sram_model
(
	.rst_n     ( rst_n        ),
	.clk       ( clk          ),

	.rd        ( rd           ),	
	.rd_addr   ( rd_addr      ),
	.rd_data   ( rd_data      ),

	.wr        ( wr           ),
	.wr_addr   ( wr_addr      ),
	.wr_data   ( wr_data      )
);

// ----------------------------------------------------------------------------
// 5. tasks
// ----------------------------------------------------------------------------

// FIXME cnt

// init
task dp_sram_init;
    begin // NOTEME: begin-end is necessary in task
		@( posedge clk ) $display("\nVVVVVV: init");
		// initi X
		#`CLK_CYC     wr = 0; wr_addr = 0; wr_data = 0; 
		              rd = 0; rd_addr = 0; rst_n = 0;
		#(`CLK_CYC/2) rst_n = 1;
	end
endtask

// wr task
task dp_sram_wr;
	input  [`ADDR_WIDTH-1:0] addr;
	input  [`DATA_WIDTH-1:0] data;

	begin // NOTEME: posedge clk, 1 unit before clk rise
		@( posedge clk ) $display("\nVVVVVV: wr");
		#(`CLK_CYC-1) wr_addr = addr; wr_data = data;
		#`CLK_CYC     wr = 1;
		#`CLK_CYC     wr = 0; wr_data = 0;
	end
endtask

// rd task
task dp_sram_rd;
	input  [`ADDR_WIDTH-1:0] addr;
	// output [7:0] data;
	
    begin
		@( posedge clk ) $display("\nVVVVVV: rd");
		#(`CLK_CYC-1) rd_addr = addr; 
		#`CLK_CYC     rd = 1;
		// #1  data = rd_data;
		#`CLK_CYC     rd = 0;
	end
endtask

// ----------------------------------------------------------------------------
// 6. stimulus
// ----------------------------------------------------------------------------

// rst,not used

// clk
initial begin
    #`CLK_CYC;
	#`CLK_CYC clk = 1'b0;
	forever #(`CLK_CYC/2) clk = !clk; // NOTEME: without delay, sim go to dead loop!
end

// generate test data
/*
genvar i; //integer i;
for ( i=0; i<=num_units; i=i+1 )
	test_data[i] <= `DATA_WIDTH'h0f + i<<4;
*/

// rd/wr, FIXME: replace with task?
initial begin
	// init
	dp_sram_init();

	// wr
	dp_sram_wr(`ADDR_WIDTH'h1,`DATA_WIDTH'h1f);
	dp_sram_wr(`ADDR_WIDTH'h2,`DATA_WIDTH'h2f);
	dp_sram_wr(`ADDR_WIDTH'h3,`DATA_WIDTH'h3f);
	dp_sram_wr(`ADDR_WIDTH'h4,`DATA_WIDTH'h4f);

	dp_sram_wr(`ADDR_WIDTH'h5,`DATA_WIDTH'h5f);
	dp_sram_wr(`ADDR_WIDTH'h6,`DATA_WIDTH'h6f);
	dp_sram_wr(`ADDR_WIDTH'h7,`DATA_WIDTH'h7f);
	dp_sram_wr(`ADDR_WIDTH'h8,`DATA_WIDTH'h8f);

	dp_sram_wr(`ADDR_WIDTH'h9,`DATA_WIDTH'h9f);
	dp_sram_wr(`ADDR_WIDTH'ha,`DATA_WIDTH'haf);
	dp_sram_wr(`ADDR_WIDTH'hb,`DATA_WIDTH'hbf);
	dp_sram_wr(`ADDR_WIDTH'hc,`DATA_WIDTH'hcf);

	dp_sram_wr(`ADDR_WIDTH'hd,`DATA_WIDTH'hdf);
	dp_sram_wr(`ADDR_WIDTH'he,`DATA_WIDTH'hef);
	dp_sram_wr(`ADDR_WIDTH'hf,`DATA_WIDTH'hff);
	dp_sram_wr(`ADDR_WIDTH'h0,`DATA_WIDTH'h0f);

	// rd
	dp_sram_rd(`ADDR_WIDTH'hf);
	dp_sram_rd(`ADDR_WIDTH'he);
	dp_sram_rd(`ADDR_WIDTH'hd);
	dp_sram_rd(`ADDR_WIDTH'hc);

	dp_sram_rd(`ADDR_WIDTH'hb); // FIXME: 'dp_sram_rd' is not a function name.
	dp_sram_rd(`ADDR_WIDTH'ha);
	dp_sram_rd(`ADDR_WIDTH'h9);
	dp_sram_rd(`ADDR_WIDTH'h8);

	dp_sram_rd(`ADDR_WIDTH'h7);
	dp_sram_rd(`ADDR_WIDTH'h6);
	dp_sram_rd(`ADDR_WIDTH'h5);
	dp_sram_rd(`ADDR_WIDTH'h4);

	dp_sram_rd(`ADDR_WIDTH'h3);
	dp_sram_rd(`ADDR_WIDTH'h2);
	dp_sram_rd(`ADDR_WIDTH'h1);
	dp_sram_rd(`ADDR_WIDTH'h0);

	//  FIXME: check ?
end

// ----------------------------------------------------------------------------
// 7. output/check
// ----------------------------------------------------------------------------

// monitor
/*
initial begin
	@(posedge clk)
		$monitor("clk=%b, rd=%b, rd_addr=%h, rd_data=%h; wr=%b, wr_addr=%h, wr_data=%h", 
				  clk,rd,rd_addr,rd_data,wr,wr_addr,wr_data);
end
*/

// vcd
initial begin
	$dumpfile("dp_sram_model_tb.vcd");
	$dumpvars(0,"dp_sram_model_tb");
end

// fsdb
/*
initial begin
	$fsdbDumpfile("dp_sram_model_tb.vcd");
	$fsdbDumpvars(0,"dp_sram_model_tb");
end
*/

// overtime finish 
initial begin
    $display("\nVVVVVV: Simulation Start");
    #`SIM_TIME $display("\nVVVVVV:   End");
	#10        $finish(0);
end

endmodule

// ============================================================================
// File End
// ============================================================================


 

4. 后记

目前只是实现了一个dual port memory model,后续完善项目见设计文件文件头说明。

经验之谈,但一家之言;持续更新,欢迎探讨。

Vivado中的SRAM IP核是一种用于实现静态随机存储器(SRAM)功能的IP核。SRAM是一种常见的存储器类型,用于存储数据和指令。使用SRAM IP核可以简化在FPGA设计中集成SRAM的过程,并提高开发效率。 要创建自定义的SRAM IP核,可以按照以下步骤进行操作: 1. 打开Vivado工具并创建一个新的IP核项目。 2. 在IP核设计窗口中,选择“Create or Import IP”选项。 3. 在新建IP核的向导中,选择“Create Custom IP”选项,然后点击“Next”继续。 4. 在IP核设置页面,选择“Memory and Storage”类别,在列表中选择“SRAM”作为IP核的基本类型。 5. 根据需求,设置SRAM的参数,如存储位宽、存储深度和接口等。 6. 完成设置后,点击“Finish”按钮生成自定义的SRAM IP核。 创建完成后,可以在Vivado中使用这个自定义的SRAM IP核。通过将其添加到IP核库中,并在设计中引用它,可以在设计中使用SRAM的功能。需要注意的是,在使用封装好的IP核时,还需要将IP核文件添加到IP核库中。 总之,Vivado中的SRAM IP核是用于实现静态随机存储器功能的IP核,可以根据具体需求创建和使用自定义的SRAM IP核,以便于在FPGA设计中集成SRAM。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Vivado自定义IP核](https://blog.csdn.net/mengzaishenqiu/article/details/130048317)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值