天天看點

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

本文設計思路與講解于參考鄧堪文老師的視訊,感謝…(不太适合一點基礎都沒有的小白)

SDRAM簡介

SDRAM(synchronous Dynamic Random ),同步動态随機存儲器,同步指記憶體工作需要同步時鐘,記憶體的指令的發送和資料的接收都以它為标準。動态是指需要不斷地重新整理來保證資料不丢失(電容存儲),随機指的是儲存位置可以随機指定,自由儲存。

這裡引薦博文DDR3詳解

這裡是我買黑金闆子裡帶的資料

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

SDRAM儲存計算方式

SDRAM 的空間 = 4(資源庫-Bank)× 2^12 行×2^8 列(尋址深度)× 16 bits

= 4 × 1048576 × 16 bits

= 4 × 1048576 / 1024 × 16 bits

= 4 × 1024 K / 1024 × 16bits

= 4 × 1M × 16 bits

= 64Mbits 或者 67,108,864 bits

常用單詞總結

  • row 行
  • column 列
  • nop(no operation) 無操作
  • precharge 預充電
  • outorefresh 自動重新整理
    基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化
    這裡還有資料手冊裡邊有一些有關單詞的解釋描述(帶"—"表示低電平有效)

資料手冊分析(及時序分析)

時鐘産生

這裡首先看一下時鐘的産生

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

因為需要讀取資料在時鐘的上升沿。這裡和iic裡邊也有點類似,為了使SDRAM時鐘采集為資料的中點。視訊裡講的是要求把系統時鐘反轉,反轉後的時鐘作為SDRAM時鐘。

從仿真截圖可以看出,反轉後SDRAM時鐘采樣點恰好為資料中點。進而達到要求。

時序圖

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

設計時序

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

可以看出這是初始化的模式寄存器配置的時序圖(program mode register 暫時不去考慮-後續博文填坑)

接下來看語言描述

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

100us的延時需要在任何操作之前除過NOP和INHIBIT指令。這兩個指令必須在200us期間應用并且持續在這個區間結束後。(這句話不懂什麼意思)在滿足上述條件後,precharge指令應該被應用在100us延時以後。所有的bank必須預充電,這将使得所有的bank進入idle狀态。在兩個auto refresh指令之後,SDRAM準備進行模式寄存器配置。

就是說這裡需要上電後進行**(1)最少200us的延時。之後所有bank進入idle狀态,然後進行(2)兩次auto refresh 狀态。之後對其進行(3)**模式寄存器配置。

即完成操作。下面看各個操作的時間間隔。

時間間隔

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

trp的最大時間間隔就是20ns

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化
基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化
基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

以上就是所有的時序需要知道的時間間隔。

COMMAND 與 LOAD MODE REGISTER

同樣看資料手冊

LOAD MODE REGISTER

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

在模式寄存器配置在A0到A12,隻有在所有bank空閑狀态這個指令才可以被發出。可以看出,這裡通過A0-A12來進行配置模式寄存器。

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

突發長度(連續讀出寫入資料的長度),突發類型,cas潛伏期,操作模式,寫突發所有作為模式寄存器定義。

先來看看每一個是什麼意思(這裡有詳細的介紹)

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

這裡解釋下潛伏期。(簡單了解就是讀使能信号來了之後資料輸出的延時,時序圖如下)

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

這裡是資料手冊對突發類型的解釋。突發類型,就是讀數的映射讀數方法

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

COMMAND

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化

代碼書寫

接下來就是代碼實作。了解起來開始這個不會很難。

module sdram_init(
	//system singles
	clk,rst_n,
	//others singles
	cmd_reg,sdram_addr,flag_init_end
    );
input 					clk 			;
input 					rst_n 			;
output [ 3:0] 			cmd_reg 		;
output [11:0] 			sdram_addr 		;
output 					flag_init_end 	;
reg 	[ 3:0]			cmd_reg 		;
reg 					flag_init_end	;
//*************************************************\
//define parameter and intennal singles
//*************************************************/
localparam DELAY_200US = 10000 	;
reg  [13:0] 	cnt_200us  		;
reg  [ 3:0]		cnt_cmd			;
wire 			flag_200us		;
//sdram command
localparam NOP  = 4'b0111		;
localparam PRE  = 4'b0010		;
localparam AREF = 4'b0001		;
localparam MSET = 4'b0000		;
//*************************************************\
//main code
//*************************************************/
//200us_cnt
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cnt_200us <= 14'd0;
	else 
		if(!flag_200us)
			cnt_200us <= cnt_200us + 1'b1;
end

assign flag_200us = (cnt_200us >= DELAY_200US) ? 1'b1 : 1'b0;

//cnt_cmd
always @ (posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cnt_cmd <= 'd0;
	else 
		if(flag_200us == 1'b1 && flag_init_end == 1'b0)
			cnt_cmd <= cnt_cmd + 'd1;
end
//flag_init_end
always	@(posedge clk or negedge rst_n)	begin
		if(!rst_n)
				flag_init_end	<=	0;
		else if(cnt_cmd == 4'd10)
				flag_init_end	<=	1;	
			
end
//cmd_reg
always @ (posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cmd_reg <= NOP;
	else 
		if(flag_200us)
			case(cnt_cmd)
				0:cmd_reg <= PRE;
				1:cmd_reg <= AREF;
				5:cmd_reg <= AREF;
				9:cmd_reg <= MSET;
				default:cmd_reg <= NOP;
			endcase
end

//sdram_addr
assign	sdram_addr		=		(cmd_reg == MSET) ? 12'b0000_0011_0010 :12'b0100_0000_0000;
//突發長度為4,潛伏期為3 Burst Type       = Sequential  Write Burst Mode = Programmed Burst Length
endmodule
           

放着結果,這裡用仿真器仿真,模拟SDRAM,同時在控制台列印相關資訊

基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化
基于FPGA的SDRAM控制器設計(一)----------SDRAM初始化