QDR SRAM接口FPGA 详细Verilog代码
QDR SRAM介绍
QDR 具有独立的读、写数据通路,均使用DDR,在每个时钟周期内会传输四个总线宽度的数据 (两个读和两个写),这就是QDR四倍数据速率的由来。
这里用到的是典型2字突发的QDR,对于4字突发的QDR操作类似,稍作改动就行。针对每个读或写请求,2 字突发器件传输两个字。DDR 地址总线用于在前半个时钟周期允许读请求,在后半个时钟周期允许写请求。
首先看接口的时序图
时序图,表明了 2 字突发 QDR II 存储器接口上的并发读 / 写操作。时钟有三组差分时钟,其中C时钟是发送寄存器的发送时钟,K时钟是目的寄存器用的采样时钟,CQ时钟是经过QDR器件延时,跟输出Q同步的时钟。
在K时钟的前半个周期,DDR 地址总线允许读地址传输给存储器;在时钟的后半个周期,DDR 地址总线允许写地址出现其中。因此,低有效的读控制 (/R) 和写控制 (/W) 控制可在同一时钟周期内有效。
设计目标就是要把QDR接口封装简化,把DDR接口都转化为FPGA内部可用的SDR,这样对用户侧而言,读写控制分离,读写地址分离,操作起来更简便。接口的原理图如下
时钟关系
可用看出两组发送给QDR的时钟,同频,满足C时钟相位为0和K时钟相位为270的关系。
写数据通路
从QDR SRAM的时序图中可以看出,写数据和地址的时序要求一样,因此处理起来也一样。多根数据总线用generate for生成,代码如下。地址通道做相同的处理
generategenvar var1;for(var1=0;var1<18;var1=var1+1)begin: gen_QDR_DODDR #(.DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE".INIT (1'b0 ), // Initial value of Q: 1'b0 or 1'b1.SRTYPE ("SYNC" ) // Set/Reset type: "SYNC" or "ASYNC") O_QDR_D_inst (.Q (O_QDR_D[var1] ), // 1-bit DDR output.C (I_user_clk0 ), // 1-bit clock input.CE(1'b1 ), // 1-bit clock enable input.D1(I_user_wr_data1[var1]), // 1-bit data input (positive edge).D2(I_user_wr_data2[var1]), // 1-bit data input (negative edge).R (1'b0 ), // 1-bit reset.S (1'b0 ) // 1-bit set);end
endgenerate
时钟通路
由于数据要经过DDR输出,为了保证时钟和数据具有相同的延时,构造相同的时钟通路,对CLK0和CLK270都进行如下处理
参考代码如下,这里只是一个差分时钟CLK270的处理,对另一个差分时钟CLK0做相同处理。
ODDR #(.DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE".INIT (1'b0 ), // Initial value of Q: 1'b0 or 1'b1.SRTYPE ("SYNC" ) // Set/Reset type: "SYNC" or "ASYNC"
) O_QDR_K_p_inst (.Q (O_QDR_K_p), // 1-bit DDR output.C (I_user_clk270), // 1-bit clock input.CE(1'b1), // 1-bit clock enable input.D1(1'b0), // 1-bit data input (positive edge).D2(1'b1), // 1-bit data input (negative edge).R (1'b0), // 1-bit reset.S (1'b0) // 1-bit set
);
ODDR #(.DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE".INIT (1'b0 ), // Initial value of Q: 1'b0 or 1'b1.SRTYPE ("SYNC" ) // Set/Reset type: "SYNC" or "ASYNC"
) O_QDR_K_n_inst (.Q (O_QDR_K_n), // 1-bit DDR output.C (I_user_clk270), // 1-bit clock input.CE(1'b1), // 1-bit clock enable input.D1(1'b1), // 1-bit data input (positive edge).D2(1'b0), // 1-bit data input (negative edge).R (1'b0), // 1-bit reset.S (1'b0) // 1-bit set
);
读数据通路
//******************************************************************************
// input data path
//******************************************************************************//-------------------------------------QDR_Q-------------------------------------
generate
genvar var3;
for(var3=0;var3<18;var3=var3+1)
begin:
gen_QDR_Q
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // "OPPOSITE_EDGE", "SAME_EDGE"// or "SAME_EDGE_PIPELINED"
.INIT_Q1 (1'b0 ), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2 (1'b0 ), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE ("SYNC" ) // Set/Reset type: "SYNC" or "ASYNC"
) I_QDR_Q_inst (
.Q1(W_rd_data1[var3]), // 1-bit output for positive edge of clock
.Q2(W_rd_data2[var3]), // 1-bit output for negative edge of clock
.C (W_dly_clk0), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D (I_QDR_Q[var3]), // 1-bit DDR data input
.R (1'b0), // 1-bit reset
.S (1'b0) // 1-bit set
);
end
endgenerate
IDELATY延时调整算法
其中IDELAY的延时调整算法如图所示,分别找到CQ的上升沿(DDR输出:01->10)和下降沿(DDR输出:10->01),然后delay_cnt取中间值,使CLK0对准CQ的中间。由于相同的延迟,CLK0也对准数据采样窗口的中间。当然,最简单的是直接上板子,输入一个正弦波,延时用vio输入,用lia查看波形。可以手动调整延时到能看到稳定的波形就行了,然后在代码里面把delay_cnt写死。也可以调两个最坏的情况,取中间的延时,跟自动调整算法一样。
(* IODELAY_GROUP = "delay1" *) IDELAYCTRL IDELAYCTRL_inst1 (.RDY(W_delay_rdy), // 1-bit output: Ready output.REFCLK(I_ref_clk_200m), // 1-bit input: Reference clock input.RST(~I_reset_n) // 1-bit input: Active high reset input);(* IODELAY_GROUP = "delay1" *) IDELAYE2 #(.CINVCTRL_SEL("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE).DELAY_SRC("IDATAIN"), // Delay input (IDATAIN, DATAIN).HIGH_PERFORMANCE_MODE("TRUE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE").IDELAY_TYPE("VAR_LOAD"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE.IDELAY_VALUE(0), // Input delay tap setting (0-31).PIPE_SEL("FALSE"), // Select pipelined mode, FALSE, TRUE.REFCLK_FREQUENCY(200.0), // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0)..SIGNAL_PATTERN("CLOCK") // DATA, CLOCK input signal)IDELAYE2_inst1 (.CNTVALUEOUT(), // 5-bit output: Counter value output.DATAOUT(W_dly_clk0), // 1-bit output: Delayed data output.C(W_fc_clk), // 1-bit input: Clock input.CE(1'b0), // 1-bit input: Active high enable increment/decrement input.CINVCTRL(1'b0), // 1-bit input: Dynamic clock inversion input.CNTVALUEIN(W_delay_cnt), // 5-bit input: Counter value input.DATAIN(1'b0), // 1-bit input: Internal delay data input.IDATAIN(I_uae_clk0), // 1-bit input: Data input from the I/O.INC(1'b0), // 1-bit input: Increment / Decrement tap delay input.LD(1'b1), // 1-bit input: Load IDELAY_VALUE input.LDPIPEEN(1'b0), // 1-bit input: Enable PIPELINE register to load data input.REGRST(1'b0) // 1-bit input: Active-high reset tap-delay input);
代码很简单,把I_user_clk0延迟一下,对齐CQ的中间,这样也就对齐了数据QDR_Q的中间了。
QDR SRAM接口FPGA 详细Verilog代码相关推荐
- FPGA纯verilog代码读写N25Q128A QSPI Flash 提供工程源码和技术支持
目录 1.N25Q128A芯片解读 2.N25Q128A读写时序 3.整体设计思路架构 4.verilog读写Flash驱动设计 5.verilog读写Flash控制器设计 6.FIFO缓存设计 7. ...
- FPGA纯verilog代码实现图像对数变换,提供工程源码和技术支持
目录 1.图像对数变换理论 2.log系数的matlab生成 3.FPGA实现图像对数变换 4.vivado与matlab联合仿真 5.vivado工程介绍 6.上板调试验证并演示 7.福利:工程代码 ...
- 【FPGA】Verilog代码实现温湿度传感器DHT11
#今天也是咸鱼的一天~ 因为参加Robei 杯 是要做一个机器人,先不说这个机器人具体怎么机器法,但是和外界互通的传感器肯定少不了,通过获取外界环境数据,进行处理,然后做出各种各样的功能. 先来讲个简 ...
- SPI接口的FPGA实现(三)——Verilog代码实现SPI接口
上一篇文章我们介绍了DAC81416的配置过程,这一篇我们就用Verilog代码具体实现这个过程,这一篇的代码具有普遍性,以后所有DA/AD的配置代码都可以在本文所展示的代码上进行修改获得.这里先给出 ...
- 基于 FPGA 的 RISC CPU 设计(2)详细的模块设计思路及其 Verilog 代码
引言 其实,一个 CPU 的设计中,各个子模块都是比较基本的.比较简单的,只是组合起来的一个整体架构会比较复杂而已,无论是时序路径,还是数据通路和控制通路,这里,主要详细介绍整个微架构 ...
- FPGA接口_N25Q128型号的spi flash驱动verilog代码编写
# N25Q128型号的spi flash驱动verilog代码编写 提示:使用正点原子达芬奇pro做的小例子,由于教程中无flash的读写,因此撰写记录 文章目录 # N25Q128型号的spi f ...
- 【入门学习四】基于 FPGA 使用 Verilog 实现串口回传通信代码及原理讲解
目录 一.相关知识 二.模块设计 三.代码设计 3.1 串口接收模块 3.2 控制模块 3.3 串口发送模块 四.FIFO 核引用 五.管脚定义及结果展示 上一篇博文:[入门学习三]基于 FPGA 使 ...
- 【Zedboard】FPGA边缘提取 图像处理 基于ZYNQ完成 灰度图像 在VGA显示与 边缘提取 二值化 Verilog代码实现
[Zedboard]FPGA边缘提取 图像处理 基于ZYNQ完成 灰度图像 在VGA显示与 边缘提取 二值化 Verilog代码实现 在项目开始到目前为止已经完成了在Zedboard的PL部分即FPG ...
- ethercat 主站 FPGA verilog 代码 EtherCAT 总线 demo 板介绍 ethercat 主站 FPGA verilog 代码
ethercat 主站 FPGA verilog 代码 ECAT运动控制器ARM软件设计 一.ARM向FPGA发送目标位置 1.对应的操作地址 define CUR_POS_SERVO 1 defin ...
最新文章
- 解决spring-boot-maven-plugin not found爆红
- html点击圆点箭头分页,css实现小箭头的实现方式
- 信息学奥赛一本通 1030:计算球的体积 | OpenJudge NOI 1.3 12
- yum安装:zabbix-web-4.2.8-1.el7.noarch: [Errno 256] No more mirrors to try
- 启动mysql5.7异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
- 进销存软件哪个简单好用?商户必看
- lex 词法分析 linux,Lex词法分析器
- PHP 100以内质数表
- javaBean本质
- [词根词缀]cre/cred/crit/cult字根由来及词源C的故事
- DBF文件使用JAVA读写解决方案
- 解决“可以联网后仍显示无法连接到Internet”
- IOS系统降级小工具
- 高效发表科技论文的写作方法与技巧
- 苹果笔记本服务器虚拟系统,苹果Mac虚拟机装Windows哪家强?
- type_traits 类型萃取
- 如何判断轨道上行下行
- 【BDTC 2016】大数据云服务论坛:云上的大数据探索
- Java中获取节假日日期
- 六顶思考帽与单一职责
热门文章
- 国内哪些公司布局了元宇宙 元宇宙公司有哪些
- 【requests爬虫用xpath解析_1】
- python旋转矩阵90°_用Python旋转矩阵
- Java的serialVersionUID
- linux 输入密码命令,linux密码口令命令passwd
- 加mp4文件后js失效_记录一波video.js的使用及问题
- pnpm、yarn和npm包管理器淘宝镜像和对比
- oracle plsql 字符串长度,plsql中常用字符串函数
- invocationHandler和invocation的区别
- python 区间频数统计_pandas分区间,算频率的实例