本文為明德?lián)P原創(chuàng)及錄用文章,轉(zhuǎn)載請注明出處!
1.1 SDRAM簡介
SDRAM即同步動態(tài)隨機存儲器,英文為Synchronous Dynamic Random Access Memory;具有容量大、讀寫速度快、價格相對便宜等優(yōu)點,但同時控制邏輯比較復(fù)雜。
1.1.1 SDRAM示意圖
其管腳圖如下所示:
1.1.2 信號說明
信號名 |
信號說明 |
clk |
SDRAM工作時鐘 |
cke |
時鐘使能信號 |
cs_n |
用于屏蔽和使能所有輸入端口,但不包括CLK,CKE和DQM,低電平有效 |
cas_n |
列地址選通 |
ras_na |
行地址選通 |
we_n |
寫使能,該信號為低時,使能寫操作和預(yù)充電 |
ba |
bank地址 |
a |
地址總線 |
dqm |
數(shù)據(jù)掩碼 |
dq |
數(shù)據(jù)總線 |
1.1.3 SDRAM中心對齊原則
SDRAM的命令與時鐘上升沿是中心對齊的,本設(shè)計采用鎖相環(huán)生成SDRAM工作時鐘,SDRAM與初始化模塊工作時鐘相差180°。這樣FPGA產(chǎn)生的信號到SDRAM正好中心對齊,如下圖所示:
1.1.4 SDRAM初始化時序
SDRAM初始化時序如上圖所示,sdr_cmd命令由sdr_cs_n, sdr_ras_n, sdr_cas_n, sdr_we_n組合而成;復(fù)位后要延時最少100us后才能工作;當(dāng)A10為高時可以對所有bank進(jìn)行操作;當(dāng)?shù)竭_(dá)Tp+3時需要將init_done拉高。
其模式寄存器配置如上圖所示,主要參數(shù)設(shè)置如下:
a. 模式寄存器的配置是確定SDRAM的工作模式
b. A2、A1、A0用作設(shè)置突發(fā)長度,本項目設(shè)置為4
c. A3用作設(shè)置突發(fā)類型,本項目設(shè)置為Sequential順序類型
d. A6、A5、A4用作設(shè)置列選通潛伏期,本項目設(shè)置為3
e. A8、A7設(shè)置操作模式,一般為00
f. A9設(shè)置寫突發(fā)模式,本項目為0
g. A12、A11、A10設(shè)置為0
1.2 頂層模塊設(shè)計
1.2.1 SDRAM頂層模塊管腳圖
1.2.2 信號說明
信號 |
說明 |
local_addr |
本地地址由行地址列地址bank地址組合而成 |
local_data |
寫入數(shù)據(jù) |
local_q |
讀出數(shù)據(jù) |
local_rdreq |
讀請求 |
local_wrreq |
寫請求 |
local_reday |
可以進(jìn)行讀寫信號 |
local_rdata_valid |
讀數(shù)據(jù)有效信號 |
init_done |
初始化完成信號 |
clk |
輸入時鐘 |
rst_n |
系統(tǒng)復(fù)位 |
sdr_dq |
SDRAM數(shù)據(jù)總線,雙向端口 |
sdr_clk |
SDRAM工作時鐘 |
sdr_cke |
SDRAM時鐘使能 |
sdr_cs_n |
片選信號 |
sdr_cas_n |
列地址選通 |
sdr_ras_n |
行地址選通 |
sdr_we_n |
寫使能,該信號為低時,使能寫操作和預(yù)充電 |
sdr_ba |
SDRAM bank地址 |
sdr_a |
SDRAM地址總線 |
sdr_dqm |
數(shù)據(jù)掩碼 |
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 初始化模塊設(shè)計
1.3.1 SDRAM出計劃模塊管腳圖
1.3.2 信號說明
信號 |
說明 |
clk |
初始化模塊工作時鐘(100MHz) |
rst_n |
復(fù)位 |
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 );
//參數(shù)定義 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設(shè)置
最后對代碼進(jìn)行仿真,modelsim生成的報告如下所示,說明初始化設(shè)置成功。
以上就是SDRAM控制器初始化設(shè)計的思考步驟以及相關(guān)代碼,更多FPGA資料可以進(jìn)入明德?lián)P論壇進(jìn)行學(xué)習(xí)交流(http://www.fpgabbs.cn/),明德?lián)P專注FPGA設(shè)計研究,對FPGA學(xué)習(xí)感興趣的朋友快快聯(lián)系我們吧!