回看《例說FPGA》---DDR2控制器集成與讀寫測試


回看《例說FPGA》

                                                                 ---DDR2控制器集成與讀寫測試

1.DDR2 IP核的配置

需要弄清楚的選項主要有:

PLL reference clock frequency

Memory clock frequency

Controller data rate

對於DDR2 芯片的選型,可以在Memory Presets 里面選擇,如果沒有符合的器件,可以任意選中一個器件,點擊modify parameters 按鈕,在 preset Editor 里面進行參數配置。

 2.片上RAM的配置

 

需要設置的選項有:

輸出數據的位寬

存儲器的深度

雙時鍾或單時鍾

雙時鍾意味着輸入輸出采用不同的時鍾:

regs/clken/byte enable/aclrs選項卡中,需要設置的是:

Which ports should be registered?  ‘ q output port’,如果選中,則在輸出端加上一個觸發器,輸出數據時候,就會用clock信號打節拍。如果不選中,則:

 3.數據源產生模塊

實驗的整體框圖如下圖所示:

 

數據源產生模塊實現的功能為:

每秒定時DDR2數據寫入控制;

每秒定時DDR2數據讀出控制;

將讀出的數據寫入片上RAM中(RAM IP核在此模塊中進行實例化);

此模塊主要用來與DDR2 controller IP核進行通信,首先需要對DDR2 controller的信號多一些了解:

 

 1 module ddr2_contral (
 2     local_address,
 3     local_write_req,
 4     local_read_req,
 5     local_burstbegin,
 6     local_wdata,
 7     local_be,
 8     local_size,
 9     global_reset_n,
10     pll_ref_clk,
11     soft_reset_n,
12     local_ready,
13     local_rdata,
14     local_rdata_valid,
15     local_refresh_ack,
16     local_init_done,
17     reset_phy_clk_n,
18     mem_odt,
19     mem_cs_n,
20     mem_cke,
21     mem_addr,
22     mem_ba,
23     mem_ras_n,
24     mem_cas_n,
25     mem_we_n,
26     mem_dm,
27     phy_clk,
28     aux_full_rate_clk,
29     aux_half_rate_clk,
30     reset_request_n,
31     mem_clk,
32     mem_clk_n,
33     mem_dq,
34     mem_dqs);
35 
36 
37     input    [22:0]    local_address;
38     input        local_write_req;
39     input        local_read_req;
40     input        local_burstbegin;
41     input    [63:0]    local_wdata;
42     input    [7:0]    local_be;
43     input    [2:0]    local_size;
44     input        global_reset_n;
45     input        pll_ref_clk;
46     input        soft_reset_n;
47     output        local_ready;
48     output    [63:0]    local_rdata;
49     output        local_rdata_valid;
50     output        local_refresh_ack;
51     output        local_init_done;
52     output        reset_phy_clk_n;
53     output    [0:0]    mem_odt;
54     output    [0:0]    mem_cs_n;
55     output    [0:0]    mem_cke;
56     output    [12:0]    mem_addr;
57     output    [1:0]    mem_ba;
58     output        mem_ras_n;
59     output        mem_cas_n;
60     output        mem_we_n;
61     output    [1:0]    mem_dm;
62     output        phy_clk;
63     output        aux_full_rate_clk;
64     output        aux_half_rate_clk;
65     output        reset_request_n;
66     inout    [0:0]    mem_clk;
67     inout    [0:0]    mem_clk_n;
68     inout    [15:0]    mem_dq;
69     inout    [1:0]    mem_dqs;

 

ddr2 controller模塊的接口可以分為三類:

第一類:系統接口,包含系統或PLL的復位,時鍾等接口;

第二類:以local開頭的接口,是DDR2 IP核與用戶邏輯間的接口;(數據源產生模塊主要用到的就是這類接口信號,需要弄懂這些信號的操作時序)

第三類:以mem開頭的接口,是DDR2 IP核與FPGA外部DDR2芯片的接口;(只需要做引腳鎖定,編程基本用不到)

關於使用DDR2 IP核用戶外部邏輯操作loca信號的時序圖如下:

在遇到local_ready拉低的讀操作,下列信號必須保持到local_ready拉高為止:

local_read_req;

local_size;

local_addr;

寫數據的時候,整個過程中,必須保持local_write_req信號一直有效。

