Seven Segment Display

Overview and use of Blackboard's seven-segment display


A seven-segment display is built from individual LED’s arranged in a figure-8 pattern as shown. Any LED/segment can be individually illuminated, so any one of 128 different patterns can be shown. The figure below shows segment illumination patterns for decimal and hexadecimal digits.

Figure 1. Seven segment display illuminatation patterns
Figure 1. Seven segment display illuminatation patterns

Blackboard’s 4-digit seven-segment display uses a common anode configuration with all signals active low. The four common anode signals (one per digit) turn on the four digits, and the seven cathode signals turn on individual segments. Each segment LED can consume up to 4mA (well within the current-sourcing abilities of the FPGA pins), so the LED cathodes are tied directly to the FPGA pins. If all segment LEDs are driven simultaneously, up to 28mA can flow through the anode signal, and that is more current than individual FPGA pins can deliver. The anode signals are driven from transistors that can provide the needed current (and the transistors are driven from the FPGA pins).

To drive a single digit, the corresponding anode signal can be driven (low), and then individual cathodes can be driven to turn on individual segments. To drive all digits to create a four-digit display, a scanning display controller is needed. To learn more about seven segment displays, including an example design of a seven-segment controller, see the “Seven segment controller” document: Seven segment display

Figure 1. Top level IP diagram
Figure 1. Top level IP diagram

Seven Segment controller FPGA IP

The “Blackboard_Standard_Config” file includes custom IP for a seven segment controller. The controller can operate in one of two modes. In default mode, the controller receives BCD/Hex data and passes it though a seven-segment decoder before driving the cathode signals (when using BCD data, codes 1010 – 1111 will be displayed as Hex digits A, b, C d, E, F). In custom mode, the seven-bit code is passed directly to the cathodes, so that any pattern can be displayed.

Figure 1. Top level IP diagram
Figure 1. Top level IP diagram

SVN_SEG_CNTL (0x43C10000): Seven-segment display configuration register

EN: Enable (‘1’ to enable, ‘0’ to disable)
M: Mode (‘0’ for default mode/BCD data, ‘1’ for custom mode/individual segment data)

SVN_SEG_DATA (0x43C10004 - 0x43C10010): Display data regsiter. Each byte defines one character - the lower 4 bits are BCD/hex data, the next 3 bits are direct-segment drive data (Mode bit = 1), and bit7 is the decimal point.

BCD_N DATA: Four-bit BCD/Hex data that is sent to the decoder and then drives display
BIN_N_Data: Together with lower four BCD data bits, provides raw segement data that directly drives cathodes

In custom mode each 8-bit field in the data register directly drives the cathodes for each digit. A ‘0’ bit will illuminate the segment, and a ‘1’ bit will turn off the segment. The highest bit in each byte-wide field controls that digit’s decimal point, the next bit controls segment A, followed by segment B, so so.

Code Example

The code below shows a program that uses both modes of the 7-segment controller. The first example shows how to display a numeric value on the display, and the second shows how to display custom characters.

First Macros are defined for easy acess to the display registers:

//7-seg control register
#define SEG_CTL *((uint32_t *) 0x43c10000)

//7-seg digit data register
#define SEG_DATA *((uint32_t *) 0x43C10004)

//7-seg decimal point data reg
#define SEG_DP *((uint32_t *) 0x43C10014)
// Displays the passed 16-bit value on the 7-seg in hexidecimal
void display_num(uint16_t n)
	int i=0;
	uint32_t temp=0;

	//set display enabled in standard (hex) mode
	SEG_CTL = 1;

		temp |= (n&0xF)<<(i*8); //put digit data in appropriate bitfield
		n>>=4; //shift out least significant digit

	//disable all decimal points

	SEG_DATA = temp;


The Following function uses ‘custom mode’ display the digits ‘r’, ‘E’, ‘A’, and ‘L’. The comments before the function definition explain which values were needed to display the digits.

#include <stdint.h>

Segments Illuminated: E,G
Value to write to Data register: 0b0101111 == 0x2F


Segments Illuminated: A,D,E,F,G
Value to write to Data register: 0b0000110 == 6

| |

Segments Illuminated: A,B,C,E,F,G
Value to write to Data register: 0b0001000 == 8

Segments Illuminated: D,E,F
Value to write to Data register: 0b1000111 == 0x47


#define R_DIG 0x2F
#define E_DIG 6
#define A_DIG 8
#define L_DIG 0x47

//Displays "rEAL" on the 7-seg disp using the numbers calculated above
void display_REAL(void)
	//temporary variable used so we only write to the seg data_reg once
	uint32_t temp;
	SEG_CTL = 3; //enable display in custom mode

	//clear data in register
	temp = 0;

	//write digit data to corresponding bitfields
	temp |= R_DIG<<24; //bits 30-24
	temp |= E_DIG<<16; //bits 22-16
	temp |= A_DIG<<8; //bits 14-8
	temp |= L_DIG; //bits 6-0

	//disable all decimal points

	//write to segment data register
	SEG_DATA = temp;

The program uses these two functions and buttons and switches to display values on the 7-segment display

#define SW_DATA		*((uint32_t *)0x41220000)
#define BTN_DATA	*((uint32_t *)0x41200000)

int main(void)

		if(BTN_DATA&1) //if first button is pressed
			display_REAL(); //display "rEAL"
			display_num(SW_DATA&0xFFF); //display Switch value

	return 1;