异步SRAM控制器的Verilog建模
前言:sram顾名思义静态随机存储器,分为asram异步型和ssram同步型。这里驱动DE2上一块ISSI公司的512KB的asram。
设计思路:因为实际应用中单字节读写效率不高,所以本设计中仿照sdram的页突发读写,提高sram的效率。因为sram不像sdram需要定期刷新以及行列地址复用,因此省却很多麻烦。拿到手册以后主要关注的就是其最快运行时钟以及数据稳定的建立时间和保持时间,以及控制线的时间参数,这些参数可以由datasheet的时序参数的min time和max time确定,通过这些参数可以简化后续的读写的时序图。
注意事项:
(a)在读操作中,读指令有效到数据有效输出有一个CLK的延迟,即latency;
(b)为了避免读写操作过程中,数据与地址之间的时钟差,其中sys_data_o与sdram_data_r寄存器直接用latch建模,综合后出现的警告;
(c)模块时钟工作在100MHz,移植过程中pll视情况而定,pll工作于normal模式即可l;
总结:以上代码结果仿真和硬件测试,并未做超频测试。这里附出源码。
源码1:sram控制器
`timescale ns / ps
`define SIM
`define IS61LV25616AL_10TL
`define SYS_CLK
`define BURST
`define BURST_WIDTH
module sram_ctrl(
sys_clk,
sys_rst_n,
//read
sys_rd_addr_i,
rreq_i,
sys_data_o,
sram_rd_ack_o,
sram_rd_valid_o,
//write
wreq_i,
sys_wr_addr_i,
sys_data_i,
sram_wr_valid_o,
sram_wr_ack_o,
//sram
sram_ce_n,
sram_oe_n,
sram_we_n,
sram_lb_n,
sram_ub_n,
sram_addr,
sram_data
);
`ifdef IS61LV25616AL_10TL
`define DSIZE
`define ASIZE
`endif
input sys_clk;
input sys_rst_n;
//read
input [`ASIZE-:] sys_rd_addr_i;
input rreq_i;
output [`DSIZE-:] sys_data_o;
output sram_rd_ack_o;
output sram_rd_valid_o;
//write
input [`ASIZE-:] sys_wr_addr_i;
input wreq_i;
input [`DSIZE-:] sys_data_i;
output sram_wr_ack_o;
output sram_wr_valid_o;
//sram
output sram_ce_n;
output sram_oe_n;
output sram_we_n;
output sram_lb_n;
output sram_ub_n;
output [`ASIZE-:] sram_addr;
inout [`DSIZE-:] sram_data;
//command
parameter CMD_NOP = 'b01000,
CMD_READ = 'b10000,
CMD_WRITE = 'b00100;
reg [:] cmd_r = CMD_NOP;
assign {sram_we_n,sram_ce_n,sram_oe_n,sram_lb_n,sram_ub_n} = cmd_r;
//FSM PARAMS
`ifdef SIM
parameter ST_WIDTH = ;
parameter IDLE = "IDLE.",
READ = "READ.",
RD = "RD...",
END = "END..",
WR = "WR...";
`else
`define FSM
parameter ST_WIDTH = ;
parameter IDLE = `FSM'b0_0001,
READ = `FSM'b0_0010,
RD = `FSM'b0_0100,
END = `FSM'b0_1000,
WR = `FSM'b1_0000;
`endif
//capture the posedge of rreq
reg rreq_r = ;
always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) rreq_r <= 0;
else rreq_r <= rreq_i;
end
wire do_rreq = rreq_i & ~rreq_r;
//generate the rd_start signal
reg rd_start = ;
always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) rd_start <= 0;
else if(sram_rd_ack_o == 'b1) rd_start <= 0;
else if(do_rreq) rd_start <= ;
else rd_start <= rd_start;
end
//capture the posedge of wreq
reg wreq_r = ;
always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) wreq_r <= 0;
else wreq_r <= wreq_i;
end
wire do_wreq = wreq_i & ~wreq_r;
//generate the rd_start signal
reg wr_start = ;
always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) wr_start <= 0;
else if(sram_wr_ack_o == 'b1) wr_start <= 0;
else if(do_wreq) wr_start <= ;
else wr_start <= wr_start;
end
//FSM register
reg [`BURST_WIDTH-:] bit_cnt = ;
reg [ST_WIDTH-:] c_st = IDLE;
reg [ST_WIDTH-:] n_st = IDLE;
reg link = ; //0:read while 1:write reg [`ASIZE-:] sram_addr = ;
//fsm-1
always @ (posedge sys_clk) begin
if('b0 == sys_rst_n) c_st <= IDLE;
else c_st <= n_st;
end
//fsm-2
always @ (*) begin
case(c_st)
IDLE:begin
if(rd_start == 'b1) begin
n_st = READ;end
else if(wr_start == 'b1) begin
n_st = WR;end
else begin
n_st = IDLE;end
end
READ:n_st = RD;
RD:n_st = (bit_cnt == `BURST)?END:RD;
END:n_st = IDLE;
WR:n_st = (bit_cnt == `BURST)?END:WR;
default:n_st = IDLE;
endcase
end
//fsm-3
always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) begin
bit_cnt <= ;
link <= ;
sram_addr <= `ASIZE'h3FFFF;
cmd_r <= CMD_NOP;
end
else begin
case(n_st)
IDLE:begin
bit_cnt <= ;
link <= ;
sram_addr <= sram_addr;
cmd_r <= CMD_NOP;
end
READ:begin
bit_cnt <= bit_cnt;
sram_addr <= sys_rd_addr_i;
link <=;
cmd_r <= CMD_READ;
end
RD:begin
bit_cnt <= (bit_cnt == `BURST)?`BURST_WIDTH'd0:bit_cnt + 1'd1;
link <= ;
sram_addr <= (bit_cnt == `BURST-)?sram_addr:sram_addr + 'd1;
cmd_r <= CMD_READ;
end
END:begin
bit_cnt <= ;
link <= ;
sram_addr <= sram_addr;
cmd_r <= CMD_NOP;
end
WR:begin
bit_cnt <= (bit_cnt == `BURST)?`BURST_WIDTH'd0:bit_cnt + 1'd1;
sram_addr <= (bit_cnt == `BURST)?sram_addr:sram_addr + 'd1;
link <=;
cmd_r <= CMD_WRITE;
end
default:begin
bit_cnt <= ;
link <= ;
sram_addr <= `ASIZE'h3FFFF;
cmd_r <= CMD_NOP;end
endcase
end
end
//generate sys_data_o
reg [`DSIZE-:] sys_data_o = ;
always @ (*) begin
if(c_st == RD) sys_data_o <= sram_data;
else sys_data_o <= sys_data_o;
end
//generate sram_data_r
reg [`DSIZE-:] sram_data_r = ;
always @ (*) begin
if(c_st == WR) sram_data_r <= sys_data_i;
else sram_data_r <= sram_data_r;
end
//assign
assign sram_data = (link == 'b1)?sram_data_r:16'hzzzz;
assign sram_rd_ack_o = ((c_st == END)&&(rd_start == 'b1))?1'b1:'b0;
assign sram_rd_valid_o = (c_st == RD)?'b1:1'b0;
assign sram_wr_ack_o = ((c_st == END)&&(wr_start == 'b1))?1'b1:'b0;
assign sram_wr_valid_o = (c_st == WR)?'b1:1'b0; endmodule
源码2:读驱动
`timescale ns / ps
`define BURST
`define BURST_WIDTH
`define ASIZE
module sram_rd_driver(
sys_clk,
sys_rst_n,
key_n,
sram_rd_valid_i,
rreq_o,
sys_rd_addr_o
);
input sys_clk;
input sys_rst_n;
input key_n;
input sram_rd_valid_i;
output rreq_o;
output [`ASIZE-:] sys_rd_addr_o;
//generate the rreq_o
reg key_r = ;
reg rreq_o = ;
always @ (posedge sys_clk) begin
if('b0 == sys_rst_n) key_r <= 1;
else key_r <= key_n;
end wire rd_trigger = ~key_n & key_r;
always @ (posedge sys_clk) begin
if('b0 == sys_rst_n) rreq_o <= 0;
else if(rd_trigger) rreq_o <= ;
else rreq_o <= ;
end //generate the sys_rd_addr_o
reg [`ASIZE-:] sys_rd_addr_o = ;
always @ (posedge sys_clk) begin
if('b0 == sys_rst_n) sys_rd_addr_o <= 0;
else if(sram_rd_valid_i) sys_rd_addr_o <= sys_rd_addr_o + 'd1;
else sys_rd_addr_o <= sys_rd_addr_o;
end endmodule
源码3:写驱动
`timescale ns / ps
`define BURST
`define BURST_WIDTH
`define ASIZE
`define DSIZE
module sram_wr_driver(
sys_clk,
sys_rst_n,
wr_key_n,
sram_wr_valid_i,
wreq_o,
sys_wr_addr_o,
sys_data_o
);
input sys_clk;
input sys_rst_n;
input wr_key_n;
input sram_wr_valid_i;
output wreq_o;
output [`ASIZE-:] sys_wr_addr_o;
output [`DSIZE-:] sys_data_o; //capture negedge of wr_key_n
reg wr_key_r = ;
always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) wr_key_r <= 1;
else wr_key_r <= wr_key_n;
end
//generate wreq_o
reg wreq_o = ;
wire wr_trigger = ~wr_key_n & wr_key_r;
always @ (posedge sys_clk) begin
if('b0 == sys_rst_n) wreq_o <= 0;
else if(wr_trigger) wreq_o <= ;
else wreq_o <= ;
end
//generate sys_data_o and sys_wr_addr_o
reg [`ASIZE-:] sys_wr_addr_o = ;
reg [`DSIZE-:] sys_data_o = ; always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) begin
sys_wr_addr_o <= ;
sys_data_o <= ;end
else if(sram_wr_valid_i) begin
sys_wr_addr_o <= sys_wr_addr_o + 'd1;
sys_data_o <= sys_data_o + 'd1;end
else begin
sys_wr_addr_o <= sys_wr_addr_o;
sys_data_o <= sys_data_o;end
end endmodule
源码4:顶层例化
`timescale ns / ps
`define ASIZE
`define DSIZE
module sram(
sys_clk,
sys_rst_n,
key_n,
wr_key_n,
//sram
sram_ce_n,
sram_oe_n,
sram_we_n,
sram_lb_n,
sram_ub_n,
sram_data,
sram_addr
);
input sys_clk;
input sys_rst_n;
input key_n;
input wr_key_n;
//SRAM
output sram_ce_n;
output sram_oe_n;
output sram_we_n;
output sram_lb_n;
output sram_ub_n;
inout [`DSIZE-:] sram_data;
output [`ASIZE-:] sram_addr; wire rreq;
wire sram_rd_ack;
wire sram_rd_valid;
wire [`ASIZE-:] sys_rd_addr; //from driver module
wire [`DSIZE-:] sys_data_o; wire wreq;
wire sram_wr_ack;
wire sram_wr_valid;
wire [`ASIZE-:] sys_wr_addr;
wire [`DSIZE-:] sys_data_i; //for hardware wire sys_clk100;
pll100 pll100_inst (
.inclk0 ( sys_clk ),
.c0 ( sys_clk100 )
); sram_ctrl inst_sram_ctrl(
.sys_clk(sys_clk100),
.sys_rst_n(sys_rst_n),
//read
.sys_rd_addr_i(sys_rd_addr),
.rreq_i(rreq),
.sys_data_o(sys_data_o),
.sram_rd_ack_o(sram_rd_ack),
.sram_rd_valid_o(sram_rd_valid),
////write
.wreq_i(wreq),
.sys_wr_addr_i(sys_wr_addr),
.sys_data_i(sys_data_i),
.sram_wr_valid_o(sram_wr_valid),
.sram_wr_ack_o(sram_wr_ack),
//sram
.sram_ce_n(sram_ce_n),
.sram_oe_n(sram_oe_n),
.sram_we_n(sram_we_n),
.sram_lb_n(sram_lb_n),
.sram_ub_n(sram_ub_n),
.sram_addr(sram_addr),
.sram_data(sram_data)
); sram_wr_driver inst_sram_wr_driver(
.sys_clk(sys_clk100),
.sys_rst_n(sys_rst_n),
.wr_key_n(wr_key_n),
.sram_wr_valid_i(sram_wr_valid),
.wreq_o(wreq),
.sys_wr_addr_o(sys_wr_addr),
.sys_data_o(sys_data_i)
); sram_rd_driver inst_sram_rd_driver(
.sys_clk(sys_clk100),
.sys_rst_n(sys_rst_n),
.key_n(key_n),
.sram_rd_valid_i(sram_rd_valid),
.rreq_o(rreq),
.sys_rd_addr_o(sys_rd_addr)
); endmodule
异步SRAM控制器的Verilog建模的更多相关文章
- Norflash控制器的Verilog建模之一
摘要:今天驱动一款SPANSION公司生产的norflash——S29AL032D70,没有别的参考资料,大致了解一下norflash的内部cmos电路架构以及其用途之后,直接看手册吧. 如何看手册: ...
- SDRAM控制器的Verilog建模之一
前言:作为经典存储器的三剑客中的flash和sram已经建模测试过了,虽然现在都已经ddr2,ddr3,667MHZ.1333MHZ的天下了,但是接下这周来准备写一下sdram的controller. ...
- Norflash控制器的Verilog建模之二(仿真)
前言:经过几天修改,norflash控制器基本已经完成,通过仿真.完整的norflash包含2个模块:直接操作硬件的norflash_ctrl.v与控制ctrl模块的驱动norflash_driver ...
- I2C控制器的Verilog建模之三(完结版)
前言:终于到了测试篇,不过悲剧了一下.按照之前<二>里面的思路,在顶层用一个复用器驱动读写独立模块的I2C总线确实失败.虽然综合过去了,不过警告里已经说明:底层的2个原本是inout三态口 ...
- Norflash控制器的Verilog建模之三(測試)
前言:回校了,辦好手續就著手寫測試篇.初步的norflash控制器已經完成,通過硬件測試.目前的norflash完成扇区块擦除.单字节写.单字节读3个功能.博文最后附上源码. 总结:和之前的博文一样, ...
- VGA逐行扫描控制器的Verilog建模
前言:因为VGA是一种模拟图像传输数据接口,所要将数字信号用DAC转换成模拟量.本文用的一款ADI公司高精度的视频IC,实则一款高带宽的视频DAC.因为VGA时序较为简单,并且网上的VGA驱动基本大同 ...
- I2C控制器的Verilog建模之一
前言:之前申请了ADI公司的一款ADV7181CBSTZ的视频解码芯片,正好原装DE2板子安的是同系列的ADV7181BBSTZ.虽然都是ADV7181的宗出,但是寄存器配置等等还是有些诧异,引脚也不 ...
- I2C控制器的Verilog建模之二
前言:接着上一篇的I2C写操作,今天要实现一个I2C的读操作.虽然在ADV7181B配置内部寄存器时没有必要使用到读操作,但是为了进一步确认寄存器是否在I2C写模块下被正确配置,这一步是必不可少的. ...
- 高性能异步SRAM技术角度
当前有两个不同系列的异步SRAM:快速SRAM(支持高速存取)和低功耗SRAM(低功耗).从技术角度看来,这种权衡是合理的.在低功耗SRAM中,通过采用特殊栅诱导漏极泄漏(GIDL)控制技术控制待机电 ...
随机推荐
- 烟草公司基于BPM的IT一体化变革
广州烟草有限公司隶属于广东省烟草专卖局,中国烟草总公司统一领导.垂直管理.主要职能是负责广州市的烟草生产.经营企业和市场的专卖管理.成立20多年来,广州烟草致力于烟叶和卷烟的生产经营.多元化经营.技术 ...
- 使用xca生成SSL证书
先下载安装xca工具,地址是http://xca.hohnstaedt.de/ 先用xca创建一本ca证书 xca打开的界面 依次File, New DataBase,选择xdb文件保存路径,再输入密 ...
- Java mysql 日期相关
获取当前系统时间和日期并格式化输出: import java.util.Date;import java.text.SimpleDateFormat; public class NowString { ...
- 实现手机扫描二维码页面登录,类似web微信-第三篇,手机客户端
转自:http://www.cnblogs.com/fengyun99/p/3541254.html 上一篇,介绍了二维码生成的机制,紧接着,我们就要开发手机客户端来识别这个二维码. 二维码,实际上是 ...
- 修改 UISearchBar cancelButton 样式
今天收到个问题,老大让我修改UISearchBar cancelButton的样式本来以为很简单的一个活,没想到让我长知识了. 开始在网上搜到的方法和我想象的一样,通过遍历Subviews获得butt ...
- jQueryMobile控件之展开与合并
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 对编写html代码的几点儿小建议
1.DOCTYPE说明:告诉浏览器要使用哪种规范来解释该文档内容: <!DOCTYPE html PUBLIC "-W3//DTD//XHTML 1.0 Transitional// ...
- HDU 5360 (贪心)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5360 题意:告诉你n个区间[ l[i],r[i] ],然后让你排序,必须左区间不大于它前边的总区间个数 ...
- 【转】Styling And Animating SVGs With CSS
原文转自:http://www.smashingmagazine.com/2014/11/03/styling-and-animating-svgs-with-css/?utm_source=CSS- ...
- Java数据结构和算法之数组与简单排序
一.数组于简单排序 数组 数组(array)是相同类型变量的集合,可以使用共同的名字引用它.数组可被定义为任何类型,可以是一维或多维.数组中的一个特别要素是通过下标来访问它.数组提供了一种将有联系的信 ...