PMOD General-Purpose-Input-Output (GPIO)

Message Passing

Laboratory 4

Laboratory Report 4

Course: EE 3420: Microprocessors

Section: L01

Submitted by: Ibrahima Balde

Email: bah.ibra1222@gmail.com

Date: March 27th, 2025

Abstract

This laboratory focused on inter-board communication using GPIO over the Blackboard FPGA's PMOD interface. The objective was to simulate traffic light behavior shared across two boards using message passing through GPIO signals. A switch determined whether the board acted as the North/South (N/S) controller or East/West (E/W) follower. The project involved configuring PMOD GPIO pins as outputs and inputs, establishing a signaling protocol between the boards, and synchronizing light sequences. This lab reinforced low-level hardware control, timing synchronization, and communication protocol design between microprocessors.

List of Symbols and Abbreviations

Symbol/Abbreviation Description
GPIO General Purpose Input Output
FPGA Field Programmable Gate Array
PMOD Peripheral Module Interface
NS North/South Board (Controller)
EW East/West Board (Follower)

Table of Contents

Introduction

This lab introduced GPIO-based message passing between two Blackboard FPGA systems. Using a simple signaling protocol, one board (N/S) controlled the traffic light sequence while the other board (E/W) mirrored its state based on received signals. Synchronization was achieved through memory-mapped register control of PMOD GPIO pins. The goal was to simulate a coordinated traffic light system across two processors.

Hardware and Pin Configuration

The hardware used for this lab includes the blackboard development board, PMODC GPIO pins, tricolor LEDS, PMOD communication wiring, and switches. The components are connected and controlled using memory-mapped registers.

PMODC GPIO Pins Used:

  • Pin 2 (Bit 16): Blue
  • Pin 3 (Bit 17): Red
  • Pin 4 (Bit 18): Green

LED Colors:

  • Red: Bit 17 (0x20000)
  • Green: Bit 18 (0x40000)
  • Yellow: Bits 17 | 18 (0x60000)

PMOD Communication Wiring:

  • PMODC[0:3] of board A connected to PMODC[4:7] of board B (per instructions)
  • GND connected between boards

Switch (SW0):

  • If high (1), board acts as NS (controller)
  • If low (0), board acts as EW (follower)

Software Implementation

Implemented in C using memory-mapped registers for both input and output control. The software determines the board's role using Switch_Data, sets GPIO directions accordingly, and performs timed light state changes.

Memory-Mapped Register Control

The sequence implemented:

  1. Both boards start RED (0x20000).
  2. NS turns GREEN, EW remains RED.
  3. NS turns YELLOW, EW remains RED.
  4. NS turns RED, EW remains RED.
  5. EW turns GREEN, NS remains RED.
  6. EW turns YELLOW, NS remains RED.
  7. EW turns RED, NS remains RED.
  8. Loop repeats.

Results and Observations

Challenges Encountered:

  • Forgetting to set enable bits caused LEDs not to light up.
  • Without initial delay or sync, the boards could get out of phase; fixed by using consistent sleep() values and starting with RED on both.

Conclusion

This lab demonstrated the fundamentals of inter-processor communication using GPIO. The traffic light simulation required precise control of memory-mapped registers, accurate timing, and synchronization between boards. The design showcased how GPIO can be used for simple and effective message passing in multi-processor systems. This experiment laid a foundation for more advanced communication strategies in embedded systems.

Appendices

Submitted Code Files:

TrafficLight.c

Lab 4 Code

/*
traffic light
*/
#include <unistd.h>
#include <stdint.h>
#define Switch_Data     *((uint32_t *)0x41220000)  // switches are the lower 12 bits

// Defines for Bank 0 (Bank 0 controal on-board stuff)
#define Bank0_Dir     	*((uint32_t *)0xE000A204)            //set each pin as input (0) or output(1)
#define Bank0_Enable    *((uint32_t *)0xE000A208)           // Enable output driver (has to be 1 to drive pin)
#define bank0_Input     *((uint32_t *)0xE000A060)          //Read current pin state
#define Bank0_Output    *((uint32_t *)0xE000A040)         //write output vaues

// Defines for Bank 2 (Bank 2 is connted to PMOD headers pin connector used to connect boards so they can talk to each other)
#define Bank2_Dir     	*((uint32_t *)0xE000A284)            //set each pin as input (0) or output(1)
#define Bank2_Enable    *((uint32_t *)0xE000A288)           // Enable output driver (has to be 1 to drive pin)
#define Bank2_Input     *((uint32_t *)0xE000A068)          //Read current pin state
#define Bank2_Output     *((uint32_t *)0xE000A048)        //write output vaues

/*
PMODC pin 1  0x8000
PMODC pin 2  0x10000
PMODC pin 3  0x20000
PMODC pin 4  0x40000
PMODC pin 7  0x80000
PMODC pin 8  0x100000
PMODC pin 9  0x200000
PMODC pin 10 0x400000

***Color Coding For LEDS***
Blue LED --> 0x10000
Red LED --> 0x20000
Green LED --> 0x40000
Yellow LED -->   0x20000 | 0x40000   (Green LED | RED LED)
*/

