Introduction: How to Make a Music-Time Display

Introduction:

For our project we will make digital stopwatch that displays the amount of time a song plays. Our device will display time (second, tenths of a seconds, hundredths of a seconds) using the 7 segment display. The user can chose from one of two songs.

A switch will allow the user to start the song and once the song is over, reset the display to zero (and the song will reset to the beginning). The potentiometer will allow the user to select one of two song, Star Wars Theme Song (pot arrow pointing up) or Star Wars Imperial March (pot arrow pointing down).

Similarly an LED will blink in unison to the song.

For this we will use both a Arduino and FPGA board (Basys 3). We choose this gizmo because we really enjoyed the clock signal found in our FPGA and it gave us an opportunity to display our mad VHDL skills. This is similar to a car radio, that displays the timing for a song. The user will have the option of selecting one of three song. Then the Arduino will play the selected song. Once the song starts playing the 7-segment display will begin to count up, displaying seconds, tenths of a second, and hundreds of a second.

Step 1: Gather Your Parts and Materials

1. Xilinx Vivado 2016.2 https://www.xilinx.com/support/download/index.htm... Arduino

2. Softwarehttps://www.xilinx.com/support/download/index.htm...

3. Arduino Uno https://www.xilinx.com/support/download/index.htm...

4. Basys 3 Board https://www.xilinx.com/support/download/index.htm... FPGA Code: (Vivado)

5. (16) Jumper Wires

6. Potentiometer

7. (6) 10k ‎Ω

8. Piezo electric buzzer ( or a small speaker)

9. Switch

10. (1) LED

11. Bread board

12. USB A to USB B

13. Micro USB cable

Optional

14. Wire Crimpers

Step 2: Wire the Arduino to the Breadboard and Components

Take the provided schematic diagram and wire the components to the Arduino. The Arduino micro controller has 14 digital input/output pins and 6 analog inputs. For this project we will be using three digital pins (7, 4, 2) and one analog pin (A0). Similarly we will use the 5V output pin and the ground pin on the Arduino board.

- Pin 7 will be connected to the buzzer, that will may the song

- Pin 4 switch, on/off switch that resets song and timer after the song has played and when on plays song

- Pin 2 resistor (2) voltage divider circuit

- Potentiometer, song selector Star Wars Theme Song or Star Wars Imperial March

- LED in parallel with buzzer

Step 3: Program the Arduino

/* Star Wars Song Selector

<p>/* Star Wars Song Selector<br> * Program to choose between two melodies by using a potentiometer and a piezo buzzer.
 */
// TONES //
// Defining the relationship between note, period & frequency. 
// period is in microsecond so P = 1/f * (1E6)</p><p>#define  c3    7634<br>#define  d3    6803
#define  e3    6061
#define  f3    5714
#define  g3    5102
#define  a3    4545
#define  b3    4049</p><p>#define  c4    3816    // 261 Hz <br>#define  d4    3401    // 294 Hz 
#define  e4    3030    // 329 Hz 
#define  f4    2865    // 349 Hz 
#define  g4    2551    // 392 Hz 
#define  a4    2272    // 440 Hz 
#define  a4s   2146
#define  b4    2028    // 493 Hz 
#define  c5    1912    // 523 Hz
#define  d5    1706</p><p>#define  d5s   1608
#define  e5    1517    // 659 Hz
#define  f5    1433    // 698 Hz
#define  g5    1276
#define  a5    1136
#define  a5s   1073
#define  b5    1012
#define  c6    955
#define  R     0      // Define a special note, 'R', to represent a rest

<p>// SETUP // <br>int speakerOut = 7;   // Set up speaker on digital pin 7
int potPin = A0;      // Set up potentiometer on analogue pin 0.
int reset = 4;        // Pin that will output signal to FPGA, Reset Signal
int VoltsOut = 2;     // Pin that will output singal to FPGA, Pause Signal</p><p>void setup() { <br>  pinMode(speakerOut, OUTPUT);
  pinMode(reset, INPUT);
  pinMode(VoltsOut , OUTPUT);
  Serial.begin(9600); // Set serial out if we want debugging
  }</p><p>// MELODIES and TIMING //<br>//  melody[] is an array of notes, accompanied by beats[], 
