EmbDev.net

Forum: FPGA, VHDL & Verilog Stopwatch on Xilinx NEXYS A7 Board using Vitis ISE(C-Code)


von Max (luit)


Rate this post
useful
not useful
Can anyone help me to build Stopwatch with Start/stop, reset, 
pause/resume functionalities?

I have .xsa bitstream from Vivado and want to implement it on 7-segment 
display of Xilinx NEXYS A7 board using C-Code (Xilinx Vitis ISE).

I'm not good with C and have to consider C in this case. The following 
is the code but not really working.

#include "xparameters.h"
#include "xgpio.h"
#include "xtmrctr.h"
#include <unistd.h>
#include "xstatus.h"

#define LED_AN_ADDR 0x40000000  //base address for digit select signals
#define LED_DIS_ADDR 0x40010000 //base address for 7-segment displays
#define SW_ADDR 0x40020000 //base address for 16 switches
#define TMRCTR_DEVICE_ID XPAR_TMRCTR_0_DEVICE_ID //device ID for the 
on-board timer

#define TIMER_FREQ 100000000 // Timer frequency in Hz
#define DISPLAY_PERIOD 100000000/10 // Period for updating the display 
in clock cycles

XGpio Gpio_LedAn;
XGpio Gpio_LedDis;
XGpio Gpio_Sw;
XTmrCtr Timer;

unsigned int hours = 0;  // Time in hours
unsigned int minutes = 0;  // Time in minutes
unsigned int seconds = 0;  // Time in seconds
int state = 0;  // 0 = stopped, 1 = running
void delay(unsigned int delay_count) {
    unsigned int i;
    for (i = 0; i < delay_count; i++);
}


unsigned int get7segData(int num)
{
    static const unsigned int segData[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 
0x6D, 0x7D, 0x07, 0x7F, 0x6F};
    if(num >= 0 && num <= 999999) {
        unsigned int result = 0;
        int i;
        for (i = 0; i < 6; i++) {
            result |= segData[num % 10] << (i * 8);
            num /= 10;
        }
        return result;
    } else {
        return 0;
    }
}


void update_display()
{
    // turn off all digit select signals
    XGpio_DiscreteWrite(&Gpio_LedAn, 1, 0x00000000);

    // Display hour tens digit on the leftmost 7-segment display
    XGpio_DiscreteWrite(&Gpio_LedDis, 1, get7segData(hours / 10));
    XGpio_DiscreteWrite(&Gpio_LedAn, 1, 0x1); // turn on digit select 
signal for leftmost display
    delay(0.05 * 1000000);

    // Display hour ones digit on the second leftmost 7-segment display
    XGpio_DiscreteWrite(&Gpio_LedDis, 1, get7segData(hours % 10));
    XGpio_DiscreteWrite(&Gpio_LedAn, 1, 0x2); // turn on digit select 
signal for second leftmost display
    delay(0.05 * 1000000);

    // Display minute tens digit on the third leftmost 7-segment display
    XGpio_DiscreteWrite(&Gpio_LedDis, 1, get7segData(minutes / 10));
    XGpio_DiscreteWrite(&Gpio_LedAn, 1, 0x4); // turn on digit select 
signal for third leftmost display
    delay(0.05 * 1000000);

    // Display minute ones digit on the fourth leftmost 7-segment 
display
    XGpio_DiscreteWrite(&Gpio_LedDis, 1, get7segData(minutes % 10));
    XGpio_DiscreteWrite(&Gpio_LedAn, 1, 0x8); // turn on digit select 
signal for fourth leftmost display
    delay(0.05 * 1000000);

    // Display second tens digit on the fifth leftmost 7-segment display
    XGpio_DiscreteWrite(&Gpio_LedDis, 1, get7segData(seconds / 10));
    XGpio_DiscreteWrite(&Gpio_LedAn, 1, 0x10); // turn on digit select 
signal for fifth leftmost display
    delay(0.05 * 1000000);

    // Display second ones digit on the rightmost 7-segment display
    XGpio_DiscreteWrite(&Gpio_LedDis, 1, get7segData(seconds % 10));
    XGpio_DiscreteWrite(&Gpio_LedAn, 1, 0x20); // turn on digit select 
signal for rightmost display
    delay(0.05 * 1000000);

    // turn off all digit select signals
    XGpio_DiscreteWrite(&Gpio_LedAn, 1, 0x00000000);
}



void timer_interrupt(void *CallbackRef, u8 TmrCtrNumber)
{
    // call the function to display the time on the 7-segment displays
    update_display();
    // increment the time
    seconds++;
    if (seconds == 60) {
        seconds = 0;
        minutes++;
    }
    if (minutes == 60) {
        minutes = 0;
        hours++;
    }
    if (hours == 100) {
        hours = 0;
    }
    // reset the timer counter value
    XTmrCtr_Reset(CallbackRef, TmrCtrNumber);
    // call the function to display the time on the 7-segment displays
    //Read switches
    int switches = XGpio_DiscreteRead(&Gpio_Sw, 1);

    // Check the reset switch
    if (switches & 0x1) {
        // Reset the timer
        hours = 0;
        minutes = 0;
        seconds = 0;
    }

    // Check the start/stop switch
    if (switches & 0x2) {
        // Toggle the state of the stopwatch
        state = !state;
    }

    // If the stopwatch is running, re-enable the timer interrupt
    if (state) {
    XTmrCtr_EnableIntr(&Timer, TmrCtrNumber);
    }
}

int main()
{
    int status;

    // Initialize the digital I/O for the 7-segment displays and digit 
select signals
    status = XGpio_Initialize(&Gpio_LedDis, LED_DIS_ADDR);
    if (status != XST_SUCCESS) return XST_FAILURE;
    status = XGpio_Initialize(&Gpio_LedAn, LED_AN_ADDR);
    if (status != XST_SUCCESS) return XST_FAILURE;

    // Initialize the digital I/O for the 16-bit switches
    status = XGpio_Initialize(&Gpio_Sw, SW_ADDR);
    if (status != XST_SUCCESS) return XST_FAILURE;

    // Initialize the timer
    status = XTmrCtr_Initialize(&Timer, TMRCTR_DEVICE_ID);
    if (status != XST_SUCCESS) return XST_FAILURE;

    // Set the timer to generate an interrupt every 1 second
    XTmrCtr_SetResetValue(&Timer, 0, DISPLAY_PERIOD);
    XTmrCtr_SetOptions(&Timer, 0, XTC_INT_MODE_OPTION | 
XTC_AUTO_RELOAD_OPTION);

    // Register the timer interrupt handler
    XTmrCtr_SetHandler(&Timer, timer_interrupt, &Timer);

    // Enable the global interrupt
    microblaze_enable_interrupts();

    // Start the timer
    XTmrCtr_Start(&Timer, 0);

    return 0;
    }

: Edited by User
von Andreas M. (amesser)


Rate this post
useful
not useful
Where is the point in using an FPGA board to implement a function using 
"C" language? What CPU is the "C" code going to be compiled for and run 
on? Wouldn't it be simpler to just implement the Stopwatch in hdl and 
use the FPGA as is?

von Max (luit)


Rate this post
useful
not useful
OS : Standalone
Processor: Microblaze

I agree with you, it is simpler in hdl but the challenge is to use C and 
it is not working as expected cause I couldnot find and fix issues.

: Edited by User
von Andreas M. (amesser)


Rate this post
useful
not useful
Its not good style to edit a post afterwards and add big amounts of 
extra information not provided in the first place. It makes other people 
look like fools. You should have typed that into your new post. 
Regarding your program:

Checking every second the input pin state will not work. One has to hold 
Keys for at least one second to have the keypress recognized. 
Furthermore if key is pressed a bit longer than one second it might 
"detect" two key presses. You need proper edge detection. (and maybe as 
well debouncing)

At the end of main() you just return. That exits your application. If 
you do that, your application is gone. Most likely the platform specific 
c runtime code will also do a reset of your software in that case. In 
most cases, embedded applications are not supposed to return from main() 
at all.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.