int main(void)
    {
       uint32_t signal;
       
       
        Bank0_Dir = 0x70000; //0x 70000 = 0b 0111 0000 0000 0000 0000 set bit/pins 16, 17, 18 to an output I want to drive this bit myself
        Bank0_Enable = 0x70000; // enables us to drive bits we just set to outputs

        Bank2_Dir = 0x70000; //0x 70000 = 0b 0111 0000 0000 0000 0000 set bit/pins 16, 17, 18 to an output I want to drive this bit myself
        Bank2_Enable = 0x70000; // enables us to drive bits we just set to outputs

        while(1)
            {

                uint32_t tempSwitch = Switch_Data;

                if((tempSwitch &= 0x1 ))
                    {

                        // turns master red for 2 seconds
                        Bank0_Output = 0x20000;
                        sleep(2);

                        //turns master green for two seconds and signals to slave stay red
                        Bank0_Output = 0x40000;
                        Bank2_Output = 0x20000;
                        sleep(2);

                        //turns master yellow for one second and signals to slave stay red
                        Bank0_Output =  0x20000 | 0x40000;
                        Bank2_Output = 0x20000;
                        sleep(1);

                        //turns master red for two seconds and signals to slave to stay red
                        Bank0_Output = 0x20000;
                        Bank2_Output = 0x20000;
                        sleep(2);

                        //keeps master red for two seconds and signals to turn green
                        Bank0_Output = 0x20000;
                        Bank2_Output = 0x40000;
                        sleep(2);

                        //keeps master red for two seconds and signals slave to turn yellow
                        Bank0_Output = 0x20000;
                        Bank2_Output = 0x20000 | 0x40000;
                        sleep(2);

                        //keeps master red for two seconds and signals slave to turn red
                        Bank0_Output = 0x20000;
                        Bank2_Output = 0x20000;
                        sleep(2);

                    }
                else
                    {
                        signal = Bank2_Input;

                        // ANDS the signal its getting from the master with 0x70000 (0x70000 = 0b 0111 0000 0000 0000 0000) to see what color it needs to be
                        if((signal & 0x700000) == 0x20000)
                            {
                                Bank0_Dir = 0x20000 ;
                                Bank0_Enable = 0x20000;
                                Bank0_Output = 0x20000;
                            }

                        // ANDS the signal its getting from the master with 0x70000 (0x70000 = 0b 0111 0000 0000 0000 0000) to see what color it needs to be
                        else if((signal & (0x700000)) == 0x40000)
                            {
                                Bank0_Dir = 0x40000 ;
                                Bank0_Enable = 0x40000;
                                Bank0_Output = 0x40000;
                            }

                        // ANDS the signal its getting from the master with 0x70000 (0x70000 = 0b 0111 0000 0000 0000 0000) to see what color it needs to be
                        else if((signal & (0x700000)) ==  (0x20000 | 0x40000))
                            {
                                Bank0_Dir = 0x20000 | 0x40000 ;
                                Bank0_Enable = 0x20000 | 0x40000;
                                Bank0_Output = 0x20000 | 0x40000;
                            }

                        // ANDS the signal its getting from the master with 0x70000 (0x70000 = 0b 0111 0000 0000 0000 0000) to see what color it needs to be
                        else
                            {
                                Bank0_Dir = 0x20000 ;
                                Bank0_Enable = 0x20000;
                                Bank0_Output = 0x20000;
                            }
                    }
            }

        return 1;
    }

References:

Lab Instructions

Background and Related Materials

  • Message passing between microcontrollers is an essential form of communication. Systems consisting of multiple processors can require a method to synchronize the two processors. The synchronization can occur through hardware or software. Utilizing the GPIO ports on a processor to send a flag or a message from one processor to the other is a less complicated design than creating dual port memory locations where both processors can read and write the same physical memory. This laboratory leverages what you have learned in the previous labs.

Laboratory Assignment – General Description

In this laboratory you will be using two microprocessors cooperating to create a simulation of a message being passed between the microprocessors.

  1. Blackboard PMODC0-3 will be setup as outputs and connected to the opposite board PMODC bits 4-7.
  2. The team needs to agree on the communications protocol. For example, what value sent across the link = what color. I.E. send a 1 to slave turns on red, send a 0 turns all off. The sequence and values you decide need to be written in your report.
  3. Set up the PMOD GPIO, to set PMODC [0:3] to be outputs.
  4. One board will be N/S the other one E/W. If SW0 is a 1 than the board is N/S else it is E/W
  5. The E/W receives a value to change the lights the N/S sends it. The labs partners must demonstrate being both the N/S and the E/W.
  6. At time 0 LD12 is red on both boards.
  7. Delay 2 seconds N/S turns green, and E/W remains red.
  8. Delay 2 Second N/S turns yellow and E/W remains red.
  9. Delay 1 second N/S turns red and E/W remains red
  10. Delay 2 seconds E/W turns green, and N/S remains red.
  11. Delay 2 Second E/W turns yellow and N/S remains red.
  12. Delay 1 second E/W turns red and N/S remains red
  13. Repeat this loop.