This project was one of the the year-2 experiment, written by Peter Cheung.
Written Verilog configuration for Cyclone V FPGA (5CSEMA5F31C6).
Link to the experiment
link to the Digital Course
-
<=non-blocking and is performed on every positive edge of clock. these are evaluated in parallel so no guarantee of order. An example of this would be a register.
-
assign =continual assignment to wire outside an always statement. value of LHS is updated when RHS changes.
-
=blocking assignment, inside always statements enforces sequential order.
- output default is wire
- reg can be assigned to in a procedural block (a block beginning with always or initial)
- wire can be assigned in a continuous assignment (an assign statement)
- avoid use x as default
parameter vs assign vs alias
- parameter: has to be constant
- assign: assigning the right-hand side of the statement to the left-hand side but not the inverse
- alias: bidirectional (SystemVerilog, not Verilog)
- ! is logical inversion
- ~ is bitwise inversion
We find out that the link between .bsf and .bdf are bidirectional, we could include only the .bsf or the .bdf, and the code will still 'Analysis and Elaboration'. But we were suggested by the UTA to include .bdf as that's how normally done.
What is the difference between SLOW 0 and 85 celcius propagation delay? According to Brownian motion, electrons move faster when the temperature is high. This results in collison between molecules, and therefore the delay time between gates rises.
We have set the pin location according to the table given on the labnotes. The pin voltage is set to 3.3 LVTTL. The pin assignment file can be accessed by the link below.
In this experiment, the get_5_get_3 algorithm was introduced to perform the conversion. The following schematic diagram shows how data flows among different blocks.
The additional "0" must be added at the beginning when a new block of three bits is introduced.(Blocks A1,A4,A10) The output would be placed in H3:H0 blocks, which represents Binary Code Decimal.
By using ModelSim of RTL Simulation, waveforms of various different signals can be shown.
The following code is the instruction:
- add wave XXXXXXXX
- force xxx
- force CLOCK_50 0 0,1 10ns -repeat xxxns
- (force can enable all signals to user defined values)
- run executes the given signals
By creating a DO file, we can simplify things extensively by running the Testbench file. Also, single stepping allows the user to debug easily.
- Always include a xxx.sdc file which specifies the working clock to a certain speed.
- Always remember to modify the pin assignment file.
- Always check if the board is chosen correctly.
The following graph indicates the truth table which implements the logic of 1+X+X^7.
This was check by using MODELSIM in Quartus Prime. The following image shows the wave diagram.
The Netlist graph was then generated to verify the correctness of design.
The clock should be working at 1ms/cycle which is equivalent to 1MHz. This can be achieved by dividing the 50MHz clock by (50000x500).For more information, please refer to the circuit diagram below:\
The aim of this section is to generate a timer using the previous part.
By modifying the previous state machine, the new FSM looks like below
The additional board was designed by our lecturer Peter Cheung. This board provides the feature of digital to analogue conversion as well as pins which can be connected to the oscilloscope for debugging purposes. The following diagram indicates the internal circuitry diagram of the board.
- DAC_CS: Digital to Analogue converter, signal name: Chip select
- DAC_SDI: Digital to Analogue converter, signal name: Serial Data input
- DAC_SCK: Digital to Analogue converter, signal name: Serial Clock input
- DAC_LD: Digital to Analogue converter, signal name: Load
The same naming convention applies for the Analogue to Digital convertor.
According to the SPI2DAC proxy mentioned in lecture, the wave form h'23B after decoding should look like the diagram below.
The next step was to change the input to switch controls. Different input would only change the DC offest. Hence, the line would be shifted up or down.
The expected output was verified as two DC voltage on both SPI and PWM channels.
The main concept of this part is that the width of the square wave changes linearly according to the digital input.
This signal is then passed into a low pass filter, which produces a digital output signal where high frequency components are
removed.
This output signal is still discontinuous. The output on scope at pin 5 is verified to be a square wave with different widths.
The output on scope at pin 9 is verified to be the signal mentioned before.
The data in the ROM was designed using the formula below
D[9:0] = int(511*sin(A[9:0]2pi/1024)+512), where A is the memory address for the ROM.\
- The data sheet for the above formula can be generated by using Python code or MATLAB script.
- Include data sheet as initialisation file for Memory Compiler
- Instuctions: Click Tools > IP Catalog to bring up a tool which helps to create a 1-Port ROM. A catalog window will pop up. Select from the window >Library >Basic Functions > On-chip Memory > ROM 1-Port. Complete the on-screen form to create ROM.v
The diagram below shows the internal digital circuit of a sine wave generator ROM.
The address counter would increment the address by one every clock cycle, as a result, reading all the sampled data from ROM and writing into the SPI interface. In this case, we have separated two channels. The left channel is connected to the SPI interface, whereas the right channel is connected to a PWM block. Two output signals do not have a significant difference.
The diagram below verifies the result.
The sampling frequency is set to 10KHz and the number of samples is 1K. Therefore, the signal frequency is 10K/1k= 10 Hz.
In addition, we also included a graph for 18 clock cycles on the scope. The figure is shown below as:
The address is now controlled by the switches. It is passed through an adder and a D_Flip Flop. In other words, the increment value is user-defined now. The multiplication block was included from IP Catalog in Quartus Prime.
The purpose of the upper line is to display the frequency of the signal. Data x sampling frequency "/" sample number.
The division by 1024 was implemented using reading DATA [23:10], which takes the upper 14 bits. As a result, the data is divided by 1024.
Because 14’h2710 is 10000 in decimal, the pointer to ROM is clocked at 10KHz, finally the ROM had stored 1k(1024) data point of one complete sine wave.
Let n be the number of address pointer increment, that means it will take 1024/x clock cycle to complete one full sin wave, and each clock cycle is 1/10000 seconds
Please see the figure below for details.
We notice that our wave stop output correct frequency after 5kHz. After some thinking, we realised it was linked to the Nyquist theorem. The sampling frequency is 10kHz, restricted by the SPI (tick) frequency we are currently using. Only waves below the frequency 5kHz will be correctly detected.
We also noticed that frequency goes extremely high, the frequency actually become detectable again. And we deduce it is because we are seeing the neighbour point of the current point in the next period. i.e. if current sampling point is at f(t), the next sampling is at f(t+T+δ), equals to f(t+δ), where T is the period of the current wave.
It's a similar example of real life, where if you stare at a care wheel spinning, it actually spins backwards when reaching a certain speed.
Instead of using the slide switches to control the frequency, use the A-to-D converter to convert the dc voltage of the potentiometer (which is between 0v and 3.3v) and use this converter value instead. Please see VERI/Part 4/ex15_top.v for more information.
A problematic issue occurred when the frequency was increased. This is due to the fact the SPI interface has a specific constant sampling frequency. For full recovery of signal, the sampling frequency must satisfy the Nyquist Sampling frequency, in other words at least twice the maximum frequency component of the original signal. This was verified by changing the input. As it approaches 5000 Hz, the signals starts aliasing.
The diagram below shows how different blocks are connected on the FPGA board.
-
The input data is subtracted by an offset since we are dealing with real analogue data which does not have negative voltages. In this case, we subtract h'181. The processor deals with two's complement signed numbers.
-
In the first experiment, we are required to verify that the main structure works. The allpass.v file describes a logic which simply passes the input to the output.
-
The output data is also corrected by adding an offset. In this case, we are adding h'200. This adjusts the analogue output signal to the range of 0-3.3V.
-
One of the raw data output was passed to a Pulse-width modulator block. As a result, the generated output would be square waves with different widths. The width of the square wave is proportional to the amplitude of the digital signal. In order to gain a suitable analogue output for earphones, it is required to pass this square wave into a low pass filter.
13 bit counter were used because the counter is the pointer to the ROM address. (2^13=8192)
The echo delay is (SW[8:0] << 2) x 1/10000 ms.
In order to allow 7-seg display time passed in ms, display=(SW[8:0] * 1638) >> 10.
By combin the two expression above, dispaly=10 / 2^4 * 1638 /2^10 = 0.999755859 ms.