Tutorial 2 : Part 1 - "Hello World" using FPGAs

2.1 Introduction


It is customary to acquire a new FPGA development board or evaluation kit, try the accompanying demonstration programs, get bored with the accompanying demonstration programs and then wonder what to do next.

More often than not the newly acquired item is placed on a dust covered shelf and a mental note is made to do something commendable with the board sometime in the future. Unfortunately, for most of us, this mental note is registered in our hippocampus, but never recalled or executed.

As this has happened to us far too often we have decided to take action to avoid it happening again. Hence, we have come up with what we think is, if we can say so ourselves, a good idea for a series of tutorials, which we could use to put each new development board or kit we purchase immediately through its paces in an interesting way.

This second set of tutorials, in the Tutorial Series, has been written to kick start our new found philosophy of developing a universal, electronic "Hello World" program.  The program could be used to quickly evaluate a FPGA development board. Also, it could allow the user to quickly become familiar with any associated development tools used to generate the program, such as Altera's Quartus, Microsemi's Libero and Xilinx's ISE.

In this first part of the series we shall introduce the specification, implementation and informal verification aspects of the design. In subsequent parts of the series we will implement the design on the various boards in our possession, including the DE0-Nano Development Board, the Igloo2 Evaluation Kit, the Bemicro CV,  Arrow's Sockit and the Cyclone V GX Starter Kit, amongst others.

In future parts in the series we will investigate more advanced concepts of the "Hello World" program. The advanced concepts will introduce using the embedded Phase Lock Loop (PLL), developing requirement specifications, formal verification and hardware debugging.

Although this particular exercise may appear quite trivial it provides a reasonable platform for purchasers of a FPGA development kit to become immediately acquainted with their new hardware and the tools used to develop for it. In future tutorials, in the series, we plan to develop programs to exercise a FPGA's Digital Signal Processing (DSP) blocks, embedded memory, SERDES, as well as address the issues of fixed and floating-point arithmetic.

2.2 Design Specification

The concept of a "Hello World" program in VHDL has been usurped from the software world where the first thing that one is taught, when a new software programming language is introduced, is to write a program that outputs the words "Hello World". Likewise, we envision a similar concept in the Hardware Description Language (HDL) world where a standard "Hello World" program could be used to introduce a new piece of kit. However, as usual, to make our programming cauldron more interesting (and complicated) we have added more to the mix than is necessary!

So, in this tutorial series, the sting in the tail is that "Hello World" should be flashed on any available LED on the development board using Morse code. With this vital piece of information we are in a position to write the project's objectives or specifications.


Figure 1: FPGA Development Board or Evaluation Kit components required to implement the "Hello World" program in Morse code.

In this design logic in a FPGA should be used to display the letters that form the words "Hello World" on a LED, Item (3) in Figure 1, using Morse code. The  FPGA's internal logic should be synchronised by, typically, using an external clock oscillator, Item (1). The logic used, to display the Morse code representation of each letter, should be reset asynchronously using an external reset switch, Item (2).

The letters, used to form the words "Hello World" should be displayed according to the design rules listed, in Table 2.1, below. The Table lists the letters in each word alongside their corresponding Morse and binary codes. A discussion on how the Morse code has been represented digitally, as binary codes, is presented in the sections below.

Table 2.1: The Morse and binary codes of the letters that make "Hello World"
Letter Morse Code Binary Codes
H dot dot dot dot 1 0 1 0 1 0 1 0 0 0
E dot 1 0 0 0
L dot dash dot dot 1 0 1 1 1 0 1 0 1 0 0 0
L dot dash dot dot 1 0 1 1 1 0 1 0 1 0 0 0
O dash dash dash 1 1 1 0 1 1 1 0 1 1 1 0 0 0
SPACE  0 0 0 0 0 0 0
W dot dash dash 1 0 1 1 1 0 1 1 1 0 0 0
O dash dash dash 1 1 1 0 1 1 1 0 1 1 1 0 0 0
R dot dash dot 1 0 1 1 1 0 1 0 0 0
L dot dash dot dot 1 0 1 1 1 0 1 0 1 0 0 0
D dash dot dot 1 1 1 0 1 0 1 0 0 0
SPACE  0 0 0 0 0 0 0

