DDR3 Vivado 仿真测试成功
DDR MIG IP 設置
1.默認就好了,不需要選擇AXI4 Interface ,除非你想用這個接口。
2.Clock Period:你想讓DDR3跑的時鐘,這里是400M,由于DDR3是在上升沿和下降沿都寫數(shù)據(jù),那么我們可以知道DDR3的帶寬為:400M*2*64bit=51200Mbit。
下面的PHY to Controller Clock Ratie 4:1 ,表示用戶時鐘是400M/4=100M,這個用戶時鐘,是IP核自動生成的(ui_clk)。后期的用戶接口寫數(shù)據(jù)和讀數(shù)據(jù)都是按照這個時鐘去操作。
用戶的接口數(shù)據(jù)位寬為=51200Mbit/100M=512bit
其中Memory Type 要特別的留意,DDR3有插座式的,還有貼片的。要根據(jù)不同型號的去選擇
3.這個時鐘是給DDR的參考輸入時鐘200M,其他的時鐘,都是根據(jù)這個時鐘產(chǎn)生的。(后面有一個界面設置這個時鐘的管腳位置)
4. system clock是差分時鐘
? Reference clk 直接使用 system clk
4.讀寫速率只有800M,50即可
只有超過1333M ,才使用40
一般設計DDR都會有一個ucf文件,里面包含設計DDR3的管腳約束,加載進來就可以了。
這個時鐘就是剛才說的那個200M時鐘
DDR MIG IP 接口信號
下一步之后,就生成了MIG IP接口,如下圖所示
mig_7series_0 u_mig_7series_0 (
// Memory interface ports
??? .ddr3_addr??????????? (ddr3_addr),? // output [15:0]? 行列地址,其中行地址線和列地址線是分時復用的,即地址要分兩次送出,先送出行地址,再送出列地址。
??? .ddr3_ba????????????? (ddr3_ba),? // output [2:0]? ? bank地址
??? .ddr3_cas_n?????????? (ddr3_cas_n),? // output? ?? 列地址選通????
??? .ddr3_ck_n??????????? (ddr3_ck_n),? // output [0:0]? 差分時鐘p端?????
??? .ddr3_ck_p??????????? (ddr3_ck_p),? // output [0:0]? 差分時鐘n端
??? .ddr3_cke???????????? (ddr3_cke),? // output [0:0]????? 時鐘有效信號,高電平有效
??? .ddr3_ras_n?????????? (ddr3_ras_n),? // output?? 行地址選通信號,低電平有效?????????
??? .ddr3_reset_n???????? (ddr3_reset_n),? // output???????? 復位信號,低電平有效????? ??????
??? .ddr3_we_n??????????? (ddr3_we_n),? // output 0-寫允許? 1-讀允許?
??? .ddr3_dq????????????? (ddr3_dq),? // inout [63:0] 數(shù)據(jù)????????????
??? .ddr3_dqs_n?????????? (ddr3_dqs_n),? // inout [7:0]? 數(shù)據(jù)選取脈沖??????
??? .ddr3_dqs_p?????????? (ddr3_dqs_p),? // inout [7:0]? 數(shù)據(jù)選取脈沖??????
??? .init_calib_complete? (init_calib_complete),? // output 初始化完成信號? ,高電平有效
?.ddr3_cs_n?????????(ddr3_cs_n),? // output [0:0]?? 片選信號,低表示命令有效,否則命令屏蔽???????
??? .ddr3_dm????????????? (ddr3_dm), ?// output [7:0]??? 數(shù)據(jù)掩碼 一位控制一個字節(jié)
??? .ddr3_odt???????????? (ddr3_odt),? // output [0:0] 片上終端使能,高電平有效???????
// Application interface ports
??? .app_addr???????????? (app_addr),? // input [29:0] 訪問的DDR3地址?
??? .app_cmd????????????? (app_cmd),? // input [2:0]?????? 000 寫命令? 001 讀命令??
??? .app_en?????????????? (app_en),? // input?? 命令路徑:的使能信號,該信號有效時,app_cmd、app_addr信號才有效,其余的時刻信號無效???????????????????????
??? .app_wdf_data???????? (app_wdf_data),? // input [511:0]? 寫數(shù)據(jù)路徑數(shù)據(jù)信號?
??? .app_wdf_end????????? (app_wdf_end),? // input 4:1模式下與app_wdf_wren相同,2:1模式下每兩個app_wdf_wren,使能一次 app_wdf_en。這個可以理解可參考UG586數(shù)據(jù)手冊P169 ?????? Figure 1-78/ Figure 1-79???????
??? .app_wdf_wren???????? (app_wdf_wren),? // input????? 寫數(shù)據(jù)的有效信號???????????????
??? .app_rd_data????????? (app_rd_data),? // output [511:0] ????????? 讀數(shù)據(jù)信號
??? .app_rd_data_end????? (app_rd_data_end),? // output?????? DDR3給用戶讀命令結束信號
??? .app_rd_data_valid??? (app_rd_data_valid),? // output????????????????? 讀數(shù)據(jù)有效信號?
??? .app_rdy????????????? (app_rdy),? // output???????????????? 命令路徑準備好接受用戶的命令信號,與app_en有效時命令有效???
??? .app_wdf_rdy????????? (app_wdf_rdy),? // output?????? MIG信號給用戶的信號,在該信號與app_wdf_wren信號同時有效時,數(shù)據(jù)被寫入DDR芯片????????????
??? .app_sr_req?????????? (1'b0),? // input?????????? 一般為0
??? .app_ref_req????????? (1'b0),? // input??????????? 一般為0?????????
??? .app_zq_req?????????? (1'b0),? // input????????? 一般為0?????????
??? .app_sr_active?????? ??(),? // output??????????????? 上面請求的響應信號?
??? .app_ref_ack????????? (),? // output???????????????? 上面請求的響應信號?
??? .app_zq_ack?????????? (),? // output?????????????? 上面請求的響應信號?
??? .ui_clk?????????????? (clk),? // output?? MIG給用戶使用的時鐘,用戶對MIG IP核的操作必須使用該時鐘?????????
??? .ui_clk_sync_rst????? (rst),? // output???? MIG給用戶使用的復位信號,用戶對MIG IP核的操作必須使用該復位信號?????????????
??? .app_wdf_mask???????? (64'd0),? // input [63:0]?? 寫數(shù)據(jù)的掩碼?????? ,一般為0
??? // System Clock Ports
??? .sys_clk_p???????????? (sys_clk_p),? // input???????? MIG的系統(tǒng)時鐘,在MIG的選項中選擇
??? .sys_clk_n???????????? (sys_clk_n),? // input????????????????????????????????????
??? .sys_rst?????????????? (sys_rst) // input sys_rst MIG IP核的復位信號,與系統(tǒng)時鐘相關聯(lián)
);
需要對接口信號做一個了解,包括DDR3的管腳接口,MIG 用戶接口,只需要了解 Application interface ports 接口就可以了,看懂DDR3的讀寫時序圖,這樣就可以完成對于DDR3的讀寫。
Application interface ports 接口主要包括:
控制命令接口信號app_addr,app_cmd,app_en, app_rdy
寫通道接口信號: ?app_wdf_data, .app_wdf_end, app_wdf_wren, app_wdf_rdy
讀通道接口信號:? app_rd_data, app_rd_data_end, app_rd_data_valid
DDR3 的接口信號讀寫時序
按照UG586的說明,當app_rdy為高時,將app_cmd,app_addr以及app_en拉高,此時,寫命令發(fā)出。在寫命令發(fā)出之前周期、當前周期或者之后3個周期之內(nèi),用戶可以進行寫操作。寫操作執(zhí)行過程同樣是:當app_wdf_rdy為高時,將app_wdf_data,app_wdf_wren以及app_wdf_end拉高,此時寫操作成功。
圖1寫時序
如下圖所示為讀操作的具體時序,同樣的先進行寫命令操作,時序同寫命令操作一樣。寫命令完成后的若干個周期,app_rd_data、app_rd_data_valid以及app_rd_data_end出現(xiàn)。當app_rd_data_valid為高時,用戶取數(shù)即可
圖2讀時序
DDR3讀寫的地址偏移?
做讀寫測試時一直困擾我的問題.上面說給DDR3指定一個地址,可以往這個地址里讀或寫8*n bits的數(shù)據(jù).按理說我要讀寫下一地址,只要地址加1就可以.但仿真時地址加1得到的數(shù)據(jù)都是亂的.要想正常讀寫數(shù)據(jù),需要每次地址加8,這是為什么呢?
我們可以看一下這個DDR3的內(nèi)部結構圖,從這個圖中我們可以看出10bit的Column Address的尋址能力只有128,只有7bits用于列地址譯碼!列地址0,1,2并沒有用,而這列地址的低三位被用于確定Burst Length 與Burst Order了.見下圖:
所以列地址的低三位并沒有用于尋址,所以如果我們想要訪問下一存儲單元的話,地址需要加8而不是加1
DDR3 的仿真驗證
.在我們上板子之前,最好可以通過仿真,先驗證自己的讀寫控制時序是否正確,如果沒有仿真,就直接上板,可能后期調試起來也比較麻煩。關于如何在Vivado中建立一個DDR3的仿真工程,可以參考特權同學2020版《深入淺出玩轉FPGA視頻教程》?中的DDR3 IP仿真的章節(jié)。嗶哩嗶哩上有這個課程。
在建立完工程后,我們可以把工程中example_top 文件下的
mig_7series_v4_0_traffic_gen_top 文件注釋掉,添加我們自己的讀寫控制文件,完成DDR3的仿真。本次仿真結構如下,主要想完成對于DDR3全部地址的讀寫測試。
整體設計思路如下:突發(fā)傳輸寫數(shù)據(jù)一次,然后突發(fā)讀出來,校驗數(shù)據(jù)是否正確。如果出錯,會有指示信號。
mig_ctrl #
?(
???? .DATA_WIDTH????????? (APP_DATA_WIDTH),
???? .ADDR_WIDTH????????? (ADDR_WIDTH)
?)
?mig_ctrl_inst(
// Application interface ports
?????? .clk? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (clk),
?????? .rst? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(rst),
?????? .app_addr?????????????????????? (app_addr),//output [29:0]
?????? .app_cmd??????????????????????? (app_cmd), //output [2:0]
?????? .app_en????????????????? ???????(app_en),? //output
?????? .app_wdf_data?????????????????? (app_wdf_data),//output [511:0]
?????? .app_wdf_end??????????????????? (app_wdf_end),// output
?????? .app_wdf_wren?????????????????? (app_wdf_wren),//output
?????? .app_rd_data?????????? ?????????(app_rd_data),// input [511:0]
?????? .app_rd_data_end??????????????? (app_rd_data_end),//input
?????? .app_rd_data_valid????????????? (app_rd_data_valid),//input
?????? .app_rdy??????????????????????? (app_rdy),? //input
?????? .app_wdf_rdy??? ????????????????(app_wdf_rdy), //input
?????? .init_calib_complete??????????? (init_calib_complete),
??? // user interface
?????? .wr_request???????????????????? (wr_request), //突發(fā)寫請求
?????? .wr_start_addr????????????????? (wr_start_addr),//突發(fā)寫首地址
?????? .wr_len???????????????????????? (wr_len), //突發(fā)寫長度
?????? .wr_data??????????????????????? (512'd0),//寫數(shù)據(jù),本次仿真未使用
?????? .wr_data_valid????????????????? (1'b0), //寫數(shù)據(jù)有效,本次仿真未使用
?????? .wr_finish????????????????????? (wr_finish),//一次突發(fā)完成結束信號
?????? .rd_request???????????????????? (rd_request),
?????? .rd_start_addr????????????????? (rd_start_addr),
?????? .rd_len???????????????????????? (rd_len),
?????? .rd_data??????????????????????? (rd_data),
?????? .rd_data_valid????????????????? (rd_data_valid),
?????? .rd_finish????????????????????? (rd_finish),
?????? .check_error??????????????????? (check_error)
);
test_ddr test_ddr(
???????? .clk??????????????????????????? (clk),
???????? .rst??????????????????????????? (rst),
???????? //mig_ctrl? interface
???????? .init_calib_complete?????????(init_calib_complete),
???????? .wr_request???????????????????? (wr_request),
???????? .wr_start_addr??????????????? (wr_start_addr),
???????? .wr_len? ? ? ? ? ? ? ? ? ? ? ? ? ?(wr_len),
???????? .wr_finish? ? ? ? ? ? ? ? ? ? ? ?(wr_finish),
???????? .rd_request???????????????????? (rd_request),
???????? .rd_start_addr?????????????????(rd_start_addr),
???????? .rd_len? ? ? ? ? ? ? ? ? ? ? ? ? ? (rd_len),
???????? .rd_finish? ? ? ? ? ? ? ? ? ? ? ? ?(rd_finish),
???????? .start_test_pulse?????????????? (start_test_pulse)???? //測試開始信號
);
?圖1寫時序
寫時序仿真
?
讀時序仿真結果
DDR3 仿真工程百度云盤:
鏈接:https://pan.baidu.com/s/19vtorLOS4zQPDnqX4Yzd0A
提取碼:53iz
希望可以對初學者有一定的用處,加油!FPGA一定可以學好的。
總結
以上是生活随笔為你收集整理的DDR3 Vivado 仿真测试成功的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javascript 快速入门
- 下一篇: 近世代数:群论