CrazyBingo

完美SRAM架构

0
阅读(3485)

完美SRAM架构

今天又有人讨教我SRAM。。。话说SRAM我写过很多次,但是一直没觉得完美。。好吧 那就浪费几个小时,完善一下架构。。。哎、、、、、

封装好接口将在最后给出!!!

 

//---------------------------------
//Sram control signal default
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		sram_cs_n	=	1'b1;		//默认关闭
		sram_ub_n	=	1'b1;		//默认关闭
		sram_lb_n	=	1'b1;		//默认关闭
		sram_oe_n	=	1'b1;		//默认关闭
		end
	else
		begin
		sram_cs_n	=	1'b0;		//sram 片选始终有效
		sram_ub_n	=	1'b0;		//sram 高8位数据始终有效
		sram_lb_n	=	1'b0;		//sram 低8为数据始终有效
		sram_oe_n	=	1'b0;		//sram 输出始终有效
		end
end


这部分是SRAM读写工作信号的默认状态控制,当然也可以直接置低,这样写只是为了更完美!

注意:由于SRAM前端输入采用同步设计,因此直接判断sram_wr_en或者sram_rd_en信号,而对双向的sram_data,也需要同步了,主要通过一下电路实现:


assign sram_data = (~sram_we_n) ? sram_din_sync : 16'hz;

Sram_din_sync为同步后的写入数据,否则会有一个数据的时间差。具体代码如下所示:



//---------------------------------
reg	[15:0]	sram_din_sync;
//sram write and read timing
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		sram_addr <= 18'h0;	//default address
		sram_we_n <= 1'b1;	//default read
		sram_din_sync <= 0;
		sram_dout <= 0;
		end
	else if(sram_wr_en)		//write data
		begin
		sram_addr <= sram_wraddr;
		sram_we_n <= 1'b0;
		sram_din_sync <= sram_din;
		sram_dout <= sram_dout;	//keep the value
		end
	else if(sram_rd_en)		//read data
		begin
		sram_addr <= sram_rdaddr;
		sram_we_n <= 1'b1;
		sram_din_sync <= 0;
		sram_dout <= sram_data;
		end
	else
		begin
		sram_addr <= 18'h0;
		sram_we_n <= 1'b1;	//default read
		sram_din_sync = 0;
		sram_dout <= sram_dout;	//keep the value
		end
end
assign	sram_data = (~sram_we_n) ? sram_din_sync : 16'hz;


wps_clip_image-32396

如上图所示,快速写入,慢速读取。在LED显示测试中,50MHz写入,0.5s间隔读取!



以上实现的是Sram的封装后的接口分析,实际工作中,只要对以下几个信号操作即可,如下:

wps_clip_image-20125

Sram_wr_en :写使能信号,

Sram_wraddr :写地址

Sram_din :写数据

这三者保持完全同步!

wps_clip_image-28906

Sram_rd_en : 读使能信号

Sram_rdaddr : 读地址

Sram_dout : 读数据

这三者保持完全同步

Sram_dout 便是读出的数据!

其实,sram_dout的读取,最后实在sram_addr中间,才是稳态。。。。呵呵,只是速度低的话,不用考虑了。。。。

wps_clip_image-19123



最后,还是给个读写的例子吧:data_generate如下:


/*-------------------------------------------------------------------------
CONFIDENTIAL IN CONFIDENCE
This confidential and proprietary software may be only used as authorized
by a licensing agreement from CrazyBingo (Thereturnofbingo).
In the event of publication, the following notice is applicable:
Copyright (C) 2011-201x CrazyBingo Corporation
The entire notice above must be reproduced on all authorized copies.
Author				:		CrazyBingo
Technology blogs 	: 		http://blog.chinaaet.com/crazybingo
							http://www.cnblogs.com/crazybingo
Eamil Address 		: 		thereturnofbingo@gmail.com
Filename			:		data_generate.v
Data				:		2013-05-05
Version				:		1.0
Description			:		Simulate data read or write sram.
Modification History	:
Data			By			Version			Change Description
===========================================================================
13/05/05		CrazyBingo	1.0				Original
--------------------------------------------------------------------------*/
`timescale 1ns/1ns

module	data_generate
(	
	input				clk,
	input				rst_n,
	
	//sram 控制器接口
	output	reg	[17:0]	sram_wraddr,	//sram 写地址寄存器
	output	reg	[15:0]	sram_din,		//sram 输入数据暂存器
	output				sram_wr_en,		//sram 写请求,高有效,优先级高
	output	reg	[17:0]	sram_rdaddr,	//sram 读地址寄存器
//	input		[15:0]	sram_dout,		//sram 数据输出暂存器
	output				sram_rd_en		//sram 读请求,低有效
);


//------------------------------------------
//读取计数模块
reg	[23:0]	cnt;	//0.5s
reg	[2:0]	state;
localparam	[23:0]	DELAY_TOP = 24'h1fffff;
//localparam	[23:0]	DELAY_TOP = 24'h7;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cnt <= 0;
	else if(state == 3'd2 || state == 3'd3)
		if(cnt < DELAY_TOP)
			cnt <= cnt + 1'b1;
		else
			cnt <= 0;
	else
		cnt <= 0;
end
wire	delay_05s = (cnt == DELAY_TOP) ? 1'b1 : 1'b0;

//-----------------------------------------
//读写测试模块状态机
parameter	DATA_LEDGTH = 8'd255;	//读写长度
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		sram_wraddr <= 0;
		sram_din <= 0;
		sram_rdaddr <= 0;
		state <= 0;
		end
	else
		begin
		case(state)
		3'd0:	state <= 3'd1;	//初始化
		3'd1:	begin	//写入DATA_LEDGTH个数据
				if(sram_wraddr < DATA_LEDGTH)	
					begin
					sram_wraddr <= sram_wraddr + 1'b1;
					sram_din <= sram_din + 1'b1;
					state <= 3'd1;
					end
				else	//写入完毕
					begin
					sram_wraddr <= 0;
					sram_din <= 0;
					state <= 3'd2;
					end
				end
		3'd2:	begin
				if(delay_05s)
					state <= 3'd3;	//Delay
				else
					state <= 3'd2;
				end
		3'd3:	begin	//读取入DATA_LEDGTH个数据,0.5s Delay
				if(delay_05s)
					begin
					if(sram_rdaddr < DATA_LEDGTH)	
						begin
						sram_rdaddr <= sram_rdaddr + 1'b1;
						state <= 3'd3;
						end
					else	//写入完毕
						begin
						sram_rdaddr <= 0;
						state <= 3'd4;
						end
					end
				else
					begin
					sram_rdaddr <= sram_rdaddr;
					state <= state;
					end
				end
		3'd4:;
		default:;
		endcase
		end
end

assign	sram_wr_en = (state == 3'd1) ? 1'b1 : 1'b0;
assign	sram_rd_en = (state == 3'd3) ? 1'b1 : 1'b0;

endmodule

谨记有个东西叫做modelsim!!!

不要轻易相信自己的眼睛—黄继业!!!!!