A dot should be represented by the LED being ON for 1 second and OFF for 1 second. Likewise,  since the ON duration of a dash should be three times as long as a dot, a dash should be represented by the LED being ON for 3 seconds and OFF for a second. For example, the letter H, which is dot dot dot dot in Morse code, is represented by the binary code 1 0 1 0 1 0 1 0. Note that each letter is followed by a pause or the LED being OFF for 2 seconds. Hence, each letter is appended with two consecutive zeroes.

Likewise, the SPACE between words should represented by 7 consecutive 0's or the LED being OFF for seven seconds. The words "Hello World" should be displayed cyclically (e.g ... Hello World Hello World ... ). Hence, the SPACE character is also used to separate the d at the end of the word "World" from the H at the beginning of the word "Hello".

2.3 Pseudo-Schematic Notation

In this section we introduce our symbolic notation, which we sometimes use to describe our digital logic design, as those familiar with our articles know. Throughout this document, where possible, pseudo-schematic notation, if there is such a thing, will be used. If the reader sees the symbol, in the Figure 2, below it would not be unreasonable to expect the reader to interpret it in the following way:

The symbol in Figure 3 could be that of an entity (VHDL) or module (Verilog) known as Register32 (1). It has a 32-bit input signal known as Din (2) and a 1-bit input signal known as Enable (3), which is asserted when set to a logic level of '1'. The value on the input, Din, is transferred to the 32-bit output signal Dout (5), on the rising edge of the Clock (4) signal. The register can be set asynchronously by asserting the Reset_n (6), that is, the Reset_n signal is active low.


Figure 2: The pseudo-symbolic schematic representation of a 32-bit register and the corresponding VHDL code.

2.4 Conceptual Design and Implementation

According to the design specifications "Hello "World" should be displayed on a LED using dots and dashes, which should last for a multiple of 1 second. In the case of a dot it should last for a multiple of 1 and 3 in the case of a dash. This suggests that we should develop an entity or module that generates a unit of time relative to 1 second. 

In our implementation we decided to develop a pulse generator that should generate a pulse once per second. The duration of the pulse should be for 1 clock cycle. Dots and dashes are then be represented by a multiple of the time duration between pulses. A VHDL implementation of our pulse generator can be seen in the code listing, in Figure 3, below.


Figure 3: VHDL implementation of the Pulse Generator process.

In fact one implementation of the digital "Hello World" design, as seen in the block diagram, in Figure 4, below not only requires the creation of a pulse generator, but a shift register too. The shift register should operate as a rotation register. Both components should be synchronised to an external clock oscillator. Also, they should both be connected to an external reset switch that allows VHDL entities, or Verilog modules, to be reset asynchronously.


Figure 4: Conceptual Design of the "Hello World" program. The Pulse Generator and Shift Register are implemented as synchronised entities, or modules, in the FPGA. Synchronisation is achieved with the use of an external clock oscillator. A reset switch is used to asynchronously reset the logic to a known initial state.

The shift register should load the binary equivalent of "Hello World" when the FPGA is asynchronously reset or on power-up. When the shifter register is enabled, a bit should be rotated out of the Most Significant Bit (MSB) position. This bit should be used to turn the LED ON or OFF. If the bit is a '1' it should turn the LED ON. If it is a '0' it should turn the LED OFF. The bit shifted out of the register should be rotated back into the shift register in the register's Least Significant Bit (LSB) position.


Figure 5: VHDL implementation of the Shift Register process.

When this design schema is implemented the simulation results can be seen in Figure 6 below. In the Figure each letter can be seen to be followed by a 2 second pause, that is two zeroes,  as specified in our design rules listed in Table 2.1.  Also, each word is followed by a SPACE, which is represented by seven second pause.


Figure 6: Simulation of the implementation of the "Hello World" architecture described above. The simulation has been performed using Modelsim

2.5 Simulation, Informal Verification and Results