//  which sets each note's relative length (higher #, longer note)</p><p>// Melody 1: Star Wars Imperial March<br>int melody1[] = {  a4, R,  a4, R,  a4, R,  f4, R, c5, R,  a4, R,  f4, R, c5, R, a4, R,  e5, R,  e5, R,  e5, R,  f5, R, c5, R,  g5, R,  f5, R,  c5, R, a4, R,
                   a4, R,  a4, R,  a4, R,  f4, R, c5, R,  a4, R,  f4, R, c5, R, a4, R,  e5, R,  e5, R,  e5, R,  f5, R, c5, R,  g5, R,  f5, R,  c5, R, a4, R,
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R
                };</p><p>int beats1[]  = {  50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5, 20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5,  20, 5, 60, 40,<br>                   50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5, 20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5,  20, 5, 60, 40,
                   50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5, 20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5,  20, 5, 60, 40,
                   50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5, 20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5,  20, 5, 60, 40, 
                };</p><p>// Melody 2: Star Wars Theme</p><p>int melody2[] = {  f4,  f4, f4,  a4s,   f5,  d5s,  d5,  c5, a5s, f5, d5s,  d5,  c5, a5s, f5, d5s, d5, d5s, c5,
                   f4,  f4, f4,  a4s,   f5,  d5s,  d5,  c5, a5s, f5, d5s,  d5,  c5, a5s, f5, d5s, d5, d5s, c5,
                   f4,  f4, f4,  a4s,   f5,  d5s,  d5,  c5, a5s, f5, d5s,  d5,  c5, a5s, f5, d5s, d5, d5s, c5,
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, 
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, 
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, 
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, 
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, 
                   R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,</p><p>				};</p><p>int beats2[]  = {  21,  21, 21,  128,  128,   21,  21,  21, 128, 64,  21,  21,  21, 128, 64,  21, 21,  21, 128,<br>                   21,  21, 21,  128,  128,   21,  21,  21, 128, 64,  21,  21,  21, 128, 64,  21, 21,  21, 128,
                   21,  21, 21,  128,  128,   21,  21,  21, 128, 64,  21,  21,  21, 128, 64,  21, 21,  21, 128,
                };</p><p>int MAX_COUNT = sizeof(melody1) / 2; // Melody length, for looping. <br>long tempo = 10000; // Set overall tempo
int pause = 1000; // Set length of pause between notes
int rest_count = 50; // Loop variable to increase Rest length (BLETCHEROUS HACK; See NOTES)
 
// Initialize core variables
int toneM = 0;
int beat = 0;
long duration  = 0;
int potVal = 0;
int resetVal = 0;
int outVoltVal = 0;
int Voltage = 0;
int number = 0;</p><p>// Play Tone Funtion<br>// Pulse the speaker to play a tone for a particular duration
void playTone() {
  long elapsed_time = 0;
  if (toneM > 0) { // if this isn't a Rest beat, while the tone has 
    while (elapsed_time < duration) {
      // PlAY
      digitalWrite(speakerOut,HIGH);
      delayMicroseconds(toneM / 2);
      // DOWN
      digitalWrite(speakerOut, LOW);
      delayMicroseconds(toneM / 2);
      // Keep track of how long we pulsed
      elapsed_time += (toneM);
    } 
  }
  else { // Rest beat; loop times delay
    for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
      delayMicroseconds(duration);  
    }                                
  }                                 
}
 
void loop () {  
  potVal = analogRead(potPin); //Read potentiometer value and store in potVal variable
  resetVal = digitalRead(reset); 
  outVoltVal = analogRead(outVolt);
  
  if (potVal < 511 && resetVal == HIGH) { // If potVal is less than 511, play Melody1...
  for (int i=0; i<max_count; i++)="" {=""  ="" if="" (i=""> 70) {
      digitalWrite(VoltsOut, HIGH);
      }
    toneM = melody1[i];
    beat = beats1[i];
    duration = beat * tempo; // Set up timing
    
    playTone(); // A pause between notes
    delayMicroseconds(pause);
    }
  }</max_count;></p><p>  
  else if (potVal > 511 && resetVal == HIGH) { // If potVal is less than 511, play Melody2...
  for (int i=0; i<max_count; i++)="" {=""  ="" if="" (i=""> 56) {
      digitalWrite(VoltsOut,HIGH);
      }
    toneM = melody2[i];
    beat = beats2[i];
    duration = beat * tempo; // Set up timing 
    playTone(); // A pause between notes
    delayMicroseconds(pause);
    }
  }
    else if (resetVal == LOW) {               
      //digitalWrite(VoltsOut, LOW);
      digitalWrite(speakerOut, LOW);
    }
  }</max_count;></p>

