基於ISE的DDR3控制器IP核調取及初始化
的建立
1、先在文件夾中建立三個文件分別存放工程文件和設計文檔還有設計代碼:
2、打開ise,點擊new project新建一個工程
3、工程名字叫ddr3_ctrl,工程存放位置放在剛剛建好的文件夾ise_prj中,點next.
4、晶元選擇根據自己開發板選擇,next.finish
5、這樣一個ddr3工程就已經建立好了
接下來我們開始對DDR3IP核進行調取,大家在調用IP核時候先把工程建立好。
1、IP核在這裡,在這裡大家會看到這裡是灰的,這是為什麼呢,這是因為我們在調取這個IP核的時候需要為IP核建立一個工程。
2、我們點擊IP核界面的newproject,新建個IP核工程,路徑為放到默認位置就可以
3、接下來晶元選擇還是選擇之前的一樣
4、這時候就會看到IP核亮了
雙擊下面這個選項
5、新建一個設計
6、下一步,可以看到bank1和bank3中,這個晶元可以掛兩個ddr3晶元。我們在這裡就選一個
7、接下來是選擇晶元型號
8、如果這裡沒有我們想要的型號,我們可以基於這個型號來新建一個自己的型號,下面的對應的參數自己找數據手冊進行修改
9、下面這個界面是ddr3引出來的用戶介面,可以自由配置為雙向口還是單向口,
這裡我選擇了兩個口,讀寫,每個口32bit位寬。一路下一步
這樣IP核就調取成功了
DDR3 SDRAM控制器IP核的初始化
1、在design裡面建立一個控制文件添加到工程
2、把我們上節課調取的ddr3的IP核文件添加進來
3、文件添加完成之後點擊我們的ip核文件mig_39_2.xco,可以找到我們的例化模板,把我們的例化模板複製出來,添加到ddr3_ctrl.v文件中來。
4、然後對ddr3_ctrl.v文件中的例化信號進行定義位寬,這些信號位寬大小可以從IP核文件夾中找到,打開,然後把這個.v文件中的埠複製出來粘貼到頂層ddr3_ctrl.v端
5、再調取一個pll,輸入時鐘50M,輸出333.333MHZ,再把時鐘IP核.xco文件加入。
6、再把IP核文件夾中的模擬模型兩個文件加入sim文件夾,並且加進來工程裡面,否則會報錯
7、然後對文件進行分類,工程文件和模擬文件,點擊需要分類的文件,選擇source properties
這樣就可以進行分類了
如圖所示:
控制代碼如下:
moduleddr3_ctrl(
inputwiresclk,
inputwirerst_n,
inout[15:]mcb1_dram_dq,
output[13:]mcb1_dram_a,//地址匯流排
output[2:]mcb1_dram_ba,//bank地址
outputmcb1_dram_ras_n,
outputmcb1_dram_cas_n,
outputmcb1_dram_we_n,
outputmcb1_dram_odt,
outputmcb1_dram_reset_n,
outputmcb1_dram_cke,
outputmcb1_dram_dm,
inoutmcb1_dram_udqs,
inoutmcb1_dram_udqs_n,
inoutmcb1_rzq,
inoutmcb1_zio,
outputmcb1_dram_udm,
inoutmcb1_dram_dqs,
inoutmcb1_dram_dqs_n,
outputmcb1_dram_ck,
outputmcb1_dram_ck_n//mcb1開頭的都是需要綁定引腳的信號
);
wireclk_333MHz;
wirec1_calib_done;//初始化成功的匹配信號,為1表示初始化成功
wirec1_clk0;//IP核生成的時鐘和複位,用戶可以使用也可以不用,
wirec1_rst0;//在這裡我們不用,所以做成了一個內部變數
//這些介面都是不希望引出開發板的,我們把它做成內部變數。
wirec1_p2_cmd_clk;//這些p2口和p3口都是IP核給我們預留的fifo的介面
wirec1_p2_cmd_en;
wire[2:]c1_p2_cmd_instr;
wire[5:]c1_p2_cmd_bl;
wire[29:]c1_p2_cmd_byte_addr;
wirec1_p2_cmd_empty;//
wirec1_p2_cmd_full;
wirec1_p2_wr_clk;
wirec1_p2_wr_en;
wire[3:]c1_p2_wr_mask;
wire[31:]c1_p2_wr_data;
wirec1_p2_wr_full;
wirec1_p2_wr_empty;
wire[6:]c1_p2_wr_count;
wirec1_p2_wr_underrun;
wirec1_p2_wr_error;
wirec1_p3_cmd_clk;
wirec1_p3_cmd_en;
wire[2:]c1_p3_cmd_instr;
wire[5:]c1_p3_cmd_bl;
wire[29:]c1_p3_cmd_byte_addr;
wirec1_p3_cmd_empty;
wire c1_p3_cmd_full ;
wire c1_p3_rd_clk ;
wire c1_p3_rd_en ;
wire [31:0] c1_p3_rd_data ;
wire c1_p3_rd_full ;
wire c1_p3_rd_empty ;
wire [6:0] c1_p3_rd_count ;
wire c1_p3_rd_overflow ;
wire c1_p3_rd_error ;
//clock
clk_wiz_v3_6clk_wiz_v3_6_inst
(// Clock in ports
.CLK_IN1(sclk), // IN50M時鐘
// Clock out ports
.CLK_OUT1(clk_333MHz)); // OUT333.333MHZ
//ddr3 controller
mig_39_2 # (
.C1_P0_MASK_SIZE(4),
.C1_P0_DATA_PORT_SIZE(32),
.C1_P1_MASK_SIZE(4),
.C1_P1_DATA_PORT_SIZE(32),
.DEBUG_EN(0),
.C1_MEMCLK_PERIOD(3000),
.C1_CALIB_SOFT_IP("TRUE"),
.C1_SIMULATION("FALSE"),
.C1_RST_ACT_LOW(1),//這個複位和我們的rst_n複位要匹配,可以查找IP核文件找到
.C1_INPUT_CLK_TYPE("SINGLE_ENDED"),
.C1_MEM_ADDR_ORDER("ROW_BANK_COLUMN"),
.C1_NUM_DQ_PINS(16),
.C1_MEM_ADDR_WIDTH(14),
.C1_MEM_BANKADDR_WIDTH(3)
)
u_mig_39_2 (
.c1_sys_clk (clk_333MHz),//需要傳進來的333.333M的時鐘
.c1_sys_rst_i (rst_n), //需要傳進來的複位
.mcb1_dram_dq (mcb1_dram_dq),
.mcb1_dram_a (mcb1_dram_a),
.mcb1_dram_ba (mcb1_dram_ba),
.mcb1_dram_ras_n (mcb1_dram_ras_n),
.mcb1_dram_cas_n (mcb1_dram_cas_n),
.mcb1_dram_we_n (mcb1_dram_we_n),
.mcb1_dram_odt (mcb1_dram_odt),
.mcb1_dram_cke (mcb1_dram_cke),
.mcb1_dram_ck (mcb1_dram_ck),
.mcb1_dram_ck_n (mcb1_dram_ck_n),
.mcb1_dram_dqs (mcb1_dram_dqs),
.mcb1_dram_dqs_n (mcb1_dram_dqs_n),
.mcb1_dram_udqs (mcb1_dram_udqs), // for X16 parts
.mcb1_dram_udqs_n (mcb1_dram_udqs_n), // for X16 parts
.mcb1_dram_udm (mcb1_dram_udm), // for X16 parts
.mcb1_dram_dm (mcb1_dram_dm),
.mcb1_dram_reset_n (mcb1_dram_reset_n),
.c1_clk0 (c1_clk0),
.c1_rst0 (c1_rst0),
.c1_calib_done (c1_calib_done),
.mcb1_rzq (mcb1_rzq),
.mcb1_zio (mcb1_zio),
.c1_p2_cmd_clk (clk_100MHz ),
.c1_p2_cmd_en (c1_p2_cmd_en ),
.c1_p2_cmd_instr (3"b000 ),//write cmd
.c1_p2_cmd_bl (c1_p2_cmd_bl ),//0~63
.c1_p2_cmd_byte_addr (c1_p2_cmd_byte_addr),//4*32/8=16 0~15
.c1_p2_cmd_empty (c1_p2_cmd_empty),
.c1_p2_cmd_full (c1_p2_cmd_full),
.c1_p2_wr_clk (clk_100MHz ),
.c1_p2_wr_en (c1_p2_wr_en),
.c1_p2_wr_mask (c1_p2_wr_mask),
.c1_p2_wr_data (c1_p2_wr_data),
.c1_p2_wr_full (c1_p2_wr_full),
.c1_p2_wr_empty (c1_p2_wr_empty),
.c1_p2_wr_count (c1_p2_wr_count),
.c1_p2_wr_underrun (c1_p2_wr_underrun),
.c1_p2_wr_error (c1_p2_wr_error),
.c1_p3_cmd_clk (clk_100MHz ),
.c1_p3_cmd_en (c1_p3_cmd_en ),
.c1_p3_cmd_instr (3"b001 ),
.c1_p3_cmd_bl (c1_p3_cmd_bl),
.c1_p3_cmd_byte_addr (c1_p3_cmd_byte_addr),
.c1_p3_cmd_empty (c1_p3_cmd_empty),
.c1_p3_cmd_full (c1_p3_cmd_full),
.c1_p3_rd_clk (clk_100MHz),
.c1_p3_rd_en (c1_p3_rd_en),
.c1_p3_rd_data (c1_p3_rd_data),
.c1_p3_rd_full (c1_p3_rd_full),
.c1_p3_rd_empty (c1_p3_rd_empty),
.c1_p3_rd_count (c1_p3_rd_count),
.c1_p3_rd_overflow (c1_p3_rd_overflow),
.c1_p3_rd_error (c1_p3_rd_error)
);
endmodule
模擬代碼如下:模擬模型的連線,可以去調取IP核端找到sim_tb_top,裡面有模擬模型的連線方式,複製出來粘貼到tb.v中。
`timescale1ns/1ns
moduletb();
regsclk;
regrst_n;
wire[15:]mcb1_dram_dq;
wire[13:]mcb1_dram_a;
wire[2:]mcb1_dram_ba;
wiremcb1_dram_ras_n;
wiremcb1_dram_cas_n;
wiremcb1_dram_we_n;
wiremcb1_dram_odt;
wiremcb1_dram_reset_n;
wiremcb1_dram_cke;
wiremcb1_dram_dm;
wiremcb1_dram_udqs;
wiremcb1_dram_udqs_n;
wiremcb1_rzq;
wiremcb1_zio;
wiremcb1_dram_udm;
wiremcb1_dram_dqs;
wiremcb1_dram_dqs_n;
wiremcb1_dram_ck;
wiremcb1_dram_ck_n;
initial
begin
sclk=1"b1;
rst_n
#200
rst_n
end
always#10sclk=~sclk;
// Instantiate the module
ddr3_ctrl ddr3_ctrl_inst(
.sclk(sclk),
.rst_n(rst_n),
.mcb1_dram_dq(mcb1_dram_dq),
.mcb1_dram_a(mcb1_dram_a),
.mcb1_dram_ba(mcb1_dram_ba),
.mcb1_dram_ras_n(mcb1_dram_ras_n),
.mcb1_dram_cas_n(mcb1_dram_cas_n),
.mcb1_dram_we_n(mcb1_dram_we_n),
.mcb1_dram_odt(mcb1_dram_odt),
.mcb1_dram_reset_n(mcb1_dram_reset_n),
.mcb1_dram_cke(mcb1_dram_cke),
.mcb1_dram_dm(mcb1_dram_dm),
.mcb1_dram_udqs(mcb1_dram_udqs),
.mcb1_dram_udqs_n(mcb1_dram_udqs_n),
.mcb1_rzq(mcb1_rzq),
.mcb1_zio(mcb1_zio),
.mcb1_dram_udm(mcb1_dram_udm),
.mcb1_dram_dqs(mcb1_dram_dqs),
.mcb1_dram_dqs_n(mcb1_dram_dqs_n),
.mcb1_dram_ck(mcb1_dram_ck),
.mcb1_dram_ck_n(mcb1_dram_ck_n)
);
// Instantiate the module
ddr3_model_c1 ddr3_model_c1_inst(
.ck(mcb1_dram_ck),
.ck_n(mcb1_dram_ck_n),
.cke(mcb1_dram_cke),
.cs_n(1"b0),
.ras_n(mcb1_dram_ras_n),
.cas_n(mcb1_dram_cas_n),
.we_n(mcb1_dram_we_n),
.dm_tdqs({mcb1_dram_udm,mcb1_dram_dm}),
.ba(mcb1_dram_ba),
.addr(mcb1_dram_a),
.dq(mcb1_dram_dq),
.dqs({mcb1_dram_udqs,mcb1_dram_dqs}),
.dqs_n({mcb1_dram_udqs_n,mcb1_dram_dqs_n}),
.tdqs_n(),
.odt(mcb1_dram_odt),
.rst_n(mcb1_dram_reset_n)
);
endmodule
然後運行模擬:點擊tb.v,然後雙擊下面那個模擬按鈕,並把ddr3_ctrl中的c1_calib_done信號載入到波形中。
模擬如下:
c1_calib_done信號由變為1了,說明初始化成功。
下一步我們進行對DDR3IP核的讀寫操作控制進行講解!
TAG:電子技術站 |