To verify the correct operation of the design a testbench has been created and the design has been simulated using SystemC. The testbench could be considered to consist of two parts. The first part consists of functions that model driving or stimulus functions. These are the functions that model the external clock oscillator and the reset button. They are denoted as the clock_asign() and the reset_generator() respectively, in Figure 7, below. In this particular simulation a clock frequency of 50MHz has been used, as this is a common clock frequency provided on many FPGA development board.

The second part comprises the checker functions check pulse, chk_pulse() and check morse code chk_morse_code(). The reset_generator() has been implemented with the help of SystemC's reset_deactivation_event, which has been used to asserted the reset signal for the initial 200ns after the simulation start. More detail of how the clock and reset functions have been written in SystemC will be provided in an upcoming series, which will describe the design's formal verification.


Figure 7: Block diagram of the VHDL entities and SystemC functions used to simulate and verify the design. The Pulse Generator and Shift Register VHDL entities are in blue, while the functions used to simulate the clock, clock_assign or Item (1) and the reset switch, reset_generator or Item (2) are in brown. The checker functions and the reporting function are in grey.

If we look at the design specifications they include two very interesting statements, which have been extracted and repeated, in Table 2.2, below for clarity. These two statements can be verified by the two corresponding checker functions also listed in the Table and shown in Figure 7, as items chk_pulse(), Item (3) and chk_morse_code(), Item (4).

Table 2.2: Design Specification Requirements and their corresponding verification functions.
Specification Function
"Hello World" should be flashed on any available LED on the development board in Morse code. chk_morse_code()
 Hence, we should develop a pulse generator that generates a pulse once per second. chk_pulse()

 The check pulse function, chk_pulse(), in our SystemC testbench is used to verify that the pulse signal is asserted once per second. The code used to implement this function is listed, in Figure 8, below. The function is used to check the number of clock cycles between each assertion of the pulse signal. For instance when a 50MHz clock oscillator is used, to synchronise the system's logic, there should be 50 million clock edges between each pulse's assertion.

In the code listing, below, with each positive edge of the clock when the pulse signal is not asserted the number of clock edges between pulses is counted. On each assertion of the pulse signal an error is reported if the number of clock edges counted between assertions is not equal to the number expected.


Figure 8: SystemC code listing for the function check pulse, chk_pulse(), which checks that the pulse signal is asserted once per second.

The other checker function, which checks the validity of the Morse code, is the chk_morse_code(). The SystemC code that implements this function can be seen in the code listing, in Figure 9, below.  On each positive clock edge and when a new bit of data is shifted out of the rotation register, to the LED, the function undergoes the following set of events to perform the check.

Firstly, the value of the bit shifted out of the register is placed in a queue. Secondly, the queue is checked for the pattern "0001", which indicates that the first bit of a new character has been received. The function validate_morse_code() is then called to search the queue for any of the letters 'H', 'E', 'L', 'O', 'W', 'R', 'D'. If one of these letters is not found an error is reported.

Finally, if one of the letters is found but it is not the next letter in the sequence of letters that make up the words "Hello World" an error is also reported. Using this approach we have been able to successfully implement and test the design, eliminating any errors during the process.


Figure 9: SystemC code listing for the function check morse code, chk_morse_code(), which validates the sequence of characters "H E L L O  W O R L D".

All errors are reported in an output file, which we have temporarily named validation_report.txt.

2.6 Conclusion

This is a fun design that, as we will see in the next part of the series, simply requires the new owner of a development board or evaluation kit to identify and connect to a few external components on the board. In this example the external components are a LED, reset switch and clock oscillator.  This part of the series has also seen our first foray into using  SystemC to verify a HDL design.  As the series progresses we shall delve deeper into using SystemC and demonstrate how some of its more advanced concepts can help ease the verification of HDL entities and modules. 

In the next part of the series we will continue with the electronic "Hello World" Morse code program by demonstrating an actual hardware implementation on one of our dust covered FPGA development boards. Also, this forth coming second part of the series will demonstrate the demands and challenges the new owner of a board or kit faces in getting to grips with the FPGA vendor's development tools.

Go to comments start