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 endendcase
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。完整程式碼下載ConclusionSdram_Control_4Port都放在完整程式碼中,有需要的人可自行下載。由於SDRAM的容量很大,4 port可以讓你在一個clock內做2次的讀寫,有效的運用將可加快整體速度。See Also