(原創) 如何在DE2用軟體存取SDRAM? (IC Design) (DE2) (Nios II)

Abstract
DE2可用的記憶體有Onchip Memory、SRAM、SDRAM和Flash,之前在Nios II討論過Onchip Memory和SRAM了,這次我們來看看SDRAM。

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

在Altera原廠提供的Using the SDRAM Memory on Altera's DE2 Board with Verilog Design,已經很清楚的介紹如何在Nios II中使用SDRAM,但有幾個遺憾:1.他是英文,2.他最後使用Nios II組合語言測試SDRAM,這和一般人使用C語言開發Nios II系統的習慣有所不同。本文將使用C語言討論。

Block Diagram

nios2_sdram00

整個系統架構如上所示,除了基本的Nios II processor,以及與host computer溝通的JTAG外,剩下的周邊都必須透過Avalon bus做溝通,on-chip memory負責放C的程式碼,由於我們希望以switch作輸入,LED做輸出,須再加上PIO interface。本範例的重點在於使用SDRAM,所以必須另外加上SDRAM controller與SDRAM做溝通。

nios2_sdram01

由上圖可知,除了SDRAM所需要的clock,SDRAM controller可提供所有的訊號,而SOPC Builder已經提供了SDRAM controller,所以我們唯一要操心的只剩下clock問題。

使用SOPC Builder

Step 1:
加入Nios II processor (Nios II/e),on-chip memory (45K),JTAG UART,System ID Peripheral,PIO for SW(width:18 bit、input ports only),PIO for LED(width:18 bit、output ports only),這些都只是基本動作,我就不再贅述,若有問題請參考:
(原創) 如何自己用SOPC Builder建立一個能在DE2上跑μC/OS-II的Nios II系統? (IC Design) (DE2) (Quartus II) (Nios II) (SOPC Builder) (μC/OS-II)
Introduction to Altera SOPC Builder Using Verilog Design
Introduction to Altera SOPC Builder Using VHDL Design

Step 2:
加入SDRAM controller

加入在左側的/Altera SOPC Builder/Memories and Memory Controllers/SDRAM/SDRAM Controller

nios2_sdram02

由於DE2上使用的SDRAM是1M * 16 bits * 4 banks = 8Mbytes,所以上方的Presets要選擇Custom,Data width要改成16 bits,最後可以發現下方Memory size顯示為8MBytes,表是設定正確。

可以不勾選include a functional memory model in the system testbench,這樣產生system時速度會快一點。

nios2_sdram03   

最後SOPC Builder設定如下

nios2_sdram04

Quartus II Top Module

若要說Quartus II這個EDA工具對於Nios II開發還需要哪增加哪些支援,相信很多人抱怨的是top module,由於很多人著重於的是Nios II嵌入式系統的軟體開發,熟悉的是C語言,但top module卻要用Verilog或VHDL這種硬體描述語言,目前Quartus II並無法為我們代勞,必須自己去寫Verilog,或許Quartus II未來的版本會有所改善,但最少目前Quartus II 7.2 SP1無法逃避Verilog。

SDRAM_SW_RW.v

