基于FPGA的嵌入式系统开发流程
Nios处理器分立元件:
RAM的设置:M9K;Data Width:12KByte;Total Size:12Kbyte
PIO的设置:Reset Value:0x00;
CPU的设置:Instruction Cache:2Kbytes
Interval Timer的设置:Presets(预先装置):Full-featured(全功能)
NiosII例化代码:
module first_q2_prj(clk,ext_rst_n,led_pio); input clk; input ext_rst_n; output[7:0] led_pio; wire rst_n; sys_ctrl uut_sc( .clk(clk), .ext_rst_n(ext_rst_n), .rst_n(rst_n) ); first_nios_sys first_nios_sys_inst ( .clk (clk), .out_port_from_the_led_pio (led_pio), .reset_n (rst_n) ); endmodule
复位延迟代码:
module sys_ctrl(clk,ext_rst_n,rst_n); input clk; input ext_rst_n; output rst_n; reg[9:0] rst_cnt; reg rst_nr; always@(posedge clk or negedge ext_rst_n) if(!ext_rst_n) begin rst_cnt<=10'b0; rst_nr<=1'b0; end else if(rst_n!=10'd000) rst_cnt<=rst_cnt+1'b1; else rst_nr<=1'b1; assign rst_n=rst_nr; endmodule
NiosII Eclipse Reduce Library Size Setting:
NiosII软体部分代码:
/************************************************************************* * Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * * All rights reserved. All use of this software and documentation is * * subject to the License Agreement located at the end of this file below.* *************************************************************************/ /****************************************************************************** * * Description * ************* * A simple program which, using an 8 bit variable, counts from 0 to ff, * repeatedly. Output of this variable is displayed on the LEDs, the Seven * Segment Display, and the LCD. The four "buttons" (SW0-SW3) are used * to control output to these devices in the following manner: * Button1 (SW0) => LED is "counting" * Button2 (SW1) => Seven Segment is "counting" * Button3 (SW2) => LCD is "counting" * Button4 (SW3) => All of the peripherals are "counting". * * Upon completion of "counting", there is a short waiting period during * which button/switch presses will be identified on STDOUT. * NOTE: These buttons have not been de-bounced, so one button press may * cause multiple notifications to STDOUT. * * Requirements * ************** * This program requires the following devices to be configured: * an LED PIO named 'led_pio', * a Seven Segment Display PIO named 'seven_seg_pio', * an LCD Display named 'lcd_display', * a Button PIO named 'button_pio', * a UART (JTAG or standard serial) * * Peripherals Exercised by SW * ***************************** * LEDs * Seven Segment Display * LCD * Buttons (SW0-SW3) * UART (JTAG or serial) * Software Files * **************** * count_binary.c ==> This file. * main() is contained here, as is the lion's share of the * functionality. * count_binary.h ==> Contains some very simple VT100 ESC sequence defines * for formatting text to the LCD Display. * * * Useful Functions * ***************** * count_binary.c (this file) has the following useful functions. * static void sevenseg_set_hex( int hex ) * - Defines a hexadecimal display map for the seven segment display. * static void handle_button_interrupts( void* context, alt_u32 id) * static void init_button_pio() * - These are useful functions because they demonstrate how to write * and register an interrupt handler with the system library. * * count_binary.h * The file defines some useful VT100 escape sequences for use on the LCD * Display. */ #include "count_binary.h" /* A "loop counter" variable. */ static alt_u8 count; /* A variable to hold the value of the button pio edge capture register. */ volatile int edge_capture; /* Button pio functions */ /* Some simple functions to: 1. Define an interrupt handler function. 2. Register this handler in the system. */ /******************************************************************* * static void handle_button_interrupts( void* context, alt_u32 id)* * * * Handle interrupts from the buttons. * * This interrupt event is triggered by a button/switch press. * * This handler sets *context to the value read from the button * * edge capture register. The button edge capture register * * is then cleared and normal program execution resumes. * * The value stored in *context is used to control program flow * * in the rest of this program's routines. * * * * Provision is made here for systems that might have either the * * legacy or enhanced interrupt API active, or for the Nios II IDE * * which does not support enhanced interrupts. For systems created * * using the Nios II softawre build tools, the enhanced API is * * recommended for new designs. * ******************************************************************/ #ifdef BUTTON_PIO_BASE #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT static void handle_button_interrupts(void* context) #else static void handle_button_interrupts(void* context, alt_u32 id) #endif { /* Cast context to edge_capture's type. It is important that this be * declared volatile to avoid unwanted compiler optimization. */ volatile int* edge_capture_ptr = (volatile int*) context; /* Store the value in the Button's edge capture register in *context. */ *edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE); /* Reset the Button's edge capture register. */ IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0); /* * Read the PIO to delay ISR exit. This is done to prevent a spurious * interrupt in systems with high processor -> pio latency and fast * interrupts. */ IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE); } /* Initialize the button_pio. */ static void init_button_pio() { /* Recast the edge_capture pointer to match the alt_irq_register() function * prototype. */ void* edge_capture_ptr = (void*) &edge_capture; /* Enable all 4 button interrupts. */ IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE, 0xf); /* Reset the edge capture register. */ IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0x0); /* Register the interrupt handler. */ #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT alt_ic_isr_register(BUTTON_PIO_IRQ_INTERRUPT_CONTROLLER_ID, BUTTON_PIO_IRQ, handle_button_interrupts, edge_capture_ptr, 0x0); #else alt_irq_register( BUTTON_PIO_IRQ, edge_capture_ptr, handle_button_interrupts); #endif } #endif /* BUTTON_PIO_BASE */ /* Seven Segment Display PIO Functions * sevenseg_set_hex() -- implements a hex digit map. */ #ifdef SEVEN_SEG_PIO_BASE static void sevenseg_set_hex(int hex) { static alt_u8 segments[16] = { 0x81, 0xCF, 0x92, 0x86, 0xCC, 0xA4, 0xA0, 0x8F, 0x80, 0x84, /* 0-9 */ 0x88, 0xE0, 0xF2, 0xC2, 0xB0, 0xB8 }; /* a-f */ unsigned int data = segments[hex & 15] | (segments[(hex >> 4) & 15] << 8); IOWR_ALTERA_AVALON_PIO_DATA(SEVEN_SEG_PIO_BASE, data); } #endif /* Functions used in main loop * lcd_init() -- Writes a simple message to the top line of the LCD. * initial_message() -- Writes a message to stdout (usually JTAG_UART). * count_<device>() -- Implements the counting on the respective device. * handle_button_press() -- Determines what to do when one of the buttons * is pressed. */ static void lcd_init( FILE *lcd ) { /* If the LCD Display exists, write a simple message on the first line. */ LCD_PRINTF(lcd, "%c%s Counting will be displayed below...", ESC, ESC_TOP_LEFT); } static void initial_message() { printf("\n\n**************************\n"); printf("* Hello from Nios II! *\n"); printf("* Counting from 00 to ff *\n"); printf("**************************\n"); } /******************************************************** * The following functions write the value of the global* * variable 'count' to 3 peripherals, if they exist in * * the system. Specifically: * * The LEDs will illuminate, the Seven Segment Display * * will count from 00-ff, and the LCD will display the * * hex value as the program loops. * * *****************************************************/ /* static void count_led() * * Illuminate LEDs with the value of 'count', if they * exist in the system */ static void count_led() { #ifdef LED_PIO_BASE IOWR_ALTERA_AVALON_PIO_DATA( LED_PIO_BASE, count ); #endif } /* static void count_sevenseg() * * Display value of 'count' on the Seven Segment Display */ static void count_sevenseg() { #ifdef SEVEN_SEG_PIO_BASE sevenseg_set_hex(count); #endif } /* static void count_lcd() * * Display the value of 'count' on the LCD Display, if it * exists in the system. * * NOTE: A HAL character device driver is used, so the LCD * is treated as an I/O device (i.e.: using fprintf). You * can read more about HAL drivers <link/reference here>. */ static void count_lcd( void* arg ) { FILE *lcd = (FILE*) arg; LCD_PRINTF(lcd, "%c%s 0x%x\n", ESC, ESC_COL2_INDENT5, count); } /* count_all merely combines all three peripherals counting */ static void count_all( void* arg ) { count_led(); count_sevenseg(); count_lcd( arg ); printf("%02x, ", count); } static void handle_button_press(alt_u8 type, FILE *lcd) { /* Button press actions while counting. */ if (type == 'c') { switch (edge_capture) { /* Button 1: Output counting to LED only. */ case 0x1: count_led(); break; /* Button 2: Output counting to SEVEN SEG only. */ case 0x2: count_sevenseg(); break; /* Button 3: Output counting to D only. */ case 0x4: count_lcd( lcd ); break; /* Button 4: Output counting to LED, SEVEN_SEG, and D. */ case 0x8: count_all( lcd ); break; /* If value ends up being something different (shouldn't) do same as 8. */ default: count_all( lcd ); break; } } /* If 'type' is anything else, assume we're "waiting"...*/ else { switch (edge_capture) { case 0x1: printf( "Button 1\n"); edge_capture = 0; break; case 0x2: printf( "Button 2\n"); edge_capture = 0; break; case 0x4: printf( "Button 3\n"); edge_capture = 0; break; case 0x8: printf( "Button 4\n"); edge_capture = 0; break; default: printf( "Button press UNKNOWN!!\n"); } } } /******************************************************************************* * int main() * * * * Implements a continuous loop counting from 00 to FF. 'count' is the loop * * counter. * * The value of 'count' will be displayed on one or more of the following 3 * * devices, based upon hardware availability: LEDs, Seven Segment Display, * * and the LCD Display. * * * * During the counting loop, a switch press of SW0-SW3 will affect the * * behavior of the counting in the following way: * * * * SW0 - Only the LED will be "counting". * * SW1 - Only the Seven Segment Display will be "counting". * * SW2 - Only the LCD Display will be "counting". * * SW3 - All devices "counting". * * * * There is also a 7 second "wait", following the count loop, * * during which button presses are still * * detected. * * * * The result of the button press is displayed on STDOUT. * * * * NOTE: These buttons are not de-bounced, so you may get multiple * * messages for what you thought was a single button press! * * * * NOTE: References to Buttons 1-4 correspond to SW0-SW3 on the Development * * Board. * ******************************************************************************/ int main(void) { int i; int wait_time; FILE * lcd; count = 0; /* Initialize the LCD, if there is one. */ lcd = LCD_OPEN(); if(lcd != NULL) {lcd_init( lcd );} /* Initialize the button pio. */ #ifdef BUTTON_PIO_BASE init_button_pio(); #endif /* Initial message to output. */ initial_message(); /* Continue 0-ff counting loop. */ while( 1 ) { usleep(100000); if (edge_capture != 0) { /* Handle button presses while counting... */ handle_button_press('c', lcd); } /* If no button presses, try to output counting to all. */ else { count_all( lcd ); } /* * If done counting, wait about 7 seconds... * detect button presses while waiting. */ if( count == 0xff ) { LCD_PRINTF(lcd, "%c%s %c%s %c%s Waiting...\n", ESC, ESC_TOP_LEFT, ESC, ESC_CLEAR, ESC, ESC_COL1_INDENT5); printf("\nWaiting..."); edge_capture = 0; /* Reset to 0 during wait/pause period. */ /* Clear the 2nd. line of the LCD screen. */ LCD_PRINTF(lcd, "%c%s, %c%s", ESC, ESC_COL2_INDENT5, ESC, ESC_CLEAR); wait_time = 0; for (i = 0; i<70; ++i) { printf("."); wait_time = i/10; LCD_PRINTF(lcd, "%c%s %ds\n", ESC, ESC_COL2_INDENT5, wait_time+1); if (edge_capture != 0) { printf( "\nYou pushed: " ); handle_button_press('w', lcd); } usleep(100000); /* Sleep for 0.1s. */ } /* Output the "loop start" messages before looping, again. */ initial_message(); lcd_init( lcd ); } count++; } LCD_CLOSE(lcd); return 0; } /****************************************************************************** * * * License Agreement * * * * Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * * All rights reserved. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * * DEALINGS IN THE SOFTWARE. * * * * This agreement shall be governed in all respects by the laws of the State * * of California and by the laws of the United States of America. * * Altera does not recommend, suggest or require that this reference design * * file be used in conjunction or combination with any other product. * ******************************************************************************/