(原創) 如何在DE2用硬體存取SDRAM(4 port)? (IC Design) (DE2)

Abstract
之前曾經討論如何在DE2用硬體的Verilog存取SDRAM,當時所使用的SDRAM controller是2 port的,一個read一個write,對大部分情況而言是夠用的,這次要討論的是4 port的SDRAM controller, 2 read, 2 write。

Introduction
使用環境:Quartus II 7.2 SP1 + MegaCore IP 7.2 SP1 + DE2(Cyclone II EP2C35F627C6)

友晶的很多範例,用的都是DE2_CCD、DE2_CCD_detect、DE2_CCD_PIP、DE2_pong_demo、DE2_LCM_CCD....等用的都是Sdram_Control_4Port這個SDRAM controller,有2個write port與2個read port,優點是在一個clock下,可做2次的read和write。但這個4 port的SDRAM controller用法與之前2 port SDAM controller用法並不一樣。

如同上一篇的範例,用switch當成2進位的輸入,用七段顯示器做16進位輸出,但這次使用的是4 port的SDRAM controller。

Verilog / SDRAM_HR_HW.v

  1 /* 
  2 (C) OOMusou 2008 http://oomusou.cnblogs.com
  3 
  4 Filename    : SDRAM_HR_HW.v
  5 Compiler    : Quartus II 7.2 SP1
  6 Description : Demo how to use abstract base class simulate interface
  7 Release     : 04/25/2008 1.0
  8 */
  9 module SDRAM_HR_HW (
 10   input         CLOCK_50,
 11   input  [3:0]  KEY,
 12   input  [17:0] SW,
 13   output [17:0] LEDR,
 14   output [6:0]  HEX0,
 15                 HEX1,
 16                 HEX2,
 17                 HEX3,
 18                 HEX4,
 19                 HEX5,
 20                 HEX6,
 21                 HEX7,
 22   //SDRAM side
 23   output [11:0] DRAM_ADDR,
 24   inout  [15:0] DRAM_DQ,
 25   output        DRAM_BA_0,
 26                 DRAM_BA_1,
 27                 DRAM_RAS_N,
 28                 DRAM_CAS_N,
 29                 DRAM_CKE,
 30                 DRAM_CLK,
 31                 DRAM_WE_N,
 32                 DRAM_CS_N,
 33                 DRAM_LDQM,
 34                 DRAM_UDQM
 35 );
 36 
 37 reg         read;             // read enable register
 38 reg         write;            // write enable register
 39 reg  [1:0]  state;            // FSM state register
 40 reg  [15:0] data_in;          // data input register
 41 wire [15:0] DATA_OUT;         // data output
 42 reg  [15:0] data_out;         // data output register
 43 wire        DELAY_RESET;      // delay for SDRAM controller load
 44 wire        RESET_n = KEY[0]; // reset from KEY[0]
 45 
 46 assign LEDR = SW;
 47 
 48 Sdram_Control_4Port u0 (
 49   // HOST Side
 50   .REF_CLK(CLOCK_50),
 51   .RESET_N(1'b1),
 52   // FIFO Write Side 1
 53   .WR1_DATA(data_in),
 54   .WR1(write),
 55   .WR1_ADDR(0),
 56   .WR1_MAX_ADDR(640*512*2),
 57   .WR1_LENGTH(9'h100),
 58   .WR1_LOAD(!DELAY_RESET),
 59   .WR1_CLK(CLOCK_50),
 60   // FIFO Read Side 1
 61   .RD1_DATA(DATA_OUT),
 62   .RD1(read),
 63   .RD1_ADDR(640*16),
 64   .RD1_MAX_ADDR(640*496),
 65   .RD1_LENGTH(9'h100),
 66   .RD1_LOAD(!DELAY_RESET),
 67   .RD1_CLK(CLOCK_50),
 68   // SDRAM Side
 69   .SA(DRAM_ADDR),
 70   .BA({DRAM_BA_1,DRAM_BA_0}),
 71   .CS_N(DRAM_CS_N),
 72   .CKE(DRAM_CKE),
 73   .RAS_N(DRAM_RAS_N),
 74   .CAS_N(DRAM_CAS_N),
 75   .WE_N(DRAM_WE_N),
 76   .DQ(DRAM_DQ),
 77   .DQM({DRAM_UDQM,DRAM_LDQM}),
 78   .SDR_CLK(DRAM_CLK)
 79 );
 80 
 81 SEG7_LUT_8 u1 (
 82   .oSEG0(HEX0),      // output SEG0
 83   .oSEG1(HEX1),      // output SEG1
 84   .oSEG2(HEX2),      // output SEG2
 85   .oSEG3(HEX3),      // output SEG3
 86   .oSEG4(HEX4),      // output SEG4
 87   .oSEG5(HEX5),      // output SEG5
 88   .oSEG6(HEX6),      // output SEG6
 89   .oSEG7(HEX7),      // output SEG7
 90   .iDIG(data_out),   // input data
 91   .iWR(1'b1),        // write enable
 92   .iCLK(CLOCK_50),   // clock
 93   .iRESET_n(RESET_n)
 94 );
 95 
 96 
 97 // reset delay for WR1_LOAD & RD1_LOAD to clear FIFO
 98 Reset_Delay    u2 (
 99   .iCLK(CLOCK_50),
100   .iRST(KEY[0]),
101   .oRST(DELAY_RESET),
102 );
103 
104 // state 0 : read switch & write SDRAM
105 // state 1 : read SDRAM & write to SEG7
106 always @(posedge CLOCK_50 or negedge RESET_n)
107 begin
108   if (!RESET_n) begin
109     read    <= 0// read enable register
110     write   <= 0// write enale register
111     state   <= 0// FSM state register
112     data_in <= 0// data input register
113     data_out <= 0// data output register
114   end
115   else
116   begin
117     case (state)
118       // state 0 : read switch & write SDRAM
119       0: begin
120         read    <= 0;          // read diable
121         write   <= 1;          // write enable
122         data_in <= {SW[15:0]}; // write SDRAM data
123         state   <= 1;          // next state
124       end
125       
126       // state 2 : read SDRAM & write to SEG7
127       1: begin
128         read  <= 1;             // read enable
129         write <= 0;             // write disable
130         data_out <= DATA_OUT;   // read SDRAM data
131         state <= 0;             // next state
132       end
133     endcase
134   end
135 end
136 
137 endmodule


109行

case (state)
  
// state 0 : read switch & write SDRAM
  0: begin
    read    
<= 0;          // read diable
    write   <= 1;          // write enable
    data_in <= {SW[15:0]}; // write SDRAM data
    state   <= 1;          // next state
  end
      
  
// state 2 : read SDRAM & write to SEG7
  1: begin
    read  
<= 1;             // read enable
    write <= 0;             // write disable
    data_out <= DATA_OUT;   // read SDRAM data
    state <= 0;             // next state
  end
endcase


2 port由於需要判斷DONE,還需多一個clock,因此需要4個FSM,但4 port並不需要,所以只要2個FSM即可。當要寫入SDRAM時,只需將read設為0,write設為1,將欲寫入的資料傳入data_in,最後進入下一個state即可。

同理,當要從SDRAM讀出資料時,只需將read設為1,write設為0,從DATA_OUT讀出資料,最後進入下一個state即可。

比較詭異的是97行

// reset delay for WR1_LOAD & RD1_LOAD to clear FIFO
Reset_Delay    u2 (
  .iCLK(CLOCK_50),
  .iRST(KEY[
0]),
  .oRST(DELAY_RESET),
);


58行的WR1_LOAD()與66行的RD1_LOAD()是為了清空FIFO,若只傳由KEY[0]所連結的RESET_n,將無法正常運作,必須做了Reset_Delay之後,再傳入SDRAM controller。

完整程式碼下載
sdram_hr_hw_4port.7z

Conclusion
Sdram_Control_4Port都放在完整程式碼中,有需要的人可自行下載。

由於SDRAM的容量很大,4 port可以讓你在一個clock內做2次的讀寫,有效的運用將可加快整體速度。

See Also
(原創) 如何在DE2用軟體存取SDRAM? (IC Design) (DE2) (Nios II)
(原創) 如何在DE2用硬體存取SDRAM? (IC Design) (DE2)
(筆記) DE2與SDRAM相關資料總整理 (SOC) (DE2)

posted on 2008-04-25 18:30  真 OO无双  阅读(9971)  评论(55编辑  收藏  举报

导航