1  /*  
2  (C) OOMusou 2008 http://oomusou.cnblogs.com
3 
4  Filename    : SDRAM_SW_RW.v
5  Compiler    : Quartus II 7.2 SP1
6  Description : SDRAM_SW_RW top module
7  Release     : 04/06/2008 1.0
8  */
9  module SDRAM_SW_RW (
10    CLOCK_50,         // On Board 50 MHz
11    KEY,              // Pushbutton[3:0]
12    SW,               // Toggle Switch[17:0]
13    LEDR,             // LED Red[17:0]
14    DRAM_DQ,          // SDRAM Data bus 16 Bits
15    DRAM_ADDR,        // SDRAM Address bus 12 Bits
16    DRAM_LDQM,        // SDRAM Low-byte Data Mask
17    DRAM_UDQM,        // SDRAM High-byte Data Mask
18    DRAM_WE_N,        // SDRAM Write Enable
19    DRAM_CAS_N,       // SDRAM Column Address Strobe
20    DRAM_RAS_N,       // SDRAM Row Address Strobe
21    DRAM_CS_N,        // SDRAM Chip Select
22    DRAM_BA_0,        // SDRAM Bank Address 0
23    DRAM_BA_1,        // SDRAM Bank Address 1
24    DRAM_CLK,         // SDRAM Clock
25    DRAM_CKE          // SDRAM Clock Enable
26  );
27 
28  input         CLOCK_50;   // On Board 50 MHz
29  input  [ 3 : 0 ]  KEY;        // Pushbutton[3:0]
30  input  [ 17 : 0 ] SW;         // Toggle Switch[17:0]
31  output [ 17 : 0 ] LEDR;       // LED Red[17:0]
32  inout  [ 15 : 0 ] DRAM_DQ;    // SDRAM Data bus 16 Bits
33  output [ 11 : 0 ] DRAM_ADDR;  // SDRAM Address bus 12 Bits
34  output        DRAM_LDQM;  // SDRAM Low-byte Data Mask
35  output        DRAM_UDQM;  // SDRAM High-byte Data Mask
36  output        DRAM_WE_N;  // SDRAM Write Enable
37  output        DRAM_CAS_N; // SDRAM Column Address Strobe
38  output        DRAM_RAS_N; // SDRAM Row Address Strobe
39  output        DRAM_CS_N;  // SDRAM Chip Select
40  output        DRAM_BA_0;  // SDRAM Bank Address 0
41  output        DRAM_BA_1;  // SDRAM Bank Address 0
42  output        DRAM_CLK;   // SDRAM Clock
43  output        DRAM_CKE;   // SDRAM Clock Enable
44 
45  nios_ii_system u0 (
46    // 1) global signals:
47    .clk(CLOCK_50),
48    .reset_n(KEY[ 0 ]),
49    // the_ledr
50    .out_port_from_the_ledr(LEDR),
51    // the_sw
52    .in_port_to_the_sw(SW),
53    // the_sdram
54    .zs_addr_from_the_sdram(DRAM_ADDR),
55    .zs_ba_from_the_sdram({DRAM_BA_1, DRAM_BA_0}),
56    .zs_cas_n_from_the_sdram(DRAM_CAS_N),
57    .zs_cke_from_the_sdram(DRAM_CKE),
58    .zs_cs_n_from_the_sdram(DRAM_CS_N),
59    .zs_dq_to_and_from_the_sdram(DRAM_DQ),
60    .zs_dqm_from_the_sdram(DRAM_LDQM),
61    .zs_ras_n_from_the_sdram(DRAM_RAS_N),
62    .zs_we_n_from_the_sdram(DRAM_WE_N)
63  );
64 
65  SDRAM_PLL u1 (
66    .inclk0(CLOCK_50),
67    .c0(DRAM_CLK)
68  );
69 
70  endmodule


第9行

module SDRAM_SW_RW (
  CLOCK_50,        
// On Board 50 MHz
  KEY,              // Pushbutton[3:0]
  SW,               // Toggle Switch[17:0]
  LEDR,             // LED Red[17:0]
  DRAM_DQ,          // SDRAM Data bus 16 Bits
  DRAM_ADDR,        // SDRAM Address bus 12 Bits
  DRAM_LDQM,        // SDRAM Low-byte Data Mask
  DRAM_UDQM,        // SDRAM High-byte Data Mask
  DRAM_WE_N,        // SDRAM Write Enable
  DRAM_CAS_N,       // SDRAM Column Address Strobe
  DRAM_RAS_N,       // SDRAM Row Address Strobe
  DRAM_CS_N,        // SDRAM Chip Select
  DRAM_BA_0,        // SDRAM Bank Address 0
  DRAM_BA_1,        // SDRAM Bank Address 1
  DRAM_CLK,         // SDRAM Clock
  DRAM_CKE          // SDRAM Clock Enable
);


宣告top module所有的port,所有的名稱均使用DE2_pin_assignments.csv所定義的標準名稱,這樣日後只需import DE2_pin_assignments.csv即可,無須再自行撰寫tcl。

45行

