Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

2 Leds -> how many PIO?

Altera_Forum
Honored Contributor II
1,094 Views

Hi all, 

I'm writing a simple program on interrupt behaviour,  

with an interval timer (that generate timer interrupt and its handler make a ledg blink) and an hardware interrupt generated by a button... 

 

All works fine, but i'd like to have another led(ledr) blink in my hardware interrupt handler.(now its function is to make the ledg blink faster) 

 

To do that my system has a 2 bit PIO(output) but I don't understand how to manage the second led... 

 

my question is: I had to use 2 different PIO(1 bit) instead of 1 PIO (2 bit)? or even if i have only one PIO i can manage 2 led?  

 

How can I do that?
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
366 Views

Of course, you can use the same PIO to control both the LEDs... for this you have to introduce an extra output signal in your HDL module and link this signal to the second bit of the PIO (you do it where you instantiated your NiosII module in QuartusII). Now make a pin assignment for this new signal to the desired LED in the board. Now the second bit of the PIO is connected to the other LED...

0 Kudos
Altera_Forum
Honored Contributor II
366 Views

In my Verilog module in quartus 2 i already have 2 output(ledr and ledg), with the right pin assignment, but in my application how can i manage the second LED? 

 

to make them blink i wrote: 

 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 1); usleep(500000); IOWR_ALTERA_AVALON_PIO_DATA(LED_POI_BASE, 0);Edit: 

 

my verilog module is: 

module test(clk,rst,button,ledr,ledg); input clk,rst,button; output ledg,ledr; nios2 test_nios (clk,rst,button,ledg,ledr); endmodule
0 Kudos
Altera_Forum
Honored Contributor II
366 Views

LED_PIO_BASE is 2 bit wide so it can control both the LEDs. if you want both the LEDs to blink together, try this code: 

 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 3); 

delay(500000); 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0); 

0 Kudos
Altera_Forum
Honored Contributor II
366 Views

If you configured your PIO for individual bit setting, you can possibly use these: 

IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(LED_PIO_BASE, led); // led on 

IOWR_ALTERA_AVALON_PIO_SET_BITS(LED_PIO_BASE, led); // led off 

led is the bit mask of the output(s) you want to set/clear: 

1: for the first led 

2: for the second led 

3: for controlling both 

Should you extend the PIO for more outputs, they would be controlled by next bits: 0x4, 0x8, 0x10, 0x20, ....
0 Kudos
Altera_Forum
Honored Contributor II
366 Views

Just be careful in the software, since changing the state of one LED requires a read/modify/write sequence - which mustn't be interrupted. 

 

This can be avoided by defining 2 registers, one to set the LED, the other to clear it. 

 

In reality whether you use 32 address locations for 32 LEDs, or one address and 32 data bits depends on how you need to access them. If you want to set/clear/read the values all at once then a single (or a set/clear pair) of PIO registers in needed. If you only ever set a single LED, then separate addresses may be more useful. 

 

The thing about an FPGA design is that you can change your mind!
0 Kudos
Altera_Forum
Honored Contributor II
366 Views

Thank you all for your answers! 

I've just some other questions to be sure to have understood: 

 

@shahzad 

in your code the LEDS blink together, but if i want manage them separately?i should use "2" for the second led and "1" for the first? 

 

example: 

 

LED1 

 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 1); 

delay(500000); 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0); 

 

 

LED2 

 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 2); 

delay(500000); 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, 0); 

 

 

or that solution works only with Cris72's code? 

 

(I've 2 different interrupt, and i want use one led in each handler) 

 

 

 

 

@Cris72 

what you mean exactly with "configured your PIO for individual bit setting"? 

2 bit-->2 output pin? 

 

 

 

 

@dsl 

you mean that if i ever use a single led the best solution should be one LED one PIO?
0 Kudos
Altera_Forum
Honored Contributor II
366 Views

 

--- Quote Start ---  

 

@Cris72 

what you mean exactly with "configured your PIO for individual bit setting"? 

2 bit-->2 output pin? 

 

--- Quote End ---  

 

You find this option in sopc builder: open the PIO module properties and just check the box labeled this way and rebuild system and fpga. 

This feature is very useful in your case where you have to set/reset in different isr. Since you don't need the double step of reading the pio register and writing again with the changed bits, you won't bother if a higher priority isr changes same bits in the meantime (which could make a mess or pio status). 

 

Regarding the other question about set bits separately, the answer is Yes: you read the register and simply change only the required bits: 

led = IORD_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE); 

/* you can use any of these */ 

led |= 1; // turn LED 1 on 

led &= ~2; // turn LED 2 off 

led ^= 0x10; // toggle an extra LED possibily connected to 6th PIO output 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led);
0 Kudos
Altera_Forum
Honored Contributor II
366 Views

ok, you can try with this macro 

 

# define SET(x,val)  

unsigned char in_led=IORD_ALTERA_AVALON_PIO_DATA(X_BASE); 

unsigned char out_tmp=1<<x; 

unsigned char out; 

if(val==1){ 

out=in_led | out_tmp; 

else{ 

out=in_led &(~out_tmp); 

IOWR_ALTERA_AVALON_PIO_DATA(X_BASE , out );\  

 

if you want set in 1, only put the macro in your code like the following 

SET(0,1)// put in 1 the led 0 

SET(1,1)// put in 1 the led 1 

SET(0,0)// put in 0 the led 0 

SET(1,0)// put in 0 the led 1 

 

 

or if you want toggle macro, try this 

 

# define TOGGLE_LED(x)  

unsigned char in_led=IORD_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE); 

unsigned char out_tmp=1<<x; 

unsigned char out=in_led ^ out_tmp; 

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE , out);\  

}
0 Kudos
Reply