(原創) 如何在DE2-70執行Count Binary project template? (SOC) (Nios II) (DE2-70)

Abstract
Nios II EDS提供了『Count Binary』這個project template,不過在DE2與DE2-70都無法執行,本文提出解決方法。

Introduction
使用環境:Quartus II 8.0 + Nios II EDS 8.0 + DE2-70 (Cyclone II EP2C70F896C6N)

回想在剛開始學習Nios II時,都會想將Nios II EDS所有的project template跑看看,不過很可惜,Count Binary就是無法在DE2與DE2-70跑,當初以為是DE2有問題,換過好幾個版子,也曾懷疑是否Nios II EDS有bug,換過好幾個Nios II版本。

count_binary00

因為最近在研究Using SignalTap II Embedded Logic Analyzers in SOPC Builder Systems這篇paper,指名要用Count Binary這個範例,我就順手改看看,看能不能一解之前無法順利執行的遺憾。

為什麼無法在DE2/DE2-70執行?
既然都是用Altera的FPGA,為什麼無法執行呢?假如DE2/DE2-70無法執行,那意味著其他廠商的Altera FPGA實驗版應該也無法執行,為什麼會這樣呢?

主要原因有2:
1.各ip在SOPC Builder內的命名與Count Binary不一樣,導致無法順利驅動。
2.DE2/DE2-70另外提供了七段顯示器的ip與HAL,也與Count Binary不一樣。

因為這兩個原因,導致Count Binary無法執行。

Count Binary簡介
這是一個很有趣的範例,同時用到了LEDG、七段顯示器、LCD、Console與KEY,當Nios II執行後,會從0x00一直數到0xff,之後會等待7秒鐘,繼續由0x00數到0xff,若中途按下KEY[0],會只用LCDG顯示,若中途按下KEY[1],會只用七段顯示顯示,若中途按下KEY[2],會只用LCD顯示,若按下KEY[3],會同時用LEDG、七段顯示器、LCD與Console一起顯示。

在這個範例中,可以學到
1.如何在Nios II控制LEDG、七段顯示器、LCD與console。
2.如何在Nios II使用interrupt方式控制KEY。
3.將exception stack放在on-chip memory提高整體效率。

系統架構圖

count_binary01

這個架構比較有疑問的應該是為什麼要使用on-chip Memory?在Using SignalTap II Embedded Logic Analyzers in SOPC Builder Systems的p.7有以下敘述:

You chage the location of the exception stack to on-chip memory so that it can be analyzed in the later sections. Placing the exception stack in a separate fast physical memory improves the performance of exception handling.


因為這篇paper本來就是要拿SignalTap II來觀察Nios II與SOPC系統,所以故意擺了on-chip來觀察,也因為用了interrupt方式,所以將exception stack放在最快的記憶體:on-chip memory將能提高整體效率。

SOPC Builder部分
(原創) 哪裡有DE2-70的Nios II reference design可以參考? (SOC) (DE2-70) (Nios II) (SOPC Builder)為範本,將不需要的ip剔除,這也是建議初學者學習SOPC的方式,不要一開始就想自己從頭到尾建立一個SOPC系統,這樣挫折感會非常的高,因為只要有一點點地方沒設定對,Nios II系統就無法執行,從前人已經穩定的SOPC系統去移除不需要的ip,是比較聰明的方式。

count_binary02

Top Module

DE2_70_NIOS.v / Verilog

  1  /*  
  2  (C) OOMusou 2008 http://oomusou.cnblogs.com
  3 
  4  Filename    : DE2_70_NIOS.v
  5  Compiler    : Quartus II 8.0
  6  Description : DE2_70_NIOS reference design
  7  Release     : 10/19/2008 1.0
  8  */
  9 