Use the provided code and upload it to your configured Arduino Uno board.

Step 4: Wire the Arduino to the Basys Board

For this step connect the ground on the Basys 3 board to the ground from the Arduino.

Next connect the H1 port on the Basys 3 board to the center stepped down voltage coming from the center node on the switch.

Finally connect the J1 port on the Basys 3 to the stepped down voltage coming from digital pin 2 on the Arduino.

Notice that the FPGA will only read LOW or HIGH signals.

Step 5: Program the Basys 3 Board

-- Authors: Andy McKeown and Salvador Cortes Soancatl
-- Digital Design

<p>library IEEE;<br>use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;</p><p>-- Top Level Code</p><p>entity DigitsDisplayModule is
    Port ( CLK : in STD_LOGIC;  
           RST : in STD_LOGIC;
           PS : in STD_LOGIC;
           Cathode : out STD_LOGIC_VECTOR (6 downto 0);
           Anode : out STD_LOGIC_VECTOR (3 downto 0));
end DigitsDisplayModule;</p><p>architecture Behavioral of DigitsDisplayModule is
    component ClockSignals Port ( CLK_IN : in STD_LOGIC;
                                  Pause : in STD_LOGIC; 
                                  Reset : in STD_LOGIC; 
                                  NUM0 : out STD_LOGIC_VECTOR (3 downto 0);
                                  NUM1 : out STD_LOGIC_VECTOR (3 downto 0);
                                  NUM2 : out STD_LOGIC_VECTOR (3 downto 0);
                                  NUM3 : out STD_LOGIC_VECTOR (3 downto 0));</p><p>    end component;
    
    signal clkRefresh  : std_logic:= '0';
    SIGNAL NUMA : STD_LOGIC_VECTOR (3 downto 0);
    SIGNAL NUMB : STD_LOGIC_VECTOR (3 downto 0);
    SIGNAL NUMC : STD_LOGIC_VECTOR (3 downto 0);
    SIGNAL NUMD : STD_LOGIC_VECTOR (3 downto 0);</p><p>begin</p><p>    SUBPART : ClockSignals port map (CLK_IN => CLK, Reset => RST,Pause => PS, NUM0 => NUMA, NUM1 => NUMB, NUM2 => NUMC, NUM3 => NUMD);
     
-- System Clock Counter</p><p>MyProcClkRefresh : process (CLK) is
    variable count : unsigned (35 downto 0) := x"000000000"; --36 zeros            -- 32 zeros to fit variable
begin   
    if (rising_edge(CLK)) then 
        count := (count + 1);
        --if count = x"00055730" then
        if count = x"000927C0" then         -- 350,000 couts = 
            count := x"000000000";
            clkRefresh <= '1';
        else clkRefresh <= '0';
        end if;
    end if;
end process MyProcClkRefresh;</p><p>-- Seven Segment Display</p><p>display : process (clkRefresh) is 
    variable digit : unsigned (1 downto 0) := "00";           
