FPGA设计——DDR2 (Altera)

本文详细介绍了DDR2 IP核的配置流程,包括时钟设置、内存预设选择及本地参数设定等内容,并通过实例展示了如何进行DDR2的读写操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. DDR2 IP系统框图

wKiom1e2zQKTWxpJAABKTTGmGgk097.jpg


2. IP参数设置

1) 时钟设置

PLL reference clock freqency是参考输入时钟,一般由外部晶振或外部PLL输出提供

Memory clock freqency是DDR时钟,一般CYCLONE IV最快只能支持200M,根据不同的型号和BANK而不同

Controller data rate有Full和Half模式,选择Half模式后,Local interface width会增加一倍

wKiom1e2znGh0a8YAAEhLj7_Uzs573.jpg

2)选择Memory Presets

根据电路中DDR2的型号选择对应的presets,这里只重点介绍Full rate下地址的设置。

在Full rate下:

local_address is 25 bits wide

local_address[23:11] = row address[13:0]

local_address[10:9] = bank address  [1:0]

local_address [8:0] = column address [9:1]

local data宽度是总线data宽度的两倍,所以IP核忽略了column的最低位

wKioL1e21m-hFDseAAHWP_qirY0059.jpg

3) 设置local参数

Local-to-Memory Address Mapping: 设置地址映射,需要和上面的地址映射说明一致

Local Maximum Burst Count:设置成32,提高读写效率

wKiom1e22cPwyZPZAADZSq077V8054.jpg


3. 例化IP核

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
ddr2_64bit ddr2_64bit_inst (
                 .local_address(local_address),
                 .local_write_req(local_write_req),
                 .local_read_req(local_read_req),
                 .local_burstbegin(local_burstbegin),
                 .local_wdata(local_wdata),
                 .local_be(16'hffff),
                 .local_size(BURST_LEN),
                 .global_reset_n(rst_n),
                 .pll_ref_clk(ref_clk),
                 .soft_reset_n(rst_n),
                 .local_ready(local_ready),
                 .local_rdata(local_rdata),
                 .local_rdata_valid(local_rdata_valid),
                 .local_refresh_ack(),
                 .local_init_done(local_init_done),
                 .reset_phy_clk_n(),        
                 .phy_clk(phy_clk),
                 .aux_full_rate_clk(),
                 .aux_half_rate_clk(),
                 .reset_request_n(),
                 .mem_odt(mem_odt),
                 .mem_cs_n(mem_cs_n),
                 .mem_cke(mem_cke),
                 .mem_addr(mem_addr),
                 .mem_ba(mem_ba),
                 .mem_ras_n(mem_ras_n),
                 .mem_cas_n(mem_cas_n),
                 .mem_we_n(mem_we_n),
                 .mem_dm(mem_dm),
                 .mem_clk(mem_clk),
                 .mem_clk_n(mem_clk_n),
                 .mem_dq(mem_dq),
                 .mem_dqs(mem_dqs)
     );


4. 设计读写测试模块

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
125
126
127
128
//-----------ddr2 read and write operation---------
reg   [25 :0]     local_address;
reg               local_burstbegin;
reg               local_read_req;
reg               local_write_req;
reg   [127 :0]    local_wdata;
 
reg [2:0] local_state;
reg [7:0] local_cnt;
reg [127:0] local_readdata;
 
parameter IDLE          = 0,
              IDLE0         = 1,
              BURST_WRITE = 2,
              IDLE1      = 3,
              BURST_READ     = 4,
              END        = 5;      
              
always @(posedge phy_clk)
     if (~rst_n)
     begin
         local_state <= IDLE0;
         local_cnt   <= 0;
     end
     else
         case (local_state)
         IDLE:
         begin
             if (local_init_done & local_ready)
                 local_state <= IDLE0;
             else
                 local_state <= IDLE;
             local_burstbegin <= 1'b0;
             local_write_req  <= 1'b0;
             local_cnt         <= 0;
             local_wdata       <= 128'h0; 
             local_address     <= 26'd32; 
         end
         IDLE0:
         begin
             if (local_init_done & local_ready)
                 local_state <= BURST_WRITE;
             else
                 local_state <= IDLE0;
             local_burstbegin <= 1'b0;
             local_write_req  <= 1'b0;
             local_cnt         <= local_cnt;
             local_wdata       <= local_wdata;
             local_address     <= local_address;
         end
         BURST_WRITE:
         begin
             if (local_cnt<=0)
                 local_burstbegin <= 1'b1;
             else
                 local_burstbegin <= 1'b0;
                 
             local_write_req  <= 1'b1;
             local_wdata      <= local_wdata + 1;
             local_read_req    <= 1'b0;
             local_address     <= 26'd32;
             
                 
             if (local_cnt>=(BURST_LEN-1))
             begin
                 local_state <= IDLE1;
                 local_cnt <= 0;
             end
             else
             begin
                 local_state <= BURST_WRITE;
                 local_cnt <= local_cnt + 1'b1;
             end
         end
         IDLE1:
         begin
             if (local_init_done & local_ready)
                 local_state <= BURST_READ;
             else
                 local_state <= IDLE1;
             local_burstbegin <= 1'b0;
             local_write_req  <= 1'b0;
             local_cnt         <= local_cnt;  
             local_address     <= 26'h0;      
         end
         BURST_READ:
         begin
             local_burstbegin <= 1'b1;
             local_write_req  <= 1'b0;
             local_read_req    <= 1'b1;
             local_cnt         <= local_cnt;
             local_state       <= END;
             local_address     <= 26'd32;
         end
         END:
         begin
             local_burstbegin <= 0;
             local_write_req  <= 0;
             local_read_req   <= 0;
             local_address     <= 0;
             
             if (local_cnt>=8'h7f)
             begin
                     local_state <= IDLE;
                     local_cnt   <= 0;
             end
             else
             begin
                     local_state <= END;
                     local_cnt <= local_cnt + 1'b1;
             end
             
             if (local_rdata_valid)
                 local_readdata <= local_rdata;
             else
                 local_readdata <= 0;
                 
         end
         default
         begin
             local_burstbegin <= 1'b0;
             local_write_req  <= 1'b0;
             local_read_req    <= 1'b0;
             local_cnt         <= 0;
             local_state       <= IDLE0;
             local_address     <= 26'h0;
         end
         endcase


5.测试结果

wKiom1e229qyntFtAAAVSqtaPEk241.png


本文转自 shugenyin 51CTO博客,原文链接:http://blog.51cto.com/shugenyin/1840396


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值