明德扬论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信扫一扫,快捷登录!

查看: 4045|回复: 0

【原创分享】基于FPGA的SDRAM控制器设计——初始化设计

[复制链接]
发表于 2020-2-28 12:20:37 | 显示全部楼层 |阅读模式

马上注册,看完整文章,学更多FPGA知识。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本文为明德扬原创及录用文章,转载请注明出处
1.1 SDRAM简介
SDRAM即同步动态随机存储器,英文为Synchronous Dynamic Random Access Memory;具有容量大、读写速度快、价格相对便宜等优点,但同时控制逻辑比较复杂。
1.1.1 SDRAM示意图
其管脚图如下所示:
1.1.2 信号说明
信号名
信号说明
clk
SDRAM工作时钟
cke
时钟使能信号
cs_n
用于屏蔽和使能所有输入端口,但不包括CLKCKEDQM,低电平有效
cas_n
列地址选通
ras_na
行地址选通
we_n
写使能,该信号为低时,使能写操作和预充电
ba
bank地址
a
地址总线
dqm
数据掩码
dq
数据总线
1.1.3 SDRAM中心对齐原则
SDRAM的命令与时钟上升沿是中心对齐的,本设计采用锁相环生成SDRAM工作时钟,SDRAM与初始化模块工作时钟相差180°。这样FPGA产生的信号到SDRAM正好中心对齐,如下图所示:
1.1.4 SDRAM初始化时序
SDRAM初始化时序如上图所示,sdr_cmd命令由sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n组合而成;复位后要延时最少100us后才能工作;当A10为高时可以对所有bank进行操作;当到达Tp+3时需要将init_done拉高。
其模式寄存器配置如上图所示,主要参数设置如下:
a.       模式寄存器的配置是确定SDRAM的工作模式
b.       A2、A1、A0用作设置突发长度,本项目设置为4
c.       A3用作设置突发类型,本项目设置为Sequential顺序类型
d.       A6、A5、A4用作设置列选通潜伏期,本项目设置为3
e.       A8、A7设置操作模式,一般为00
f.        A9设置写突发模式,本项目为0
g.       A12、A11、A10设置为0
1.2 顶层模块设计1.2.1 SDRAM顶层模块管脚图
1.2.2 信号说明
信号
说明
local_addr
本地地址由行地址列地址bank地址组合而成
local_data
写入数据
local_q
读出数据
local_rdreq
读请求
local_wrreq
写请求
local_reday
可以进行读写信号
local_rdata_valid
读数据有效信号
init_done
初始化完成信号
clk
输入时钟
rst_n
系统复位
sdr_dq
SDRAM数据总线,双向端口
sdr_clk
SDRAM工作时钟
sdr_cke
SDRAM时钟使能
sdr_cs_n
片选信号
sdr_cas_n
列地址选通
sdr_ras_n
行地址选通
sdr_we_n
写使能,该信号为低时,使能写操作和预充电
sdr_ba
SDRAM bank地址
sdr_a
SDRAM地址总线
sdr_dqm
数据掩码
1.2.3 参考代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module sdram_top(
    clk    ,
    sys_rst_n  ,
    //其他信号,举例dout
    local_addr,
    local_data,
    local_q,
    local_rdreq,
    local_wrreq,
    local_reday,
    local_rdata_vaild,
    init_done,
    sdr_cke,
    sdr_cs_n,
    sdr_ras_n,
    sdr_cas_n,
    sdr_we_n,
    sdr_ba,
    sdr_a,
    sdr_dq,
    sdr_dqm,
    sdr_clk
    );

         input clk;
         input sys_rst_n;
         input [24:0] local_addr;
         input [63:0] local_data;
         output [63:0] local_q;
         input local_rdreq;
         input local_wrreq;
         output local_reday;
         output local_rdata_vaild;
         output init_done;
         output sdr_cke;
         output sdr_cs_n;
         output sdr_ras_n;
         output sdr_cas_n;
         output sdr_we_n;
         output [1:0] sdr_ba;
         output [12:0] sdr_a;
         output [15:0] sdr_dq;
         output [1:0] sdr_dqm;
         output sdr_clk;

         wire phy_clk;
         wire rst_n;
         wire [19:0] init_bus;

         assign {sdr_cke, sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n, sdr_ba, sdr_a} = init_bus;
         assign sdr_dqm = 2'b00;

    sdram_init sdram_init_inst(
        .clk            (phy_clk)       ,
        .rst_n          (rst_n)       ,
        //其他信号,举例dout
        .init_done      (init_done)       ,
        .init_bus       (init_bus)
    );

                 my_pll PLL(
                         .areset             (~sys_rst_n)            ,
                         .inclk0              (clk)                          ,
                         .c0                    (phy_clk)                  ,
                         .c1                    (sdr_clk)                   ,
                         .locked             (rst_n)
                 );

    endmodule