begin
    if (rising_edge(clkRefresh)) then
        case digit is 
            when "00" =>        -- display digit 1
                Anode <= "1110";
                case (NUMA (3 downto 0)) is 
                    WHEN "0000" => CATHODE <= "0000001";    
                    WHEN "0001" => CATHODE <= "1001111";
                    WHEN "0010" => CATHODE <= "0010010";    --2
                    WHEN "0011" => CATHODE <= "0000110";    
                    WHEN "0100" => CATHODE <= "1001100";    --4
                    WHEN "0101" => CATHODE <= "0100100";    --5
                    WHEN "0110" => CATHODE <= "0100000";    --6
                    WHEN "0111" => CATHODE <= "0001111";
                    WHEN "1000" => CATHODE <= "0000000";    --8 
                    WHEN "1001" => CATHODE <= "0001100";                                 
                    WHEN OTHERS => CATHODE <= "1111111"; 
                end case;
            when "01" =>
                Anode <= "1101";
                case (NUMB (3 downto 0)) is 
                    WHEN "0000" => CATHODE <= "0000001";    
                    WHEN "0001" => CATHODE <= "1001111";
                    WHEN "0010" => CATHODE <= "0010010";    --2
                    WHEN "0011" => CATHODE <= "0000110";    
                    WHEN "0100" => CATHODE <= "1001100";    --4
                    WHEN "0101" => CATHODE <= "0100100";    --5
                    WHEN "0110" => CATHODE <= "0100000";    --6
                    WHEN "0111" => CATHODE <= "0001111";
                    WHEN "1000" => CATHODE <= "0000000";    --8 
                    WHEN "1001" => CATHODE <= "0001100";                                 
                    WHEN OTHERS => CATHODE <= "1111111"; 
                end case;   
            when "10" =>        -- display digit 1
                Anode <= "1011";
                case (NUMC (3 downto 0)) is 
                    WHEN "0000" => CATHODE <= "0000001";    
                    WHEN "0001" => CATHODE <= "1001111";
                    WHEN "0010" => CATHODE <= "0010010";    --
                    WHEN "0011" => CATHODE <= "0000110";    
                    WHEN "0100" => CATHODE <= "1001100";    --4
                    WHEN "0101" => CATHODE <= "0100100";    --5
                    WHEN "0110" => CATHODE <= "0100000";    --6
                    WHEN "0111" => CATHODE <= "0001111";
                    WHEN "1000" => CATHODE <= "0000000";    --8 
                    WHEN "1001" => CATHODE <= "0001100";                                 
                    WHEN OTHERS => CATHODE <= "1111111"; 
                end case;
             when "11" =>
                Anode <= "0111";
                case (NUMD (3 downto 0)) is 
                    WHEN "0000" => CATHODE <= "0000001";    
                    WHEN "0001" => CATHODE <= "1001111";
                    WHEN "0010" => CATHODE <= "0010010";                           
                    WHEN "0011" => CATHODE <= "0000110";    
                    WHEN "0100" => CATHODE <= "1001100";    --4
                    WHEN "0101" => CATHODE <= "0100100";    --5
                    WHEN "0110" => CATHODE <= "0100000";    --6
                    WHEN "0111" => CATHODE <= "0001111";
                    WHEN "1000" => CATHODE <= "0000000";    --8 
                    WHEN "1001" => CATHODE <= "0001100";                                 
                    WHEN OTHERS => CATHODE <= "1111111"; 
                end case;                                     
        end case;
        digit := digit +1;  -- move to the next digit
    end if;
end process Display;</p><p>end Behavioral;</p>


-- Subpart Module Clock Signals 
<p>library IEEE;<br>use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;</p><p>entity ClockSignals is
    Port ( CLK_IN : in STD_LOGIC;
           Pause :  in STD_LOGIC; 
           Reset  : in STD_LOGIC; 
           NUM0 : out STD_LOGIC_VECTOR (3 downto 0);
           NUM1 : out STD_LOGIC_VECTOR (3 downto 0);
           NUM2 : out STD_LOGIC_VECTOR (3 downto 0);
           NUM3 : out STD_LOGIC_Vector (3 downto 0));
