Start date: February 7/8
End date: February 15/16
Lab: 2
Status Complete
Lab 2 CutsheetECE_383_Lab2_Cutsheet.pdf
Lab 2 Editable Block DiagramECE383_Lab2_Block_Diagram.pptx
lab2_block_diagram.vsdx (Visio file)
Lab 2 Supplemental PowerPointECE_383_Lab2.pptx

Lab 2 - Data Acquisition, Storage and Display

Lab Overview

In this lab, we will integrate the video display controller developed in Lab 1 with the audio codec on the Nexys Video board to build a basic 2-channel oscilloscope. When complete, your lab should generate an output similar to the picture below.


Just like the design of Lab 1, Lab 2 is broken down into a bunch of separate modules, shown in the block diagram below. Some of the components in the block diagram will be given to you and some you created in Lab 1. It is important to note that some of the components and signals associated with this diagram will not be needed for Lab 2, but have been included because you will need them in Labs 3 and 4.

Consider the data in the diagram as flowing from left to right. You will provide an input signal to the Nexys board via a 3.5mm cable connected to the blue line-in jack. This signal then passes through an Analog Devices ADAU1761 SigmaDSP Audio Codec. The ADAU1761 samples the audio input at 48kHz into separate 18-bit 2's complement left and right channels. The ADAU1761 then transfers this data to our Artix 7 chip over a serial bus through the 7 signals on the left side of the Lab2 component. You can read more about the audio codec on page 27 of the Nexys Video manual (here).

The serial protocol coming from the audio codec is quite complex, so you will be given the Audio Codec Wrapper component as an interface to extract the incoming signal (Audio Codec Wrapper in the Figure above). Whenever new converted data is ready from the Audio Codec, the ready signal will go high for a single clock cycle. Your circuit will then do two things with the incoming L_bus_out and R_bus_out signals: First, it will loop both of these signals back into the Audio Codec so that you can verify (by listening on the green line-out jack) that the Audio Codec hardware and firmware are operating correctly. This is accomplished using the VHDL code below.
    process (clk)
	if (rising_edge(clk)) then
	    if reset_n = '0' then
		L_bus_in <= (others => '0');
		R_bus_in <= (others => '0');				
	    elsif(ready = '1') then
		L_bus_in <= L_bus_out;
		R_bus_in <= R_bus_out;
	    end if;
	end if;
    end process;
Second, your circuit will need to send the L_bus_out and R_bus_out signals in an unsigned format to be stored in the block ram (BRAM). To do this, you will need to convert the 2's complement values to unsigned. Performing this conversion is technically easy, but may be a little difficult to wrap your head around, so let's do some examples. Consider the table below.
Input Value Ouput Value
2's complement 2's value unsigned unsigned value
100...000 -131072 000...000 0
111...111 -1 011...111 131071
000...000 0 100...000 131072
000...001 1 100...001 131073
011...111 131071 111...111 262143
The values in the left 2 columns represent the 2's complement number coming out of the Audio Codec, in this case L_bus_out, while the right 2 columns represent the output of the box labeled "sign2unsign" in the block diagram. What we are essentially doing is shifting the unsigned values up by 131072 (the value which will make all 18-bit numbers positive) so that they all fall into a positive range.

Here are a couple more pieces of info to help you understand the block diagram above. Consider the mux with its input going to the WRADDR input of the "BRAM_SDP" block in the block diagram. This mux circuitry attached to the write address of the BRAM will be used in Lab3, allowing the microBlaze processor to take over write duties for the RAM (as opposed to an external signal from the Audio Codec). Independent of the write circuitry, the read circuit pulls data from the RAM, and draws the waveform. Unlike for the write circuitry, the read circuitry requires no FSM control.


Since its a very complex piece of circuitry, the entity for the datapath (LAB2_DP in the block diagram) is given below.
entity lab2_datapath is
	clk : in  STD_LOGIC;
	reset_n : in  STD_LOGIC;
	ac_mclk : out STD_LOGIC;
	ac_adc_sdata : in STD_LOGIC;
	ac_dac_sdata : out STD_LOGIC;
	ac_bclk : out STD_LOGIC;
	ac_lrclk : out STD_LOGIC;
	scl : inout STD_LOGIC;
	sda : inout STD_LOGIC;	
	tmds : out  STD_LOGIC_VECTOR (3 downto 0);
	tmdsb : out  STD_LOGIC_VECTOR (3 downto 0);
	sw: out std_logic_vector(2 downto 0);
	cw: in std_logic_vector (2 downto 0);
	btn: in	STD_LOGIC_VECTOR(4 downto 0);
	exWrAddr: in std_logic_vector(9 downto 0);
	exWen, exSel: in std_logic;
	Lbus_out, Rbus_out: out std_logic_vector(15 downto 0);
	exLbus, exRbus: in std_logic_vector(15 downto 0);
	flagQ: out std_logic_vector(7 downto 0);
	flagClear: in std_logic_vector(7 downto 0));
end lab2_datapath;

Flag Register