nios_ii_system u0 (
 
// 1) global signals:
  .clk(CLOCK_50),
  .reset_n(KEY[
0 ]),
 
// the_ledr
  .out_port_from_the_ledr(LEDR),
 
// the_sw
  .in_port_to_the_sw(SW),
 
// the_sdram
  .zs_addr_from_the_sdram(DRAM_ADDR),
  .zs_ba_from_the_sdram({DRAM_BA_1, DRAM_BA_0}),
  .zs_cas_n_from_the_sdram(DRAM_CAS_N),
  .zs_cke_from_the_sdram(DRAM_CKE),
  .zs_cs_n_from_the_sdram(DRAM_CS_N),
  .zs_dq_to_and_from_the_sdram(DRAM_DQ),
  .zs_dqm_from_the_sdram(DRAM_LDQM),
  .zs_ras_n_from_the_sdram(DRAM_RAS_N),
  .zs_we_n_from_the_sdram(DRAM_WE_N)
);


建立nios_ii_system instance,並連上需要的連線,前面有提到SDRAM controller可負責SDRAM所需要的所有signal,但唯一要特別考量的是SDRAM所需要的clock,根據IS42S16400 datasheet,SDRAM所需要的clock是50MHz但須延遲3 ns,而不是DE2所提供的50MHz,這裡我們使用MegaFunction為我們產生一個SDRAM所需要的clock,你可以自己使用MegaWizard產生,或者在\DE2_CD\DE2_demonstrations\SOPC_Builder\Reference_Design\DE2_NIOS\ 將SDRAM_PLL.v複製你的project下即可。

65行

SDRAM_PLL u1 (
  .inclk0(CLOCK_50),
  .c0(DRAM_CLK)
);


輸入50MHz的clock,並產生SDRAM所需要的clock。

最後也附上SDRAM_PLL.v供參考

  1  // megafunction wizard: %ALTPLL%
  2  // GENERATION: STANDARD
  3  // VERSION: WM1.0
  4  // MODULE: altpll
  5 
  6  // ============================================================
  7  // File Name: SDRAM_PLL.v
  8  // Megafunction Name(s):
  9  //              altpll