10  module DE2_70_NIOS (
11    input          iCLK_28,        // 28.63636 MHz
12    input          iCLK_50,        // 50 MHz
13    input          iCLK_50_2,      // 50 MHz
14    input          iCLK_50_3,      // 50 MHz
15    input          iCLK_50_4,      // 50 MHz
16    input          iEXT_CLOCK,     // External Clock
17    // Push Button
18    input   [ 3 : 0 ]  iKEY,           // Pushbutton[3:0]
19    // DPDT Switch
20    input   [ 17 : 0 ] iSW,            // Toggle Switch[17:0]
21    // 7-SEG Dispaly 
22    output [ 6 : 0 ]  oHEX0_D,        // Seven Segment Digit 0
23    output         oHEX0_DP,       // Seven Segment Digit 0 decimal point
24    output [ 6 : 0 ]  oHEX1_D,        // Seven Segment Digit 1
25    output         oHEX1_DP,       // Seven Segment Digit 1 decimal point
26    output [ 6 : 0 ]  oHEX2_D,        // Seven Segment Digit 2
27    output         oHEX2_DP,       // Seven Segment Digit 2 decimal point
28    output [ 6 : 0 ]  oHEX3_D,        // Seven Segment Digit 3
29    output         oHEX3_DP,       // Seven Segment Digit 3 decimal point
30    output [ 6 : 0 ]  oHEX4_D,        // Seven Segment Digit 4
31    output         oHEX4_DP,       // Seven Segment Digit 4 decimal point
32    output [ 6 : 0 ]  oHEX5_D,        // Seven Segment Digit 5
33    output         oHEX5_DP,       // Seven Segment Digit 5 decimal point
34    output [ 6 : 0 ]  oHEX6_D,        // Seven Segment Digit 6
35    output         oHEX6_DP,       // Seven Segment Digit 6 decimal point
36    output [ 6 : 0 ]  oHEX7_D,        // Seven Segment Digit 7
37    output         oHEX7_DP,       // Seven Segment Digit 7 decimal point
38    // // LED /// /
39    output [ 8 : 0 ]  oLEDG,          // LED Green[8:0]
40    output [ 17 : 0 ] oLEDR,          // LED Red[17:0]
41    // // UART /// /
42    output         oUART_TXD,      // UART Transmitter
43    input          iUART_RXD,      // UART Receiver
44    output         oUART_CTS,      // UART Clear To Send
45    input          iUART_RTS,      // UART Requst To Send
46    // // IRDA /// /
47    output         oIRDA_TXD,      // IRDA Transmitter
48    input          iIRDA_RXD,      // IRDA Receiver
49    // // SDRAM Interface
50    inout   [ 31 : 0 ] DRAM_DQ,        // SDRAM Data bus 32 Bits
51    output [ 12 : 0 ] oDRAM0_A,       // SDRAM0 Address bus 12 Bits
52    output [ 12 : 0 ] oDRAM1_A,       // SDRAM1 Address bus 12 Bits
53    output         oDRAM0_LDQM0,   // SDRAM0 Low-byte Data Mask
54    output         oDRAM1_LDQM0,   // SDRAM1 Low-byte Data Mask
55    output         oDRAM0_UDQM1,   // SDRAM0 High-byte Data Mask
56    output         oDRAM1_UDQM1,   // SDRAM1 High-byte Data Mask
57    output         oDRAM0_WE_N,    // SDRAM0 Write Enable
58    output         oDRAM1_WE_N,    // SDRAM1 Write Enable
59    output         oDRAM0_CAS_N,   // SDRAM0 Column Address Strobe
60    output         oDRAM1_CAS_N,   // SDRAM1 Column Address Strobe
61    output         oDRAM0_RAS_N,   // SDRAM0 Row Address Strobe
62    output         oDRAM1_RAS_N,   // SDRAM1 Row Address Strobe
63    output         oDRAM0_CS_N,    // SDRAM0 Chip Select
64    output         oDRAM1_CS_N,    // SDRAM1 Chip Select
65    output [ 1 : 0 ]  oDRAM0_BA,      // SDRAM0 Bank Address
66    output [ 1 : 0 ]  oDRAM1_BA,      // SDRAM1 Bank Address
67    output         oDRAM0_CLK,     // SDRAM0 Clock
68    output         oDRAM1_CLK,     // SDRAM0 Clock
69    output         oDRAM0_CKE,     // SDRAM0 Clock Enable
70    output         oDRAM1_CKE,     // SDRAM1 Clock Enable
71    // // Flash Interface
72    inout   [ 14 : 0 ] FLASH_DQ,       // FLASH Data bus 15 Bits (0 to 14)
73    inout          FLASH_DQ15_AM1, // FLASH Data bus Bit 15 or Address A-1
74    output [ 25 : 0 ] oFLASH_A,       // FLASH Address bus 26 Bits
75    output         oFLASH_WE_N,    // FLASH Write Enable
76    output         oFLASH_RST_N,   // FLASH Reset
77    output         oFLASH_WP_N,    // FLASH Write Protect /Programming Acceleration
78    input          iFLASH_RY_N,    // FLASH Ready/Busy output
79    output         oFLASH_BYTE_N,  // FLASH Byte/Word Mode Configuration
80    output         oFLASH_OE_N,    // FLASH Output Enable
81    output         oFLASH_CE_N,    // FLASH Chip Enable
82    // // SRAM Interface
83    inout   [ 31 : 0 ] SRAM_DQ,        // SRAM Data Bus 32 Bits
84    inout   [ 3 : 0 ]  SRAM_DPA,       // SRAM Parity Data Bus
85    output [ 20 : 0 ] oSRAM_A,        // SRAM Address bus 21 Bits
86    output         oSRAM_ADSC_N,   // RAM Controller Address Status    
87    output         oSRAM_ADSP_N,   // SRAM Processor Address Status
88    output         oSRAM_ADV_N,    // SRAM Burst Address Advance
89    output [ 3 : 0 ]  oSRAM_BE_N,     // SRAM Byte Write Enable
90    output         oSRAM_CE1_N,    // SRAM Chip Enable
91    output         oSRAM_CE2,      // SRAM Chip Enable
92    output         oSRAM_CE3_N,    // SRAM Chip Enable
93    output         oSRAM_CLK,      // SRAM Clock
94    output         oSRAM_GW_N,     // SRAM Global Write Enable
95    output         oSRAM_OE_N,     // SRAM Output Enable
96    output         oSRAM_WE_N,     // SRAM Write Enable
97    // // ISP1362 Interface
98    inout   [ 15 : 0 ] OTG_D,          // ISP1362 Data bus 16 Bits
99    output [ 1 : 0 ]  oOTG_A,         // ISP1362 Address 2 Bits
100    output         oOTG_CS_N,      // ISP1362 Chip Select
101    output         oOTG_OE_N,      // ISP1362 Read
102    output         oOTG_WE_N,      // ISP1362 Write
103    output         oOTG_RESET_N,   // ISP1362 Reset
104    inout          OTG_FSPEED,     // USB Full Speed, 0 = Enable, Z = Disable
105    inout          OTG_LSPEED,     // USB Low Speed,     0 = Enable, Z = Disable
106    input          iOTG_INT0,      // ISP1362 Interrupt 0
107    input          iOTG_INT1,      // ISP1362 Interrupt 1
108    input          iOTG_DREQ0,     // ISP1362 DMA Request 0
109    input          iOTG_DREQ1,     // ISP1362 DMA Request 1
110    output         oOTG_DACK0_N,   // ISP1362 DMA Acknowledge 0
111    output         oOTG_DACK1_N,   // ISP1362 DMA Acknowledge 1
112    // // LCD Module 16X2 /// /
113    inout   [ 7 : 0 ]  LCD_D,          // LCD Data bus 8 bits
114    output         oLCD_ON,        // LCD Power ON/OFF
115    output         oLCD_BLON,      // LCD Back Light ON/OFF
116    output         oLCD_RW,        // LCD Read/Write Select, 0 = Write, 1 = Read
117    output         oLCD_EN,        // LCD Enable
118    output         oLCD_RS,        // LCD Command/Data Select, 0 = Command, 1 = Data
119    // // SD Card Interface
120    inout          SD_DAT,         // SD Card Data
121    inout          SD_DAT3,        // SD Card Data 3
122    inout          SD_CMD,         // SD Card Command Signal
123    output         oSD_CLK,        // SD Card Clock
124    // // I2C // //
125    inout          I2C_SDAT,       // I2C Data
126    output         oI2C_SCLK,      // I2C Clock
127    // // PS2 /// /
128    inout          PS2_KBDAT,      // PS2 Keyboard Data
129    inout          PS2_KBCLK,      // PS2 Keyboard Clock
130    inout          PS2_MSDAT,      // PS2 Mouse Data
131    inout          PS2_MSCLK,      // PS2 Mouse Clock
132    // // VGA /// /
133    output         oVGA_CLOCK,     // VGA Clock
134    output         oVGA_HS,        // VGA H_SYNC
135    output         oVGA_VS,        // VGA V_SYNC
136    output         oVGA_BLANK_N,   // VGA BLANK
137    output         oVGA_SYNC_N,    // VGA SYNC
138    output [ 9 : 0 ]  oVGA_R,         // VGA Red[9:0]
139    output [ 9 : 0 ]  oVGA_G,         // VGA Green[9:0]
140    output [ 9 : 0 ]  oVGA_B,         // VGA Blue[9:0]
141    // // Ethernet Interface /// /
142    inout   [ 15 : 0 ] ENET_D,         // DM9000A DATA bus 16Bits
143    output         oENET_CMD,      // DM9000A Command/Data Select, 0 = Command, 1 = Data
144    output         oENET_CS_N,     // DM9000A Chip Select
145    output         oENET_IOW_N,    // DM9000A Write
146    output         oENET_IOR_N,    // DM9000A Read
147    output         oENET_RESET_N,  // DM9000A Reset
148    input          iENET_INT,      // DM9000A Interrupt
149    output         oENET_CLK,      // DM9000A Clock 25 MHz
150    // // Audio CODEC /// /
151    inout          AUD_ADCLRCK,    // Audio CODEC ADC LR Clock
152    input          iAUD_ADCDAT,    // Audio CODEC ADC Data
153    inout          AUD_DACLRCK,    // Audio CODEC DAC LR Clock
154    output         oAUD_DACDAT,    // Audio CODEC DAC Data
155    inout          AUD_BCLK,       // Audio CODEC Bit-Stream Clock
156    output         oAUD_XCK,       // Audio CODEC Chip Clock
157    // // TV Devoder /// /
158    input          iTD1_CLK27,     // TV Decoder1 Line_Lock Output Clock
159    input   [ 7 : 0 ]  iTD1_D,         // TV Decoder1 Data bus 8 bits
160    input          iTD1_HS,        // TV Decoder1 H_SYNC
161    input          iTD1_VS,        // TV Decoder1 V_SYNC
162    output         oTD1_RESET_N,   // TV Decoder1 Reset
163    input          iTD2_CLK27,     // TV Decoder2 Line_Lock Output Clock        
164    input   [ 7 : 0 ]  iTD2_D,         // TV Decoder2 Data bus 8 bits
165    input          iTD2_HS,        // TV Decoder2 H_SYNC
166    input          iTD2_VS,        // TV Decoder2 V_SYNC
167    output         oTD2_RESET_N,   // TV Decoder2 Reset
168    // // GPIO // //
169    inout   [ 31 : 0 ] GPIO_0,         // GPIO Connection 0 I/O
170    input          GPIO_CLKIN_N0,  // GPIO Connection 0 Clock Input 0
171    input          GPIO_CLKIN_P0,  // GPIO Connection 0 Clock Input 1
172    output         GPIO_CLKOUT_N0, // GPIO Connection 0 Clock Output 0
173    output         GPIO_CLKOUT_P0, // GPIO Connection 0 Clock Output 1
174    inout   [ 31 : 0 ] GPIO_1,         // GPIO Connection 1 I/O
175    input          GPIO_CLKIN_N1,  // GPIO Connection 1 Clock Input 0
176    input          GPIO_CLKIN_P1,  // GPIO Connection 1 Clock Input 1
177    output         GPIO_CLKOUT_N1, // GPIO Connection 1 Clock Output 0
178    output         GPIO_CLKOUT_P1  // PIO Connection 1 Clock Output 1
179  );
180 
181  // 16*2 LCD Module
182  assign oLCD_ON   =   1 ' b1; // LCD ON
183  assign oLCD_BLON =   1 ' b1; // LCD Back Light
184 
185  // SDRAM
186  // the sdram is shahred with rtl and nios
187  assign oDRAM1_CLK = oDRAM0_CLK;
188 
189  // NIOS II system
190  nios_ii nios_ii0 (
191    // 1) global signals:
192    .clk_50(iCLK_50),
193    .pll_c0_system(CPU_CLK),
194    .pll_c1_memory(oDRAM0_CLK),
195    .pll_c2_audio(oAUD_XCK),
196    .reset_n( 1 ' b1),
197    // the_lcd
198    .LCD_E_from_the_lcd(oLCD_EN),
199    .LCD_RS_from_the_lcd(oLCD_RS),
200    .LCD_RW_from_the_lcd(oLCD_RW),
201    .LCD_data_to_and_from_the_lcd(LCD_D),
202    // the_pio_button
203    .in_port_to_the_pio_button(iKEY),
204    // the_pio_green_led
205    .out_port_from_the_pio_green_led(oLEDG),
206    // the_pio_red_led
207    .out_port_from_the_pio_red_led(oLEDR),
208    // the_seg7 
209    .avs_s1_export_seg7_from_the_SEG7({oHEX7_DP, oHEX7_D, oHEX6_DP, oHEX6_D, oHEX5_DP,
210      oHEX5_D, oHEX4_DP,oHEX4_D, oHEX3_DP, oHEX3_D, oHEX2_DP, oHEX2_D, oHEX1_DP, oHEX1_D,
211      oHEX0_DP, oHEX0_D}),
212    // the_sdram (u1)
213    .zs_addr_from_the_sdram_u1(oDRAM0_A),
214    .zs_ba_from_the_sdram_u1(oDRAM0_BA),
215    .zs_cas_n_from_the_sdram_u1(oDRAM0_CAS_N),
216    .zs_cke_from_the_sdram_u1(oDRAM0_CKE),
217    .zs_cs_n_from_the_sdram_u1(oDRAM0_CS_N),
218    .zs_dq_to_and_from_the_sdram_u1(DRAM_DQ[ 15 : 0 ]),
219    .zs_dqm_from_the_sdram_u1({oDRAM0_UDQM1,oDRAM0_LDQM0}),
220    .zs_ras_n_from_the_sdram_u1(oDRAM0_RAS_N),
221    .zs_we_n_from_the_sdram_u1(oDRAM0_WE_N),
222    // the_sdram (u2)
223    .zs_addr_from_the_sdram_u2(oDRAM1_A),
224    .zs_ba_from_the_sdram_u2(oDRAM1_BA),
225    .zs_cas_n_from_the_sdram_u2(oDRAM1_CAS_N),
226    .zs_cke_from_the_sdram_u2(oDRAM1_CKE),
227    .zs_cs_n_from_the_sdram_u2(oDRAM1_CS_N),
228    .zs_dq_to_and_from_the_sdram_u2(DRAM_DQ[ 31 : 16 ]),
229    .zs_dqm_from_the_sdram_u2({oDRAM1_UDQM1,oDRAM1_LDQM0}),
230    .zs_ras_n_from_the_sdram_u2(oDRAM1_RAS_N),
231    .zs_we_n_from_the_sdram_u2(oDRAM1_WE_N)
232  );
233 
234  endmodule


190行

nios_ii nios_ii0 (
 
// 1) global signals:
  .clk_50(iCLK_50),
  .pll_c0_system(CPU_CLK),
  .pll_c1_memory(oDRAM0_CLK),
  .pll_c2_audio(oAUD_XCK),
  .reset_n(
1 ' b1),


這裡我將.reset_n()直接接1'b1,是有特殊原因,一般會接Reset_Delay module送出來的CPU_RESET_N,而這個CPU_RESET_N是從KEY[0]而來,但因為Count Binary需要用KEY[0]做控制,所以只好將reset功能拿掉。

Nios II的C語言部分

count_binary.c / C

  1  /* ************************************************************************
  2  * Copyright (c) 2006 Altera Corporation, San Jose, California, USA.      *
  3  * All rights reserved. All use of this software and documentation is     *
  4  * subject to the License Agreement located at the end of this file below.*
  5  ************************************************************************ */
  6  /* *****************************************************************************
  7  *
  8  * Description
  9  * *************
10  * A simple program which, using an 8 bit variable, counts from 0 to ff,
11  * repeatedly.  Output of this variable is displayed on the LEDs, the Seven
12  * Segment Display, and the LCD.  The four "buttons" (SW0-SW3) are used
13  * to control output to these devices in the following manner:
14  *   Button1 (SW0) => LED is "counting"
15  *   Button2 (SW1) => Seven Segment is "counting"
16  *   Button3 (SW2) => LCD is "counting"
17  *   Button4 (SW3) => All of the peripherals are "counting".
18  *
19  * Upon completion of "counting", there is a short waiting period during
20  * which button/switch presses will be identified on STDOUT.
21  * NOTE:  These buttons have not been de-bounced, so one button press may
22  *        cause multiple notifications to STDOUT.
23  *
24  * Requirements
25  * **************
26  * This program requires the following devices to be configured:
27  *   an LED PIO named 'led_pio',
28  *   a Seven Segment Display PIO named 'seven_seg_pio',
29  *   an LCD Display named 'lcd_display',
30  *   a Button PIO named 'button_pio',
31  *   a UART (JTAG or standard serial)
32  *
33  * Peripherals Exercised by SW
34  * *****************************
35  * LEDs
36  * Seven Segment Display
37  * LCD
38  * Buttons (SW0-SW3)
39  * UART (JTAG or serial)
40 
41  * Software Files
42  * ****************
43  * count_binary.c ==>  This file.
44  *                     main() is contained here, as is the lion's share of the
45  *                     functionality.
46  * count_binary.h ==>  Contains some very simple VT100 ESC sequence defines
47  *                     for formatting text to the LCD Display.
48  *
49  *
50  * Useful Functions
51  * *****************
52  * count_binary.c (this file) has the following useful functions.
53  *   static void sevenseg_set_hex( int hex )
54  *     - Defines a hexadecimal display map for the seven segment display.
55  *   static void handle_button_interrupts( void* context, alt_u32 id)
56  *   static void init_button_pio()
57  *     - These are useful functions because they demonstrate how to write
58  *       and register an interrupt handler with the system library.
59  *
60  * count_binary.h
61  *   The file defines some useful VT100 escape sequences for use on the LCD
62  *   Display.
63    */
64 
65  #include " count_binary.h "
66 
67  /* A "loop counter" variable. */
68  static alt_u8 count;
69  /* A variable to hold the value of the button pio edge capture register. */
70  volatile   int edge_capture;
71 
72  /* Button pio functions */
73 
74  /*
75    Some simple functions to:
76    1.  Define an interrupt handler function.
77    2.  Register this handler in the system.
78  */
79 
80  /* ******************************************************************
81  * static void handle_button_interrupts( void* context, alt_u32 id)*
82  *                                                                 * 
83  * Handle interrupts from the buttons.                             *
84  * This interrupt event is triggered by a button/switch press.     *
85  * This handler sets *context to the value read from the button    *
86  * edge capture register.  The button edge capture register        *
87  * is then cleared and normal program execution resumes.           *
88  * The value stored in *context is used to control program flow    *
89  * in the rest of this program's routines.                         *
90  ***************************************************************** */
91 
92  #ifdef PIO_BUTTON_NAME
93  static   void handle_button_interrupts( void * context, alt_u32 id) {
94    /* Cast context to edge_capture's type. It is important that this be
95    * declared volatile to avoid unwanted compiler optimization.
96    */
97    volatile   int * edge_capture_ptr = ( volatile   int * ) context;
98    /* Store the value in the Button's edge capture register in *context. */
99    * edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(PIO_BUTTON_BASE);
100    /* Reset the Button's edge capture register. */
101    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_BUTTON_BASE, 0 );
102  }
103 
104  /* Initialize the button_pio. */
105  static   void init_button_pio() {
106    /* Recast the edge_capture pointer to match the alt_irq_register() function
107    * prototype. */
108    void * edge_capture_ptr = ( void * ) & edge_capture;
109    /* Enable all 4 button interrupts. */
110    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_BUTTON_BASE, 0xf );
111    /* Reset the edge capture register. */
112    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_BUTTON_BASE, 0x0 );
113    /* Register the interrupt handler. */
114    alt_irq_register(PIO_BUTTON_IRQ, edge_capture_ptr, handle_button_interrupts );
115  }
116  #endif
117 
118  /* Seven Segment Display PIO Functions
119  * sevenseg_set_hex() --  implements a hex digit map.
120    */
121   
122  #ifdef SEG7_NAME
123  static   void sevenseg_set_hex( int hex) {
124    SEG7_Hex(hex, 0x00 );
125  }
126  #endif
127 
128  /* Functions used in main loop
129  * lcd_init() -- Writes a simple message to the top line of the LCD.
130  * initial_message() -- Writes a message to stdout (usually JTAG_UART).
131  * count_<device>() -- Implements the counting on the respective device.
132  * handle_button_press() -- Determines what to do when one of the buttons
133  * is pressed.
134    */
135  static   void lcd_init( FILE * lcd ) {
136    /* If the LCD Display exists, write a simple message on the first line. */
137    LCD_PRINTF(lcd, " %c%s Counting will be displayed below " , ESC, ESC_TOP_LEFT);
138  }
139 
140  static   void initial_message() {
141    printf( " \n\n**************************\n " );
142    printf( " * Hello from Nios II!    *\n " );
143    printf( " * Counting from 00 to ff *\n " );
144    printf( " **************************\n " );
145  }
146 
147  /* *******************************************************
148  * The following functions write the value of the global*
149  * variable 'count' to 3 peripherals, if they exist in  *
150  * the system.  Specifically:                           *
151  * The LEDs will illuminate, the Seven Segment Display  *
152  * will count from 00-ff, and the LCD will display the  *
153  * hex value as the program loops.                      *
154  * **************************************************** */
155 
156  /* static void count_led()
157  *
158  * Illuminate LEDs with the value of 'count', if they
159  * exist in the system
160    */
161 
162  static   void count_led() {
163    alt_u8 b = count;
164    #ifdef PIO_GREEN_LED_NAME
165      /* Logic to make the LEDs count from right-to-left,
166       LSB on the right. */
167      IOWR_ALTERA_AVALON_PIO_DATA(
168          PIO_GREEN_LED_BASE,
169          ((b *   0x0802LU   &   0x22110LU ) |
170           (b *   0x8020LU   &   0x88440LU )) *   0x10101LU   >>   16
171          );
172    #endif
173  }
174 
175  /* static void count_sevenseg()
176  *
177  * Display value of 'count' on the Seven Segment Display
178    */
179 
180  static   void count_sevenseg() {
181    #ifdef SEG7_NAME
182      sevenseg_set_hex(count);
183    #endif
184  }
185 
186  /* static void count_lcd()
187  *
188  * Display the value of 'count' on the LCD Display, if it
189  * exists in the system.
190  *
191  * NOTE:  A HAL character device driver is used, so the LCD
192  * is treated as an I/O device (i.e.: using fprintf).  You
193  * can read more about HAL drivers <link/reference here>.
194    */
195 
196  static   void count_lcd( void * arg ) {
197    #ifdef LCD_NAME
198      FILE * lcd = (FILE * ) arg;
199      LCD_PRINTF(lcd, " %c%s 0x%x\n " , ESC, ESC_COL2_INDENT5, count);
200    #endif
201  }
202 
203  /* count_all merely combines all three peripherals counting */
204  static   void count_all( void * arg ) {
205    count_led();
206    count_sevenseg();
207    count_lcd( arg );
208    printf( " %02x,  " , count);
209  }
210   
211  static   void handle_button_press(alt_u8 type, FILE * lcd) {
212    /* Button press actions while counting. */
213    if (type ==   ' c ' ) {
214      switch (edge_capture) {
215        /* Button 1:  Output counting to LED only. */
216        case   0x1 :
217          count_led();
218          break ;
219         
220        /* Button 2:  Output counting to SEVEN SEG only. */
221        case   0x2 :
222          count_sevenseg();
223          break ;
224         
225        /* Button 3:  Output counting to D only. */
226        case   0x4 :
227          count_lcd(lcd);
228          break ;
229         
230        /* Button 4:  Output counting to LED, SEVEN_SEG, and D. */  
231        case   0x8 :
232          count_all(lcd);
233          break ;
234         
235        /* If value ends up being something different (shouldn't) do
236        same as 8. */
237        default :
238          count_all( lcd );
239          break ;
240         
241      }
242    }
243    /* If 'type' is anything else, assume we're "waiting" */
244    else {
245      switch (edge_capture) {
246        case   0x1 :
247          printf( " Button 1\n " );
248          edge_capture =   0 ;
249          break ;
250         
251        case   0x2 :
252          printf( " Button 2\n " );
253          edge_capture =   0 ;
254          break ;
255         
256        case   0x4 :
257          printf( " Button 3\n " );
258          edge_capture =   0 ;
259          break ;
260         
261        case   0x8 :
262          printf( " Button 4\n " );
263          edge_capture =   0 ;
264          break ;
265         
266        default :
267          printf( " Button press UNKNOWN!!\n " );
268      }
269    }
270  }
271 
272  /* ******************************************************************************
273  * int main()                                                                  *
274  *                                                                             *
275  * Implements a continuous loop counting from 00 to FF.  'count' is the loop   *
276  * counter.                                                                    *
277  * The value of 'count' will be displayed on one or more of the following 3    *
278  * devices, based upon hardware availability:  LEDs, Seven Segment Display,    *
279  * and the LCD Display.                                                        *
280  *                                                                             *
281  * During the counting loop, a switch press of SW0-SW3 will affect the         *
282  * behavior of the counting in the following way:                              *
283  *                                                                             *
284  * SW0 - Only the LED will be "counting".                                      *
285  * SW1 - Only the Seven Segment Display will be "counting".                    *
286  * SW2 - Only the LCD Display will be "counting".                              *
287  * SW3 - All devices "counting".                                               *
288  *                                                                             *
289  * There is also a 7 second "wait", following the count loop,                 *
290  * during which button presses are still                                       *
291  * detected.                                                                   *
292  *                                                                             *
293  * The result of the button press is displayed on STDOUT.                      *
294  *                                                                             *
295  * NOTE:  These buttons are not de-bounced, so you may get multiple            *
296  * messages for what you thought was a single button press!                    *
297  *                                                                             *
298  * NOTE:  References to Buttons 1-4 correspond to SW0-SW3 on the Development   *
299  * Board.                                                                      *
300  ***************************************************************************** */
301 
302  int main( void ) {
303    int i;
304    int wait_time;
305    FILE * lcd;
306 
307    count =   0 ;
308 
309    /* Initialize the LCD, if there is one. */
310    lcd = LCD_OPEN();
311    if (lcd != NULL)
312      lcd_init( lcd );
313     
314    /* Initialize the button pio. */
315 
316    #ifdef PIO_BUTTON_NAME
317      init_button_pio();
318    #endif
319 
320    /* Initial message to output. */
321 
322    initial_message();
323 
324    /* Continue 0-ff counting loop. */
325 
326    while ( 1 ) {
327      usleep( 100000 );
328      if (edge_capture !=   0 ) {
329        /* Handle button presses while counting  */
330        handle_button_press( ' c ' , lcd);
331      }
332      /* If no button presses, try to output counting to all. */
333      else {
334        count_all( lcd );
335      }
336      /*
337       * If done counting, wait about 7 seconds
338       * detect button presses while waiting.
339       */
340      if ( count ==   0xff ) {
341        LCD_PRINTF(lcd, " %c%s %c%s %c%s Waiting\n " , ESC, ESC_TOP_LEFT,
342          ESC, ESC_CLEAR, ESC, ESC_COL1_INDENT5);
343        printf( " \nWaiting " );
344        edge_capture =   0 ; /* Reset to 0 during wait/pause period. */
345 
346        /* Clear the 2nd. line of the LCD screen. */
347        LCD_PRINTF(lcd, " %c%s, %c%s " , ESC, ESC_COL2_INDENT5, ESC,
348          ESC_CLEAR);
349       
350        wait_time =   0 ;
351        for (i =   0 ; i < 70 ; ++ i) {
352          printf( " . " );
353          wait_time = i / 10 ;
354          LCD_PRINTF(lcd, " %c%s %ds\n " , ESC, ESC_COL2_INDENT5,
355            wait_time + 1 );
356 
357          if (edge_capture !=   0 ) {
358            printf( " \nYou pushed:  " );
359            handle_button_press( ' w ' , lcd);
360          }
361         
362          usleep( 100000 ); /* Sleep for 0.1s. */
363        }
364 
365        /*   Output the "loop start" messages before looping, again. */
366        initial_message();
367        lcd_init( lcd );
368      }
369 
370      count ++ ;
371    }
372 
373    LCD_CLOSE(lcd);
374    return   0 ;
375  }
376  /* *****************************************************************************
377  *                                                                             *
378  * License Agreement                                                           *
379  *                                                                             *
380  * Copyright (c) 2006 Altera Corporation, San Jose, California, USA.           *
381  * All rights reserved.                                                        *
382  *                                                                             *
383  * Permission is hereby granted, free of charge, to any person obtaining a     *
384  * copy of this software and associated documentation files (the "Software"),  *
385  * to deal in the Software without restriction, including without limitation   *
386  * the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
387  * and/or sell copies of the Software, and to permit persons to whom the       *
388  * Software is furnished to do so, subject to the following conditions:        *
389  *                                                                             *
390  * The above copyright notice and this permission notice shall be included in  *
391  * all copies or substantial portions of the Software.                         *
392  *                                                                             *
393  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
394  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
395  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
396  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
397  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
398  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
399  * DEALINGS IN THE SOFTWARE.                                                   *
400  *                                                                             *
401  * This agreement shall be governed in all respects by the laws of the State   *
402  * of California and by the laws of the United States of America.              *
403  * Altera does not recommend, suggest or require that this reference design    *
404  * file be used in conjunction or combination with any other product.          *
405  ***************************************************************************** */
406 


