vfifo控制mig_MIG IP控制DDR3读写测试
本文設(shè)計(jì)思想采用明德?lián)P至簡(jiǎn)設(shè)計(jì)法。在高速信號(hào)處理場(chǎng)合下,很短時(shí)間內(nèi)就要緩存大量的數(shù)據(jù),這時(shí)片內(nèi)存儲(chǔ)資源已經(jīng)遠(yuǎn)遠(yuǎn)不夠了。DDR SDRAM因其極高的性價(jià)比幾乎是每一款中高檔FPGA開(kāi)發(fā)板的首選外部存儲(chǔ)芯片。DDR操作時(shí)序非常復(fù)雜,之所以在FPGA開(kāi)發(fā)中用途如此廣泛,都要得意于MIG IP核。網(wǎng)上關(guān)于MIG控制DDR的資料很多,因此本文只講述個(gè)人認(rèn)為較重要的內(nèi)容。由于MIG IP核用戶接口時(shí)序較復(fù)雜,這里給出擴(kuò)展接口模塊用于進(jìn)一步簡(jiǎn)化接口時(shí)序。
先來(lái)看看MIG IP核的架構(gòu):
了解下存儲(chǔ)芯片側(cè)重要接口:
ddr_addr DDR3的行列地址
ddr_ba ? ? DDR3的bank地址
ddr_cas_n ddr_ras_n ddr_we_n 命令控制
ddr_ck ddr_ck_n ?差分時(shí)鐘
ddr_dm ? 數(shù)據(jù)輸入屏蔽
ddr_o_dt 片上終端使能,用于使能和禁止片內(nèi)終端電阻
ddr_reset_n ? DDR3復(fù)位
ddr_dqs ddr_dqs_n ?數(shù)據(jù)同步信號(hào)
ddr_dq ? ?傳輸數(shù)據(jù)
之后我們從IP核配置開(kāi)始說(shuō)起。Controller Options這頁(yè)最為重要,其中包括時(shí)鐘策略和外部DDR芯片參數(shù)配置。首先時(shí)鐘周期選擇為400MHz,此時(shí)PHY to Controller Clock Ratio只能是4:1,也就是說(shuō)MIG用戶側(cè)時(shí)鐘為100MHz。下半部分是選擇合適的DDR芯片型號(hào)和參數(shù),要再三確認(rèn)無(wú)誤。
Memory Options這頁(yè)輸入時(shí)鐘周期選擇為200MHz,根據(jù)Controller Options頁(yè)的選項(xiàng),該時(shí)鐘經(jīng)過(guò)PLL分頻和倍頻后的時(shí)鐘分別作為用戶側(cè)時(shí)鐘100MHz和DDR接口時(shí)鐘400MHz。
這里有個(gè)參考時(shí)鐘選項(xiàng),如果Memory Options頁(yè)P(yáng)LL輸入時(shí)鐘頻率選為200MHz,此處可以直接選擇Use System Clock,從而簡(jiǎn)化接口。
以上是MIG IP核配置過(guò)程中較為重要的部分,實(shí)際上上述配置也可通過(guò)修改工程代碼中參數(shù)來(lái)重定義。IP核配置完成,打開(kāi)example design工程頂層文件,我們來(lái)重點(diǎn)關(guān)注下用戶側(cè)接口功能和時(shí)序。
這是本人寫的注釋,更具體清晰的說(shuō)明還是要查看官方文檔UG586.接下來(lái)看看寫數(shù)據(jù)和讀數(shù)據(jù)的接口時(shí)序圖(時(shí)鐘比例4:1,burst length = 8為例):
指令通道:
寫數(shù)據(jù):
從時(shí)序圖可以看出,指令地址和數(shù)據(jù)使用兩套時(shí)序,彼此相互獨(dú)立。為了便于設(shè)計(jì),直接將兩套時(shí)序嚴(yán)格對(duì)齊(情況1)也可以正常工作。
讀數(shù)據(jù):
為什么說(shuō)“時(shí)鐘比例4:1,burst length = 8為例”?這一點(diǎn)特別關(guān)鍵。此時(shí)用戶時(shí)鐘周期是DDR接口時(shí)鐘周期的4倍,也就是一個(gè)用戶時(shí)鐘信號(hào)上升沿對(duì)應(yīng)8個(gè)DDR時(shí)鐘邊沿。burst length可以理解為MIG連續(xù)操作DDR地址的個(gè)數(shù),故在4:1時(shí)鐘比例下,一個(gè)用戶時(shí)鐘周期正好對(duì)8個(gè)地址進(jìn)行了讀/寫操作,256bit數(shù)據(jù)分8次(32bit)寫入DDR中。由此分析,在寫數(shù)據(jù)時(shí)讓app_wdf_end = app_wdf_wren即可,并且讀/寫操作時(shí)地址遞增步長(zhǎng)為8.
雖然MIG IP核提供了用戶接口,但讀寫指令通道復(fù)用且需要實(shí)時(shí)關(guān)注兩個(gè)rdy信號(hào)造成了時(shí)序操作上的不方便。為此我們需要對(duì)接口進(jìn)一步封裝,保證寫操作時(shí)只關(guān)注:寫使能user_wdata_en 寫地址user_waddr 寫數(shù)據(jù)user_wdata和寫準(zhǔn)備就緒信號(hào)user_wdata_rdy,讀操作時(shí)只關(guān)注:讀使能user_rdata_en 讀地址user_raddr 讀數(shù)據(jù)user_rdata 讀數(shù)據(jù)有效user_rdata_vld和讀操作準(zhǔn)備就緒user_rdata_rdy。
利用擴(kuò)展接口模塊,將讀通道和寫通道接口分離,并分別例化一個(gè)FIFO緩存地址和數(shù)據(jù)。當(dāng)讀/寫指令同時(shí)有效時(shí),通過(guò)MIG側(cè)的優(yōu)先級(jí)輪換邏輯輪流讀取其中一個(gè)FIFO,每次選一個(gè)FIFO讀取直至FIFO為空再重新選擇。其工程結(jié)構(gòu)和核心代碼如下:
讀側(cè)邏輯核心代碼:
1 //讀側(cè)--------------------------------------------------------------
2
3 always @(posedge clk or negedge rst_n )begin
4 if(rst_n==0) begin
5 rd_flag <= (0) ;6 end
7 else if(rd_flag == 0 && mig_rdy && mig_wdf_rdy && !rdempty1 && (rdempty0 || (!rdempty0 && priority == 0)))begin
8 rd_flag <= (2'b01) ;//讀取 寫指令FIFO
9 end
10 else if(rd_flag == 0 && mig_rdy && !rdempty0 && (rdempty1 || (!rdempty1 && priority == 1)))begin
11 rd_flag <= (2'b10) ;//讀取 讀指令FIFO
12 end
13 else if((rd_flag == 2'b01 && rdempty1)||(rd_flag == 2'b10 &&rdempty0))14 rd_flag <= 0;15 end
16
17 //同時(shí)非空時(shí)輪換優(yōu)先級(jí)
18 always @(posedge clk or negedge rst_n )begin
19 if(rst_n==0) begin
20 priority <= (0) ;21 end
22 else if(rd_flag == 0 && !rdempty0 && !rdempty1)begin
23 priority <= (!priority) ;24 end
25 end
為了方便測(cè)試,設(shè)計(jì)樣式生成模塊與擴(kuò)展接口模塊用戶側(cè)連接,不斷向一段地址寫入固定數(shù)據(jù)序列并在一段時(shí)間后讀回。
1 `timescale 1ns /1ps2 /*
3 該模塊功能:4 周期性向一段地址執(zhí)行讀寫操作 產(chǎn)生固定樣式待寫入數(shù)據(jù)用戶測(cè)試目的5 測(cè)試完畢后刪除該模塊,開(kāi)發(fā)用戶接口6
7 具體為:8 1 寫從0開(kāi)始之后的10個(gè)用戶地址(80個(gè)DDR地址):0~9遞增序列9 2 等待20個(gè)時(shí)鐘周期10 3 讀取寫入的10個(gè)用戶地址11 4 等待20個(gè)時(shí)鐘周期12 5 重復(fù)上述步驟13
14 說(shuō)明:15 1 每個(gè)步驟之間有一個(gè)時(shí)鐘周期空閑16 2 由于burst_len = 8 4:1時(shí)鐘模式下一個(gè)用戶時(shí)鐘周期寫入數(shù)據(jù)對(duì)應(yīng)同樣時(shí)間內(nèi)8個(gè)DDR時(shí)鐘邊沿寫入數(shù)據(jù),17 因此地址遞增步長(zhǎng)為818 */
19 moduletraffic_gen20 #(parameter DATA_WIDTH = 32,21 ADDR_WIDTH = 29)22 (23 inputclk ,24 inputrst_n ,25
26 output reggen_wdata_en ,27 output reg [ ADDR_WIDTH-1:0] gen_waddr ,28 output reg [ DATA_WIDTH-1:0] gen_wdata ,29 input gen_wdata_rdy ,//寫指令和數(shù)據(jù)通道準(zhǔn)備就緒
30
31 output reggen_rdata_en ,32 output reg [ ADDR_WIDTH-1:0] gen_raddr ,33 input [ DATA_WIDTH-1:0] gen_rdata ,34 inputgen_rdata_vld ,35 input gen_rdata_rdy //讀指令通道準(zhǔn)備就緒
36 );37
38
39 reg [ (8-1):0] cnt0 ;40 wireadd_cnt0 ;41 wireend_cnt0 ;42 reg [ (2-1):0] cnt1 ;43 wireadd_cnt1 ;44 wireend_cnt1 ;45
46 reg [ DATA_WIDTH-1:0] gen_rdata_r ;47 reggen_rdata_vld_r ;48 regcom_flag ;49
50 wirewri_state;51 wirerd_state;52 wirecom_change_t;53
54 //操作周期計(jì)數(shù)器,計(jì)數(shù)值為欲操作用戶地址段長(zhǎng)度+1(需要一個(gè)時(shí)鐘周期空閑)
55 always @(posedge clk or negedge rst_n) begin
56 if (rst_n==0) begin
57 cnt0 <= 0;58 end
59 else if(add_cnt0) begin
60 if(end_cnt0)61 cnt0 <= 0;62 else
63 cnt0 <= cnt0+1;64 end
65 end
66 assign add_cnt0 = (com_flag == 0 && gen_wdata_rdy) || (com_flag == 1 &&gen_rdata_rdy);67 assign end_cnt0 = add_cnt0 && cnt0 == (30)-1;68
69 //指令標(biāo)志位 先是0--寫 再是1--讀
70 always @(posedge clk or negedge rst_n )begin
71 if(rst_n==0) begin
72 com_flag <= (0) ;73 end
74 else if(com_change_t)begin
75 com_flag <= (!com_flag) ;76 end
77 end
78
79 assign com_change_t = add_cnt0 && cnt0 == 10 - 1;80
81 //寫操作---------------------------------------------
82 always @(posedge clk or negedge rst_n )begin
83 if(rst_n==0) begin
84 gen_wdata_en <= (0) ;85 end
86 else if(wri_state)begin
87 gen_wdata_en <= (1'b1) ;
88 end
89 else begin
90 gen_wdata_en <= (0) ;91 end
92 end
93
94 assign wri_state = add_cnt0 && cnt0 <= 10-1 && com_flag == 0;95 assign rd_state = add_cnt0 && cnt0 <= 10-1 && com_flag == 1;96
97 always @(posedge clk or negedge rst_n )begin
98 if(rst_n==0) begin
99 gen_wdata <= (0) ;100 end
101 else begin
102 gen_wdata <=(cnt0) ;103 end
104 end
105
106 always@(posedge clk or negedge rst_n)begin
107 if(rst_n == 0)108 gen_waddr <= 0;109 else if(wri_state)110 gen_waddr <= gen_waddr + 29'd8;
111 else
112 gen_waddr <= 0;113 end
114 //讀操作----------------------------------------------
115
116 always @(posedge clk or negedge rst_n )begin
117 if(rst_n==0) begin
118 gen_rdata_en <= (0) ;119 end
120 else if(rd_state)begin
121 gen_rdata_en <= (1'b1) ;
122 end
123 else begin
124 gen_rdata_en <= (0) ;125 end
126 end
127
128 always@(posedge clk or negedge rst_n)begin
129 if(rst_n == 0)130 gen_raddr <= 0;131 else if(rd_state)132 gen_raddr <= gen_raddr + 29'd8;
133 else
134 gen_raddr <= 0;135 end
136
137 always @(posedge clk or negedge rst_n )begin
138 if(rst_n==0) begin
139 gen_rdata_r <= (0) ;140 end
141 else begin
142 gen_rdata_r <=(gen_rdata) ;143 end
144 end
145
146 always @(posedge clk or negedge rst_n )begin
147 if(rst_n==0) begin
148 gen_rdata_vld_r <= (0) ;149 end
150 else if(gen_rdata_vld)begin
151 gen_rdata_vld_r <= (1'b1) ;
152 end
153 else begin
154 gen_rdata_vld_r <= (0) ;155 end
156 end
157
158 endmodule
將traffic_gen和extend_interface模塊例化在MIG的example design中,利用ILA抓取MIG IP核用戶接口信號(hào)。
向地址8~80寫入數(shù)據(jù)0~9,再?gòu)拇硕蔚刂分凶x回?cái)?shù)據(jù),0~9被正確讀出,MIG IP核控制DDR3讀寫測(cè)試完畢。
總結(jié)
以上是生活随笔為你收集整理的vfifo控制mig_MIG IP控制DDR3读写测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 小米手机怎么查看云盘照片
- 下一篇: 曝Redmi K60系列芯片将下放至No