天天看點

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

Spartan6 FPGA DDR3自建寫測試平台

FPGA

先簡單總結一下前面建立FPGA DDR3 IP Core,以及簡單簡述一下DDR3 IP Core的信号。

1.DDR3 IP core建立的時候,如果網上沒有搭建這個IP核的資料,我們要怎麼搭建呢? 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
2.打開後得到這個文檔,點選Click here,可以獲得這個IP Core的搭建設定方法 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
3.點選Click here後,得到User Guide手冊 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
DDR3 IP Core各個信号,檢視MCB這個文檔
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
他的引腳信号分布 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
我們控制的就是右邊的IOB信号。左邊的信号有幾個端口就要看你建立IP核的時候的Port設定了。 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
因為我之前建立IP核的時候是将他設定成了2個64bit的Port。是以這裡是有P0和P1信号端口。 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
接口的分類
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

command path 中比較有用的幾個信号 

(c3_p0_cmd_clk),//cmd FIFO的使用者時鐘,上升沿有效 

(c3_p0_cmd_en), //該高電平有效信号是用于寫入的寫入使能信号 

(c3_p0_cmd_instr),//指令端口 

(c3_p0_cmd_bl),//突發長度,0-63 

(c3_p0_cmd_byte_addr),//位元組開始的位址,他的後面幾位不能為0 

(c3_p0_cmd_empty),//FIFO的空标志,高有效 

(c3_p0_cmd_full),//FIFO的滿标志

由MCB的手冊可知,這些信号都是Command path信号 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
那我們如何向DDR3寫入command呢?打開目錄,找到command path timing,找到他的時序圖,根據手冊時序圖寫程式就可以向DDR3寫入指令。 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
command path的讀寫時序。

寫時序 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

注意:這裡需要注意時鐘,這裡有好幾個時鐘,command path timing(write)時鐘是cmd_clk,這個時鐘主要是用來檢測cmd_en信号的,而我們如果需要将instr指令端口信号寫入DDR3,則使用的是Wr_clk

我們看看cmd_clk和wr_clk手冊怎麼說的吧

cmd_clk 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
wr_clk 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

write_path_timing 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

那cmd和wirte是怎麼協調的呢?

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

我們可以看到在command path timing 時序和write path timing都可以看到cmd和write都有調用到FIFO。cmd_FIFO存儲的是指令指令,write data fifo裡面存儲是要寫入到DDR3中的資料。那我們要往DDR3寫入資料,那麼DDR3先讀入cmd_instr的資料。先知道是讀操作還是寫操作。得知是寫操作後,會去通路Write Data FIFO裡面的資料,将Write FIFO裡面的資料寫入DDR3 FIFO。讀操作,就是講Read FIFO裡面的資料讀出來。是以,在寫指令的時候,我們需要確定DDR3的Wr_data_FIFO裡面是有資料的。是以我們要将上面的步驟反過來,先向Write data fifo寫入想要DDR3晶片内部資料,之後再向cmd fifo中寫入相應的寫指令。這樣的話,我們的時序圖可以這麼寫 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

cmd_en也就是去檢測wr_en的下降沿。

代碼的實作

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

将頂層檔案DDR3的command 引腳和 write引腳引出來。 

因為我們是仿真時序,是以我們建立一個wr_trig來控制wr_en。 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

仿真時序圖

建立一個ddr3_drive檔案。 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

上圖是ddr3_drive的引腳資訊。因為我們是仿真,是以我們将instr直接固定成3'b000寫模式,将Bl,mask也固定。

ddr3_drive代碼:

module ddr3_drive(
//system signal
input                   s_clk                   ,       
input                   s_rst_n                 ,       
//DDR3 User Interface
output wire             p0_cmd_en               ,       
output wire [2:0]       p0_cmd_instr            ,       
output wire [5:0]       p0_cmd_bl               ,       
output wire [29:0]      p0_cmd_byte_addr        ,       
output reg              p0_wr_en                ,       
output wire [7:0]       p0_wr_mask              ,       
output reg [63:0]       p0_wr_data              ,       
//Debug
input                   wr_trig 
);


//========================================================================\
// =========== Define Parameter and Internal signals =========== 
//========================================================================/
reg                             p0_wr_en_r1                     ;      //用于捕獲wr_en的下降沿 


//=============================================================================
//**************    Main Code   **************
//=============================================================================
always  @(posedge s_clk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
            p0_wr_en <= 'd0;
        else if(p0_wr_data >= 'd15)
            p0_wr_en <= 'd0;
        else if(wr_trig == 1'b1)
            p0_wr_en <= 1'b1;
end

always  @(posedge s_clk or negedge s_rst_n) begin
        if(s_rst_n == 1'b0)
            p0_wr_data <= 'd0;
        else if(p0_wr_en == 1'b1)
            p0_wr_data <= p0_wr_data + 1'b1;
end


always  @(posedge s_clk) begin
       p0_wr_en_r1 <= p0_wr_en;
end

assign p0_cmd_en = ~p0_wr_en & p0_wr_en_r1;
assign p0_cmd_instr = 3'b000;//write
assign p0_cmd_bl = 'd15;
assign p0_cmd_byte_addr = 'd0;
assign p0_wr_mask = 8'b0;

    endmodule 
           
頂層檔案将ddr3_drive檔案例化進去。 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
注意:這裡給ddr3_drive的是ddr3例化檔案給出的user clock和user reset。reset是高電平有效的,即高電平複位。是以給ddr3_drive傳入的是~c3_rst0。需要去一次反。 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

讓ddr3_drive的信号與ddr3的例化檔案信号一緻。 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

将cmd_clk和wr_clk都用c3_clk0傳入。

在top檔案中再聲明一下即可。 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

接下來就是寫仿真的腳本檔案了

主要就是去産生一個wr_trig信号 

代碼如下

initial begin
    wr_trig = 0;
    @(posedge c3_calib_done)
    #10_0000;//10ns
    wr_trig = 1;
    #25600;
    wr_trig = 0;
end
           

因為ddr3的操作要在calib_done完成後(calib_done是指MCB初始化完成的信号)才能讀寫ddr3.是以top檔案也需要将c3_calib_done引出,在tb檔案中例化進來。 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
接着因為我們需要檢視ddr3_drive_inst,u_mig_39_2的信号,為了提高效率,我們通過tcl腳本添加。 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
在工程檔案中有fdo和udo兩個檔案。這就相當于我們平時自己寫的do檔案。fdo是ISE産生的,一般不改變,udo是ISE給使用者添加的do檔案。udo也就是user do的意思。 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
将分組和添加信号的腳本解除安裝udo檔案中。 
Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作
點選開始仿真。

波形的分析

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

我們要先找到wr_trig信号。因為真正的資料端口是ddr3_dq引腳,我們主要檢視的是wr_trig拉高後的ddr3_dq引腳信号。看波形我們可以知道wr_trig引腳在34855200ps後拉高。我們就去看這個時間後的列印資訊。 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

注意:因為我們FPGA DDR3 IP是64bit port,而我們DDR3實際是16bit的port。是以我們這裡是并不是0000,0001,0002這樣下去。 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

而是這樣四個一組的。 

因為我們測試是0-15,是以最終到0x0f,看列印資訊,可知仿真正确。 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作

歡迎關注微信公衆号:文鴻開源工作室 

Spartan6 FPGA 使用ISE自建DDR3寫測試平台Spartan6 FPGA DDR3自建寫測試平台代碼的實作