Kaloyan’s Status Report for 4/25

This week, I worked on adding some more features to the VGA display, finishing the debugging for polyphony, and looking into a basic LFO implementation.

For the VGA display, I’m working on creating a live oscilloscope, that will be reactive to the current note + effects the user is utilizing. However, this is adding additional complexity to the VGA pipeline: since the oscilloscope operates based on buffers of audio data being captured, it causes the VGA output to be delayed by one clock cycle. Although the trigger point detection and actual audio capture can be hidden by the wait times for VGA sync, the actual readout of BRAM cannot. I also plan on adding something to show the current drum pattern.

The polyphony debugging ended up being much simpler than expected. The clock domain crossing I had previously accounted for (with the difference in clock speeds for the round robin-arbiter and actual audio generation) introduced a bug where the keypresses were not being detected properly. By removing this, the arbiter worked properly and 4-voice polyphony worked!

Finally, I began implementing a basic LFO. Since we already have the existing code for our actual audio generation, it was quite simple to port it over to the LFO. Fundamentally, we are still working with the same phase accumulators and shapes. The only difference is that the frequency is now much lower, and user controllable. I have not finished implementing this feature yet, but if it works well I can also see it being viable to have multiple. Our entire 4-voice audio generation logic was only utilizing 18% of logic and 2% of memory, meaning that should be able to be fine in terms of utilization.

Kaloyan’s Status Report for 4/18

This week, I spent time on developing the VGA display, choosing the buttons for the drum sequencer, and integrating 4-voice polyphony.

For the VGA, I was able to get an initial image running quite quickly. I followed some online blog posts and after a bug with forgetting to output a VGA clock, I managed to display a single line. I then worked on creating two modules, a static line module and a dynamic line module. I’m currently using a DSP approach (calculating the cross product between a pixel and an established line), but may switch to Bresenham’s algorithm which instead uses BRAM and precomputes all the plotted pixels without using DSPs. The static line is defined at compile time, meaning that the resource usage can be folded and done without using DSPs. Using this, I linked the values from the ADSR and created a small depiction of what the amplitude envelope looks like. The youtube video shows an example of it being adjusted using the knobs. Next, I’m going to work on displaying the drum sequencer and effects.

For the buttons, I researched different varieties. I wanted a good aesthetic for them, but also functional use. I ended up deciding to use buttons with LEDs on top to depict step pattern, an LED driver (to reduce engineering effort and controlling dimness), a perfboard, and some other materials. Once they come in, I’ll work on wiring them up and then connecting them to the VGA display.

For the remainder of my time, I worked on trying to get polyphony working. Unfortunately, I’m still debugging some weird sync issue. The clock crossing from the input domain (100 MHz) of the arbiter, which assigns key presses, to the actual audio domain (50MHz) may be causing some issue. Although multiple notes will play, their note value seems to change sporadically. I’ll keep debugging and will hopefully find the issue soon.

Throughout my time, I’ve had to learn various effective hardware algorithms/methods to efficiently implement my tasks. For example, the ADSR required careful analysis on whether to use DSP blocks or not. Since it works based on a sample tick enable, the latency to calculate the phase steps for attack, sustain, decay, and release can be hidden. This makes using the DSPs viable, since storing all the necessary LUTs in BRAM would consume too much memory. Another hardware algorithm involved the dynamic line drawing for VGA. As previously mentioned, it may be better to use Bresenham’s algorithm. For learning these methods, I have been using blog posts. I find that they go into tremendous, specific detail. Much of the time, its better than youtube videos because they cover much more ground. I find that the detailed content makes it easier to conceptualize and fully understand.

Kaloyan’s Status Report for 4/4

This week, I worked on prepping for our demo and getting started with some VGA code for giving the user a visual view of what’s going on.

My plan is to have the VGA show the live drum sequence, effects being used, filter shape, ADSR shape, and (hopefully) some representation of the audio output. I’ll use one of the monitors in HH to debug this. I am also looking into what screen to attach to the FPGA. This small screen will be directly integrated onto the synthesizer, and will provide a more minimal UI to the user for interfacing with the synth.

I’m also working on getting more drum samples onto the FPGA and figuring out an efficient way to route an ADSR to all of them. Unfortunately, I may just have to duplicate the ADSR module for every drum track. Without doing this, the user won’t have the full customization of the drums that I want to provide.

For testing, I’m planning on capturing the output from the ADSR using a testbench and then validating the output using C++. By just capturing the envelope values based on what I set to be the attack, decay, sustain, and release, I can compare the envelope’s value with what is expected. For the drums, I will capture the output and load it into Ableton. I’ll make sure that the BPM is correctly configured and then also test the output volume levels of the drum tracks. To make sure that the wavetable is outputting the correct tones and notes, I’ll capture the output and use fourier transform to decompose the frequencies and ensure they correspond to the correct note. For a quick check, I’m also going to just use a handheld tuner.

Kaloyan’s Status Report for 3/28

This week, I finished working on ADSR, saturator, and the initial drum machine RTL. I tested ADSR and the drum machine, but have not yet integrated saturator and tested it. By testing, I simply validated the audio output by ear to make sure it matches what I expect. Later, I am planning on using C++ testbenches to fully validate the ADSR output.

ADSR was difficult to implement, namely because I wanted to do the division in an efficient manner. Unfortunately, since decay is reliant on the sustain value chosen by the user, a 2D lookup table felt too memory-hungry to use. Instead, I opted for just using the division operator, and mapping it to DSP blocks. Since this is only done once (at the start of the keypress), I believe the latency is properly hidden. There was a glitch involving the timestep of the ADSR, which I fixed by using a 48KHz sample tick, rather than the FPGA clock itself.

