Abstract
前一篇(原創) 如何在DE2將CCD影像顯示在彩色LCD上? (純硬體篇) (IC Design) (DE2) 討論了使用Verilog純硬體的方式實作簡易的數位相機,為了實現SOC和軟硬體整合,本文我們將加上Nios II CPU,透過軟體的方式去控制CCD和彩色LCD。
使用環境:Quartus II 7.2 SP1 + Nios II 7.2 SP1 + DE2(Cyclone II EP2C35F627C6) + TRDB_LCM + TRDB_DC2
Introduction
若就功能面而言,使用Verilog純硬體實作的數位相機已經達到功能了,唯一的缺憾是他是『純硬體』,我們無法使用C語言軟體的方式去控制CCD和LCD,所以我們打算加上Nios II CPU,透過記憶體定址的方式去控制硬體。
在(原創) 如何在DE2將CCD影像顯示在彩色LCD上? (純硬體篇) (IC Design) (DE2)中,我們使用了KEY和SW作為輸入的介面,這些KEY和SW直接與硬體的module相接,這是純硬體的方式。若要用軟體,我們勢必得用軟體去攔截KEY和SW輸入的結果,然後再將結果送到控制CCD和LCD的module。由於要使用軟體,一定需要一顆CPU,Nios II softcore CPU剛好可扮演這個角色,而軟體一定得載入記憶體執行,所以還需要一塊記憶體,DE2上有很多種記憶體可用,除了FPGA上的onchip-memory外,還有SRAM、SDRAM、Flash,為了簡化問題,本文先討論最單純的onchip-memory,後續會繼續討論使用SRAM等其他記憶體。
該如何攔截KEY和SW呢?Nios II提供了PIO的方式,可以輕易的攔截KEY和SW,這問題不大,但該如何用軟體去控制CCD和LCD呢?這就是本文的重點了。
Nios II提供了Avalon Bus,所有的周邊要和Nios II CPU溝通,都得透過這個bus,當然也必須遵守Avalon Bus的協定才能順利與Nios II溝通,所以必須將原來純硬體的Verilog程式碼,再多加上一個Adapter(是的,就是Design Pattern那個Adapter Pattern),讓原來的硬體能掛上Avalon Bus和Nios II溝通,只要能掛上Avalon Bus後,Nios II就能對這個Adapter做記憶體定址,只要有記憶體位址,C語言就能靠著記憶體位址對Adapter作存取了,也因此間接控制了CCD和LCD。
建立DE2_LCM_CCD_onchip專案
Step 1:
建立DE2_LCM_CCD_onchip目錄,將原本用Verilog純硬體的DE2_LCM_CCD.7z下載,將解壓縮後DE2_LCM_CCD下所有的檔案放到DE2_LCM_CCD_onchip下。
Step 2:
在DE2_LCM_CCD_onchip下建立ip子目錄。
要使SOPC Builder抓到你自己寫的controller,在Quartus II 7.2和以前版本有些不同,有兩種方法[1]:
1.將自己寫的controller放在專案目錄的ip子目錄下,這樣SOPC Builder在啟動時就會自動載入。這種方式適合controller只有這個專案會用到,而且期望你將專案複製給其他人時,不用設定就能抓到controller。
2.將controller放在獨立目錄,然後在SOPC Builder的Tools->Options->IP Search Path加入controller目錄,讓SOPC Builder可以找的到,這種方式適合多個專案要共用一個controller,不過若將專案複製給其他人時,對方還得自己設定controller路徑。
SOPC Builder更詳細的運作方式,請參閱(原創) 如何加速Altera的EDA工具? (IC Design) (Quartus II) (Nios II) (SOPC Builder) 。
本文採用的是第一種方法。
Step 3:
在ip目錄下建立CCD_Controller子目錄。
將CCD_Controller的Verilog code放在CCD_Controller目錄下。
撰寫CCD_Controller
CCD_Controller.v
2 // Avalon clock interface siganals
3 csi_clockreset_clk,
4 csi_clockreset_reset_n,
5 // Signals for Avalon-MM slave port
6 avs_s1_address,
7 avs_s1_chipselect,
8 avs_s1_write,
9 avs_s1_writedata,
10 // export
11 avs_s1_export_o_key,
12 avs_s1_export_o_sw
13 );
14
15 input csi_clockreset_clk;
16 input csi_clockreset_reset_n;
17
18 input avs_s1_address;
19 input avs_s1_chipselect;
20 input avs_s1_write;
21 input [ 15 : 0 ] avs_s1_writedata;
22
23 output [ 2 : 0 ] avs_s1_export_o_key;
24 output [ 15 : 0 ] avs_s1_export_o_sw;
25
26 reg [ 2 : 0 ] r_key;
27 reg [ 15 : 0 ] r_sw;
28
29 // write to export
30 always@(posedge csi_clockreset_clk or negedge csi_clockreset_reset_n)
31 begin
32 if ( ! csi_clockreset_reset_n)
33 begin
34 r_key <= 4 ' b1111;
35 r_sw <= 16 ' b0000_0000_0000_0000;
36 end
37 else
38 begin
39 if (avs_s1_address == 1 ' b0 && avs_s1_chipselect && avs_s1_write)
40 begin
41 r_key <= avs_s1_writedata[ 2 - : 3 ];
42 r_sw <= r_sw;
43 end
44 else if (avs_s1_address == 1 ' b1 && avs_s1_chipselect && avs_s1_write)
45 begin
46 r_key <= r_key;
47 r_sw <= avs_s1_writedata;
48 end
49 end
50 end
51
52 assign avs_s1_export_o_key = r_key;
53 assign avs_s1_export_o_sw = r_sw;
54
55 endmodule
這個CCD_Controller.v主要的目的在做什麼?由於CCD_Controller.v需要掛在Avalon Bus上,所以必須遵守Avalon-MM slave的規定,如clk、reset_n、address、chip_select、write、writedata這些port,尤其若要將資料送進CCD_Controller,Nios II是將資料送進writedata中,所以我們必須將writedata的資料進行解析,然後export出來,與CCD和LCD相關module相連。在Quartus II早期的版本,在port命名並沒有規定naming convention,所以在Component Editor的Signals還必須手動指定Signal Type,但在Quartus II 5.1以後增加了以下規定:
Interface Type | Meaning |
avs | Avalon-MM Slave |
avm | Avalon-MM Master |
ats | Avalon-MM Tristate Slave |
atm | Avalon-MM Tristate Master |
aso | Avalon-ST Source |
asi | Avalon-ST Sink |
cso | Clock Output |
csi | Clock Input |
inr | Interrupt Receiver |
ins | Interupt Sender |
cos | Conduit Start |
coe | Conduit End |
ncm | Nios II Custom Instruction Master |
ncs | Nios II Custom Instruction Slave |
csi_clockreset_clk | Clock Reset |
csi_clockreset_reset_n | Clock Reset N |
Table.1 Interface type value meaning [2]
20行
為什麼avs_s1_writedata要設定16 bit寬呢?因為這個controller主要的input為KEY和SW,KEY[0]由於作為硬體reset用,所以軟體就不加以攔截了,所以只有KEY[1]、KEY[2]、KEY[3]共3 bit,SW為16 bit,所以由最大的16 bit決定writedata寬度。
23行、24行
output [ 15 : 0 ] avs_s1_export_o_sw;
如前段所解釋,因為KEY只有3 bit,所以export用的avs_s1_export_key也只有3 bit,同理,avs_s1_export_o_sw也只有如SW的16 bit。
39行到43行
begin
r_key <= avs_s1_writedata[ 2 - : 3 ];
r_sw <= r_sw;
end
目的是將writedata資料解析為KEY,address的功用是做什麼呢?由於所有輸入的訊號都由writedata進來,我該怎麼分辨進來的訊號是KEY還是SW?就是靠address!!由於本controller只須分辨KEY和SW兩種訊號,所以address只需1 bit分辨0與1即可,並且規定1'b0為KEY,1'b1為SW,除此之外,Avalon Bus還規定chipselect和write為1時訊號才有效,所以必須增加判斷。
為什麼只抓writedata[2-:3]呢?由於writedata為16 bit,但KEY只有3 bit,所以只需writedata低3bit的資料即可,[2-:3]為Verilog專屬語法,表是從3bit開始往下抓3 bit。
44行到48行解析SW同理,由於SW和writedata同寬,只需用assign vector的方式即可。
最後必須將CCD_Controller.v存到DE2_LCM_CCD_onchip\ip\CCD_Controller\hdl\目錄下。
使用Component Editor建立CCD_Controller
Verilog程式寫好還不夠,還必須使用Component Editor將CCD_Controller.v包裝成SOPC Builder能用的controller。
Step 1:
按右上角圖示啟動SOPC Builder。
Fig.1 SOPC Builder圖示
Step 2:
設定System名稱,輸入nios_ii_system。
Fig.2 設定System名稱
Step 3:
啟動Component Editor
Fig.3 SOPC Builder
Step 4:
按下Add HDL File,加入CCD_Controller.v
Fig.4 Component Editor
Fig.5 加入CCD_Controller.v
加入後,Component Editor會對CCD_Controller.v作及時編譯,若Verilog語法有錯會顯示出來,若成功將出現以下畫面。
Fig.6 CCD_Controller.v編譯成功
Step 5:
設定Signals
由於CCD_Controller.v已經依照naming convention寫了,所以就不用再設定Signal Type,Component Editor會自動抓到。
Fig.7 Component Editor : Signals
Step 6:
設定Interfaces
Component Editor預設多抓了export_0這個interface(原因不明),須手動按Remove Interfaces With No Signals將其刪除。
Fig.8 Component Editor:Interfaces
移除export_0後,將s1的Associated Clock選擇clockreset,Slave Addressing選擇NATIVE。
Fig.9 Component Editor:Interfaces 2
Step 7:
填入Controller資訊
這些資訊可依你的需要自行修改,不會影響功能,最後按下Finish。
Fig.10 Component Editor:Component Wizard
Step 8:
完成CCD_Controller
按下Yes, Save後,Component Editor會為你在DE2_LCM_CCD_onchip\ip\CCD_Controller\hdl下產生CCD_Controller_hw.tcl。
Fig.11 確定產生CCD_Controller_hw.tcl
Fig.12 SOPC Builder出現CCD_Controller
建立Nios II System
接著我們要使用SOPC Builder產生以Nios II為基礎的SOC
Step 1:
加入Nios II Processor
選擇左側Altera SOPC Builder->Nios II Processor,滑鼠按兩下加入
Fig.13 加入Nios II Processor
選擇Nios II/e,因為本專案要使用on-chip memory,所以只好選Nios II/e以節省logic element,讓on-chip memory能開到最大。
Fig.14 選用Nios II/e
Step 2:
加入on-chip memory
由於要使用軟體,所以必須使用記憶體載入程式,為了簡化問題,所以本專案選擇最單純的on-chip memory,將記憶體直接放在FPGA內。
選擇左側Altera SOPC Builder->Memories and Memory Controller->On-Chip->On-Chip Memory(RAM or ROM),滑鼠按兩下加入
Fig.15 加入on-chip memory
設定on-chip memory大小為35KB。
為什麼只設定35KB,而不設定其他數值呢?Cyclone II(EP2C35F672C6)的Nios II,若取最單純的設定:Nios II/e + on-chip memory + JTAG UART + System ID Peripheral,且不包含任何自己寫的Verilog,極限可設定on-chip memory 49KB,且可正常編譯,以本例而言,由於CCD和LCD已經寫了不少Verilog,所以已經占了FPGA不少logic element,導致on-chip memory的極限只能設定到36KB,若更大則Quartus II無法正常編譯,這裡取35KB只因為剛好為整數,且對本系統已經夠用。
Fig.16 on-chip memory size
Step 3:
加入JTAG UART
本專案雖然不需在Console顯示文字,不過在Console使用printf()仍為最常用的debug方式,所以建議還是加上JTAG UART。
在左側SOPC Builder->Interface Protocols->Serial下找到JTAG UART,滑鼠點兩下加入,接受預設值即可,按Finish。
Fig.17 加入JTAG UART
Fig.18 JTAG UART window
Step 4:
加入System ID Peripheral
System ID Peripheral可以用來辨識硬體,雖然沒有加入也能執行,不過Altera原廠手冊仍建議加入此controller。
在左側Altera SOPC Builder->Peripherals->Debug and Performance下找到System ID Peripheral,滑鼠按兩下加入,接受預設值即可,按Finish。
Fig.19 加入System ID Peripheral
Fig.20 System ID Peripheral window
Step 5:
加入CCD_Controller
現在要加入剛剛自己寫好的CCD_Controller。
在左側Altera SOPC Builder->My Controller下找到CCD_Controller,滑鼠按兩下加入,接受預設值即可,按Finish。
Fig.21 加入CCD_Controller
Fig.22 CCD_Controller window
Step 6:
加入KEY PIO
由於我們要用軟體攔截KEY的輸入,所以要加上PIO。
在左側Altera SOPC Builder->Peripherals->Microcontroller Peripherals下找到PIO(Parallel I/O),滑鼠按兩下加入,接受預設值即可,按Finish。
Fig.23 加入PIO
由於KEY[0]是reset,因此軟體不攔,只用軟體攔KEY[1]、KEY[2]與KEY[3]而已,所以Width填3 bit。因為只是讀取KEY的輸入值,所以選Input ports only。
Fig.24 PIO window
更名為key_pio
Fig.25 更名為key_pio
Step 7:
加入SW PIO
由於我們要用軟體攔截SW的輸入,所以要加上PIO。
在左側Altera SOPC Builder->Peripherals->Microcontroller Peripherals下找到PIO(Parallel I/O),滑鼠按兩下加入,接受預設值即可,按Finish。
Fig.25 加入PIO
由於SW為16 bit,所以Width填3 bit。因為只是讀取SW的輸入值,所以選Input ports only。
Fig.26 PIO window
更名為sw_pio
Fig.27 更名為sw_pio
Step 8:
設定reset和exception vector
在右側CPU用滑鼠點兩下。
Fig.28 設定reset與exception
將reset和exception vector設在onchip_mem,這也是本專案唯一的記憶體。
Fig.29 將reset和exception設在onchip_mem
Step 9:
重新設定Base Address
由下方的錯誤訊息得知,有些元件所分配的base address衝突了,所以必須重新指定base address。
選擇System->Auto-Assign Base Address
Fig.30 Auto-Assign Base Address
Step 10:
產生Nios II System
截至目前為止,整個Nios II System已經設定完成,按Generate產生nios_ii_system.ptf,這需要一點時間,非常依賴CPU運算速度。
Fig.31 Generate System
按Save對Nios II System存檔。
Fig.32 Save system
經過一段時間後,值到右下方出現Generate,表是建立完成,按Exit回到Quartus II。
Fig.33 Generate complete
修改Top mudule:DE2_LCM_CCD.v
雖然SOPC Builder和Component Editor自動產生了很多Verilog程式碼,為我們省下不少工夫,但Top module還是得手動自己改,主要為了連接Nios II System和原本純硬體的CCD和LCD。
DE2_LCM_CCD.V
2 ///////////////////// / Clock Input ////////////////// //
3 CLOCK_27, // 27 MHz
4 CLOCK_50, // 50 MHz
5 EXT_CLOCK, // External Clock
6 ///////////////////// / Push Button ////////////////// //
7 KEY, // Pushbutton[3:0]
8 ////////////////// // DPDT Switch ////////////////// //
9 SW, // Toggle Switch[17:0]
10 ///////////////////// / 7-SEG Dispaly ////////////////// //
11 HEX0, // Seven Segment Digit 0
12 HEX1, // Seven Segment Digit 1
13 HEX2, // Seven Segment Digit 2
14 HEX3, // Seven Segment Digit 3
15 HEX4, // Seven Segment Digit 4
16 HEX5, // Seven Segment Digit 5
17 HEX6, // Seven Segment Digit 6
18 HEX7, // Seven Segment Digit 7
19 ///////////////////// / LED ////////////////////////
20 LEDG, // LED Green[8:0]
21 LEDR, // LED Red[17:0]
22 ///////////////////// / UART ////////////////////////
23 UART_TXD, // UART Transmitter
24 UART_RXD, // UART Receiver
25 ///////////////////// / IRDA ////////////////////////
26 IRDA_TXD, // IRDA Transmitter
27 IRDA_RXD, // IRDA Receiver
28 ///////////////////// / SDRAM Interface /////////////// /
29 DRAM_DQ, // SDRAM Data bus 16 Bits
30 DRAM_ADDR, // SDRAM Address bus 12 Bits
31 DRAM_LDQM, // SDRAM Low-byte Data Mask
32 DRAM_UDQM, // SDRAM High-byte Data Mask
33 DRAM_WE_N, // SDRAM Write Enable
34 DRAM_CAS_N, // SDRAM Column Address Strobe
35 DRAM_RAS_N, // SDRAM Row Address Strobe
36 DRAM_CS_N, // SDRAM Chip Select
37 DRAM_BA_0, // SDRAM Bank Address 0
38 DRAM_BA_1, // SDRAM Bank Address 0
39 DRAM_CLK, // SDRAM Clock
40 DRAM_CKE, // SDRAM Clock Enable
41 ///////////////////// / Flash Interface /////////////// /
42 FL_DQ, // FLASH Data bus 8 Bits
43 FL_ADDR, // FLASH Address bus 22 Bits
44 FL_WE_N, // FLASH Write Enable
45 FL_RST_N, // FLASH Reset
46 FL_OE_N, // FLASH Output Enable
47 FL_CE_N, // FLASH Chip Enable
48 ///////////////////// / SRAM Interface /////////////// /
49 SRAM_DQ, // SRAM Data bus 16 Bits
50 SRAM_ADDR, // SRAM Address bus 18 Bits
51 SRAM_UB_N, // SRAM High-byte Data Mask
52 SRAM_LB_N, // SRAM Low-byte Data Mask
53 SRAM_WE_N, // SRAM Write Enable
54 SRAM_CE_N, // SRAM Chip Enable
55 SRAM_OE_N, // SRAM Output Enable
56 ///////////////////// / ISP1362 Interface /////////////// /
57 OTG_DATA, // ISP1362 Data bus 16 Bits
58 OTG_ADDR, // ISP1362 Address 2 Bits
59 OTG_CS_N, // ISP1362 Chip Select
60 OTG_RD_N, // ISP1362 Write
61 OTG_WR_N, // ISP1362 Read
62 OTG_RST_N, // ISP1362 Reset
63 OTG_FSPEED, // USB Full Speed, 0 = Enable, Z = Disable
64 OTG_LSPEED, // USB Low Speed, 0 = Enable, Z = Disable
65 OTG_INT0, // ISP1362 Interrupt 0
66 OTG_INT1, // ISP1362 Interrupt 1
67 OTG_DREQ0, // ISP1362 DMA Request 0
68 OTG_DREQ1, // ISP1362 DMA Request 1
69 OTG_DACK0_N, // ISP1362 DMA Acknowledge 0
70 OTG_DACK1_N, // ISP1362 DMA Acknowledge 1
71 ///////////////////// / LCD Module 16X2 /////////////// /
72 LCD_ON, // LCD Power ON/OFF
73 LCD_BLON, // LCD Back Light ON/OFF
74 LCD_RW, // LCD Read/Write Select, 0 = Write, 1 = Read
75 LCD_EN, // LCD Enable
76 LCD_RS, // LCD Command/Data Select, 0 = Command, 1 = Data
77 LCD_DATA, // LCD Data bus 8 bits
78 ///////////////////// / SD_Card Interface /////////////// /
79 SD_DAT, // SD Card Data
80 SD_DAT3, // SD Card Data 3
81 SD_CMD, // SD Card Command Signal
82 SD_CLK, // SD Card Clock
83 ///////////////////// / USB JTAG link ////////////////// //
84 TDI, // CPLD -> FPGA (data in)
85 TCK, // CPLD -> FPGA (clk)
86 TCS, // CPLD -> FPGA (CS)
87 TDO, // FPGA -> CPLD (data out)
88 ///////////////////// / I2C /////////////////////////// /
89 I2C_SDAT, // I2C Data
90 I2C_SCLK, // I2C Clock
91 ///////////////////// / PS2 /////////////////////////// /
92 PS2_DAT, // PS2 Data
93 PS2_CLK, // PS2 Clock
94 ///////////////////// / VGA /////////////////////////// /
95 VGA_CLK, // VGA Clock
96 VGA_HS, // VGA H_SYNC
97 VGA_VS, // VGA V_SYNC
98 VGA_BLANK, // VGA BLANK
99 VGA_SYNC, // VGA SYNC
100 VGA_R, // VGA Red[9:0]
101 VGA_G, // VGA Green[9:0]
102 VGA_B, // VGA Blue[9:0]
103 ///////////////////// / Ethernet Interface ////////////////////////
104 ENET_DATA, // DM9000A DATA bus 16Bits
105 ENET_CMD, // DM9000A Command/Data Select, 0 = Command, 1 = Data
106 ENET_CS_N, // DM9000A Chip Select
107 ENET_WR_N, // DM9000A Write
108 ENET_RD_N, // DM9000A Read
109 ENET_RST_N, // DM9000A Reset
110 ENET_INT, // DM9000A Interrupt
111 ENET_CLK, // DM9000A Clock 25 MHz
112 ///////////////////// / Audio CODEC ////////////////////////
113 AUD_ADCLRCK, // Audio CODEC ADC LR Clock
114 AUD_ADCDAT, // Audio CODEC ADC Data
115 AUD_DACLRCK, // Audio CODEC DAC LR Clock
116 AUD_DACDAT, // Audio CODEC DAC Data
117 AUD_BCLK, // Audio CODEC Bit-Stream Clock
118 AUD_XCK, // Audio CODEC Chip Clock
119 ///////////////////// / TV Decoder ////////////////////////
120 TD_DATA, // TV Decoder Data bus 8 bits
121 TD_HS, // TV Decoder H_SYNC
122 TD_VS, // TV Decoder V_SYNC
123 TD_RESET, // TV Decoder Reset
124 ///////////////////// / GPIO /////////////////////////// /
125 GPIO_0, // GPIO Connection 0
126 GPIO_1 // GPIO Connection 1
127 );
128
129 ////////////////////////////// Clock Input ////////////////////////
130 input CLOCK_27; // 27 MHz
131 input CLOCK_50; // 50 MHz
132 input EXT_CLOCK; // External Clock
133 ////////////////////////////// Push Button ////////////////////////
134 input [ 3 : 0 ] KEY; // Pushbutton[3:0]
135 ////////////////////////////// DPDT Switch ////////////////////////
136 input [ 17 : 0 ] SW; // Toggle Switch[17:0]
137 ////////////////////////////// 7-SEG Dispaly ////////////////////////
138 output [ 6 : 0 ] HEX0; // Seven Segment Digit 0
139 output [ 6 : 0 ] HEX1; // Seven Segment Digit 1
140 output [ 6 : 0 ] HEX2; // Seven Segment Digit 2
141 output [ 6 : 0 ] HEX3; // Seven Segment Digit 3
142 output [ 6 : 0 ] HEX4; // Seven Segment Digit 4
143 output [ 6 : 0 ] HEX5; // Seven Segment Digit 5
144 output [ 6 : 0 ] HEX6; // Seven Segment Digit 6
145 output [ 6 : 0 ] HEX7; // Seven Segment Digit 7
146 ////////////////////////////// LED /////////////////////////// /
147 output [ 8 : 0 ] LEDG; // LED Green[8:0]
148 output [ 17 : 0 ] LEDR; // LED Red[17:0]
149 ////////////////////////////// UART /////////////////////////// /
150 output UART_TXD; // UART Transmitter
151 input UART_RXD; // UART Receiver
152 ////////////////////////////// IRDA /////////////////////////// /
153 output IRDA_TXD; // IRDA Transmitter
154 input IRDA_RXD; // IRDA Receiver
155 ////////////////////////////// SDRAM Interface ////////////////////////
156 inout [ 15 : 0 ] DRAM_DQ; // SDRAM Data bus 16 Bits
157 output [ 11 : 0 ] DRAM_ADDR; // SDRAM Address bus 12 Bits
158 output DRAM_LDQM; // SDRAM Low-byte Data Mask
159 output DRAM_UDQM; // SDRAM High-byte Data Mask
160 output DRAM_WE_N; // SDRAM Write Enable
161 output DRAM_CAS_N; // SDRAM Column Address Strobe
162 output DRAM_RAS_N; // SDRAM Row Address Strobe
163 output DRAM_CS_N; // SDRAM Chip Select
164 output DRAM_BA_0; // SDRAM Bank Address 0
165 output DRAM_BA_1; // SDRAM Bank Address 0
166 output DRAM_CLK; // SDRAM Clock
167 output DRAM_CKE; // SDRAM Clock Enable
168 ////////////////////////////// Flash Interface ////////////////////////
169 inout [ 7 : 0 ] FL_DQ; // FLASH Data bus 8 Bits
170 output [ 21 : 0 ] FL_ADDR; // FLASH Address bus 22 Bits
171 output FL_WE_N; // FLASH Write Enable
172 output FL_RST_N; // FLASH Reset
173 output FL_OE_N; // FLASH Output Enable
174 output FL_CE_N; // FLASH Chip Enable
175 ////////////////////////////// SRAM Interface ////////////////////////
176 inout [ 15 : 0 ] SRAM_DQ; // SRAM Data bus 16 Bits
177 output [ 17 : 0 ] SRAM_ADDR; // SRAM Address bus 18 Bits
178 output SRAM_UB_N; // SRAM High-byte Data Mask
179 output SRAM_LB_N; // SRAM Low-byte Data Mask
180 output SRAM_WE_N; // SRAM Write Enable
181 output SRAM_CE_N; // SRAM Chip Enable
182 output SRAM_OE_N; // SRAM Output Enable
183 ////////////////////////////// ISP1362 Interface ////////////////////////
184 inout [ 15 : 0 ] OTG_DATA; // ISP1362 Data bus 16 Bits
185 output [ 1 : 0 ] OTG_ADDR; // ISP1362 Address 2 Bits
186 output OTG_CS_N; // ISP1362 Chip Select
187 output OTG_RD_N; // ISP1362 Write
188 output OTG_WR_N; // ISP1362 Read
189 output OTG_RST_N; // ISP1362 Reset
190 output OTG_FSPEED; // USB Full Speed, 0 = Enable, Z = Disable
191 output OTG_LSPEED; // USB Low Speed, 0 = Enable, Z = Disable
192 input OTG_INT0; // ISP1362 Interrupt 0
193 input OTG_INT1; // ISP1362 Interrupt 1
194 input OTG_DREQ0; // ISP1362 DMA Request 0
195 input OTG_DREQ1; // ISP1362 DMA Request 1
196 output OTG_DACK0_N; // ISP1362 DMA Acknowledge 0
197 output OTG_DACK1_N; // ISP1362 DMA Acknowledge 1
198 ////////////////////////////// LCD Module 16X2 /////////////////////////// /
199 inout [ 7 : 0 ] LCD_DATA; // LCD Data bus 8 bits
200 output LCD_ON; // LCD Power ON/OFF
201 output LCD_BLON; // LCD Back Light ON/OFF
202 output LCD_RW; // LCD Read/Write Select, 0 = Write, 1 = Read
203 output LCD_EN; // LCD Enable
204 output LCD_RS; // LCD Command/Data Select, 0 = Command, 1 = Data
205 ////////////////////////////// SD Card Interface ////////////////////////
206 inout SD_DAT; // SD Card Data
207 inout SD_DAT3; // SD Card Data 3
208 inout SD_CMD; // SD Card Command Signal
209 output SD_CLK; // SD Card Clock
210 ////////////////////////////// I2C ////////////////////////////// //
211 inout I2C_SDAT; // I2C Data
212 output I2C_SCLK; // I2C Clock
213 ////////////////////////////// PS2 ////////////////////////////// //
214 input PS2_DAT; // PS2 Data
215 input PS2_CLK; // PS2 Clock
216 ////////////////////////////// USB JTAG link /////////////////////////// /
217 input TDI; // CPLD -> FPGA (data in)
218 input TCK; // CPLD -> FPGA (clk)
219 input TCS; // CPLD -> FPGA (CS)
220 output TDO; // FPGA -> CPLD (data out)
221 ////////////////////////////// VGA /////////////////////////// /
222 output VGA_CLK; // VGA Clock
223 output VGA_HS; // VGA H_SYNC
224 output VGA_VS; // VGA V_SYNC
225 output VGA_BLANK; // VGA BLANK
226 output VGA_SYNC; // VGA SYNC
227 output [ 9 : 0 ] VGA_R; // VGA Red[9:0]
228 output [ 9 : 0 ] VGA_G; // VGA Green[9:0]
229 output [ 9 : 0 ] VGA_B; // VGA Blue[9:0]
230 ////////////////////////////// Ethernet Interface /////////////////////////// /
231 inout [ 15 : 0 ] ENET_DATA; // DM9000A DATA bus 16Bits
232 output ENET_CMD; // DM9000A Command/Data Select, 0 = Command, 1 = Data
233 output ENET_CS_N; // DM9000A Chip Select
234 output ENET_WR_N; // DM9000A Write
235 output ENET_RD_N; // DM9000A Read
236 output ENET_RST_N; // DM9000A Reset
237 input ENET_INT; // DM9000A Interrupt
238 output ENET_CLK; // DM9000A Clock 25 MHz
239 ////////////////////////////// Audio CODEC /////////////////////////// /
240 inout AUD_ADCLRCK; // Audio CODEC ADC LR Clock
241 input AUD_ADCDAT; // Audio CODEC ADC Data
242 inout AUD_DACLRCK; // Audio CODEC DAC LR Clock
243 output AUD_DACDAT; // Audio CODEC DAC Data
244 inout AUD_BCLK; // Audio CODEC Bit-Stream Clock
245 output AUD_XCK; // Audio CODEC Chip Clock
246 ////////////////////////////// TV Devoder /////////////////////////// /
247 input [ 7 : 0 ] TD_DATA; // TV Decoder Data bus 8 bits
248 input TD_HS; // TV Decoder H_SYNC
249 input TD_VS; // TV Decoder V_SYNC
250 output TD_RESET; // TV Decoder Reset
251 ////////////////////////////// GPIO ////////////////////////////// //
252 inout [ 35 : 0 ] GPIO_0; // GPIO Connection 0
253 inout [ 35 : 0 ] GPIO_1; // GPIO Connection 1
254
255 // Turn on all display
256 assign LCD_ON = 1 ' b1;
257 assign LCD_BLON = 1 ' b1;
258
259 // All inout port turn to tri-state
260 assign DRAM_DQ = 16 ' hzzzz;
261 assign FL_DQ = 8 ' hzz;
262 assign SRAM_DQ = 16 ' hzzzz;
263 assign OTG_DATA = 16 ' hzzzz;
264 assign LCD_DATA = 8 ' hzz;
265 assign SD_DAT = 1 ' bz;
266 assign ENET_DATA = 16 ' hzzzz;
267 assign AUD_ADCLRCK = 1 ' bz;
268 assign AUD_DACLRCK = 1 ' bz;
269 assign AUD_BCLK = 1 ' bz;
270 assign TD_RESET = 1 ' b1;
271
272 //////////////////////// For TFT LCD Module ///////////////////// //
273 wire [ 7 : 0 ] LCM_DATA; // LCM Data 8 Bits
274 wire LCM_GRST; // LCM Global Reset
275 wire LCM_SHDB; // LCM Sleep Mode
276 wire LCM_DCLK; // LCM Clcok
277 wire LCM_HSYNC; // LCM HSYNC
278 wire LCM_VSYNC; // LCM VSYNC
279 wire LCM_SCLK; // LCM I2C Clock
280 wire LCM_SDAT; // LCM I2C Data
281 wire LCM_SCEN; // LCM I2C Enable
282 wire CLK_18;
283
284 assign GPIO_0[ 18 ] = LCM_DATA[ 6 ];
285 assign GPIO_0[ 19 ] = LCM_DATA[ 7 ];
286 assign GPIO_0[ 20 ] = LCM_DATA[ 4 ];
287 assign GPIO_0[ 21 ] = LCM_DATA[ 5 ];
288 assign GPIO_0[ 22 ] = LCM_DATA[ 2 ];
289 assign GPIO_0[ 23 ] = LCM_DATA[ 3 ];
290 assign GPIO_0[ 24 ] = LCM_DATA[ 0 ];
291 assign GPIO_0[ 25 ] = LCM_DATA[ 1 ];
292 assign GPIO_0[ 26 ] = LCM_VSYNC;
293 assign GPIO_0[ 28 ] = LCM_SCLK;
294 assign GPIO_0[ 29 ] = LCM_DCLK;
295 assign GPIO_0[ 30 ] = LCM_GRST;
296 assign GPIO_0[ 31 ] = LCM_SHDB;
297 assign GPIO_0[ 33 ] = LCM_SCEN;
298 assign GPIO_0[ 34 ] = LCM_SDAT;
299 assign GPIO_0[ 35 ] = LCM_HSYNC;
300
301 //////////////////////// For CMOS Sensor 1 ///////////////////// //
302 wire [ 9 : 0 ] CCD_DATA;
303 wire CCD_SDAT;
304 wire CCD_SCLK;
305 wire CCD_FLASH;
306 wire CCD_FVAL;
307 wire CCD_LVAL;
308 wire CCD_PIXCLK;
309 reg CCD_MCLK; // CCD Master Clock
310
311 wire [ 15 : 0 ] Read_DATA1;
312 wire [ 15 : 0 ] Read_DATA2;
313 wire [ 9 : 0 ] mCCD_DATA;
314 wire mCCD_DVAL;
315 wire mCCD_DVAL_d;
316 wire [ 10 : 0 ] X_Cont;
317 wire [ 10 : 0 ] Y_Cont;
318 wire [ 9 : 0 ] X_ADDR;
319 wire [ 31 : 0 ] Frame_Cont;
320 wire [ 9 : 0 ] mCCD_R;
321 wire [ 9 : 0 ] mCCD_G;
322 wire [ 9 : 0 ] mCCD_B;
323 wire DLY_RST_0;
324 wire DLY_RST_1;
325 wire DLY_RST_2;
326 wire Read;
327 reg [ 9 : 0 ] rCCD_DATA;
328 reg rCCD_LVAL;
329 reg rCCD_FVAL;
330 wire [ 9 : 0 ] sCCD_R;
331 wire [ 9 : 0 ] sCCD_G;
332 wire [ 9 : 0 ] sCCD_B;
333 wire sCCD_DVAL;
334
335 // add by oomusou
336 wire [ 2 : 0 ] CCD_KEY;
337 wire [ 15 : 0 ] CCD_SW;
338
339
340 assign CCD_DATA[ 0 ] = GPIO_1[ 0 ];
341 assign CCD_DATA[ 1 ] = GPIO_1[ 1 ];
342 assign CCD_DATA[ 2 ] = GPIO_1[ 5 ];
343 assign CCD_DATA[ 3 ] = GPIO_1[ 3 ];
344 assign CCD_DATA[ 4 ] = GPIO_1[ 2 ];
345 assign CCD_DATA[ 5 ] = GPIO_1[ 4 ];
346 assign CCD_DATA[ 6 ] = GPIO_1[ 6 ];
347 assign CCD_DATA[ 7 ] = GPIO_1[ 7 ];
348 assign CCD_DATA[ 8 ] = GPIO_1[ 8 ];
349 assign CCD_DATA[ 9 ] = GPIO_1[ 9 ];
350 assign GPIO_1[ 11 ] = CCD_MCLK;
351 assign GPIO_1[ 15 ] = CCD_SDAT;
352 assign GPIO_1[ 14 ] = CCD_SCLK;
353 assign CCD_FVAL = GPIO_1[ 13 ];
354 assign CCD_LVAL = GPIO_1[ 12 ];
355 assign CCD_PIXCLK = GPIO_1[ 10 ];
356
357 // edit by oomusou
358 assign LEDR = CCD_SW;
359 assign LEDG = Y_Cont;
360
361 always@(posedge CLOCK_50)
362 CCD_MCLK <= CCD_MCLK;
363
364 always@(posedge CCD_PIXCLK)
365 begin
366 rCCD_DATA <= CCD_DATA;
367 rCCD_LVAL <= CCD_LVAL;
368 rCCD_FVAL <= CCD_FVAL;
369 end
370
371 LCM_PLL u0 (
372 .inclk0(CLOCK_27),
373 .c0(CLK_18)
374 );
375
376 LCM_Controller u1 (
377 // Host Side
378 .iRed(Read_DATA2[ 9 : 2 ]),
379 .iGreen({Read_DATA1[ 14 : 10 ],Read_DATA2[ 14 : 12 ]}),
380 .iBlue(Read_DATA1[ 9 : 2 ]),
381 // LCM Side
382 .LCM_DATA(LCM_DATA),
383 .LCM_VSYNC(LCM_VSYNC),
384 .LCM_HSYNC(LCM_HSYNC),
385 .LCM_DCLK(LCM_DCLK),
386 .LCM_SHDB(LCM_SHDB),
387 .LCM_GRST(LCM_GRST),
388 // Control Signals
389 .oDATA_REQ(Read),
390 .iCLK(CLK_18),
391 .iRST_N(DLY_RST_2)
392 );
393
394 Reset_Delay u2 (
395 .iCLK(CLOCK_50),
396 .iRST(KEY[ 0 ]),
397 .oRST_0(DLY_RST_0),
398 .oRST_1(DLY_RST_1),
399 .oRST_2(DLY_RST_2)
400 );
401
402 CCD_Capture u3 (
403 .oDATA(mCCD_DATA),
404 .oDVAL(mCCD_DVAL),
405 .oX_Cont(X_Cont),
406 .oY_Cont(Y_Cont),
407 .oFrame_Cont(Frame_Cont),
408 .iDATA(rCCD_DATA),
409 .iFVAL(rCCD_FVAL),
410 .iLVAL(rCCD_LVAL),
411 .iSTART( ! CCD_KEY[ 2 ]), // edit by oomusou
412 .iEND( ! CCD_KEY[ 1 ]), // edit by oomusou
413 .iCLK(CCD_PIXCLK),
414 .iRST(DLY_RST_1)
415 );
416
417 RAW2RGB u4 (
418 .oRed(mCCD_R),
419 .oGreen(mCCD_G),
420 .oBlue(mCCD_B),
421 .oDVAL(mCCD_DVAL_d),
422 .iX_Cont(X_Cont),
423 .iY_Cont(Y_Cont),
424 .iDATA(mCCD_DATA),
425 .iDVAL(mCCD_DVAL),
426 .iCLK(CCD_PIXCLK),
427 .iRST(DLY_RST_1)
428 );
429
430 SEG7_LUT_8 u5 (
431 .oSEG0(HEX0),
432 .oSEG1(HEX1),
433 .oSEG2(HEX2),
434 .oSEG3(HEX3),
435 .oSEG4(HEX4),
436 .oSEG5(HEX5),
437 .oSEG6(HEX6),
438 .oSEG7(HEX7),
439 .iDIG(Frame_Cont)
440 );
441
442 Sdram_Control_4Port u6 (
443 // HOST Side
444 .REF_CLK(CLOCK_50),
445 .RESET_N( 1 ' b1),
446 // FIFO Write Side 1
447 .WR1_DATA({sCCD_G[ 9 : 5 ], sCCD_B[ 9 : 0 ]}),
448 .WR1(sCCD_DVAL),
449 .WR1_ADDR( 0 ),
450 .WR1_MAX_ADDR( 320 * 256 ),
451 .WR1_LENGTH( 9 ' h100),
452 .WR1_LOAD( ! DLY_RST_0),
453 .WR1_CLK(CCD_PIXCLK),
454 // FIFO Write Side 2
455 .WR2_DATA( {sCCD_G[ 4 : 0 ], sCCD_R[ 9 : 0 ]}),
456 .WR2(sCCD_DVAL),
457 .WR2_ADDR( 22 ' h100000),
458 .WR2_MAX_ADDR( 22 ' h100000+320*256),
459 .WR2_LENGTH( 9 ' h100),
460 .WR2_LOAD( ! DLY_RST_0),
461 .WR2_CLK(CCD_PIXCLK),
462 // FIFO Read Side 1
463 .RD1_DATA(Read_DATA1),
464 .RD1(Read),
465 .RD1_ADDR( 320 * 8 ),
466 .RD1_MAX_ADDR( 320 * 248 ),
467 .RD1_LENGTH( 9 ' h100),
468 .RD1_LOAD( ! DLY_RST_0),
469 .RD1_CLK(CLK_18),
470 // FIFO Read Side 2
471 .RD2_DATA(Read_DATA2),
472 .RD2(Read),
473 .RD2_ADDR( 22 ' h100000+320*8),
474 .RD2_MAX_ADDR( 22 ' h100000+320*248),
475 .RD2_LENGTH( 9 ' h100),
476 .RD2_LOAD( ! DLY_RST_0),
477 .RD2_CLK(CLK_18),
478 // SDRAM Side
479 .SA(DRAM_ADDR),
480 .BA({DRAM_BA_1,DRAM_BA_0}),
481 .CS_N(DRAM_CS_N),
482 .CKE(DRAM_CKE),
483 .RAS_N(DRAM_RAS_N),
484 .CAS_N(DRAM_CAS_N),
485 .WE_N(DRAM_WE_N),
486 .DQ(DRAM_DQ),
487 .DQM({DRAM_UDQM,DRAM_LDQM}),
488 .SDR_CLK(DRAM_CLK)
489 );
490
491 I2C_CCD_Config u7 (
492 // Host Side
493 .iCLK(CLOCK_50),
494 .iRST_N(CCD_KEY[ 0 ]), // edit by oomusou
495 .iExposure(CCD_SW[ 15 : 0 ]), // edit by oomusou
496 // I2C Side
497 .I2C_SCLK(CCD_SCLK),
498 .I2C_SDAT(CCD_SDAT)
499 );
500
501 I2S_LCM_Config u8 (
502 // Host Side
503 .iCLK(CLOCK_50),
504 .iRST_N(KEY[ 0 ]),
505 // I2C Side
506 .I2S_SCLK(LCM_SCLK),
507 .I2S_SDAT(LCM_SDAT),
508 .I2S_SCEN(LCM_SCEN)
509 );
510
511 I2C_AV_Config u9 (
512 // Host Side
513 .iCLK(CLOCK_50),
514 .iRST_N(KEY[ 0 ]),
515 // I2C Side
516 .I2C_SCLK(I2C_SCLK),
517 .I2C_SDAT(I2C_SDAT)
518 );
519
520 Mirror_Col u10 (
521 // Input Side
522 .iCCD_R(mCCD_R),
523 .iCCD_G(mCCD_G),
524 .iCCD_B(mCCD_B),
525 .iCCD_DVAL(mCCD_DVAL_d),
526 .iCCD_PIXCLK(CCD_PIXCLK),
527 .iRST_N(DLY_RST_1),
528 // Output Side
529 .oCCD_R(sCCD_R),
530 .oCCD_G(sCCD_G),
531 .oCCD_B(sCCD_B),
532 .oCCD_DVAL(sCCD_DVAL)
533 );
534
535 nios_ii_system nios_ii (
536 .clk(CLOCK_50),
537 .reset_n(KEY[ 0 ]),
538 .in_port_to_the_key_pio(KEY[ 3 : 1 ]),
539 .in_port_to_the_sw_pio(SW),
540 .avs_s1_export_o_key_from_the_CCD_Controller_inst(CCD_KEY),
541 .avs_s1_export_o_sw_from_the_CCD_Controller_inst(CCD_SW)
542 );
543
544 endmodule
535行
.clk(CLOCK_50),
.reset_n(KEY[ 0 ]),
.in_port_to_the_key_pio(KEY[ 3 : 1 ]),
.in_port_to_the_sw_pio(SW),
.avs_s1_export_o_key_from_the_CCD_Controller_inst(CCD_KEY),
.avs_s1_export_o_sw_from_the_CCD_Controller_inst(CCD_SW)
);
將我們剛剛所建立的nios_ii_system加入,或許你會疑問?我怎麼知道SOPC Builder為我們產生的nios_ii_system有哪些port?請參考nios_ii_system.v內nios_ii_system這個module。
clk和reset_n直接接上top module所定義的CLOCK_50和KEY[0]即可,這不是問題,由於我們就是要用軟體去攔截KEY和SW,所以in_port_to_the_key_pio與in_port_to_the_sw_pio要與硬體的KEY[3:1]與SW相接。
avs_s1_export_o_key_from_the_CCD_Controller_inst與avs_s1_export_o_sw_from_the_CCD_Controller_inst輸出我們經由avalon bus writedata解析後的KEY和SW,與自己加上CCD_KEY和CCD_SW這兩個wire相接,準備將這兩個wire和原來CCD和LCM的module相連。
335行
wire [ 2 : 0 ] CCD_KEY;
wire [ 15 : 0 ] CCD_SW;
宣告了新產生的wire
358行
由於LEDR會根據SW的on或off改變,原本接的是硬體SW,現在改接我們輸出的CCD_SW。
402行
.oDATA(mCCD_DATA),
.oDVAL(mCCD_DVAL),
.oX_Cont(X_Cont),
.oY_Cont(Y_Cont),
.oFrame_Cont(Frame_Cont),
.iDATA(rCCD_DATA),
.iFVAL(rCCD_FVAL),
.iLVAL(rCCD_LVAL),
.iSTART( ! CCD_KEY[ 2 ]), // edit by oomusou
.iEND( ! CCD_KEY[ 1 ]), // edit by oomusou
.iCLK(CCD_PIXCLK),
.iRST(DLY_RST_1)
);
iSTART和iEND原來也是直接硬體KEY和SW,現在改接自己的CCD_KEY和CCD_SW。
491行
// Host Side
.iCLK(CLOCK_50),
.iRST_N(CCD_KEY[ 0 ]), // edit by oomusou
.iExposure(CCD_SW[ 15 : 0 ]), // edit by oomusou
// I2C Side
.I2C_SCLK(CCD_SCLK),
.I2C_SDAT(CCD_SDAT)
);
.iRST與iExposure原來接的是硬體的KEY與SW,現在改接自己的CCD_KEY和CCD_SW。
使用Quartus II編譯Verilog
截至目前為止,SOPC和硬體部分已經完全,開始使用Quartus II編譯Verilog。Quartus II編譯需要一段時間,以我目前的配備Intel Core 2 Duo T7500,編譯還需要1分26秒。
Fig.34 編譯Verilog
使用Programmer將DE2_LCM_CCD.sof燒進FPGA
編譯完產生DE2_LCM_CCD.sof,使用Programmer燒進F PGA後,完成硬體佈署。
Fig.35 啟動Programmer
按Start將DE2_LCM_CCD.sof燒進FPGA。
Fig.36 按Start開始燒錄
開發Nios II軟體
硬體部分完成了,現在我們要開發Nios II軟體。
Step 1:
啟動Nios II EDS
Fig.37 Nios II EDS
Step 2:
建立Nios II C/C++ Application
按滑鼠右鍵,New->Nios II C/C++ Application
Fig.38 New Nios II C/C++ Application
選擇右側Hello World template,將SOPC Builder System PTF File指向DE2_LCM_CCD_onchip\nios_ii_system.ptf,這是由SOPC Builder所產生的檔案,描述著我們剛剛建立的Nios II System,最後直接按Finish。
Fig. 40 New Project
Step 3:
修改hello_world.c
hello_world.c
2 #include < io.h >
3
4 int main() {
5
6 while(1) {
7 // read switch
8 unsigned char key = IORD(KEY_PIO_BASE, 0);
9 unsigned int sw = IORD(SW_PIO_BASE, 0);
10
11 // write CCD
12 IOWR(CCD_CONTROLLER_INST_BASE, 1, sw);
13 IOWR(CCD_CONTROLLER_INST_BASE, 0, key);
14 }
15}
第8行
unsigned int sw = IORD(SW_PIO_BASE, 0 );
使用IORD去讀取目前KEY和SW的狀態,IORD()和IOWR()定義在io.h當中,由Nios II所提供。
KEY_PIO_BASE和SW_PIO_BASE定義在system.h,你可以在\DE2_LCM_CCD_onchip\software\hello_world_0_syslib\Debug\system_description\system.h找到,當建立project時,Nios II EDS會根據nios_ii_system.ptf的內容自動產生system.h,主要記載著SOPC中各controller的base address,透過base address,我們就可以在軟體存取硬體了。
第二個參數0是address,填0即可。
11行
IOWR(CCD_CONTROLLER_INST_BASE, 0 , key);
將在軟體讀到的KEY和SW送進自己寫的CCD_Controller,CCD_CONTROLLER_INST_BASE定義在system.h中。為什麼傳sw時,第二個參數是1呢?而key是0呢?在CCD_Controller.v中,我們曾經這樣定義:
begin
r_key <= avs_s1_writedata[ 2 - : 3 ];
r_sw <= r_sw;
end
else if (avs_s1_address == 1 ' b1 && avs_s1_chipselect && avs_s1_write)
begin
r_key <= r_key;
r_sw <= avs_s1_writedata;
end
address 0表示傳入KEY,address 1表示傳入SW,所以我們在軟體端必須遵照這個規則。
這樣整個軟硬體就大功告成了!!
完整程式碼下載
DE2_LCM_CCD_onchip.7z
Conclusion
這篇文章是我寫過最長的blog,用到的圖片達40張也破紀錄了,其實關鍵的觀念只有一個:『如何將自己寫的Verilog包成component加進Nios II?』,Altera在Quartus II 7.2 Handbook Volumn 4: SOPC Builder Ch.9 Developing Components for SOPC Builder提供了一個完整的範例:Checksm Master,可以參考拙作(原創) 如何在DE2執行Checksum Master範例? (中級) (IC Design) (DE2) (Quartus II) (Nios II) (SOPC Builder),本文也可當成一篇練習寫component的tutorial。
還缺什麼呢?
1.本篇作法雖然已經讓軟硬體整合,讓軟體控制Nios II硬體,不過嚴格來說還不算Driver,一般來說,還會提供HAL(Hardware Abstraction Layer),以API的方式讓軟體呼叫。
2.使用on-chip memory並不實際,實務上幾乎不會用on-chip memory,會用SRAM或SDRAM。
3.還沒有上OS。
下一篇(原創) 如何在DE2將CCD影像顯示在彩色LCD? (Nios II軟體篇 + μC/OS-II + SRAM + 驅動程式) (IC Design) (DE2) (Nios II) (μC/OS-II) (SOPC Builder),我將以這個專案為基礎下,繼續加上API和OS,並跑在SRAM,讓它更完整。
See Also
(原創) 如何在DE2執行Checksum Master範例? (中級) (IC Design) (DE2) (Quartus II) (Nios II) (SOPC Builder)
(原創) 如何在DE2將CCD影像顯示在彩色LCD上? (純硬體篇) (IC Design) (DE2)
(原創) 如何在DE2將CCD影像顯示在彩色LCD? (Nios II軟體篇 + μC/OS-II + SRAM + 驅動程式) (IC Design) (DE2) (Nios II) (μC/OS-II) (SOPC Builder)
(原創) 如何加速Altera的EDA工具? (IC Design) (Quartus II) (Nios II) (SOPC Builder)
(原創) 深入探討Altera的Checksum Master範例 (SOC) (SOPC Builder) (Nios II) (DE2)
Reference
[1] Quartus II 7.2 Handbook Volumn 4 : SOPC Builder P.4-4
[2] Quartus II 7.2 Handbook Volumn 4 : SOPC Builder P.5-4