1.3 初始化模块设计1.3.1 SDRAM出计划模块管脚图
1.3.2 信号说明
信号
说明
clk
初始化模块工作时钟(100MHz
rst_n
复位
init_done
初始化完成信号
init_bus
SDRAM信号组成
1.3.3 参考代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
module sdram_init(
    clk    ,
    rst_n  ,
    //其他信号,举例dout
    init_done,
    init_bus
    );

    //参数定义
    parameter      DATA_W    =      20      ;
    parameter      T100us    =      10_000  ;
    parameter      TRP       =      2       ;
    parameter      TRFC      =      7       ;
    parameter      TMRD      =      2       ;
        parameter      NOP       =      4'b0111       ;
        parameter      PRE       =      4'b0010       ;
        parameter      REF       =      4'b0001       ;
        parameter      LMR       =      4'b0000       ;
        parameter      CODE      =      13'b000_000_011_0010       ;
        parameter      CNT_MAX   =      10_021    ;

    //输入信号定义
    input               clk    ;
    input               rst_n  ;

    //输出信号定义
    output              init_done  ;
    output[DATA_W-1:0]  init_bus   ;

    //输出信号reg定义
    reg                 init_done  ;
    wire  [DATA_W-1:0]  init_bus   ;

    //中间信号定义
    reg   [20:0]        cnt        ;
    reg                 sdr_cke    ;
    reg   [3:0]         sdr_cmd    ;
    reg   [1:0]         sdr_ba     ;
    reg   [12:0]        sdr_a      ;

        wire                                           add_cnt           ;
        wire                                         end_cnt           ;

    assign init_bus = {sdr_cke, sdr_cmd, sdr_ba, sdr_a};

    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt <= 0;
        end
        else if(add_cnt)begin
            if(end_cnt)
                cnt <= 0;
            else
                cnt <= cnt + 1;
        end
    end

    assign add_cnt = init_done == 0;      
    assign end_cnt = add_cnt && cnt==CNT_MAX - 1 ;

        always @(posedge clk or negedge rst_n)begin
                 if(rst_n==1'b0)begin
                         sdr_cke <= 1'b0;
                 end
                 else if(add_cnt&&cnt==10_000-1)begin
                         sdr_cke <= 1'b1;
                 end
                 else
                         sdr_cke <= sdr_cke;
        end

        always @(posedge clk or negedge rst_n)begin
                 if(rst_n==1'b0)begin
                         sdr_cmd <= NOP;
                 end
                 else if(add_cnt&&cnt==10_001-1)begin
                         sdr_cmd <= PRE;
                 end
                 else if(add_cnt&&cnt==10_003-1)begin
                         sdr_cmd <= REF;
                 end
                 else if(add_cnt&&cnt==10_012-1)begin
                         sdr_cmd <= REF;
                 end
                 else if(add_cnt&&cnt==10_019-1)begin
                         sdr_cmd <= LMR;
                 end
                 else if(add_cnt&&cnt==10_020-1)begin
                         sdr_cmd <= NOP;
                 end
                 else begin
                         sdr_cmd <= NOP;
                 end
        end

        always @(posedge clk or negedge rst_n)begin
                 if(rst_n==1'b0)begin
                         sdr_a <= 13'd0;
                 end
                 else if(add_cnt&&cnt==10_001-1)begin
                         sdr_a[10] <= 1'b1;
                 end
                 else if(add_cnt&&cnt==10_019-1)begin
                         sdr_a <= CODE;
                 end
                 else begin
                         sdr_a <= 13'd0;
                 end
        end

        always @(posedge clk or negedge rst_n)begin
                 if(rst_n==1'b0)begin
                         init_done <= 1'b0;
                 end
                 else if(add_cnt&&cnt==10_021-1)begin
                         init_done <= 1'b1;
                 end
                else begin
                         init_done <= init_done;
                 end
        end

endmodule

1.4 PLL设置   
最后对代码进行仿真,modelsim生成的报告如下所示,说明初始化设置成功。
以上就是SDRAM控制器初始化设计的思考步骤以及相关代码,更多FPGA资料可以进入明德扬论坛进行学习交流(http://www.fpgabbs.cn/),明德扬专注FPGA设计研究,对FPGA学习感兴趣的朋友快快联系我们吧!

FPGA视频课程  培训班 FPGA学习资料
吴老师 18022857217(微信同号) Q1241003385
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|MDYBBS ( 粤ICP备16061416号 )

GMT+8, 2024-4-20 20:36 , Processed in 0.070667 second(s), 22 queries .

Powered by Discuz! X3.4

本论坛由广州健飞通信有限公司所有

© 2001-2019 Comsenz Inc.

快速回复 返回顶部 返回列表