Welcome to this archive! It documents the development of an IP block designed to control communication with the Digilent OLEDrgb PMOD. This project allows you to interface with the PMOD and manage the display using an FPGA or compatible device.
In this repository, you'll find all the necessary files required to recreate the results, including the hardware design, configuration files, and any supporting scripts. There's also a brief explanation of how the project works, step-by-step instructions on setting it up, and how to execute it on your own system.
Whether you're looking to understand the design process or replicate the setup for your own projects, this archive serves as a helpful reference. Feel free to explore and reach out if you have any questions or feedback!
In this project, we set out to explore the development of an IP block, focusing not only on defining the hardware but also on creating the necessary drivers and documentation that would accompany it. This gave us an opportunity to dive deep into the world of hardware and software co-design, exploring how both domains can come together to create a seamless, functional system.
Our main objective was to replicate the functionality of the IP block developed by Digilent, which serves to manage communication with their OLEDrgb PMOD. However, we wanted to take a hands-on approach by rebuilding everything from scratch. This meant we didn’t rely on pre-built IPs or libraries, but instead, we described the hardware entirely in VHDL, creating a custom solution tailored to our needs.
Throughout the project, we encountered challenges that pushed us to think critically about both the hardware design and software integration.
To sum up, this project was a great learning experience, as we challenged ourselves to design and deploy an IP block from the ground up, managing communication with a PMOD without relying on pre-existing solutions. It was a valuable exploration of the intersection between hardware design and software control, and we're excited to share the results with the community.
As you can see, the system is neatly encapsulated inside an IP block, making it easy to reuse across different projects. This modular approach allowed us to build a simple system capable of displaying an example image—both in a bare-metal environment and under Embedded Linux.
To make this possible, we developed a solution that communicates with the chipset on the board via SPI. On top of that, we created some basic drivers that handle core routines like powering the display on and off, and sending both commands and data.
While the system is simple, it lays the groundwork for more advanced applications and demonstrates how a clean hardware/software co-design can lead to a flexible and reusable IP block.
Note
For the driver documentation, we used Doxygen-style notation. If you're working within the Vitis environment, you can easily view and navigate the documentation directly there.
Follow these steps to get the IP block up and running in your Vivado project:
- Download the
Display_OLEDrgb
folder from this repository. - Create a new project, and add the IP block to your local IP repository.
- Set up a basic hardware system that includes the necessary components.
Note
Make sure to set the SPI clock to 50 MHz, as specified in the display's datasheet. In the provided examples, I’ve created a dedicated clock specifically for this purpose.
Once the hardware platform is set up, you're all set to start building your application on top of it!
Important
Due to a known bug in Vivado 2023.1, the generated Makefiles for the drivers can be IDE-specific. If you notice that the drivers are missing or not compiling correctly, take a look at the Makefiles and adjust them to match your specific environment or version. A quick patch there should get things working again.
In this section, I try to explain some key concepts in more detail—either because I found them particularly interesting or because they might help you in your own project.
To group the main output signals of the IP, I reused an interface originally defined by Digilent. This makes things cleaner and more modular.
If you'd like to create your own custom interfaces and organize them into a bus, you can use the files in Display_OLEDrgb/if/dummy_pmod_v1_0
as a starting point. They're quite easy to adapt to your own project—just tweak them to fit your needs.
Once you've defined your custom interface and added it to your IP repository (as described in the installation section), you're ready to connect your signals to the bus. You can see how this is done in the Ports and Interface step—just take a look at the example images below for guidance through the process.
Note
For more detailed information on developing custom IP blocks, you can refer to the official AMD manual — [UG1118] Creating and Packaging Custom IP. It’s a great resource if you want to dive deeper into the process.
If you're looking for technical details about the PMOD device, I recommend checking out their official website. That said, I’ve already gathered the most relevant documents for this project and included them in the ./Doc
folder for your convenience.
To better understand how the hardware connects and interacts with the software, I highly recommend reading A Practical Introduction to Hardware/Software Codesign. It’s a solid resource for diving into the co-design approach.
And if you're looking for a good foundation in digital systems, definitely check out Digital Design and Computer Architecture, RISC-V Edition—it's an excellent book for beginners and beyond.
If you're wondering what's actually going on inside the IP block, feel free to take a look at the VHDL files on ./Display_OLEDrgb_1_0/src
—I’ve tried to add comments throughout to make each component easier to understand. I’ve also followed the design idioms and practices described in Digital Design and Computer Architecture, RISC-V Edition to keep things structured and clear.
At a high level, here’s what you’ll find inside:
- A Mealy state machine handling SPI communication
- Additional combinational circuits
- Mailbox logic, including:
- Registers
- A Mealy state machine
- Additional logic to support the AXI Lite interface
Note
If you're planning to build a similar project, I highly recommend sketching out the circuit first. Drawing the system really helped me visualize the architecture and make better design decisions.