Digital Microphone

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was completed in June 2015.

I've got a PmodMIC3, which is a Micro-Electro-Mechanical system (MEMS) Microphone connected to a 12-bit ADC from Texas Instruments.

Here's a die-shot of some Infineon MEMS microphones I found on the internet, at EE Times:

Mems die.png

And here is a cross-section of the microphone, from http://etienne.ece.jhu.edu/projects/memsmic/mem_pix.gif:

Mem pix.gif

Although it is only a 12-bit ADC, it can sample at 1 MHz, which can then be down-sampled to a higher bit rate at normal audio sample rates. (16-bit/48 kHz). That might mage a good project....

Anyhow, here is the code to get samples from the microphone, and display them on the LEDs.

Contents

Source files

pmod_mic3_test.vhd

Just displays any new sample values from the microphone, as long as they are above 0x800 (half scale). This gives a clearer indication that something is actually working. If I just displayed the raw value, any noise would cause all the LEDs to light with a 50% duty cycle, which is no good to anybody!

----------------------------------------------------------------------------------
-- Module Name: pmod_mic3_test - Behavioral
--
-- Engineer: Mike Field <hamster@snap.net.nz> 
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity pmod_mic3_test is
    Port ( clk100    : in STD_LOGIC;
           pmod_sclk : out STD_LOGIC;
           pmod_cs   : out STD_LOGIC;
           pmod_miso : in STD_LOGIC;
           led       : out STD_LOGIC_VECTOR (15 downto 0));
end pmod_mic3_test;

architecture Behavioral of pmod_mic3_test is
    component pmod_mic3 is
        Port ( clk100    : in STD_LOGIC;
               pmod_sclk : out STD_LOGIC;
               pmod_cs   : out STD_LOGIC;
               pmod_miso : in STD_LOGIC;
               value     : out STD_LOGIC_VECTOR(11 downto 0);
               new_value : out STD_LOGIC);
    end component;       

    signal new_value : STD_LOGIC;
    signal value     : STD_LOGIC_VECTOR(11 downto 0);        
begin

uut: pmod_mic3 port map (
       clk100    => clk100, 
       pmod_sclk => pmod_sclk,
       pmod_cs   => pmod_cs,
       pmod_miso => pmod_miso,
       value     => value,
       new_value => new_value);

clk_proc: process(clk100)
    begin
        if rising_edge(clk100) then
            if new_value = '1' and value(value'high) = '1' then
                led <= "0000" & value;
            end if;
        end if;
    end process;

end Behavioral;

pmod_mic3.vhd

----------------------------------------------------------------------------------
-- Module Name: pmod_mic3 - Behavioral
-- Engineer: Mike Field <hamster@snap.net.nz> 
--
-- Description: Recieve data from the PmodMIC3 microphone
--
-- The Serial clock runs at 1/10th that of the supplied 100MHz clock,
-- and it takes 20 cycles to take a sample, acheiving a 0.5 million
-- samples per second. (half the ADC's 1 megasample/sec rating) 
--
-- This could be doubled with a friendlier clock rate (e.g. 80MHz) by
-- adjusting the length of clk_div_sr to being 4 bits long with an inital 
-- value of "0011"
----------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity pmod_mic3 is
    Port ( clk100    : in STD_LOGIC;
           pmod_sclk : out STD_LOGIC;
           pmod_cs   : out STD_LOGIC;
           pmod_miso : in  STD_LOGIC;
           value     : out STD_LOGIC_VECTOR(11 downto 0);
           new_value : out STD_LOGIC);
end pmod_mic3;

architecture Behavioral of pmod_mic3 is
    signal clk_div_sr : std_logic_vector(9 downto 0) := "0000011111";
    signal cs_sr      : std_logic_vector(19 downto 0) := "00000000000000001111";
    signal data_sr    : std_logic_vector(15 downto 0) := (others => '0');
begin

process(clk100)
    begin
        if rising_edge(clk100) then
            new_value <= '0';
            if clk_div_sr(3 downto 2) = "01" then
                -- advance the CS shift register slightly out
                -- of phase with the sclk signal
                cs_sr <= cs_sr(0) & cs_sr(cs_sr'high downto 1); 
            end if;

            if clk_div_sr(1 downto 0) = "10" then
                -- sample as we are about to have a rising edge;
                data_sr <= data_sr(data_sr'high-1 downto 0) & pmod_miso;
               
                if cs_sr(1 downto 0) = "01" then
                    value <= data_sr(data_sr'high downto data_sr'high-value'high);
                    new_value <= '1';
                end if;
            end if;
            clk_div_sr <= clk_div_sr(0) & clk_div_sr(clk_div_sr'high downto 1);
            pmod_cs    <= cs_sr(0);
            pmod_sclk  <= clk_div_sr(0);
        end if;
    end process;
end Behavioral;

basys3.xdc

####################################################
# Constraints file for the Digilent Basys3 board,
# with the PMOD-DA3 attached on the top pins of JA 
####################################################

set_property PACKAGE_PIN W5 [get_ports clk100]							
	set_property IOSTANDARD LVCMOS33 [get_ports clk100]
	create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk100]

## Switches
## LEDs
set_property PACKAGE_PIN U16 [get_ports {led[0]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
set_property PACKAGE_PIN E19 [get_ports {led[1]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property PACKAGE_PIN U19 [get_ports {led[2]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property PACKAGE_PIN V19 [get_ports {led[3]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
set_property PACKAGE_PIN W18 [get_ports {led[4]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}]
set_property PACKAGE_PIN U15 [get_ports {led[5]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}]
set_property PACKAGE_PIN U14 [get_ports {led[6]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}]
set_property PACKAGE_PIN V14 [get_ports {led[7]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}]
set_property PACKAGE_PIN V13 [get_ports {led[8]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[8]}]
set_property PACKAGE_PIN V3 [get_ports {led[9]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[9]}]
set_property PACKAGE_PIN W3 [get_ports {led[10]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[10]}]
set_property PACKAGE_PIN U3 [get_ports {led[11]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[11]}]
set_property PACKAGE_PIN P3 [get_ports {led[12]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[12]}]
set_property PACKAGE_PIN N3 [get_ports {led[13]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[13]}]
set_property PACKAGE_PIN P1 [get_ports {led[14]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[14]}]
set_property PACKAGE_PIN L1 [get_ports {led[15]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {led[15]}]
	
##Sch name = JA1
set_property PACKAGE_PIN J1 [get_ports {pmod_cs}]                    
    set_property IOSTANDARD LVCMOS33 [get_ports {pmod_cs}]
##Sch name = JA2
#set_property PACKAGE_PIN L2 [get_ports {pmod_mosi}]                    
#    set_property IOSTANDARD LVCMOS33 [get_ports {pmod_mosi}]
##Sch name = JA3
set_property PACKAGE_PIN J2 [get_ports {pmod_miso}]                    
    set_property IOSTANDARD LVCMOS33 [get_ports {pmod_miso}]
##Sch name = JA4
set_property PACKAGE_PIN G2 [get_ports {pmod_sclk}]                    
    set_property IOSTANDARD LVCMOS33 [get_ports {pmod_sclk}]

Personal tools