DDR3 MIG IP核仿真与学习
MIG IP核介紹
在Xilinx系列的FPGA中,為了方便用戶對DDR進(jìn)行讀寫,官方提供了用于訪問DDR的IP核MIG,全稱為Memory Interface Generator,具體可參考賽靈思官方文檔參考手冊:ug586(7 Series Devices Memory Interface Solutions v4.1)。下圖是MIG IP核的架構(gòu),從圖中可以看出,MIG主要有面向用戶的端口和面向DDR的端口,用戶通過使用MIG能夠通過用戶端口的信號,來完成對DDR SDRAM的訪問,達(dá)到簡化操作的目的。
在本文中,我們僅關(guān)注某些面向用戶的端口,即以下端口:
clk,rst
app_addr,app_cmd,app_en,app_rdy
app_wdf_wren,app_wdf_end,app_wdf_rdy,app_wdf_data
app_rd_data,app_rd_data_valid
其中,第一行信號為全局的時鐘和復(fù)位信號,第二行信號為命令通道信號,用于發(fā)出讀寫命令,第三行信號為寫數(shù)據(jù)通道信號,最后一行信號為讀數(shù)據(jù)通道信號。
命令通道
如上圖所示,app_cmd用于指定是何命令,3’b000為寫命令,而3’b001為讀命令,app_addr為相應(yīng)的讀寫地址,命令只會在app_en和app_rdy同時為高時,才會被接受。
讀數(shù)據(jù)通道
如上圖所示,讀數(shù)據(jù)的時序比較簡單,當(dāng)讀命令發(fā)出后,過若干時鐘周期,app_rd_data_valid信號便會拉高,此時對應(yīng)的app_rd_data就是讀出的數(shù)據(jù)。
寫數(shù)據(jù)通道
上圖是一張MIG控制器的寫時序圖和官方對這幾種寫操作的解釋,通過官方文檔的介紹我們可以知道寫入的數(shù)據(jù)可以在寫命令給出之前,之時或者之后給出,但是在寫命令之后給出的寫數(shù)據(jù)不能超過兩個時鐘周期。在寫命令之前給出寫數(shù)據(jù)則沒有這些限制。之所以能過這樣操作,是因為在IP核內(nèi)部有寫入數(shù)據(jù)的FIFO能夠?qū)?shù)據(jù)實現(xiàn)緩沖。
在本文中,我們采用1這種方式的數(shù)據(jù)寫入。
DDR3 MIG實驗
在本實驗中,我們實現(xiàn)了一個接口轉(zhuǎn)換:將MIG用戶側(cè)的app_*接口信號轉(zhuǎn)化為AXI4接口信號,以供用戶更方便的進(jìn)行調(diào)用。
轉(zhuǎn)化的代碼如下:
我們通過MIG IP提供的DDR3仿真模型進(jìn)行仿真,如下圖所示,只需添加ddr3_model.sv和ddr3_model_parameters.vh文件至仿真平臺即可。
下面的代碼用于產(chǎn)生AXI4測試信號:
axi4_master.sv
整個工程的頂層文件top.sv為:
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2022/01/03 14:22:32 // Design Name: // Module Name: top // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // //module top( input sys_clk, //???�� input sys_rst_n, //��λ,����Ч // DDR3 inout [15:0] ddr3_dq, //DDR3 ���� inout [1:0] ddr3_dqs_n, //DDR3 dqs�� inout [1:0] ddr3_dqs_p, //DDR3 dqs�� output [13:0] ddr3_addr, //DDR3 ��? output [2:0] ddr3_ba, //DDR3 banck ?�� output ddr3_ras_n, //DDR3 ��?�� output ddr3_cas_n, //DDR3 ��?�� output ddr3_we_n, //DDR3 ��д?�� output ddr3_reset_n, //DDR3 ��λ output [0:0] ddr3_ck_p, //DDR3 ?���� output [0:0] ddr3_ck_n, //DDR3 ?�?� output [0:0] ddr3_cke, //DDR3 ?��?�� output [0:0] ddr3_cs_n, //DDR3 ?? output [1:0] ddr3_dm, //DDR3_dm output [0:0] ddr3_odt //DDR3_odt);//axi接口 logic ACLK; logic ARESETn; //讀地址通道 logic [31:0] ARADDR; logic [7:0] ARLEN; logic ARVALID; logic ARREADY; //讀數(shù)據(jù)通道 logic [127:0] RDATA; logic [1:0] RRESP; logic RLAST; logic RVALID; logic RREADY; //寫地址通道 logic [31:0] AWADDR; logic [7:0] AWLEN; logic AWVALID; logic AWREADY; //寫數(shù)據(jù)通道 logic [127:0] WDATA; logic [15:0] WSTRB; logic WLAST; logic WVALID; logic WREADY; //寫應(yīng)答通道 logic [1:0] BRESP; logic BVALID; logic BREADY; //mig接口 logic app_rdy; logic app_wdf_rdy; logic app_rd_data_valid; logic [127:0] app_rd_data; logic [27:0] app_addr; logic app_en; logic app_wdf_wren; logic app_wdf_end; logic [2:0] app_cmd; //3'b000為寫數(shù)據(jù),3'b001為讀數(shù)據(jù) logic [127:0] app_wdf_data; logic init_calib_complete; // logic clk_200; logic ui_clk; logic ui_clk_sync_rst; logic locked; // assign ACLK=ui_clk; assign ARESETn=~ui_clk_sync_rst; //ddr側(cè)信號 // logic ddr3_addr (ddr3_addr), // output [14:0] ddr3_addr // logic ddr3_ba (ddr3_ba), // output [2:0] ddr3_ba // logic ddr3_cas_n (ddr3_cas_n), // output ddr3_cas_n // logic ddr3_ck_n (ddr3_ck_n), // output [0:0] ddr3_ck_n // logic ddr3_ck_p (ddr3_ck_p), // output [0:0] ddr3_ck_p // logic ddr3_cke (ddr3_cke), // output [0:0] ddr3_cke // logic ddr3_ras_n (ddr3_ras_n), // output ddr3_ras_n // logic ddr3_reset_n (ddr3_reset_n),// output ddr3_reset_n // logic ddr3_we_n (ddr3_we_n), // output ddr3_we_n // logic ddr3_dq (ddr3_dq), // inout [31:0] ddr3_dq // logic ddr3_dqs_n (ddr3_dqs_n), // inout [3:0] ddr3_dqs_n // logic ddr3_dqs_p (ddr3_dqs_p), // inout [3:0] ddr3_dqs_p // logic ddr3_cs_n (ddr3_cs_n), // output [0:0] ddr3_cs_n // logic ddr3_dm (ddr3_dm), // output [3:0] ddr3_dm // logic ddr3_odt (ddr3_odt), // output [0:0] ddr3_odt//模塊例化 axi4_master U1( .ACLK(ACLK), .ARESETn(ARESETn), //讀地址通道 .ARADDR(ARADDR), .ARLEN(ARLEN), .ARVALID(ARVALID), .ARREADY(ARREADY), //讀數(shù)據(jù)通道 .RVALID(RVALID), .RDATA(RDATA), .RRESP(RRESP), .RLAST(RLAST), .RREADY(RREADY), //寫地址通道 .AWADDR(AWADDR), .AWLEN(AWLEN), .AWVALID(AWVALID), .AWREADY(AWREADY), //寫數(shù)據(jù)通道 .WDATA(WDATA), .WSTRB(WSTRB), .WLAST(WLAST), .WVALID(WVALID), .WREADY(WREADY), //寫應(yīng)答通道 .BRESP(BRESP), .BVALID(BVALID), .BREADY(BREADY), //初始化完成信號 .init_calib_complete(init_calib_complete) );mig2axi4 U2( //AXI4接口 //全局信號 .ACLK(ACLK), .ARESETn(ARESETn), //讀地址通道 .ARADDR(ARADDR), .ARLEN(ARLEN), .ARSIZE(), //2^7=128 .ARBURST(), .ARPROT(), .ARVALID(ARVALID), .ARREADY(ARREADY), //讀數(shù)據(jù)通道 .RVALID(RVALID), .RDATA(RDATA), .RRESP(RRESP), .RLAST(RLAST), .RREADY(RREADY), //寫地址通道 .AWADDR(AWADDR), .AWLEN(AWLEN), .AWSIZE(), .AWBURST(), .AWPROT(), .AWVALID(AWVALID), .AWREADY(AWREADY), //寫數(shù)據(jù)通道 .WDATA(WDATA), .WSTRB(WSTRB), .WLAST(WLAST), .WVALID(WVALID), .WREADY(WREADY), //寫應(yīng)答通道 .BRESP(BRESP), .BVALID(BVALID), .BREADY(BREADY), //MIG側(cè)接口 .ui_clk(ui_clk), .ui_clk_sync_rst(ui_clk_sync_rst), .init_calib_complete(init_calib_complete), .app_rdy(app_rdy), .app_wdf_rdy(app_wdf_rdy), .app_rd_data_valid(app_rd_data_valid), .app_rd_data(app_rd_data), .app_addr(app_addr), .app_en(app_en), .app_wdf_wren(app_wdf_wren), .app_wdf_end(app_wdf_end), .app_cmd(app_cmd), //3'b000為寫數(shù)據(jù),3'b001為讀數(shù)據(jù) .app_wdf_data(app_wdf_data));mig_7series_0 u_mig_7series_0 (// Memory interface ports.ddr3_addr (ddr3_addr), // output [14:0] ddr3_addr.ddr3_ba (ddr3_ba), // output [2:0] ddr3_ba.ddr3_cas_n (ddr3_cas_n), // output ddr3_cas_n.ddr3_ck_n (ddr3_ck_n), // output [0:0] ddr3_ck_n.ddr3_ck_p (ddr3_ck_p), // output [0:0] ddr3_ck_p.ddr3_cke (ddr3_cke), // output [0:0] ddr3_cke.ddr3_ras_n (ddr3_ras_n), // output ddr3_ras_n.ddr3_reset_n (ddr3_reset_n),// output ddr3_reset_n.ddr3_we_n (ddr3_we_n), // output ddr3_we_n.ddr3_dq (ddr3_dq), // inout [31:0] ddr3_dq.ddr3_dqs_n (ddr3_dqs_n), // inout [3:0] ddr3_dqs_n.ddr3_dqs_p (ddr3_dqs_p), // inout [3:0] ddr3_dqs_p.init_calib_complete (init_calib_complete), // init_calib_complete.ddr3_cs_n (ddr3_cs_n), // output [0:0] ddr3_cs_n.ddr3_dm (ddr3_dm), // output [3:0] ddr3_dm.ddr3_odt (ddr3_odt), // output [0:0] ddr3_odt// Application interface ports.app_addr (app_addr), // input [28:0] app_addr.app_cmd (app_cmd), // input [2:0] app_cmd.app_en (app_en), // input app_en.app_wdf_data (app_wdf_data),// input [255:0] app_wdf_data.app_wdf_end (app_wdf_end), // input app_wdf_end.app_wdf_wren (app_wdf_wren),// input app_wdf_wren.app_rd_data (app_rd_data), // output [255:0]app_rd_data.app_rd_data_end (app_rd_data_end), // output app_rd_data_end.app_rd_data_valid (app_rd_data_valid), // output app_rd_data_valid.app_rdy (app_rdy), // output app_rdy.app_wdf_rdy (app_wdf_rdy), // output app_wdf_rdy.app_sr_req (1'b0), // input app_sr_req.app_ref_req (1'b0), // input app_ref_req.app_zq_req (1'b0), // input app_zq_req.app_sr_active (app_sr_active),// output app_sr_active.app_ref_ack (app_ref_ack), // output app_ref_ack.app_zq_ack (app_zq_ack), // output app_zq_ack.ui_clk (ui_clk), // output ui_clk.ui_clk_sync_rst (ui_clk_sync_rst), // output ui_clk_sync_rst.app_wdf_mask (31'b0), // input [31:0] app_wdf_mask// System Clock Ports.sys_clk_i (clk_200),// Reference Clock Ports.clk_ref_i (clk_200),.sys_rst (sys_rst_n) // input sys_rst);//PLL?�� clk_wiz_0 u_clk_wiz_0(// Clock out ports.clk_out1(clk_200), // output clk_out1// Status and control signals.reset(1'b0), // input resetn.locked(locked), // output locked// Clock in ports.clk_in1(sys_clk)); endmodule測試平臺文件編寫如下,只需例化top模塊和ddr3仿真模型模塊即可:
test_tb.sv
下圖是整個工程的RTL視圖,它很好的揭示了上述代碼之間的關(guān)系:
結(jié)果分析
AXI4寫數(shù)據(jù)波形圖
可以看到,當(dāng)app_rdy、app_wdf_rdy(表明ddr已經(jīng)準(zhǔn)備好接收數(shù)據(jù))以及WVALID信號(表示要寫的數(shù)據(jù)已經(jīng)有效)同時為高時,app_en、app_wdf_wren、WREADY信號均被拉高,開始寫入一個數(shù)據(jù)。
AXI4讀數(shù)據(jù)波形圖
寫命令
如圖所示,app_cmd為3’b001,app_en,app_rdy均為高,表示該讀命令已被接受,而app_addr為要讀的數(shù)據(jù)的地址。
讀數(shù)據(jù)
如圖所示,MIG將讀取的數(shù)據(jù)先存入緩存中,然后再將緩存中的數(shù)據(jù)通過AXI4的讀數(shù)據(jù)通道發(fā)送給主機。(通過使用FIFO可以進(jìn)一步增大讀數(shù)據(jù)的效率)
總結(jié)
以上是生活随笔為你收集整理的DDR3 MIG IP核仿真与学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: machine id linux,lin
- 下一篇: 重学算法第三期|数据结构与算法001