惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
N
Netflix TechBlog - Medium
大猫的无限游戏
大猫的无限游戏
Cyberwarzone
Cyberwarzone
T
Troy Hunt's Blog
Vercel News
Vercel News
T
The Blog of Author Tim Ferriss
U
Unit 42
Last Week in AI
Last Week in AI
云风的 BLOG
云风的 BLOG
F
Full Disclosure
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google DeepMind News
Google DeepMind News
Hacker News - Newest:
Hacker News - Newest: "LLM"
IT之家
IT之家
Google Online Security Blog
Google Online Security Blog
Cloudbric
Cloudbric
月光博客
月光博客
Hacker News: Ask HN
Hacker News: Ask HN
罗磊的独立博客
N
News and Events Feed by Topic
S
Secure Thoughts
The Last Watchdog
The Last Watchdog
Google DeepMind News
Google DeepMind News
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
I
InfoQ
Hugging Face - Blog
Hugging Face - Blog
I
Intezer
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 聂微东
P
Privacy International News Feed
有赞技术团队
有赞技术团队
博客园_首页
F
Fortinet All Blogs
Recent Announcements
Recent Announcements
O
OpenAI News
博客园 - 【当耐特】
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tor Project blog
B
Blog
量子位
T
Threatpost
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
CXSECURITY Database RSS Feed - CXSecurity.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
Vulnerabilities – Threatpost
酷 壳 – CoolShell
酷 壳 – CoolShell
S
SegmentFault 最新的问题
L
LangChain Blog

StrongWong

什么是超低功耗基准测试——ULPMark Benchmark 浅谈 RISC-V 软件开发生态之 IDE 简单了解一下小米 vela wujian100 的 PWM 周期问题 用 Kindle 做树莓派的显示屏 关于 RISC-V 架构下 RTOS 的一些知识 使用 vivado 综合 wujian100 生成 bitstream 文件 Windows 下学习阿里平头哥 RISC-V 芯片开发平台 wujian100 FPGA 数字图像处理联合仿真平台的搭建及使用举例 拆解一个很有意思的开关 拆解某宝上热销的一款蓝牙耳机 Archives Windows10 环境下搭建 RISC-V 调试环境 Contact 使用汇编实现 pc 和 sp 的保存及恢复操作 数字 IC 设计流程 初窥 SDRAM 从计数器开始,看数字 IC 设计 使用 Docker + GitLab 构建自用的代码管理服务 提升数字 IC 设计效率从 Vim 开始 总线- SoC 内部的主干道 Tools 使用树莓派 3b 和 RTL_SDR 搭建小功率无线电监测点 关于 ARM Cortex-M3 的启动文件分析及分散加载 make 命令及 makefile 文件编写 ROS 基础知识 在 Jetson TX2 上安装 ROS 机器人操作系统 Jetson TX2 重新编译内核添加usb等驱动 Nvidia Jetson TX2 刷机并安装JetPack3.1 我的毕业设计--基于ROS的移动机器人 使用 Hexo+Github Pages 搭建个人博客 About
SDRAM 两次踏进同一条河
BH6BAO · 2018-12-07 · via StrongWong

人不能两次踏进同一条河,但 SDRAM 可以 ——SDRAM的刷新

前言

上周去了趟深圳,所以摸鱼拖更了,在那边发现真的是机遇越大的地方努力的脚步就越匆忙,某企业的 boss 是位国家科学技术奖的获得者,公司已经上市了,却依然吃 13 元的小店套餐,而且饭几乎是倒进嘴里的,5 分钟左右吃完马上就又去和合作对象谈判去了! …… 所以我们更要加油了,不然只会被大佬们越拉越远 …… 加油吧!

在初窥 sdram 中我们留了一个坑——首先我们在第一页就可以看到它的刷新周期是 64ms(这个重要参数将在后面进行具体介绍)

今天我们就来填这个坑……

「人不能两次踏进同一条河流」是古希腊哲学家赫拉克利特说的。阐述「变」的哲学在米利都学派和毕达戈拉斯学派之后,爱菲斯的赫拉克利特创立了一种变的哲学。他的哲学充满了辩证法思想,对后来辩证法的发展产生过重大影响。

他形象地表达了他关于变的思想,说:「太阳每天都是新的。」他把存在的东西比作一条河,声称人不能两次踏进同一条河。因为当人第二次进入这条河时,是新的水流而不是原来的水流在流淌。SDRAM 不断地刷新,但却能保证刷新后的数据与刷新前一致,人踏进河是为什么我不知道,但是 SDRAM 正是为了保证内部电容的电量最终实现数据的不丢失才会不断地刷新。我们人做不到的事,就用 RTL 让 SDRAM 帮我们做了吧。

参数分析