邏輯代碼:

  1 module data_source(
  2             clk,         //75MHz
  3             rst_n,
  4             local_address,
  5             local_write_req,
  6             local_read_req,
  7             local_wdata,
  8             local_ready,
  9             local_rdata,
 10             local_rdata_valid,
 11             local_init_done
 12 );
 13 
 14 // 1/75MHz = 13.33ns;
 15     input        clk;            
 16     input       rst_n;
 17     output   [22:0]local_address;    
 18     output   local_write_req;    
 19     output   local_read_req;        
 20     output    [63:0]local_wdata;    
 21     input        local_ready;         
 22     input       [63:0]local_rdata;    
 23     input        local_rdata_valid;        
 24     input        local_init_done;
 25 
 26 reg[26:0] scnt; 
 27 reg[7:0] times;    
 28 
 29 //計數器,當local_init_done有效時,計數器scnt開始計數
 30 always @(posedge clk or negedge rst_n)
 31     if(!rst_n) scnt <= 27'd0;
 32     else if(local_init_done) scnt <= scnt+1'b1;
 33 
 34 wire timer_wrreq = (scnt == 27'h00_001_000);     //  55us
 35 wire timer_rdreq = (scnt == 27'h00_005_000);     //  273us
 36 
 37 //每當timer_rdreq有效時,計數器times增加1,此模塊用來計數讀取數據的個數
 38 always @(posedge clk or negedge rst_n)
 39     if(!rst_n) times <= 8'd0;
 40     else if(timer_rdreq) times <= times+1'b1;   
 41 
 42 //狀態機
 43 parameter SIDLE = 4'd0;
 44 parameter SWRDB = 4'd1;
 45 parameter SRDDB = 4'd2;
 46 parameter SSTOP = 4'd3;
 47     
 48 reg[3:0] cstate;
 49 reg[8:0] num;
 50 
 51 always @(posedge clk or negedge rst_n)
 52     if(!rst_n) cstate <= SIDLE;
 53     else begin
 54         case(cstate)
 55             SIDLE: begin       //控制狀態機的跳轉,timer_wrreq有效,則跳轉到SWRDB,timer_rdreq有效,則跳轉到SRDDB
 56                 if(timer_wrreq) cstate <= SWRDB;
 57                 else if(timer_rdreq) cstate <= SRDDB;
 58                 else cstate <= SIDLE;
 59             end
 60             SWRDB: begin       //如果寫入255個數據,並且local_ready有效,則狀態結束
 61                 if((num == 9'd255) && local_ready) cstate <= SSTOP;
 62                 else cstate <= SWRDB;
 63             end
 64             SRDDB: begin      ////如果讀取255個數據,並且local_ready有效,則狀態結束
 65                 if((num == 9'd255) && local_ready) cstate <= SSTOP;
 66                 else cstate <= SRDDB;
 67             end
 68             SSTOP: cstate <= SIDLE;
 69             default: cstate <= SIDLE;
 70         endcase
 71     end
 72 
 73 always @(posedge clk or negedge rst_n)
 74     if(!rst_n) num <= 9'd0;
 75     else if((cstate == SWRDB) || (cstate == SRDDB)) begin     //如果狀態處在SWRDB或者是SRDDB時,進入下一個判斷階段
 76         if(local_ready) num <= num+1'b1;                       //如果local_ready有效時,num開始計數
 77         else ;
 78     end
 79     else num <= 9'd0; 
 80 
 81 assign local_address = (cstate == SWRDB) ? {13'h0a55,2'd1,num[7:0]}:{13'h0a55,2'd1,num[7:0]};   //地址采用num這個寄存器來進行地址偏移
 82 assign local_wdata = {times,{num[5:0],2'b00},times,{num[5:0],2'b01},times,{num[5:0],2'b10},times,{num[5:0],2'b11}};        
 83 assign local_write_req = (cstate == SWRDB);        //當狀態機處在SWRDB時,發出寫請求
 84 assign local_read_req = (cstate == SRDDB);       //當狀態機處在SRDDB時,發出讀請求
 85                 
 86 reg[7:0] ram_addr;
 87 always @(posedge clk or negedge rst_n)
 88     if(!rst_n) ram_addr <= 8'd0;
 89     else if(timer_rdreq) ram_addr <= 8'd0;      //當timer_rdreq讀數請求有效時,ram_addr清零,即讀數據請求到來時,ram_addr指向第一個地址
 90     else if(local_rdata_valid) ram_addr <= ram_addr+1'b1;   //當local_rdata_valid信號有效時候,片上ram_addr開始偏移
 91     else ;
 92         
 93 //此ram只寫入,不輸出
 94 ram_1port u1 (
 95         .address(ram_addr),
 96         .clock(clk),
 97         .data(local_rdata),
 98         .wren(local_rdata_valid),
 99         .q()
100 );        
101 
102 endmodule

綜合結果,RTL圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM