This example builds on the previous one and adds both digital input and output to the BASYS3 board. It reads every second the switch settings and then turns the corresponding leds on or off. Additionally, it outputs the switch settings to the UART.
Make a copy the previous Hello World project by using File / Save Project As... from the main menu. (This step is optional but it may save a lot of time in case you want to go back to the previous design.)
In the IP Integrator, Open the the Block Design, click on the Board tab and drag the "16 Switches" and then the "16 LEDs" into the board design.
Run the Connection Automation and select the default configuration. Validate your design and Regenerate the Layout and you should get the design shown above. Make sure that the switches are connected to GPIO and the leds to GPIO2.
Save your desing and Run Synthesis.
From the main menu, select File / Export / Export Hardware. (Overwrite existing file.)
From the main menu, select File / Launch SKD. (Without including Bitstream.)
Once SDK has launched, you will get a message that the files need to be updated and you may see a new hardware platform folder. Depending on your previous design name, you will see something like design_1_wrapper_hw_platform_0 (the old file) and design_1_wrapper_hw_platform_1, the folder with the new design. You may delete the folder with the old design. You may also delete your old SDK project and board support (bsp) folders.
Create a new Hello World Application project by selecting File / New / Application Project. Name it and then select "next," select the "Hello World" example.
Drill down to the new source file in your new application and find the "helloworld.c" file and double click on it. (It will be located at XXX\src\helloworld.c.) where XXX corresponds to your project name you entered in the previous step.
Delete everything in the file and copy the contents of the SDK file shown below into it. Save everything and check that there were no errors creating the ELF files.
Back in Vivado, associate the ELF file by clicking on "Open Block Design" and then from the menu, Tools \ Associate Elf File.. Like before, click on the Design Source "Select ELF Files" button and locate your new ELF file. (It should be in your Vivado's project yyy.SDK\XXX\Debug folder. (XXX again pertains to the file name from a few steps ago, yyy is current Vivado project name.)
Since there are now 2 ELF files associated with your project, delete the old one clicking on it in the Sources tab and removing it from the project.
Generate the bitstream and program the board in the hardware manager.
If you get stuck see the detailed instructions for the Hello World example.
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xgpio.h"
#include "microblaze_sleep.h"
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define GPIO_OUTPUT_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
#define GPIO_INPUT_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
#define GPIO_BITWIDTH 16 /* This is the width of the GPIO */
/* The following constant is used to determine which channel of the GPIO is
* used if there are 2 channels supported in the GPIO. Must be either 1 or 2.
*/
#define INPUT_SWITCH_CHANNEL 1 //in block design defined as GPIO
#define OUTPUT_LED_CHANNEL 2 //in block design defined as GPIO_2
/************************** Variable Definitions **************************/
/*
* The following are declared globally so they are zeroed and so they are
* easily accessible from a debugger
*/
XGpio GpioOutput; /* The driver instance for GPIO Device configured as O/P */
XGpio GpioInput; /* The driver instance for GPIO Device configured as I/P */
/*****************************************************************************/
int main()
{
u8 i;
u32 DataRead;
int Status;
init_platform();
xil_printf("Initialize\n\r");
/*
* Initialize the GPIO driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h
* also set its data direction
*/
Status = XGpio_Initialize(&GpioOutput, GPIO_OUTPUT_DEVICE_ID); //output
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/* Set the direction for all signals to be outputs */
XGpio_SetDataDirection(&GpioOutput, OUTPUT_LED_CHANNEL, 0x0);
Status = XGpio_Initialize(&GpioInput, GPIO_INPUT_DEVICE_ID); //input
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/* Set the direction for all signals to be inputs */
XGpio_SetDataDirection(&GpioInput, INPUT_SWITCH_CHANNEL, 0xFFFFFFFF);
xil_printf("Start\n\r");
for(i = 0; i < 20; i++)
{
/* Read the state of the data so that it can be verified */
DataRead = XGpio_DiscreteRead(&GpioInput, INPUT_SWITCH_CHANNEL);
/* Set the GPIO outputs to low */
XGpio_DiscreteWrite(&GpioOutput, OUTPUT_LED_CHANNEL, DataRead);
xil_printf("%u\tSwitch Settings: 0x%4X\n\r",i,DataRead);
MB_Sleep(1000);
}
xil_printf("Done\n\r");
cleanup_platform();
return 0;
}
A sample terminal output is shown below. The communication port (COM6 below) might be different as well as the switch setting. As indicated, the switches were moved during the run.
Connected to COM6 at 115200
Initialize
Start
0 Switch Settings: 0x 5
1 Switch Settings: 0x 5
2 Switch Settings: 0x 5
3 Switch Settings: 0x 5
4 Switch Settings: 0x 5
5 Switch Settings: 0x 5
6 Switch Settings: 0x 5
7 Switch Settings: 0x 5
8 Switch Settings: 0x 5
9 Switch Settings: 0x 5
10 Switch Settings: 0x 5
11 Switch Settings: 0x 5
12 Switch Settings: 0x 5
13 Switch Settings: 0x 15
14 Switch Settings: 0x 35
15 Switch Settings: 0x 135
16 Switch Settings: 0x1135
17 Switch Settings: 0x1135
18 Switch Settings: 0x1035
19 Switch Settings: 0x1035
Done
We measured the maximum achievable speed out of the GPIO while toggling or increment the output in an infinite while-loop to be abut 1 MHz. This is about 100x slower than the system clock. See the block design below which sends the output to JA[]. Note that XORing or negating the output variable, i, did not affect the measurement results. (The best results all were either 500 kHz or 1 MHz.)
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xgpio.h"
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define GPIO_OUTPUT_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
#define GPIO_BITWIDTH 8 /* This is the width of the GPIO */
/* The following constant is used to determine which channel of the GPIO is
* used if there are 2 channels supported in the GPIO. Must be either 1 or 2.
*/
#define OUTPUT_LED_CHANNEL 1 //in block design defined as GPIO_2
/************************** Variable Definitions **************************/
/*
* The following are declared globally so they are zeroed and so they are
* easily accessible from a debugger
*/
XGpio GpioOutput; /* The driver instance for GPIO Device configured as O/P */
/*****************************************************************************/
int main()
{
u8 i=0;
int Status;
init_platform();
xil_printf("Initialize\n\r");
/*
* Initialize the GPIO driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h
* also set its data direction
*/
Status = XGpio_Initialize(&GpioOutput, GPIO_OUTPUT_DEVICE_ID); //output
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/* Set the direction for all signals to be outputs */
XGpio_SetDataDirection(&GpioOutput, OUTPUT_LED_CHANNEL, 0x0);
xil_printf("Start\n\r");
while(1)
{
/* Set the GPIO outputs to counter */
XGpio_DiscreteWrite(&GpioOutput, OUTPUT_LED_CHANNEL, i++);
}
cleanup_platform();
return 0;
}
Channel 1 is JA[0] and channel 2 JA[1].