我不打算將整個程式講解,讀者可自行研究,我主要是放在如何改成讓DE2-70可以跑。

122行

#ifdef SEG7_NAME
static   void sevenseg_set_hex( int hex) {
  SEG7_Hex(hex,
0x00 );
}
#endif


用#ifdef判斷是否有七段顯示器存在,Altera之所以要這樣做,是顧慮到一些周邊不是每個實驗版都有,若判斷沒有周邊存在,就不執行該功能。

這立意雖好,但卻沒顧慮到就算相同實驗版,只要在SOPC Builder的命名不同, 一樣也抓不到這些周邊,原來project template用的是#ifdef SEVEN_SEG_PIO_BASE,難怪會無法在DE2-70執行。

所以若要能在DE2-70執行,必須將這些#ifdef全部改掉,這些名字可在system.h內找的到

除此之外,由於七段顯示器已經改用友晶科技提供的ip,所以也要改成友晶提供HAL:SEG7_Hex(),詳細請參考(原創) 如何在Nios II顯示8位數的七段顯示器? (SOC) (Nios II) (SOPC Builder) (DE2-70)

162行

static   void count_led() {
  alt_u8 b
= count;
  #ifdef PIO_GREEN_LED_NAME
   
/* Logic to make the LEDs count from right-to-left,
     LSB on the right.
*/
    IOWR_ALTERA_AVALON_PIO_DATA(
        PIO_GREEN_LED_BASE,
        ((b
*   0x0802LU   &   0x22110LU ) |
         (b
*   0x8020LU   &   0x88440LU )) *   0x10101LU   >>   16
        );
 
#endif
}


