异步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)控制技术控制待机电 ...
随机推荐
- C语言基础--二维数组
二维数组概念: 数组中的每一个元素又是一个数组, 那么这个数组就称之为二维数组,二维数组是特殊的一维数组. 二维数组格式: 元素类型 数组名称[一维数组的个数][每个一维数组的元素个数]; 元素类型 ...
- Servlet路径跳转2--在servlet当中,跳转到某网页时的路径写法
课程1-13 http://www.imooc.com/video/5554 Servlet路径跳转: 绝对路径:放在任何地方都对的路径 相对路径:相对于当前资源的路径 两种方法:请求重定向,服务 ...
- SQL Server2012关于表内事项出现次数降序排列(存储过程)
USE [growup] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[S_GetRanking ...
- MJExtension框架介绍
MJExtension框架介绍 标签: MJExtension 2015-05-01 08:22 1120人阅读 评论(0) 收藏 举报 分类: Foundation(14) 版权声明:本文为博主 ...
- Ubuntu中查看32还是64
安装ubuntu在pc上,不推荐在32位pc安装64位操作系统,64位pc安装32位操作系统 方法/步骤 1 按ctrl+shift+t 快捷键,打开终端,输入sudo uname --m ,按下 ...
- HDU 5373 (大水坑题---被11整除原来有规律)
题意:告诉一个数n,然后求出所有的位数和,插在n的尾部,重复求t次,判断最终的数是否能被11整除. 分析:直接模拟的过程,并且模拟的除的过程,却TLE,以为是方法错了,因为每次都得循环求一遍位数和: ...
- 开发经验之状态机思想,分别使用了swift,OC,C,PHP语言实现
这里设计一个简单的练习,使用状态机思想实现,分别使用了swift,OC,C,PHP语言实现 题目:1到10000遍历,开始-打印奇数-遇到7的倍数开始打印偶数--遇到10的倍数打印奇数 //部分结 ...
- android 检测网络是否连接,或者GPS是否可用
很多android程序在打开时,检测网络是否连接,或者GPS是否可用: 1.网络是否连接(包括Wifi和移动网络) // 是否有可用网络 private boolean isNetworkConnec ...
- Spark SQL Thrift Server 配置 Kerberos身份认证和权限管理
转载请注明出处:http://www.cnblogs.com/xiaodf/ 之前的博客介绍了通过Kerberos + Sentry的方式实现了hive server2的身份认证和权限管理功能,本文主 ...
- JSP EL表达式 与输入有关的内置对象
与输入有关的隐含对象有两个param和paramValues,用来取得用户的请求参数.在使用EL之前可以使用如下代码取得用户的请求参数: request.getParameter(String nam ...