end ClockSignals;</p><p>architecture Behavioral of ClockSignals is
    signal w0,w1,w2,w3 : STD_LOGIC_VECTOR(3 downto 0);</p><p>begin   </p><p>    CountHundredth : process (CLK_IN, Reset, Pause) is
        variable X : unsigned (31 downto 0) := x"00000000" ;
        variable SEC0 : unsigned (3 downto 0) := "0000";  
    begin       
        if Reset = '0' then 
             SEC0:= "0000";
      
        elsif (rising_edge(CLK_IN)) then -- 1/100 second counter         
            if Pause = '0' then
            X := (X + 1); 
                if X = x"000F4240" then
                    SEC0 := SEC0 + 1;
                    X := x"00000000";
                    if SEC0 = "1010" then
                        SEC0 := "0000";
                    end if;
                end if;                                       
           end if;     
        end if;            
    w0 <= STD_LOGIC_VECTOR(SEC0);
    end process CountHundredth;
    
    
        
    CountTenth : process (CLK_IN, Reset, Pause) is</p><p>        variable X : unsigned (31 downto 0) := x"00000000" ;
        variable SEC1: unsigned (3 downto 0) := "0000";  
    begin       
        if Reset = '0' then 
             SEC1:= "0000";
              
        elsif (rising_edge(CLK_IN)) then -- 1/10 second counter         
            if Pause = '0' then
                X := (X + 1); 
                if X = x"00989680" then
                    SEC1 := SEC1 + 1;
                    X := x"00000000";
                    if SEC1 = "1010" then
                        SEC1 := "0000";
                    end if;
                end if;                                       
           end if;     
        end if;            
    w1 <= STD_LOGIC_VECTOR(SEC1);
    end process CountTenth;
    
        
    CountOne : process (CLK_IN, Reset, Pause) is -- 1 and 10 second counter</p><p>        variable X : unsigned (31 downto 0) := x"00000000" ;
        variable SEC2: unsigned (3 downto 0) := "0000";
        variable SEC3: unsigned (3 downto 0) := "0000";
    begin
        if Reset = '0' then 
            SEC2 := "0000";
            SEC3 := "0000";</p><p>        elsif (rising_edge(CLK_IN)) then        
            if Pause = '0' then
                X := (X + 1);
                if X = x"05F5E100" then  
                    SEC2 := SEC2 + 1;
                    X := x"00000000";
                    if SEC2 = "1010" then
                        SEC2 := "0000";
                        SEC3 := SEC3 +1;
                        if SEC3 = "1010" then
                            SEC3 := "0000";                   
                        end if;
                    end if;     
                end if;                 
            end if;     
        end if;           
    w2 <= STD_LOGIC_VECTOR(SEC2);
    w3 <= STD_LOGIC_VECTOR(SEC3); 
    end process CountOne;
 
    Num0 <= w0;
    Num1 <= w1;
    Num2 <= w2;
    Num3 <= w3;</p><p>end behavioral;</p>
-- Constraints File for FPGA Basys 3 board

<p>set_property PACKAGE_PIN W4 [get_ports {Anode[3]}]<br>set_property IOSTANDARD LVCMOS33 [get_ports {Anode[3]}]</p><p>set_property PACKAGE_PIN V4 [get_ports {Anode[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Anode[2]}]</p><p>set_property PACKAGE_PIN U4 [get_ports {Anode[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Anode[1]}]</p><p>set_property PACKAGE_PIN U2 [get_ports {Anode[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Anode[0]}]</p><p>set_property PACKAGE_PIN W7 [get_ports {Cathode[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[6]}]</p><p>set_property PACKAGE_PIN W6 [get_ports {Cathode[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[5]}]</p><p>set_property PACKAGE_PIN U8 [get_ports {Cathode[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[4]}]</p><p>set_property PACKAGE_PIN V8 [get_ports {Cathode[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[3]}]</p><p>set_property PACKAGE_PIN U5 [get_ports {Cathode[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[2]}]</p><p>set_property PACKAGE_PIN V5 [get_ports {Cathode[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[1]}]</p><p>set_property PACKAGE_PIN U7 [get_ports {Cathode[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Cathode[0]}]</p><p>set_property PACKAGE_PIN H1 [get_ports {RST}]
set_property IOSTANDARD LVCMOS33 [get_ports {RST}]</p><p>set_property PACKAGE_PIN J1 [get_ports {PS}]
set_property IOSTANDARD LVCMOS33 [get_ports {PS}]</p><p>set_property PACKAGE_PIN W5 [get_ports {CLK}]
set_property IOSTANDARD LVCMOS33 [get_ports {CLK}]</p><p>create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {CLK}]</p>


For this project you will need three files, two .HDL files and one .XDC file

Step 6: Plug Everything In, Power Up and Test

Enjoy!

Step 7: Overall Project Design - Black Box Diagram

Black Box Diagram

Authors: Andy McKeown & Salvador Cortes Soancatl