IOWR()家族的macro,都要傳入base address,這種macro也會隨著在SOPC Builder內的命名而不同,原來project template是LED_PIO_BASE,當然無法在DE2-70執行。

所以若要能在DE2-70執行,必須將這些base address的macro全部改掉,這些名字可在system.h內找的到。 

SEG7.h / C

1  /* ************************************************************************
2  * Copyright (c) 2006 Altera Corporation, San Jose, California, USA.      *
3  * All rights reserved. All use of this software and documentation is     *
4  * subject to the License Agreement located at the end of this file below.*
5  ************************************************************************ */
6 
7  #include " alt_types.h "
8  #include " altera_avalon_pio_regs.h "
9  #include " sys/alt_irq.h "
10  #include " system.h "
11  #include < stdio.h >
12  #include < unistd.h >
13  #include " SEG7.h "
14 
15  #ifndef LCD_NAME
16  /* Some hardware is not present because of system or because of simulation */
17  #   define LCD_CLOSE(x) /* Do Nothing */
18  #   define LCD_OPEN() NULL
19  #   define LCD_PRINTF(lcd, args) fprintf(lcd, args)
20 
21  #else
22  /* With hardware devices present, use these definitions */
23  #   define LCD_CLOSE(x) fclose((x))
24  #   define LCD_OPEN() fopen(LCD_NAME, " w " )
25  #   define LCD_PRINTF fprintf
26 
27  #endif
28 
29  /* Cursor movement on the LCD */
30  /* Clear */
31  #define ESC 27
32  /* Position cursor at row 1, column 1 of LCD. */
33  #define ESC_CLEAR "K"
34  /* Position cursor at row1, column 5 of LCD. */
35  #define ESC_COL1_INDENT5 "[1;5H"
36  /* Position cursor at row2, column 5 of LCD. */
37  #define ESC_COL2_INDENT5 "[2;5H"
38  /* Integer ASCII value of the ESC character. */
39  #define ESC_TOP_LEFT "[1;0H"
40 
41  /* *****************************************************************************
42  *                                                                             *
43  * License Agreement                                                           *
44  *                                                                             *
45  * Copyright (c) 2006 Altera Corporation, San Jose, California, USA.           *
46  * All rights reserved.                                                        *
47  *                                                                             *
48  * Permission is hereby granted, free of charge, to any person obtaining a     *
49  * copy of this software and associated documentation files (the "Software"),  *
50  * to deal in the Software without restriction, including without limitation   *
51  * the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
52  * and/or sell copies of the Software, and to permit persons to whom the       *
53  * Software is furnished to do so, subject to the following conditions:        *
54  *                                                                             *
55  * The above copyright notice and this permission notice shall be included in  *
56  * all copies or substantial portions of the Software.                         *
57  *                                                                             *
58  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
59  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
60  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
61  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
62  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
63  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
64  * DEALINGS IN THE SOFTWARE.                                                   *
65  *                                                                             *
66  * This agreement shall be governed in all respects by the laws of the State   *
67  * of California and by the laws of the United States of America.              *
68  * Altera does not recommend, suggest or require that this reference design    *
69  * file be used in conjunction or combination with any other product.          *
70  ***************************************************************************** */
71 


15行

#ifndef LCD_NAME


一樣要自己去改#ifndef

執行結果

de2_70_count10

完整程式碼下載
DE2_70_NIOS_count_binary.7z

Conclusion
在本文我們學到如何將Altera的project template移植到DE2-70上,事實上很多Altera原廠的範例,都是為Altera原廠開發版所設計,只要使用本文所提出的技巧,就能移植到DE2/DE2-70上執行。

See Also
(原創) 哪裡有DE2-70的Nios II reference design可以參考? (SOC) (DE2-70) (Nios II) (SOPC Builder)
(原創) 如何在Nios II顯示8位數的七段顯示器? (SOC) (Nios II) (SOPC Builder) (DE2-70)

Reference
Using SignalTap II Embedded Logic Analyzers in SOPC Builder Systems

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值