- Create a 256 * 8 bit rom.sv module with sinewave datapoints as its memory content.
- Create a sinegen.sv module which links the counter and rom together.
- Create a cpp testbench code to simulate the sinegen module on Vbduddy.
- Modify design to use Vbuddy knob to alter the frequency of the generated wave.
Initially, we are provided with the sinegen.py file which uses a simple for loop to generate 256 sinewave datapoints and writes it into sinerom.mem to be read from by the system verilog rom file. rom.sv is created by intialising the size of the the amount of memory and number of bits per memory address. It was interesting to learn how simple the syntax was for setting this up. Then, the SV code uses pseudo commands display UI when the rom has been created and then loads the datapoints from sinerom.mem into rom_array. Finally output of this module at each clock positive edge is the data stored within each address.
However, this address can't increment on its own hence a counter is needed to do this at each clock cycle. These two modules are linked together using singen.sv which simply acts as a communication point between the two modules. As shown below, each internal signal in counter is connected through to rom with one exception of using an extrenal signal "address" because rom.sv has no such signal name count.
Now, to actually simulate the sinwave on Vbduddy, we need to create a testbench file called sinegen_tb.cpp. Here are the lines we needed to change or add from standard code:
- Line 1: Including Vsinegen.h module so it can be used.
- Line 12: Assigning top to be Vsinegen and not some other function.
- Line 17: Storing the recorded data in a file named sinegen.vcd.
- Line 28: Initialising incr = 1 which determines in what jumps the counter increments through the rom_array.
- Line 31: Increased the for loop count to go to a much higher number so the simulation doesn't end so quickly.
- Line 33-37: [CHALLENGE] The purpose of the code here was to use vbdValue() function, which is the knob on the Vbuddy, to change the frequency of the sine wave generated. This is where we thought to change vbdValue() = incr and likewise in the count module for count = count + incr which allows us to change the jumps between datapoints hence the frequency. However, this resulted in the frequency change happening too rapidly that the plot would look very spaced out and mupltiple sine waves dotted around. Hence, we implemented an if statement to update the value of incr every 50 cycles so that change was gradual and not sudden. As a result, the curve looked much smoother and was very satisfying!
- Line 47-48: Uses an if statement to reminate the simulation if either the program has finished or if the key is pressed which is equal to the ASCII value of "q".
Instead of using the rotary encoder to alter the frequency of the wave generated, we used it to set the phase shift between two generated sine waves.
For this task, I required a way of keeping the frequency constant (so got rid of incr logic) but being able to change "how ahead" the second generated sine wave was of the first one. One thing to consider was that when there is an offset, it needs to be a constant phase difference between the two waves, which meant that at each clock cycle, I needed to increment address of sinewave one and address of sinewave two by 1 while keeping the offset. This is achieved in sinegen.sv by assigning an internal logic called address2 = address1 + offset which is fed into the rom to allow the next rom memory value of dout2 to be jump ahead accordingly and hence shifting the phase.