首先我们来看 SDRAM 参数:8K Refresh Cycles/64 ms,意味着:

  • 刷新速率 = 64ms / 8192 行 => 7us;
  • 刷新时钟周期 = 7us * CPU 运行频率;

例:CPU 运行频率 50MHz 时钟周期 = 7.81us * 50MHz = 390.5;64ms 为刷新周期最大值,为保证可靠运行,实际刷新实间要稍小于 64ms;例:时钟周期 = 390.5 ≈ 380

这就意味着每 380 个时钟周期,我们便需要对我们的 SDRAM 进行一次刷新,那么进行刷新的时候需要进行哪些操作呢?我们还是回到我们的数据手册中。

如图示,我们可以看到首先是要进行一次预充电操作(precharge)(同时选中所有的 bank),在经过 tRP 延时后进行一次自刷新操作(auto refresh),再经过一次 tRC 后又进行一次自刷新操作(auto refresh)【注:实际使用中可以只进行一次自刷新操作】,最后进入到我们下一步 ……

那么根据第一篇《初窥 SDRAM》后我们知道以上的几个操作对应的指令码分别为:

CMDCSRASCASWE
Precharge0010
Auto-Refresh0001
Nop0111

延时 tRP,tRC 则分别对应 15ns(至少 1 个周期,实际操作中取 1 个周期),60ns (至少 3 个周期,实际操作中取 4 个周期)。

那么我们的设计即可为:一个 8us 的定时器,控制刷新的周期,作为刷新的开始信号;一个命令计数器,用于记录对应的延时节点(tRP,tRC);最后即为达到对应节点输出对应指令即可。

由此踏进的河流变和 8us 前的河流是同一条河流的 ……

实现代码

具体实现代码如下: 上代码!

/*
File name: sdram_autoref
Function: Auto refresh for IS42S16320D-7TL SDRAM
Module name: sdram_autoref
Author: Ricky
Time: 20181130
*/

module sdram_autoref(
	//system signals
	input                   sys_clk    ,
	input                   sys_rst_n  ,

	//others
	input                   init_flag  ,
	input                   ref_en     ,

	output reg              ref_req    ,
	output wire             ref_flag   ,
	output reg   [3:0]      cmd_reg    ,
	output wire  [12:0] 	sdram_addr
);

/*==============================================================================
**********************Define Parameter and inside Signals***********************

Note: sys_clk=50MHz
      tRP|min=15ns >>> 20ns >>> 1sys_clk >>> [4:0] cnt_cmd
      tRC|min=60ns >>> 80ns >>> 4sys_clk >>> [4:0] cnt_cmd
      8K refresh cycles every 64ms >>> 8us >>> 380sys_clk
===============================================================================*/

reg [4:0]     cnt_cmd      ;
reg [8:0]     cnt_ref      ;
reg   	      flag_ref     ;

localparam delay_8us = 380 ;

//define sdram autorefresh cmd
localparam  precharge    = 4'b0010;
localparam  auto_refresh = 4'b0001;
localparam  nop          = 4'b0111;

/*==============================================================================
**********************************Main Logic************************************
==============================================================================*/

//auto_refresh counter
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        cnt_ref <= 9'b0;
    else if(cnt_ref >= delay_8us)
            cnt_ref <= 9'b0;
    else if(init_flag == 1'b1)
            cnt_ref <= cnt_ref + 1'b1;
end

//ref flag signal
always  @(posedge sys_clk or negedge sys_rst_n) begin
        if(sys_rst_n == 1'b0)
                flag_ref        <=      1'b0;
        else if(ref_flag == 1'b1)
                flag_ref        <=      1'b0;
        else if(ref_en == 1'b1)
                flag_ref        <=      1'b1;
end

//cmd counter
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        cnt_cmd <= 4'd0;
    else if (flag_ref == 1'b1)
             cnt_cmd <= cnt_cmd + 1'b1;
    else     cnt_cmd <= 4'b0;
end

//cmd
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(~sys_rst_n)
        cmd_reg <= nop;
    else
        case(cnt_cmd)
            1:       cmd_reg <= precharge;
            2:       cmd_reg <= auto_refresh;
            6:       cmd_reg <= auto_refresh;
            default  cmd_reg <= nop;
        endcase
end

//request signal(8K refresh cycles every 64ms >>> 8us >>> 380sys_clk)
always @(posedge sys_clk or negedge sys_rst_n)begin
    if(~sys_rst_n)
        ref_req <= 1'b0;
    else if(ref_en)
        ref_req <= 1'b0;
    else if(cnt_ref >= delay_8us)
        ref_req <= 1'b1;
end

assign sdram_addr = 13'b0010000000000;
assign ref_flag   = (cnt_cmd >= 9)? 1'b1 : 1'b0;

endmodule

{% endfold %}

实现后我们可以看到毎 8us 完成一次所有 bank 的刷新

仿真波形

By Ricky