完美SRAM架构
0赞完美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;
如上图所示,快速写入,慢速读取。在LED显示测试中,50MHz写入,0.5s间隔读取!
以上实现的是Sram的封装后的接口分析,实际工作中,只要对以下几个信号操作即可,如下:
Sram_wr_en :写使能信号,
Sram_wraddr :写地址
Sram_din :写数据
这三者保持完全同步!
Sram_rd_en : 读使能信号
Sram_rdaddr : 读地址
Sram_dout : 读数据
这三者保持完全同步
Sram_dout 便是读出的数据!
其实,sram_dout的读取,最后实在sram_addr中间,才是稳态。。。。呵呵,只是速度低的话,不用考虑了。。。。
最后,还是给个读写的例子吧: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!!!
不要轻易相信自己的眼睛—黄继业!!!!!