For this project, we created a variable metronome which displays the rate of ticking on the built in Basys3 LED ports. The tempo will be presented on the built in 7-segment display of the board, and can be adjusted via inputting a binary representation of the desired tempo on the built in switches of the board; for instance, if a tempo of 8 is desired, the 4th switch from the right will be toggled. As we will only be using 8 switches for our input, a maximum tempo of 255 will be possible. Additionally, a switch will be included to change the time signature of the metronome, or otherwise change the amount of beats before the metronome repeats its cycle.
- Basys3 FPGA Board
- HDL (VHDL in our example) to implement on the FPGA
For reference, our main code and the sub module code that it uses can be found below.
Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.
Step 1: Understanding the Framework
As all of the construction of this project is performed through VHDL code, an understanding of the hierarchy is needed to understand the project. As shown by the following figure, the main module of the file is to be divided into the following sub components:
A sub module to convert a hexadecimal input (originally intended for the 7-segment display) to a decimal output
A sub module to control the timing and response of the LEDs in accordance to the inputted tempo
A sub module generating signals to be sent to the 7-segment display in order to show the inputted tempo.
Each Sub module may have more modules within it, which will be addressed later.
Overall, the system will be largely controlled by the clock signal of the board, which is 1 MHz: This will be an important number for calculations later on. Eight switch inputs will be used, and the system will in the end output a 16 bit output to control the LEDS, a 7-bit output to control the 7-segment display, and a 4-bit output to enable or disable digits on the display.
Step 2: Creating Code to Convert Hexadecimal to Decimal.
A full explanation of the algorithm used to convert hexadecimal to decimal can be found here:
Essentially, sub modules are used to perform addition on each digit place value. In the algorithm, the binary number shifted left one place value, then conditionally adds 3 to different bit slices of the binary number. This process is then repeated 8 times on the same number. The resulting product is the desired decimal number, where each group of four bits represent a single digit of the decimal number. The module used in our code, ConvertHextoDec, performs the sequential shifting of the number 8 times using the sub module Add3_3times to perform the conditional addition on each bit slice. A graphic of the operation, taken from the above link, is included in the attachments.
To reduce redundant code each sub module of Add3_3times breaks the 12 bit input into 4 bit sections that is then routed to the sub module Add3 which will add binary value of 3 “0011” to the 4 bit input if the value is greater than 5, ”1001”.
To perform the addition of two 4 bit values we used a RCA designed using the module Full_Adder and its sub module SubFull_Adder to create a ripple carry adder of 4 bit inputs.
The resulting hierarchy of sub modules can be found in the attatched photos.
Step 3: Setting Up the LEDs
Another part of our project is the Module LEDFlip. This takes in the binary number of what the user selected on the BASYS 3 switches, the switch controlling what time signature the user wants, and a clock pulse. From the binary value combined with a long case statement calculates the necessary delay in between each beat of the metronome. We used a big case statement because we initially tried to make a circuit do division of the BPM (beat per minute) and and a constant value with for loops however the code would not synthesis because the high number of for loops required Vivado got stuck trying to optimize our code. This is why we have 127 case statements. With the default value of the case statement disabling the metronome when the user sets a BPM of zero.
Next there is a process block with the input TICK (a clock pulse) on the sensitivity list with an internal variable counting the number of rising edge clock pulses.There is an if statement checking whether the metronome is enabled or not so we don't change the leds when it should be off. When this variable is greater than the desired delay it increments another internal variable representing each state the led pattern is at. Depending on what time signature the user wants (between 4/4 or 7/4) the leds have a different pattern. The pattern on 4/4 is start at the far right led and turn on the led to its left until 4 leds have been toggled then invert the far right 8 leds except for the 4th led and then count down with the inverted led signifying what is the current beat led is. For 7/4 the pattern is the same except the the eds count up to 7 instead of 4. Also the leds on the far left of the board signify what time signature the user selected. The far left 7 leds are on when 7/4 time is activated or 4 far left leds are one when in 4/4 time.
The leds are inverted using a 16 bit long signal vector with a single bit signal signifying inverting all the leds or not. The pattern for each time signature on the leds is done in a case statement for each time signature changing on what the internal state of the variable “count” that is incremented each time the desired amount of delay time has been reached for the selected BPM. There are more states in 7/4 time for the led pattern so “count” is reset to 0 at different values depending on what time signature it is running.
The signal “sLED” is then transfer to the output “LED” that is then routed to the BASYS 3 board through the man code's LED output.
Step 4: Success
Your Basys3 board should now function as demonstrated in the video.