10  // ============================================================
11  // ************************************************************
12  // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
13  //
14  // 6.0 Build 202 06/20/2006 SP 1 SJ Full Version
15  // ************************************************************
16 
17 
18  // Copyright (C) 1991-2006 Altera Corporation
19  // Your use of Altera Corporation's design tools, logic functions
20  // and other software and tools, and its AMPP partner logic
21  // functions, and any output files any of the foregoing
22  // (including device programming or simulation files), and any
23  // associated documentation or information are expressly subject
24  // to the terms and conditions of the Altera Program License
25  // Subscription Agreement, Altera MegaCore Function License
26  // Agreement, or other applicable license agreement, including,
27  // without limitation, that your use is for the sole purpose of
28  // programming logic devices manufactured by Altera and sold by
29  // Altera or its authorized distributors.  Please refer to the
30  // applicable agreement for further details.
31 
32 
33  // synopsys translate_off
34  `timescale 1 ps /   1 ps
35  // synopsys translate_on
36  module SDRAM_PLL (
37      inclk0,
38      c0,
39      c1,
40      c2);
41 
42      input      inclk0;
43      output      c0;
44      output      c1;
45      output      c2;
46 
47      wire [ 5 : 0 ] sub_wire0;
48      wire [ 0 : 0 ] sub_wire6 =   1 ' h0;
49      wire [ 2 : 2 ] sub_wire3 = sub_wire0[ 2 : 2 ];
50      wire [ 1 : 1 ] sub_wire2 = sub_wire0[ 1 : 1 ];
51      wire [ 0 : 0 ] sub_wire1 = sub_wire0[ 0 : 0 ];
52      wire  c0 = sub_wire1;
53      wire  c1 = sub_wire2;
54      wire  c2 = sub_wire3;
55      wire  sub_wire4 = inclk0;
56      wire [ 1 : 0 ] sub_wire5 = {sub_wire6, sub_wire4};
57 
58      altpll    altpll_component (
59                  .inclk (sub_wire5),
60                  .clk (sub_wire0),
61                  .activeclock (),
62                  .areset ( 1 ' b0),
63                  .clkbad (),
64                  .clkena ({ 6 { 1 ' b1}}),
65                  .clkloss (),
66                  .clkswitch ( 1 ' b0),
67                  .enable0 (),
68                  .enable1 (),
69                  .extclk (),
70                  .extclkena ({ 4 { 1 ' b1}}),
71                  .fbin ( 1 ' b1),
72                  .locked (),
73                  .pfdena ( 1 ' b1),
74                  .pllena ( 1 ' b1),
75                  .scanaclr ( 1 ' b0),
76                  .scanclk ( 1 ' b0),
77                  .scandata ( 1 ' b0),
78                  .scandataout (),
79                  .scandone (),
80                  .scanread ( 1 ' b0),
81                  .scanwrite ( 1 ' b0),
82                  .sclkout0 (),
83                  .sclkout1 ());
84      defparam
85          altpll_component.clk0_divide_by =   1 ,
86          altpll_component.clk0_duty_cycle =   50 ,
87          altpll_component.clk0_multiply_by =   1 ,
88          altpll_component.clk0_phase_shift =   " -3000 " ,
89          altpll_component.clk1_divide_by =   1 ,
90          altpll_component.clk1_duty_cycle =   50 ,
91          altpll_component.clk1_multiply_by =   2 ,
92          altpll_component.clk1_phase_shift =   " 0 " ,
93          altpll_component.clk2_divide_by =   2 ,
94          altpll_component.clk2_duty_cycle =   50 ,
95          altpll_component.clk2_multiply_by =   1 ,
96          altpll_component.clk2_phase_shift =   " 0 " ,
97          altpll_component.compensate_clock =   " CLK0 " ,
98          altpll_component.inclk0_input_frequency =   20000 ,
99          altpll_component.intended_device_family =   " Cyclone II " ,
100          altpll_component.lpm_type =   " altpll " ,
101          altpll_component.operation_mode =   " NORMAL " ,
102          altpll_component.pll_type =   " FAST " ,
103          altpll_component.port_activeclock =   " PORT_UNUSED " ,
104          altpll_component.port_areset =   " PORT_UNUSED " ,
105          altpll_component.port_clkbad0 =   " PORT_UNUSED " ,
106          altpll_component.port_clkbad1 =   " PORT_UNUSED " ,
107          altpll_component.port_clkloss =   " PORT_UNUSED " ,
108          altpll_component.port_clkswitch =   " PORT_UNUSED " ,
109          altpll_component.port_fbin =   " PORT_UNUSED " ,
110          altpll_component.port_inclk0 =   " PORT_USED " ,
111          altpll_component.port_inclk1 =   " PORT_UNUSED " ,
112          altpll_component.port_locked =   " PORT_UNUSED " ,
113          altpll_component.port_pfdena =   " PORT_UNUSED " ,
114          altpll_component.port_pllena =   " PORT_UNUSED " ,
115          altpll_component.port_scanaclr =   " PORT_UNUSED " ,
116          altpll_component.port_scanclk =   " PORT_UNUSED " ,
117          altpll_component.port_scandata =   " PORT_UNUSED " ,
118          altpll_component.port_scandataout =   " PORT_UNUSED " ,
119          altpll_component.port_scandone =   " PORT_UNUSED " ,
120          altpll_component.port_scanread =   " PORT_UNUSED " ,
121          altpll_component.port_scanwrite =   " PORT_UNUSED " ,
122          altpll_component.port_clk0 =   " PORT_USED " ,
123          altpll_component.port_clk1 =   " PORT_USED " ,
124          altpll_component.port_clk2 =   " PORT_USED " ,
125          altpll_component.port_clk3 =   " PORT_UNUSED " ,
126          altpll_component.port_clk4 =   " PORT_UNUSED " ,
127          altpll_component.port_clk5 =   " PORT_UNUSED " ,
128          altpll_component.port_clkena0 =   " PORT_UNUSED " ,
129          altpll_component.port_clkena1 =   " PORT_UNUSED " ,
130          altpll_component.port_clkena2 =   " PORT_UNUSED " ,
131          altpll_component.port_clkena3 =   " PORT_UNUSED " ,
132          altpll_component.port_clkena4 =   " PORT_UNUSED " ,
133          altpll_component.port_clkena5 =   " PORT_UNUSED " ,
134          altpll_component.port_enable0 =   " PORT_UNUSED " ,
135          altpll_component.port_enable1 =   " PORT_UNUSED " ,
136          altpll_component.port_extclk0 =   " PORT_UNUSED " ,
137          altpll_component.port_extclk1 =   " PORT_UNUSED " ,
138          altpll_component.port_extclk2 =   " PORT_UNUSED " ,
139          altpll_component.port_extclk3 =   " PORT_UNUSED " ,
140          altpll_component.port_extclkena0 =   " PORT_UNUSED " ,
141          altpll_component.port_extclkena1 =   " PORT_UNUSED " ,
142          altpll_component.port_extclkena2 =   " PORT_UNUSED " ,
143          altpll_component.port_extclkena3 =   " PORT_UNUSED " ,
144          altpll_component.port_sclkout0 =   " PORT_UNUSED " ,
145          altpll_component.port_sclkout1 =   " PORT_UNUSED " ;
146 
147 
148  endmodule
149 
150  // ============================================================
151  // CNX file retrieval info
152  // ============================================================
153  // Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
154  // Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
155  // Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0"
156  // Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
157  // Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
158  // Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
159  // Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0"
160  // Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
161  // Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
162  // Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
163  // Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "1"
164  // Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
165  // Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
166  // Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
167  // Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
168  // Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0"
169  // Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "Any"
170  // Retrieval info: PRIVATE: DEV_FAMILY STRING "Cyclone II"
171  // Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
172  // Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "2"
173  // Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1"
174  // Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
175  // Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
176  // Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
177  // Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
178  // Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
179  // Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "1"
180  // Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
181  // Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
182  // Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
183  // Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "50.000"
184  // Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
185  // Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "50.000"
186  // Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
187  // Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
188  // Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
189  // Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
190  // Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0"
191  // Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
192  // Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
193  // Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
194  // Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
195  // Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
196  // Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps"
197  // Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
198  // Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
199  // Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
200  // Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
201  // Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"
202  // Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "1"
203  // Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
204  // Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "50.00000000"
205  // Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000"
206  // Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "25.00000000"
207  // Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
208  // Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
209  // Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "1"
210  // Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
211  // Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
212  // Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
213  // Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "-3.00000000"
214  // Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
215  // Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
216  // Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "ns"
217  // Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "ps"
218  // Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps"
219  // Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
220  // Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
221  // Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
222  // Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0"
223  // Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
224  // Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
225  // Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
226  // Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
227  // Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
228  // Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
229  // Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
230  // Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0"
231  // Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
232  // Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
233  // Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
234  // Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
235  // Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
236  // Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
237  // Retrieval info: PRIVATE: SPREAD_USE STRING "0"
238  // Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
239  // Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
240  // Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
241  // Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
242  // Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
243  // Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
244  // Retrieval info: PRIVATE: USE_CLK0 STRING "1"
245  // Retrieval info: PRIVATE: USE_CLK1 STRING "1"
246  // Retrieval info: PRIVATE: USE_CLK2 STRING "1"
247  // Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
248  // Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
249  // Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
250  // Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
251  // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
252  // Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"
253  // Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
254  // Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "1"
255  // Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "-3000"
256  // Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1"
257  // Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
258  // Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2"
259  // Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
260  // Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "2"
261  // Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
262  // Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "1"
263  // Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
264  // Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
265  // Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000"
266  // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
267  // Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
268  // Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
269  // Retrieval info: CONSTANT: PLL_TYPE STRING "FAST"
270  // Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
271  // Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
272  // Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
273  // Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
274  // Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
275  // Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
276  // Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
277  // Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
278  // Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
279  // Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_UNUSED"
280  // Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
281  // Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
282  // Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
283  // Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
284  // Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
285  // Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
286  // Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
287  // Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
288  // Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
289  // Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
290  // Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
291  // Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
292  // Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
293  // Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
294  // Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
295  // Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
296  // Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
297  // Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
298  // Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
299  // Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
300  // Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
301  // Retrieval info: CONSTANT: PORT_enable0 STRING "PORT_UNUSED"
302  // Retrieval info: CONSTANT: PORT_enable1 STRING "PORT_UNUSED"
303  // Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
304  // Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
305  // Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
306  // Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
307  // Retrieval info: CONSTANT: PORT_extclkena0 STRING "PORT_UNUSED"
308  // Retrieval info: CONSTANT: PORT_extclkena1 STRING "PORT_UNUSED"
309  // Retrieval info: CONSTANT: PORT_extclkena2 STRING "PORT_UNUSED"
310  // Retrieval info: CONSTANT: PORT_extclkena3 STRING "PORT_UNUSED"
311  // Retrieval info: CONSTANT: PORT_sclkout0 STRING "PORT_UNUSED"
312  // Retrieval info: CONSTANT: PORT_sclkout1 STRING "PORT_UNUSED"
313  // Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]"
314  // Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..0]"
315  // Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
316  // Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
317  // Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
318  // Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
319  // Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
320  // Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
321  // Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
322  // Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
323  // Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
324  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL.v TRUE FALSE
325  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL.inc FALSE FALSE
326  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL.cmp FALSE FALSE
327  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL.bsf FALSE FALSE
328  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL_inst.v FALSE FALSE
329  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL_bb.v FALSE FALSE
330  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL_waveforms.html FALSE FALSE
331  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL_wave*.jpg FALSE FALSE
332  // Retrieval info: GEN_FILE: TYPE_NORMAL SDRAM_PLL.ppf TRUE FALSE
333 


最後的pin assignment、compiling、programmer部分我就不在多言。

Nios II軟體部分

Step 1:
在Nios II EDS建立一個Hello World project,請參考
(原創) 如何自己用SOPC Builder建立一個能在DE2上跑μC/OS-II的Nios II系統? (IC Design) (DE2) (Quartus II) (Nios II) (SOPC Builder) (μC/OS-II)

Step 2:
hello_world.c

 1  /*  
 2  (C) OOMusou 2008  http://oomusou.cnblogs.com
 3 
 4  Filename    : hello_world.c
 5  Compiler    : gcc
 6  Description : Demo how to read / write SDRAM
 7  Release     : 04/09/2008 1.0
 8  */
 9  #include  " system.h "
10  #include  < io.h >
11 
12  int  main() {
13     while ( 1 ) {
14       //  method 1
15       //  read switch 
16      unsigned  int  i  =  IORD(SW_BASE,  0 );  
17      unsigned  int  j  =   0 ;
18       
19      IOWR(SDRAM_BASE,  0 , i);
20      j  =  IORD(SDRAM_BASE,  0 );
21      
22       //  write ledr
23      IOWR(LEDR_BASE,  0 , j);
24    }
25  }
26 


想做的事情很簡單,LEDR會根據switch的撥動而做不同的顯示,但這裡做了小小的改變,我故意將switch讀到的值利用IOWR(SDRAM_BASE, 0, i)存入SDRAM,然後再用IORD(SDRAM_BASE, 0)從SDRAM讀出,最後透過IOWR(LEDR_BASE, 0)顯示LEDR,總之,有了SDRAM controller之後,C語言也能利用IORD()與IOWR()對SDRAM做讀寫。

Conclsion
要在Nios II系統利用C語言讀寫SDRAM並不難,只要透過SDRAM controller即可,但由於SDRAM所需要的clock不同,所以還需要SDRAM_PLL去調整clock,這是SDRAM與on-chip memory、SRAM不同之處。

完整程式碼下載
SDRAM_SW_RW.7z

See Also
(原創) 如何自己用SOPC Builder建立一個能在DE2上跑μC/OS-II的Nios II系統? (IC Design) (DE2) (Quartus II) (Nios II) (SOPC Builder) (μC/OS-II)
(原創) 如何在DE2將CCD影像顯示在彩色LCD上? (Nios II軟體篇 + onchip memory) (IC Design) (DE2) (Nios II) (SOPC Builder)
(原創) 如何在DE2將CCD影像顯示在彩色LCD? (Nios II軟體篇 + μC/OS-II + SRAM + 驅動程式) (IC Design) (DE2) (Nios II) (μC/OS-II) (SOPC Builder)
(原創) 如何在DE2執行Checksum Master範例? (IC Design) (DE2) (Quartus II) (Nios II) (SOPC Builder)
(原創) 如何在DE2用硬體存取SDRAM? (IC Design) (DE2)
(原創) 如何在DE2用硬體存取SDRAM(4 port)? (IC Design) (DE2)
(筆記) DE2與SDRAM相關資料總整理 (SOC) (DE2)

Reference
Introduction to Altera SOPC Builder Using Verilog Design
Introduction to Altera SOPC Builder Using VHDL Design
Using the SDRAM Memory on Altera's DE2 Board with Verilog Design
Using the SDRAM Memory on Altera's DE2 Board with VHDL Design
張志剛, 2007, FPGA與SOPC設計教程--DE2實踐, 西安電子科技大學出版社


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值