Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 years ago

2 Leds -> how many PIO?

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?

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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...

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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);

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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, ....
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- 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);
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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);\

    }