In Lab 3, we will be integrating most of the components from this lab with the MicroBlaze processor (a processor we program onto our FPGA). In order to make this smooth, we will need a way to transfer information between the two systems a technique similar to a 2-line handshake. To make this possible, you will need to build a component called a flag register. The behavior of the flag register is shown in the table below.
reset_n clk set clear Q+
0 X X X 0
1 0,1,falling X X Q
1 rising 0 0 Q
1 rising 1 0 1
1 rising 0 1 0
1 rising 1 1 X
The flag register will interface our lab2 component with a MicroBlaze as follows: The LAB2 component will produce some data, put it on a data line to the MicroBlaze, and then set one of the bits of the flag register. Then, the MicroBlaze will, at some point, look at the flag register bit. When it sees that the 'set' bit is 1, the MicroBlaze will grab the data from the register and clear the set bit. These are just like the flag bits on the MSP 430. Use the following entity declaration for the flag register:
entity flagRegister is
	Generic (N: integer := 8);
	Port(	clk: in  STD_LOGIC;
			reset_n : in  STD_LOGIC;
			set, clear: in std_logic_vector(N-1 downto 0);
			Q: out std_logic_vector(N-1 downto 0));
end flagRegister
The set lines should be connected to the signals below. For the time being, you can leave the Q outputs to open.


You need to map the ports of BRAM to include it in your lab2_datapath. The component is declared in the UNIMACRO library - look at that library to figure out how to port map BRAM.
	library UNIMACRO;		-- This contains links to the Xilinx block RAM
	use UNIMACRO.vcomponents.all;


The files below will give you a start on Lab 2.


Generating Audio Waveforms

Since you need to use a 3.5mm jack to input signals to the Nexys board, your phone's audio output works quite well. However, make sure you get an app where you can control both the left and right audio channels individually (i.e. the green and yellow signals in the figure above). The Keuwl Dual Channel Function Generator (available on Google Play) works well for Android Phones, and is easy to use once you get the hang of it.

Gate Checks for Required Functionality

There are 2 gate checks associated with this lab, each worth 5 points - see the rubric below.

Gate Check 1

By COB Lesson 13, you must have started a Lab 2 Vivado project and downloaded the template files and drop in your Video, VGA, Scopeface, dvid, and tdms files from Lab 1 into your Lab 2 project in order to test your Lab 1 Scopeface works when you implement you Audio Code Wrapper.  Notice from the block diagram…you will copy your Video instantiation and button processes from Lab 1 into your Lab 2 Datapath.  You will also have to re-implement the Lab 1 Clocking Wizard in you Lab 2 project.  Doing this will eliminate a lot of errors from un-driven output signals on lab 2 top.
Next, you will need to have implement another Clocking Wizard and the Audio Codec Wrapper inside the Datapath entity to get your Audio Codec to begin functioning. Once you fully implement the Audio Codec Wrapper, you will drop in the Loopback process and make connections to loopback the serial ADC input back out to the DAC output (i.e. send the signal back into the Codec). Once you implement the design on the board, you can verify functionality by applying an audio signal to the audio line in jack (blue) and listening to it on the audio line out jack (Green) using a standard oscilloscope. Additionally your Scopeface and Button inputs from Lab 1 should be functional as well.

Gate Check 2

NOTE: THIS IS THE HARDEST PART! By BOC Lesson 15, you must have implemented and connected the left channel BRAM and BRAM Address Counter to write Audio Codec data to BRAM. Once implemented, you can verify your BRAM works by using the given datapath testbench and watching the BRAM write address increment and data be written/read from the BRAM.
Once this is working, you must implement Video entity (from Lab 1) to take the left channel output from BRAM and send it to the Channel 1 waveform to be displayed when the readL value equals the row value. Once implemented, this functionality can be verified first with the given datapath testbench to verify the channel 1 values are being updated properly when readL equals the row value. Additionally, you may try to implement this on the hardware and verify that your scopeface is still present and some values are being displayed for Channel 1 (at this point the waveform will be scrolling across the display or may be scaled wrong).

Required Functionality

Get a single channel of the oscilloscope to display with reliable triggering that holds the waveform at a single point on the left edge of the display. A 220Hz waveform should display something similar to what is shown in the screenshot at the top of this page. Additionally, you must have the following done:

B-level functionality

A-level functionality

Turn In

All your work in this lab is to be submitted using Bitbucket. The main part of the lab is your README, documenting your design. Your README must include the following:


Item Grade Points Out of Date Due
Gate Check 1 On-Time ------------------------------------------------------------------ Late: 1Day ---- 2Days ---- 3Days ---- 4+Days 5 COB L13
Gate Check 2 On-Time ------------------------------------------------------------------ Late: 1Day ---- 2Days ---- 3Days ---- 4+Days 5 BOC L15
Required Functionality On-Time ------------------------------------------------------------------ Late: 1Day ---- 2Days ---- 3Days ---- 4+Days 30 BOC L17
B Functionality On-Time ------------------------------------------------------------------ Late: 1Day ---- 2Days ---- 3Days ---- 4+Days 10 BOC L17
A Functionality On-Time ------------------------------------------------------------------ Late: 1Day ---- 2Days ---- 3Days ---- 4+Days 10 BOC L17
Use of Git / Bitbucket On-Time: 0 ---- Check Minus ---- Check ---- Check Plus ---- Late: 1Day ---- 2Days ---- 3Days ---- 4+Days 5 COB L17
Code Style On-Time: 0 ---- Check Minus ---- Check ---- Check Plus ---- Late: 1Day ---- 2Days ---- 3Days ---- 4+Days 10 COB L17
README On-Time: 0 ---- Check Minus ---- Check ---- Check Plus ---- Late: 1Day ---- 2Days ---- 3Days ---- 4+Days 25 COB L17
Total 100