The initial drum machine was not too hard to implement. I took some drum samples and wrote a python script to generate .mem files from them. These are then loaded into separate ROMs, which are read out from over the course of the sequence. The sequencer uses the switches and buttons on the DE10, and currently just plays the sample out completely without doing anything else. Next, I want to implement ADSR on the drums to give the user a more customized feel.

Videos of ADSR and drums:
ADSR

Drums

Team Status Report for 3/21

This week, we all came together to integrate our separate modules. The end result was creating a pseudo-keyboard using the FPGA switches, and being able to output various notes using the sine wavetable. All in all, we consider this a great success and we are still on track. The biggest risk we are looking at is demo day, and ensuring that we remain on schedule and can provide a good look into how our final product will look. Some issues may be difficulty with the MIDI interface, along with ensuring that our sound quality remains good.

Video of current stage: https://youtube.com/shorts/-aKYDpD8pd4?feature=share

Kaloyan’s Status Report for 3/21

This week, I worked with Jose and Misho to properly integrate all of our modules into a top-level design. By doing this, we were able to successfully output a sine wave playing at different frequencies, based on a simulated key press through the FPGA switches! The next steps on my end involve creating the ADSR envelope for the note amplitude. Once that’s done, I’ll talk with Misho about integrating it into his filter design. I also need to validate the note frequency (for now, we will hook up the FPGA to a speaker and then use a tuner app to validate the frequency of the outputted note) and integrate interpolation for the other waveforms (saw, square, triangle).

I have also started thinking about how to integrate the drum track into our design. Although the samples will be quite small in memory footprint, we want to support as many as possible. Thus, it may be necessary to use the SD card for extra memory and interface with the Arm core. The MVP for this should still be just using BRAM, but it’s possible that we can have a reach goal that involves using this more ambitious goal. Another question to consider is the input interface for the drums. I would love to have a nice, 3D printed design and chassis that we can interface with to give the user a more intuitive feel. However, we will see if we have enough time at the end of the project.

All in all, I am happy with the progress we have made and believe that we are on a good pace.

Kaloyan’s Status Report for 3/14

This week, I spent a large amount of time on the ethics assignment. This involved doing the required readings, along with answering the appropriate questions and then applying that same thinking to my own project. In addition to my work on the ethics assignment, I also worked more on the RTL for the wavetable. I began integrating the phase accumulator into the input to the wavetable, and worked on creating the proper look up table for matching MIDI input to the correct frequency addition when updating the phase accumulator. I then use this phase accumulator value to index into the wavetable and output the correct amplitude. I am also working with Joaco and Misho to integrate these separate modules and ensure that they are functioning properly together. To validate the wavetable output, I ran a verilog testbench which saved the output and then compared to the expected value for each note. We then began validating the output on the audio CODEC, but have not done significant analysis to ensure that it matches directly with the expected note frequency we are playing. For next week, I am going to work on validating the note output.

Kaloyan’s Status Report for 03/07

This week, I worked on developing the RTL for the ADSR and the wavetable sampling. I also worked on the design report, and thought through the implementation details for various subsystems in the RTL that I was working on. This involved the design of the ADSR RTL and FSM. Although it was simple, the design helped guide my implementation process.  I’ve attached a diagram of the FSM below, which I used when implementing my design.

These attack, decay, sustain, and release times will eventually be set by the user, and configured in order to provide a dynamic filter and amplitude response. Additionally, I worked on understanding BLEP (Band-Limited Step Functions) to correctly interpolate sounds when working with signals like square, saw, and triangle. The use of BLEP allows the sound to avoid infinite harmonics and harsh frequencies, creating a continuous change rather than a sudden discontinuous jump. Through this, we are able to preserve the harmonics of the sound while avoiding harsh frequencies, at the cost of minimal additional memory usage and simple digital logic.

Kaloyan’s Status Report for 02/21

This week, I worked on implementing the basic waveforms in RTL. This process involves describing the 4 basic waves we set out to provide to the user, sine, square, saw, and triangle, and then allowing the user to play these notes out through the MIDI keyboard. In order to do this, I am using a LUT for the sine wave values. I generated this LUT using python, and then stored the values in BRAM. Then, I use a phase accumulator to index into the LUT table and play out the corresponding amplitude for that phase index. For playing different frequencies (AKA pitches), we can vary how much we increment the phase in every clock cycle. I have implemented this partially in RTL, but am now planning on verifying it by capturing the output and then comparing it with the sine wave we would expect for a given note. The next step will be to try to play the audio out of the CODEC, to verify that the generation is happening smoothly. Additionally, I will also work on the square, saw, and triangle wave, which will need interpolation in order to properly play and avoid harsh aliasing errors.

Kaloyan’s Status Report for 02/14

This week I worked on determining our solution approach for how to represent the audio we will be processing.

One option is to make no noticeable change, and just treat every number as a standard int interpretation (similar to how something like C would do it). This is beneficial because of its simplicity, and will require fewer hardware resources, since all the arithmetic is already provided with FPGA primitives.

However, this may cause problems later down the line. Since our CODEC works from an I2S protocol with 24-bit precision, and it expects amplitudes in the form of -1 to 1, we would have to do some conversion at the end. Alternatively, we can adopt a fixed-point notation to represent this amplitude range. Namely, Q 1.23 provides one sign bit and 23 fractional bits, allowing us to represent the range of -1 to 1 nicely. However, this comes at the additional cost of extra hardware to instantiate the proper arithmetic. The engineering effort is relatively low, since there are already Verilog libraries for this kind of work, but the hardware utilization will still be higher.

Ultimately, we favored the Q1.23 form. I also worked on the block diagram for the design presentation, and am excited to start working on the RTL next week!