posts - 858, comments - 3583, trackbacks - 161, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

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

1 module CCD_Controller (
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>_<interface name>_<signal type>

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行

input  [15:0] avs_s1_writedata;


為什麼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 [2:0]  avs_s1_export_o_key;
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行

if (avs_s1_address == 1'b0 && avs_s1_chipselect && avs_s1_write)
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。

 de2_lcm_ccd_04

Fig.1 SOPC Builder圖示

Step 2:
設定System名稱,輸入nios_ii_system。

de2_lcm_ccd_04a 

Fig.2 設定System名稱

Step 3:
啟動Component Editor

 de2_lcm_ccd_05

Fig.3 SOPC Builder

Step 4:
按下Add HDL File,加入CCD_Controller.v

de2_lcm_ccd_06

Fig.4 Component Editor

de2_lcm_ccd_06a 

Fig.5 加入CCD_Controller.v

加入後,Component Editor會對CCD_Controller.v作及時編譯,若Verilog語法有錯會顯示出來,若成功將出現以下畫面。

de2_lcm_ccd_07

Fig.6 CCD_Controller.v編譯成功

Step 5:
設定Signals
由於CCD_Controller.v已經依照naming convention寫了,所以就不用再設定Signal Type,Component Editor會自動抓到。

de2_lcm_ccd_08 

Fig.7 Component Editor : Signals

Step 6:
設定Interfaces
Component Editor預設多抓了export_0這個interface(原因不明),須手動按Remove Interfaces With No Signals將其刪除。

 de2_lcm_ccd_09

Fig.8 Component Editor:Interfaces

移除export_0後,將s1的Associated Clock選擇clockreset,Slave Addressing選擇NATIVE。

de2_lcm_ccd_10

Fig.9 Component Editor:Interfaces 2

Step 7:
填入Controller資訊
這些資訊可依你的需要自行修改,不會影響功能,最後按下Finish。

de2_lcm_ccd_11 

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。

de2_lcm_ccd_12

Fig.11 確定產生CCD_Controller_hw.tcl

de2_lcm_ccd_13

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,滑鼠按兩下加入

de2_lcm_ccd_14

Fig.13 加入Nios II Processor

選擇Nios II/e,因為本專案要使用on-chip memory,所以只好選Nios II/e以節省logic element,讓on-chip memory能開到最大。

 de2_lcm_ccd_15

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),滑鼠按兩下加入

de2_lcm_ccd_16

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只因為剛好為整數,且對本系統已經夠用。

 de2_lcm_ccd_17

Fig.16 on-chip memory size

Step 3:
加入JTAG UART
本專案雖然不需在Console顯示文字,不過在Console使用printf()仍為最常用的debug方式,所以建議還是加上JTAG UART。

在左側SOPC Builder->Interface Protocols->Serial下找到JTAG UART,滑鼠點兩下加入,接受預設值即可,按Finish。

de2_lcm_ccd_18

Fig.17 加入JTAG UART

de2_lcm_ccd_19

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。

de2_lcm_ccd_20

Fig.19 加入System ID Peripheral

de2_lcm_ccd_21

Fig.20 System ID Peripheral window

Step 5:
加入CCD_Controller
現在要加入剛剛自己寫好的CCD_Controller。

在左側Altera SOPC Builder->My Controller下找到CCD_Controller,滑鼠按兩下加入,接受預設值即可,按Finish。

de2_lcm_ccd_22

Fig.21 加入CCD_Controller

de2_lcm_ccd_23

Fig.22 CCD_Controller window

Step 6:
加入KEY PIO
由於我們要用軟體攔截KEY的輸入,所以要加上PIO。

在左側Altera SOPC Builder->Peripherals->Microcontroller Peripherals下找到PIO(Parallel I/O),滑鼠按兩下加入,接受預設值即可,按Finish。

de2_lcm_ccd_24

Fig.23 加入PIO

由於KEY[0]是reset,因此軟體不攔,只用軟體攔KEY[1]、KEY[2]與KEY[3]而已,所以Width填3 bit。因為只是讀取KEY的輸入值,所以選Input ports only。

de2_lcm_ccd_25

Fig.24 PIO window

更名為key_pio

de2_lcm_ccd_26

Fig.25 更名為key_pio

Step 7:
加入SW PIO
由於我們要用軟體攔截SW的輸入,所以要加上PIO。

在左側Altera SOPC Builder->Peripherals->Microcontroller Peripherals下找到PIO(Parallel I/O),滑鼠按兩下加入,接受預設值即可,按Finish。

de2_lcm_ccd_24

Fig.25 加入PIO

由於SW為16 bit,所以Width填3 bit。因為只是讀取SW的輸入值,所以選Input ports only。

de2_lcm_ccd_27

Fig.26 PIO window

更名為sw_pio

de2_lcm_ccd_28

Fig.27 更名為sw_pio

Step 8:
設定reset和exception vector

在右側CPU用滑鼠點兩下。

de2_lcm_ccd_29

Fig.28 設定reset與exception

將reset和exception vector設在onchip_mem,這也是本專案唯一的記憶體。

de2_lcm_ccd_30

Fig.29 將reset和exception設在onchip_mem

Step 9:
重新設定Base Address
由下方的錯誤訊息得知,有些元件所分配的base address衝突了,所以必須重新指定base address。

選擇System->Auto-Assign Base Address

de2_lcm_ccd_31

Fig.30 Auto-Assign Base Address

Step 10:
產生Nios II System

截至目前為止,整個Nios II System已經設定完成,按Generate產生nios_ii_system.ptf,這需要一點時間,非常依賴CPU運算速度。

de2_lcm_ccd_32

Fig.31 Generate System

按Save對Nios II System存檔。

 de2_lcm_ccd_33

Fig.32 Save system

經過一段時間後,值到右下方出現Generate,表是建立完成,按Exit回到Quartus II。

de2_lcm_ccd_34

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

  1 module DE2_LCM_CCD (
  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行

nios_ii_system nios_ii (
  .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行

// add by oomusou
wire [2:0]  CCD_KEY;
wire [
15:0] CCD_SW;


宣告了新產生的wire

358行

assign LEDR        = CCD_SW;


由於LEDR會根據SW的on或off改變,原本接的是硬體SW,現在改接我們輸出的CCD_SW。

402行

CCD_Capture u3 (
  .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行

I2C_CCD_Config u7 (
 
// 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秒。

de2_lcm_ccd_35

Fig.34 編譯Verilog

使用Programmer將DE2_LCM_CCD.sof燒進FPGA
編譯完產生DE2_LCM_CCD.sof,使用Programmer燒進F PGA後,完成硬體佈署。

 de2_lcm_ccd_36

Fig.35 啟動Programmer

按Start將DE2_LCM_CCD.sof燒進FPGA。

de2_lcm_ccd_37

Fig.36 按Start開始燒錄

開發Nios II軟體
硬體部分完成了,現在我們要開發Nios II軟體。

Step 1:
啟動Nios II EDS

de2_lcm_ccd_38

Fig.37 Nios II EDS

Step 2:
建立Nios II C/C++ Application

按滑鼠右鍵,New->Nios II C/C++ Application

de2_lcm_ccd_39

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。

de2_lcm_ccd_40

Fig. 40 New Project

Step 3:
修改hello_world.c

hello_world.c

1#include "system.h"
2#include <io.h>
3
4int 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 char key = IORD(KEY_PIO_BASE, 0);
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, 1, sw);
IOWR(CCD_CONTROLLER_INST_BASE,
0, key);


將在軟體讀到的KEY和SW送進自己寫的CCD_Controller,CCD_CONTROLLER_INST_BASE定義在system.h中。為什麼傳sw時,第二個參數是1呢?而key是0呢?在CCD_Controller.v中,我們曾經這樣定義:

if (avs_s1_address == 1'b0 && avs_s1_chipselect && avs_s1_write)
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

Feedback

#1楼   回复  引用    

2008-01-31 00:16 by adamyjj[未注册用户]
博主你好 ...看到這篇文章受益良多

不知有方法可以透過avalon bus的方式,將CCD擷取的影像資料寫入到SDRAM,在從SDRAM讀取影像資料。





#2楼[楼主]   回复  引用  查看    

2008-01-31 00:36 by 真 OO无双      
--引用--------------------------------------------------
adamyjj: 博主你好 ...看到這篇文章受益良多

不知有方法可以透過avalon bus的方式,將CCD擷取的影像資料寫入到SDRAM,在從SDRAM讀取影像資料。
--------------------------------------------------------

我正在研究這個
我也想從SDRAM抓到資料後,然後在軟體動演算法

不過還沒成功,若我成功我會寫出來

若你成功了,別忘了也告訴我一聲,我論文要用到!!

#3楼   回复  引用    

2008-01-31 11:22 by adamyjj[未注册用户]
博主你好
我是有一個想法,將原程式DE2_LCM_CCD分解成兩部分,一部分為Avalon_CCD,另一部分Avalon_LCD,而原程式用的SDRAM改用SOPC Buildeer內元件取代,分別掛在Avalon_Bus上面,讀取的方式有兩種,一種為用NIOS II CPU讀寫影像資料而另一種用DMA的方式讀寫影像資料。這些是我大概初步構想......................^^

#4楼[楼主]   回复  引用  查看    

2008-01-31 12:12 by 真 OO无双      
--引用--------------------------------------------------
adamyjj: 博主你好
我是有一個想法,將原程式DE2_LCM_CCD分解成兩部分,一部分為Avalon_CCD,另一部分Avalon_LCD,而原程式用的SDRAM改用SOPC Buildeer內元件取代,分別掛在Avalon_Bus上面,讀取的方式有兩種,一種為用NIOS II CPU讀寫影像資料而另一種用DMA的方式讀寫影像資料。這些是我大概初步構想......................^^

--------------------------------------------------------

聽起來不錯
若你成功別忘了分享一下

#5楼   回复  引用    

2008-02-05 15:10 by qinguodong[未注册用户]
很好,很有启发,我是初学者,看完你这几篇关于 niosII得文章受益匪浅。

#6楼[楼主]   回复  引用  查看    

2008-02-06 15:35 by 真 OO无双      
@qinguodong
--引用--------------------------------------------------
qinguodong: 很好,很有启发,我是初学者,看完你这几篇关于 niosII得文章受益匪浅。
--------------------------------------------------------

希望對你有幫助。

#7楼   回复  引用    

2008-02-08 03:27 by huanf[未注册用户]
请问为何设定35KB的onchip mem,够用吗。博主有一篇文章说压榨出49K的onchip mem是什么意思?

#8楼[楼主]   回复  引用  查看    

2008-02-08 11:30 by 真 OO无双      
--引用--------------------------------------------------
huanf: 请问为何设定35KB的onchip mem,够用吗。博主有一篇文章说压榨出49K的onchip mem是什么意思?
--------------------------------------------------------
以本例來說,35K on-chip mem就夠用了,極限可以設到36K,選擇35K只是剛好整數,你可以下載完整的程式碼看看,的確可以正常執行,為什麼這麼小還夠用?因為目前還沒有上OS,也還沒用到什麼library,所以夠用

所謂的壓榨出49K,是DE2的極限,這是實際測試出來的結果
但必須在幾個前提下
1.使用Nios II/e
2.只使用on-chip mem, JTAG-UART, sysid,剩下其他的controller都不用
3.不再寫其他額外的Verilog code

#9楼   回复  引用    

2008-04-18 17:52 by 张成[未注册用户]
我是个初学者,看了你写的文章之后,深受启发,
我在想可不可以将LCM_Controler也写成component呢?
怎么写呢?请指教,谢谢

#10楼[楼主]   回复  引用  查看    

2008-04-18 18:27 by 真 OO无双      
@张成
可以
其實原理方法都一樣
我寫看看
若成功再分享給大家

#11楼   回复  引用    

2008-04-21 09:55 by 哈比兔[未注册用户]
不知道可不可以問一下!
我自己新增一個COMPONENT 可是用完以後,我不知道要去哪邊查NISO那邊要如何知道BASE多少是哪個位置,我是用ADD SINGALS 作法,不是先寫個.V,因為寫.V我寫失敗,不知輸出輸入要怎麼同時寫。
目前是在寫LCM控制的東西,因為專題要用到LCM。

#12楼[楼主]   回复  引用  查看    

2008-04-21 16:15 by 真 OO无双      
@哈比兔
在\[project name]\software\hello_world_0_syslib\Debug\system_description\system.h可以找到BASE的位址

你可以將專案寄給我看看。

#13楼   回复  引用    

2008-04-25 13:27 by ttse7[未注册用户]
you are great!I learn a lot from you!

#14楼   回复  引用    

2008-04-27 10:56 by 小祁[未注册用户]
我使用的是quartus 4.2破解版,kde是1.1,使用您提供的CCD_Controller.v作为用户单元,在新建立用户单元的时候,提示是 Slave must have a read or write interface, or support interrupts,请问您是什么原因

#15楼[楼主]   回复  引用  查看    

2008-04-27 11:11 by 真 OO无双      
@小祁
請用Quartus II 7.2以上的版本
Quartus II 7.1以後經過一次大改,尤其是SOPC的部分,格式完全不相容

#16楼   回复  引用    

2008-05-07 15:31 by ltl[未注册用户]
博主你好,请问你在使用de2系统盘提供的isp1362这个自定器件的时候,在Q7.2版本上是要进行升级的,升级以后有一个引脚的信号类型的中断一直提示“Error: avalon_slave_1_irq: Parameter associatedAddressablePoint out of range”,请问你是如何解决的呢?
谢谢?

#17楼   回复  引用    

2008-05-15 20:36 by 小张张[未注册用户]
请问您使用过nios ide中spi的函数吗,请问您如何对spi进行操作在nios ide中呢,谢谢您了

#18楼[楼主]   回复  引用  查看    

2008-05-16 09:02 by 真 OO无双      
@小张张
不好意思
我癌沒用過spi

#19楼[楼主]   回复  引用  查看    

2008-05-16 09:06 by 真 OO无双      
@ltl
DE2所提供的範例程式有兩個版本
一個是Quartus II 6.0
另一個是Quartus II 7.1
由於7.1之後在SOPC部分大改,所以如果你要用在7.2,請使用7.1的範例。

#20楼   回复  引用    

2008-07-16 21:23 by zzx[未注册用户]
@adamyjj
那你觉得nios II在这里有什么作用呢?

#21楼[楼主]   回复  引用  查看    

2008-07-16 21:42 by 真 OO无双      
@zzx

這只是軟硬體設計的初步

是我當初練習用Nios II透過Avalon與PIO與custom slave component做夠通


比如說在key和sw輸入後,須透過一些算法的轉換再交給CMOS,當然直接寫Verilog亦可,但可能因為時間與成本的關係,用Verilog實踐較麻煩,可以先用Nios II + C語言去實踐,產品先上市減少time to market,再慢慢的改成純硬體的Verilog。

#22楼   回复  引用    

2008-07-17 11:45 by zzx[未注册用户]
@真 OO无双
nios +c语言去实践?
有什么方法呢?能否讲讲流程啊?
另外,您说的改成rtl,是怎么改的呢?

#23楼[楼主]   回复  引用  查看    

2008-07-17 12:10 by 真 OO无双      
@zzx
你可以參考這一篇,不過我還沒寫完,因為篇幅較長,我就一天寫一點....
http://www.cnblogs.com/oomusou/archive/2008/07/08/checksum_master_explained.html" target="_new">http://www.cnblogs.com/oomusou/archive/2008/07/08/checksum_master_explained.html

這是Nios II軟硬體設計一個很重要的範例,非常經典

#24楼   回复  引用    

2008-08-05 20:29 by 阿酷[未注册用户]
版主大大:
你在文中提到的這句話:
2.
使用on-chip memory並不實際,實務上幾乎不會用on-chip memory,會用SRAM或SDRAM。

我想問一下就是~在範例中~CCD純硬體的程式部分都有使用到SDRAM,
那我在SOPC設定時~可以使用SDRAM嗎???
兩個之間的關係我搞的有些模糊!!!
謝謝版主

#25楼[楼主]   回复  引用  查看    

2008-08-05 20:54 by 真 OO无双      
--引用--------------------------------------------------
阿酷: 版主大大:
你在文中提到的這句話:
2.
使用on-chip memory並不實際,實務上幾乎不會用on-chip memory,會用SRAM或SDRAM。
--------------------------------------------------------
因為在DE2,onchip memory很小,只能設40K左右,隨便一個hello world就爆了,所以真的像樣的程式,on-chip memory一定不夠用,當然像DE2-70與DE3的onchip memory大很多就另當別論。

--引用--------------------------------------------------
我想問一下就是~在範例中~CCD純硬體的程式部分都有使用到SDRAM,
那我在SOPC設定時~可以使用SDRAM嗎???
兩個之間的關係我搞的有些模糊!!!
謝謝版主
--------------------------------------------------------
不行,因為SDRAM已經被VGA拿去當frame buffer了,所以SOPC就不能用了

你可以想看看,當你SOPC又加入SDRAM controller時,你的top module要怎麼連?要連到SOPC的SDRAM controller呢?還是連給sdram_control_4port?
所以你只能選其一

像DE2_CCD這種,由於SDRAM已經被硬體占走了,SOPC就只剩下SRAM/flash與onchip memory可以用了。

不過也該知足啦,很多開發版,只有onchip memory, SDRAM, flash可用,根本沒有SRAM可用,在DE2下,我們還有SRAM可以放OS。

#26楼   回复  引用    

2008-08-06 10:23 by 点[未注册用户]
不知道能不能将SDRAM分成两部分用呢?DE2的SDRAM有8M,

sdram_control_4port给VGA用,再写一个sdram_control_2port给数据用,

最后在总的来个仲裁,决定SDRAM接哪个sdram_control。

#27楼[楼主]   回复  引用  查看    

2008-08-06 10:36 by 真 OO无双      
@点
--引用--------------------------------------------------
点: 不知道能不能将SDRAM分成两部分用呢?DE2的SDRAM有8M,

sdram_control_4port给VGA用,再写一个sdram_control_2port给数据用,

最后在总的来个仲裁,决定SDRAM接哪个sdram_control。
--------------------------------------------------------

不太懂你的意思
什麼是給VGA用與數據用分開

#28楼   回复  引用    

2008-08-06 12:21 by 点[未注册用户]
@真 OO无双
--引用-------------------------------------------------
不太懂你的意思
什麼是給VGA用與數據用分開
-------------------------------------------------------
前辈,你好!
如果只在系统中加SDRAM(我们的代码量挺大,担心sram不够用)。
有sdram_control_4port和sdram_control_2port两个sdram_controler:
前者负责传送数据给VGA显示,后者负责系统中其他数据的传送。这样,就应该有个仲裁来裁决吧?

还是可以写一个既有Avalon Master又有Avalon Slaver的custom components就可以完成以上所有的功能呢?

这两天一直在看checksum范例,终于有一点入门的感觉了!!虽然还是不知道这个components怎么开始写,还请您多多指教啊!!

#29楼[楼主]   回复  引用  查看    

2008-08-06 16:46 by 真 OO无双      
--引用--------------------------------------------------
前辈,你好!
如果只在系统中加SDRAM(我们的代码量挺大,担心sram不够用)。
有sdram_control_4port和sdram_control_2port两个sdram_controler:
前者负责传送数据给VGA显示,后者负责系统中其他数据的传送。这样,就应该有个仲裁来裁决吧?

还是可以写一个既有Avalon Master又有Avalon Slaver的custom components就可以完成以上所有的功能呢?

这两天一直在看checksum范例,终于有一点入门的感觉了!!虽然还是不知道这个components怎么开始写,还请您多多指教啊!!
--------------------------------------------------------

這我就不清楚了
期待其他高手解決

不過是我的話,我就去買DE2-70了
有2MB SRAM

#30楼   回复  引用    

2008-08-07 15:44 by 点[未注册用户]
@真 OO无双
前辈:
在DE2_CCD.v中:
Sdram_Control_4Port u6 (

……
//FIFO Write Side 1
.WR1_ADDR(0),
.WR1_MAX_ADDR(640*512),
.WR1_LENGTH(9'h100),
……
// FIFO Read Side 1
.RD1_ADDR(640*16),
.RD1_MAX_ADDR(640*496),
.RD1_LENGTH(9'h100),
………);
WR1和RD1操作的应该是同一块存储空间吧,
可是为什么RD1_ADDR比WR1_ADDR大了640*16,
而RD1_MAX_ADDR比WR1_MAX_ADDR小了640*16?
我发现在DE2_LCM_CCD中,这个地方也有一个offset,
不过是360*8。这是怎么回事啊?

#31楼[楼主]   回复  引用  查看    

2008-08-07 18:01 by 真 OO无双      
--引用--------------------------------------------------
点: @真 OO无双
前辈:
在DE2_CCD.v中:
Sdram_Control_4Port u6 (
……
//FIFO Write Side 1
.WR1_ADDR(0),
.WR1_MAX_ADDR(640*512),
.WR1_LENGTH(9'h100),
……
// FIFO Read Side 1
.RD1_ADDR(640*16),
.RD1_MAX_ADDR(640*496),
.RD1_LENGTH(9'h100),
………);
WR1和RD1操作的应该是同一块存储空间吧,
可是为什么RD1_ADDR比WR1_ADDR大了640*16,
而RD1_MAX_ADDR比WR1_MAX_ADDR小了640*16?
我发现在DE2_LCM_CCD中,这个地方也有一个offset,
不过是360*8。这是怎么回事啊?


--------------------------------------------------------

好問題,我星期天上課幫你問問,已經加上你的問題了
我猜可能是timing的問題

#32楼   回复  引用    

2008-08-07 18:31 by 阿酷[未注册用户]
版主大哥:
我在DE2_LCM_CCD.V檔中有看到flash和sram的腳位:例如
169 inout [7:0] FL_DQ; // FLASH Data bus 8 Bits
170 output [21:0] FL_ADDR; // FLASH Address bus 22 Bits
這些等等的...

那麼我將SOPC的部分使用SRAM/FLASH,會不會有有影響呢???
在RTL中,SRAM/FLASH的腳位似乎沒有用到耶!!!
希望版主大哥能解惑一下~~^^
謝謝

#33楼[楼主]   回复  引用  查看    

2008-08-07 18:57 by 真 OO无双      
--引用--------------------------------------------------
阿酷: 版主大哥:
我在DE2_LCM_CCD.V檔中有看到flash和sram的腳位:例如
169 inout [7:0] FL_DQ; // FLASH Data bus 8 Bits
170 output [21:0] FL_ADDR; // FLASH Address bus 22 Bits
這些等等的...

那麼我將SOPC的部分使用SRAM/FLASH,會不會有有影響呢???
在RTL中,SRAM/FLASH的腳位似乎沒有用到耶!!!
希望版主大哥能解惑一下~~^^
謝謝
--------------------------------------------------------

不會有影響
在DE2_LCM_CCD的硬體並沒有用到SRAM與flash
所以這兩個你可以拿來在SOPC Builder配置,然後給Nios II用
當然別忘了在top module,你要將flash跟SRAM接到你的Nios II module

#34楼   回复  引用    

2008-08-07 20:22 by 点[未注册用户]
@真 OO无双

--引用--------------------------------------------------
真 OO无双: 好問題,我星期天上課幫你問問,已經加上你的問題了
我猜可能是timing的問題

--------------------------------------------------------
好啊!!我期待您的回答,谢谢!

#35楼   回复  引用    

2008-08-10 21:57 by 点[未注册用户]
前辈:
在DE2_CCD 的demo中,在数据从CMOS中传出来后,
经过处理后在存入SDRAM中,
但代码在什么地方有设置图像数据结束的标志呀?
我的意思是,再传数据的过程中,遇到什么判断条件,
就确定这一幅图像的数据已经全部存入SDRAM中了。

#36楼[楼主]   回复  引用  查看    

2008-08-10 23:22 by 真 OO无双      
--引用--------------------------------------------------
点: 前辈:
在DE2_CCD 的demo中,在数据从CMOS中传出来后,
经过处理后在存入SDRAM中,
但代码在什么地方有设置图像数据结束的标志呀?
我的意思是,再传数据的过程中,遇到什么判断条件,
就确定这一幅图像的数据已经全部存入SDRAM中了。
--------------------------------------------------------

SDRAM只是一個frame buffer,就cmos一直進,vga一直取
所以判斷frame結束是由vga_controller.v去判斷
至於怎麼判斷呢?真的沒有結束標誌
是vga_controller.v用 counter算出來的!!

這次上課後,對DE2_CCD的rtl又有更深的認識了
我打算開一個系列好好講DE2_CCD每個module
到時候再詳細解釋

#37楼   回复  引用    

2008-08-18 10:49 by 点[未注册用户]
前辈:
我在我的机器上编译我的工程的时候出现了一下信息:
Critical Warning: Timing requirements for slow timing model timing analysis were not met. See Report window for details.
这是哪方面的问题?应该影响整个系统的工作的。

#38楼   回复  引用    

2008-08-18 21:36 by 点[未注册用户]
前辈,我的project能跑“hello niosii!”了,
我把基本的API 也写好了!
不过还是麻烦您看看我发给你的project,
帮我检查一下有什么不合理的地方。
谢谢!!
挺高兴的!!

#39楼   回复  引用    

2008-08-19 20:18 by 点[未注册用户]
前辈,
DE2_CCD.V里的Mirror_Col.v有什么作用呀?
我看了好长时间,好像里边就是缓冲,
它实现的是什么功能?

#40楼[楼主]   回复  引用  查看    

2008-08-19 20:36 by 真 OO无双      
--引用--------------------------------------------------
点: 前辈,
DE2_CCD.V里的Mirror_Col.v有什么作用呀?
我看了好长时间,好像里边就是缓冲,
它实现的是什么功能?
--------------------------------------------------------

功能就是為了Mirror Column
因為CMOS最先進來的pixel到時會在右下方
所以影像會上下顛倒,左右相反

不使用Mirror Column也行,直接設定I2C_CCD_Config.v也可以
CMOS的register已經內建這個功能,只要設定register就可以。

#41楼   回复  引用    

2008-08-28 07:55 by 点[未注册用户]
在我的project里有没有用到
I2C_SDAT;oI2C_SCLK;这两个引脚?
以前没注意这个问题,
我刚发现好像没用到,是吗?

#42楼   回复  引用    

2008-08-28 08:03 by 点[未注册用户]
不对,应该使用到的!
我可能把端口和信号的关系弄混了!
还麻烦您给说一下吧!
谢谢!

#43楼   回复  引用    

2008-09-02 11:24 by gunking[未注册用户]
博主您好,這幾天看了您這篇範例以後回去試著操作一遍,可是在NIOS IDE裡面要編譯程式的時候一直出現這個訊息:
Creating generated_app.mk...
Compiling crt0.S...
/bin/sh: -c: line 0: unexpected EOF while looking for matching `''
/bin/sh: -c: line 1: syntax error: unexpected end of file
make[1]: *** [crt0.o] Error 2
make: *** [system_project] Error 2
Build completed in 4.266 seconds
我本來以為是我變更到什麼設定了,可是當我重慣以後再編譯一樣會出現這樣的問題,用您的範例出來的程式卻沒有這個問題,請問一下大概是什麼原因呢?非常感謝~

#44楼   回复  引用    

2008-09-02 13:09 by gunking[未注册用户]
博主不好意思再請教一下,我目前qurtus的版本是7.2,有更新到SP3了,出現上面問題的編譯錯誤以後我又嘗試了其他可能出錯的部分,後來發現當我在SOPC的部分不要加入CCD_Controller以後,之後就不會出現上面那個編譯的錯誤了,請問一下這是因為CCD_Controller的問題嗎?非常感謝~

#45楼[楼主]   回复  引用  查看    

2008-09-02 13:14 by 真 OO无双      
--引用--------------------------------------------------
gunking: 博主不好意思再請教一下,我目前qurtus的版本是7.2,有更新到SP3了,出現上面問題的編譯錯誤以後我又嘗試了其他可能出錯的部分,後來發現當我在SOPC的部分不要加入CCD_Controller以後,之後就不會出現上面那個編譯的錯誤了,請問一下這是因為CCD_Controller的問題嗎?非常感謝~
--------------------------------------------------------
你將有問題的project壓縮給我,我來看看

#46楼   回复  引用    

2008-09-02 14:47 by 哈比兔[未注册用户]
--引用--------------------------------------------------
真 OO无双: --引用--------------------------------------------------
<br>点: @真 OO无双
<br>前辈:
<br>在DE2_CCD.v中:
<br>Sdram_Control_4Port u6 (
<br> ……
<br> //FIFO Write Side 1
<br> .WR1_ADDR(0),
<br> .WR1_MAX_ADDR(640*512),
<br> .WR1_LENGTH(9'h100),
<br> ……
<br> // FIFO Read Side 1
<br> .RD1_ADDR(640*16),
<br> .RD1_MAX_ADDR(640*496),
<br> .RD1_LENGTH(9'h100),
<br> ………);
<br>WR1和RD1操作的应该是同一块存储空间吧,
<br>可是为什么RD1_ADDR比WR1_ADDR大了640*16,
<br>而RD1_MAX_ADDR比WR1_MAX_ADDR小了640*16?
<br>我发现在DE2_LCM_CCD中,这个地方也有一个offset,
<br>不过是360*8。这是怎么回事啊?
<br>
<br>
<br>--------------------------------------------------------
<br>
<br>好問題,我星期天上課幫你問問,已經加上你的問題了
<br>我猜可能是timing的問題
<br>
--------------------------------------------------------
我想
VGA顯示範圍是640*480
然後他有個RAW2RGB模組,將CMOS畫面1280*1024縮小2倍
然後因為不符合VGA大小
因此要犧牲上下邊界 640*0 ~ 640*16 跟 640*496 ~ 640*512
只抓取中間的畫面給VGA

LCM同此320*0 ~ 640*8 跟 320*248 ~ 320*256

------------
不知這想法對不對QQ

#47楼[楼主]   回复  引用  查看    

2008-09-02 15:12 by 真 OO无双      
@哈比兔
--引用--------------------------------------------------
我想
VGA顯示範圍是640*480
然後他有個RAW2RGB模組,將CMOS畫面1280*1024縮小2倍
然後因為不符合VGA大小
因此要犧牲上下邊界 640*0 ~ 640*16 跟 640*496 ~ 640*512
只抓取中間的畫面給VGA

LCM同此320*0 ~ 640*8 跟 320*248 ~ 320*256

------------
不知這想法對不對QQ
--------------------------------------------------------

對 就是這樣子

#48楼   回复  引用    

2008-09-02 16:16 by gunking[未注册用户]
@真 OO无双
博主您好,我已經寄到您gmail的信箱了,麻煩您了~謝謝

#49楼   回复  引用    

2008-09-03 19:49 by 沙漠洲[未注册用户]
在Sdram_Control_4Port里面的command.v中,模式寄存器的设置决定着它的操作模式,如突发长度,突发类型等等。但是找不到对模式寄存器设置的语句。
1:if(do_load_mode==1)

SA <= {2'b00,SDR_CL,SDR_BT,SDR_BL};
这个是不是对它的设置呢?
2:如果是的话,SDR_CL,SDR_BT,SDR_BL它们的取值是不是在头文件中定义的值啊?
3:如果2也成立的话,为什么在头文件中同时定义
parameter SC_PM = 1;
parameter SC_BL = 1; 呢?我感觉它们是冲突的啊?因为在页模式情况下突发长度是256啊?
谢谢!

#50楼   回复  引用    

2008-09-03 20:08 by 沙漠洲[未注册用户]
在Sdram_Control_4Port里,
1:ST==SC_CL+mLENGTH
2:ST==SC_CL+SC_RCD+mLENGTH+2,这两个条件是什么意思啊?
而且mLENGTH只是定义的一个[8..0]的reg型变量,它的值是多大啊?
3:DQM <= ( active && (ST>=SC_CL) )?(((ST==SC_CL+mLENGTH) && Write)?2'b11 :2'b00) :2'b11;这个长语句理解不了?
我问的问题太细了,真的是麻烦大家了

#51楼   回复  引用    

2008-09-03 20:46 by 沙漠洲[未注册用户]
在Sdram_Control_4Port里,
4个fifo的load信号都是和!DLY_RST_0相连的,这里的意思是不是说系统复位时,4个fifo都获得初始地址啊?
另外这段程序中的2条语句不大明白:

if(WR1_LOAD)
begin
rWR1_ADDR <= WR1_ADDR;
rWR1_LENGTH <= WR1_LENGTH;
end
else if(mWR_DONE&WR_MASK[0]) 这个应该是写操作完成
begin
if(rWR1_ADDR<rWR1_MAX_ADDR-rWR1_LENGTH) 这个if,else 语 句不理解了?
rWR1_ADDR<=rWR1_ADDR+rWR1_LENGTH;
else
rWR1_ADDR<=WR1_ADDR;

#52楼   回复  引用    

2008-09-03 21:07 by 沙漠洲[未注册用户]
@沙漠洲
--引用--------------------------------------------------
沙漠洲: 在Sdram_Control_4Port里,
1:ST==SC_CL+mLENGTH
2:ST==SC_CL+SC_RCD+mLENGTH+2,这两个条件是什么意思啊?
而且mLENGTH只是定义的一个[8..0]的reg型变量,它的值是多大啊?
3:DQM &lt;= ( active &amp;&amp; (ST&gt;=SC_CL) )?(((ST==SC_CL+mLENGTH) &amp;&amp; Write)?2'b11 :2'b00) :2'b11;这个长语句理解不了?
我问的问题太细了,真的是麻烦大家了
--------------------------------------------------------
--引用--------------------------------------------------
沙漠洲: 在Sdram_Control_4Port里,
1:ST==SC_CL+mLENGTH
2:ST==SC_CL+SC_RCD+mLENGTH+2,这两个条件是什么意思啊?
而且mLENGTH只是定义的一个[8..0]的reg型变量,它的值是多大啊?
3:DQM &lt;= ( active &amp;&amp; (ST&gt;=SC_CL) )?(((ST==SC_CL+mLENGTH) &amp;&amp; Write)?2'b11 :2'b00) :2'b11;这个长语句理解不了?
我问的问题太细了,真的是麻烦大家了
--------------------------------------------------------
mLENGTH的大小我已经知道了,是在后面的fifo读写中又定义了,是256

#53楼[楼主]   回复  引用  查看    

2008-09-03 21:36 by 真 OO无双      
--引用--------------------------------------------------
我问的问题太细了,真的是麻烦大家了
--------------------------------------------------------
不好意思,不是我不回答
Sdram_Control_4Port的code我不會,已經超出我的能力範圍了

#54楼   回复  引用    

2008-09-06 21:30 by 祥祥[未注册用户]
版主您好
我有個疑問,
在硬體部分做完影像處理,將需要的結果傳入cpu內去做運算的話!!!!
那 硬體跟的上軟體的速度嗎??
clock上需要做什麼考量嗎???

#55楼[楼主]   回复  引用  查看    

2008-09-07 09:11 by 真 OO无双      
--引用--------------------------------------------------
祥祥: 版主您好
我有個疑問,
在硬體部分做完影像處理,將需要的結果傳入cpu內去做運算的話!!!!
那 硬體跟的上軟體的速度嗎??
clock上需要做什麼考量嗎???
--------------------------------------------------------

軟硬體合作的部分,我也還沒真的做出來,所以目前還無法跟您做建議

#56楼   回复  引用    

2008-09-10 15:10 by gunking[未注册用户]
博主不好意思,請問一下我之前寄給您的project有幫我看嗎?非常感謝~

#57楼[楼主]   回复  引用  查看    

2008-09-10 21:07 by 真 OO无双      
--引用--------------------------------------------------
gunking: 博主不好意思,請問一下我之前寄給您的project有幫我看嗎?非常感謝~
--------------------------------------------------------

不好意思,拖這麼久才看你寄來的project
我已經將你的project改好寄給你了

你主要的問題在於
你沒有ip的目錄放置CCD Controler,但你的ptf又記載的這個CCD controler,導致Nios II EDS在建立system.h時,因為找不到這個ip而出錯

Nios II EDS會出現以下這個錯誤

> Creating generated_app.mk...
> Compiling crt0.S...
> /bin/sh: -c: line 0: unexpected EOF while looking for matching `''
> /bin/sh: -c: line 1: syntax error: unexpected end of file
> make[1]: *** [crt0.o] Error 2
> make: *** [system_project] Error 2
> Build completed in 4.281 seconds

一定都是需要某個ip,但在ptf就找不到,導致產生system.h時異常

#58楼   回复  引用    

2008-11-13 16:15 by qwertyuio[未注册用户]
我在实际操作的时候(V7.2 SP3),还需要把ip文件夹中的CCD_Controller.v复制一份到最外层文件夹才能通过编译,原因是系统生成的一个文件CCD_Controller_inst.v调用了此模块。
不知博主大哥是否也遇到了这样的情况呢?

#59楼   回复  引用    

2008-11-29 00:52 by DAVID999[未注册用户]
樓主您好:
請問我執行出現
Error: Node instance "the_CCD_Controller_inst" instantiates undefined entity "CCD_Controller_inst"
Error: Quartus II Analysis & Synthesis was unsuccessful. 1 error, 170 warnings
Info: Allocated 156 megabytes of memory during processing
Error: Processing ended: Sat Nov 29 00:13:56 2008
Error: Elapsed time: 00:00:08
Error: Quartus II Full Compilation was unsuccessful. 1 error, 170 warnings
這些錯誤不知道為什麼?該如何解決呢~?
謝謝

#60楼[楼主]   回复  引用  查看    

2008-11-29 00:59 by 真 OO无双      
--引用--------------------------------------------------
DAVID999: 樓主您好:
請問我執行出現
Error: Node instance &quot;the_CCD_Controller_inst&quot; instantiates undefined entity &quot;CCD_Controller_inst&quot;
Error: Quartus II Analysis &amp; Synthesis was unsuccessful. 1 error, 170 warnings
Info: Allocated 156 megabytes of memory during processing
Error: Processing ended: Sat Nov 29 00:13:56 2008
Error: Elapsed time: 00:00:08
Error: Quartus II Full Compilation was unsuccessful. 1 error, 170 warnings
這些錯誤不知道為什麼?該如何解決呢~?
謝謝
--------------------------------------------------------

這主要的原因是Quartus II版本的問題
因為我是用Quartus II 7.2 sp1寫的
所以*.tcl也是Quartus II 7.2 sp1的格式
若你是用其他Quartus II版本,會導致無法讀取*.tcl
而導致他不會自動將CCD_Controller.v 複製到project的根目錄

有3種解決方法
1.一樣跟我使用Quartus II 7.2 SP1

2.將*.tcl砍掉重建ip,這樣就能建出你Quartus II版本的*.tcl

3.將CCD_Controller.v加入到project manager當中,讓Quartus II找的到

#61楼   回复  引用    

2008-11-29 02:31 by DAVID999[未注册用户]
我重建新的ip也是一樣的問題耶~~我也是用Quartus II 7.2的版本~~
真不知道問題出在哪~~苦惱中~!

#62楼[楼主]   回复  引用  查看    

2008-11-29 09:42 by 真 OO无双      
--引用--------------------------------------------------
DAVID999: 我重建新的ip也是一樣的問題耶~~我也是用Quartus II 7.2的版本~~
真不知道問題出在哪~~苦惱中~!
--------------------------------------------------------

Quartus II 7.2有三個版本,SP1 ~ SP3,你也是用SP1?
那你試試第3個方法吧

#63楼   回复  引用    

2009-03-12 20:16 by super[未注册用户]

楼主你好:我想问一下Sdram_Control_4Port中的这几项分别代表什么意思,尤其是WR1(WR_STAR)和WR1_LENGTH(9'h100)。

.WR1_DATA({WR_DATA_G[9:5],WR_DATA_B[9:0]}),
.WR1(WR_STAR),
.WR1_ADDR(0),
.WR1_MAX_ADDR(320*240),//320*240
.WR1_LENGTH(9'h100),
.WR1_LOAD(!DLY_RST_0),
.WR1_CLK(WR_CLK),
最后还有一个问题:CCD的输出和LCM的输入是怎样保持一至的。

#64楼   回复  引用    

2009-04-10 14:08 by moxu[未注册用户]
問個比較低級的問題。我看用純硬體做那篇并沒有CCD_Controller.v,這樣的話在這篇用nios做的專案中,不要這個模塊行嗎?在修改的DE2_LCM_CCD中已經把nios模塊加進去了,而且相關端口也做了修改,不就可以了嗎?

#65楼   回复  引用    

2009-04-16 19:38 by zhangjie
楼主大哥:我在照着你的东西坐的时候,在nois里编译工程时出现以下错误:
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: region onchip_mem is full (hello_world_0.elf section .text). Region needs to be 10484 bytes larger.
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .rodata [00010020 -> 000104ff] overlaps section .exceptions [00010020 -> 000101c7]
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .rwdata [00010500 -> 00011f2b] overlaps section .text [000101c8 -> 0001b4f3]
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .bss [00011f2c -> 0001213f] overlaps section .text [000101c8 -> 0001b4f3]
困扰了很久,不知如何改正!!请楼主赐教,不胜感激

#66楼[楼主]   回复  引用  查看    

2009-04-16 19:49 by 真 OO无双      
--引用--------------------------------------------------
zhangjie: 楼主大哥:我在照着你的东西坐的时候,在nois里编译工程时出现以下错误:
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: region onchip_mem is full (hello_world_0.elf section .text). Region needs to be 10484 bytes larger.
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .rodata [00010020 -&gt; 000104ff] overlaps section .exceptions [00010020 -&gt; 000101c7]
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .rwdata [00010500 -&gt; 00011f2b] overlaps section .text [000101c8 -&gt; 0001b4f3]
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .bss [00011f2c -&gt; 0001213f] overlaps section .text [000101c8 -&gt; 0001b4f3]
困扰了很久,不知如何改正!!请楼主赐教,不胜感激
--------------------------------------------------------

你的onchip memory已經滿了
有3個方法
1.onchip memory再設大一點
2.改跑在sram或sdram
3.讓nios ii的執行檔小一點,請參考
http://www.cnblogs.com/oomusou/archive/2008/01/20/1046257.html" target="_new">http://www.cnblogs.com/oomusou/archive/2008/01/20/1046257.html

#67楼   回复  引用    

2009-04-17 13:17 by zhangjie
--引用--------------------------------------------------
真 OO无双: --引用--------------------------------------------------
zhangjie: 楼主大哥:我在照着你的东西坐的时候,在nois里编译工程时出现以下错误:
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: region onchip_mem is full (hello_world_0.elf section .text). Region needs to be 10484 bytes larger.
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .rodata [00010020 -&amp;gt; 000104ff] overlaps section .exceptions [00010020 -&amp;gt; 000101c7]
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .rwdata [00010500 -&amp;gt; 00011f2b] overlaps section .text [000101c8 -&amp;gt; 0001b4f3]
/cygdrive/f/Q7.2/nios2eds/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/../../../../nios2-elf/bin/ld: section .bss [00011f2c -&amp;gt; 0001213f] overlaps section .text [000101c8 -&amp;gt; 0001b4f3]
困扰了很久,不知如何改正!!请楼主赐教,不胜感激
--------------------------------------------------------

你的onchip memory已經滿了
有3個方法
1.onchip memory再設大一點
2.改跑在sram或sdram
3.讓nios ii的執行檔小一點,請參考
<a href="http://www.cnblogs.com/oomusou/archive/2008/01/20/1046257.html" target="_new">http://www.cnblogs.com/oomusou/archive/2008/01/20/1046257.html</a>
--------------------------------------------------------
恩,谢谢楼主大哥!问题解决了。



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1056870




相关文章:

相关链接: