MIC and AMP

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was completed in Jan 2016.

I hand an PMODmic3 module handy, so added it to my the PMODamp3 project.

It's a tiny module to added earlier project, and uses the I2S MCLK that runs at 256x the sample frequency to drive the microphone's A2D converter.

I've also included a something to delay the samples from the microphone by 32,768 cycles (682 ms, as the design runs at 48,000 samples per second)

Contents

Source files

Most of the source can be taken from the PMODamp3 page. This is just the microphone input module and the modifications to the top level design required to integrate it.

pmod_mic3.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name: pmod_mic3 - Behavioral
--
-- Description: Sample input form a PMOD_MIC3, once every 256 ticks of the
--              master clock (mclk). 
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity pmod_mic3 is
    Port ( mclk   : in  STD_LOGIC;
           sclk   : out STD_LOGIC;
           cs     : out STD_LOGIC;
           sdat   : in  STD_LOGIC;
           de     : out STD_LOGIC;
           sample : out STD_LOGIC_VECTOR (15 downto 0) := (others => '0'));
end pmod_mic3;

architecture Behavioral of pmod_mic3 is
    signal counter : unsigned(7 downto 0)          := (others => '0');
    signal data_sr : std_logic_vector(11 downto 0) := (others => '0');
begin

process(mclk) 
    begin
        if rising_edge(mclk) then
            de <= '0';
            if counter > 5 and counter < 6 + 16*8 then
                cs <= '0';
            else
                cs <= '1';
            end if;
            if counter(2 downto 0) = 0 then
                data_sr  <= data_sr(10 downto 0) & sdat; 
            end if;
            if counter = 17 * 8 then
                ---------------------------------------------
                -- counvert the 12-bit unsigned sample to the
                -- lowest 12 bits of a 16-bit signed sample
                -- by adding it to -2048 
                ---------------------------------------------
                de <= '1';
                sample <= std_logic_vector(to_unsigned(63488,16) + unsigned(data_sr)); 
            end if;
            sclk <= std_logic(counter(2));

            counter <= counter + 1;
        end if;
    end process;
 
end Behavioral;

delay_buffer.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name: delay_buffer - Behavioral
--
-- Description: Delay the data by 32,768 cycles where "de" (data_enable)
--              is asserted.
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity delay_buffer is
    Port ( clk : in STD_LOGIC;
           wr_de : in STD_LOGIC;
           wr_data : in STD_LOGIC_VECTOR (15 downto 0);
           rd_de : out STD_LOGIC;
           rd_data : out STD_LOGIC_VECTOR (15 downto 0));
end delay_buffer;

architecture Behavioral of delay_buffer is 
    type a_memory is array(0 to 32767) of std_logic_vector(15 downto 0);
    signal memory  : a_memory              := (others => (others => '0')); 
    signal counter : unsigned(14 downto 0) := (others => '0'); 
begin

process(clk)
    begin
        if rising_edge(clk) then
            if wr_de = '1' then
                rd_de <= '1';
                rd_data <= memory(to_integer(counter));
                memory(to_integer(counter)) <= wr_data;                
                counter <= counter + 1;
            end if;
        end if;
    end process;
end Behavioral;

the updated pmod_amp3_test.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: pmod_amp3_test - Behavioral
--
-- Description: Send a sine wave out over I2S to the PMODamp3
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

Library UNISIM;
use UNISIM.VComponents.all;

entity pmod_amp3_test is
    Port ( clk100         : in  STD_LOGIC;

           pmod_mic_cs    : out STD_LOGIC;
           pmod_mic_sclk  : out STD_LOGIC;
           pmod_mic_sdat  : in  STD_LOGIC;

           pmod_i2s_sd    : out STD_LOGIC := '0';
           pmod_i2s_mclk  : out STD_LOGIC;
           pmod_i2s_bclk  : out STD_LOGIC;
           pmod_i2s_lrclk : out STD_LOGIC;
           pmod_i2s_sdat  : out STD_LOGIC);
end pmod_amp3_test;

architecture Behavioral of pmod_amp3_test is
    component pmod_mic3 is
    Port ( mclk   : in  STD_LOGIC;
           sclk   : out STD_LOGIC;
           cs     : out STD_LOGIC;
           sdat   : in  STD_LOGIC;
           de     : out STD_LOGIC;
           sample : out STD_LOGIC_VECTOR (15 downto 0));
    end component;

    component delay_buffer is
    Port ( clk     : in STD_LOGIC;
           wr_de   : in STD_LOGIC;
           wr_data : in STD_LOGIC_VECTOR (15 downto 0);
           rd_de   : out STD_LOGIC;
           rd_data : out STD_LOGIC_VECTOR (15 downto 0));
    end component;

    component i2s_clock_generator is
    Port ( clk100    : in  STD_LOGIC;
           i2s_mclk  : out STD_LOGIC;
           i2s_bclk  : out STD_LOGIC;
           i2s_lrclk : out STD_LOGIC);
    end component;

    component osc_sine is
    Port ( mclk   : in STD_LOGIC;
           lrclk  : in STD_LOGIC;
           sample : out STD_LOGIC_VECTOR (15 downto 0));
    end component;

    component powerup_controller is
    Port ( mclk         : in  STD_LOGIC;
           powerup      : out STD_LOGIC);
    end component;

    component i2s_transmitter is
    Port ( mclk         : in  STD_LOGIC;
           bclk         : in  STD_LOGIC;
           lrclk        : in  STD_LOGIC;
           sample_left  : in  STD_LOGIC_VECTOR (15 downto 0);
           sample_right : in  STD_LOGIC_VECTOR (15 downto 0);
           sdat         : out STD_LOGIC);
    end component;

    signal i2s_mclk    : STD_LOGIC;
    signal i2s_bclk    : STD_LOGIC;
    signal i2s_lrclk   : STD_LOGIC;
    signal i2s_sdat    : STD_LOGIC;
    signal i2s_powerup : STD_LOGIC;
    signal mic_de      : STD_LOGIC;
    signal mic_sample  : STD_LOGIC_VECTOR(15 downto 0);
    signal sample      : STD_LOGIC_VECTOR(15 downto 0);
begin

    ------------------------------------------
    -- Generate the different clocks. Only
    -- i2s_mclk should be used as a clock!
    ------------------------------------------
generate_clock: i2s_clock_generator PORT MAP (
    clk100 => clk100,
    i2s_mclk  => i2s_mclk,
    i2s_bclk  => i2s_bclk,
    i2s_lrclk => i2s_lrclk);

i_pmod_mic3: pmod_mic3 port map (
           mclk   => i2s_mclk,  -- Use a common clock for input and output
           sclk   => pmod_mic_sclk,
           cs     => pmod_mic_cs,
           sdat   => pmod_mic_sdat,
           de     => mic_de,
           sample => mic_sample);

i_delay: delay_buffer port map (
    clk  => i2s_mclk,
    wr_de     => mic_de,
    wr_data   => mic_sample,
    rd_de     => open,
    rd_data   => sample);
     
    ------------------------------------------
    -- Generate a quiet sine wave from a table
    ------------------------------------------
--i_osc_sine : osc_sine Port map ( 
--    mclk   => i2s_mclk,
--    lrclk  => i2s_lrclk,
--    sample => sample);

    ------------------------------------------
    -- Convert the samples into an I2S bitstream
    ------------------------------------------
i_i2s_transmitter: i2s_transmitter port map (
    mclk         => i2s_mclk,
    bclk         => i2s_bclk,
    lrclk        => i2s_lrclk,
    sample_left  => sample,
    sample_right => sample,
    sdat         => i2s_sdat);

i_powerup_controller: powerup_controller port map (
    mclk    => i2s_mclk,
    powerup => i2s_powerup);

    -------------------------------------------------------------
    -- Send it to the PMOD's interface 
    -------------------------------------------------------------
    -- Use a DDR output register to send out the I2S master clock
mclk_ODDR : ODDR generic map(
      DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE" 
      INIT => '0',                     -- Initial value for Q port ('1' or '0')
      SRTYPE => "SYNC")                -- Reset Type ("ASYNC" or "SYNC")
   port map (
      Q  => pmod_i2s_mclk, -- 1-bit DDR output
      C  => i2s_mclk,      -- 1-bit clock input
      CE => '1',           -- 1-bit clock enable input
      D1 => '1',           -- 1-bit data input (positive edge)
      D2 => '0',           -- 1-bit data input (negative edge)
      R  => '0',           -- 1-bit reset input
      S  => '0'            -- 1-bit set input
   );    

    pmod_i2s_sd    <= i2s_powerup;   -- Active low shutdown signal 
    pmod_i2s_bclk  <= i2s_bclk;
    pmod_i2s_lrclk <= i2s_lrclk;
    pmod_i2s_sdat  <= i2s_sdat;
end Behavioral;

the updated basys3.ucf

#####################################################################
# Constraits for the Basys3 board, PMOD B
#
#####################################################################
# Clock signal
#####################################################################
set_property PACKAGE_PIN W5      [get_ports clk100]
set_property IOSTANDARD LVCMOS33 [get_ports clk100]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk100]

#####################################################################
##Pmod Header JA
##Sch name = JA1
#####################################################################
set_property PACKAGE_PIN J1 [get_ports {pmod_mic_cs}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {pmod_mic_cs}]
##Sch name = JA3
set_property PACKAGE_PIN J2 [get_ports {pmod_mic_sdat}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {pmod_mic_sdat}]
##Sch name = JA4
set_property PACKAGE_PIN G2 [get_ports {pmod_mic_sclk}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {pmod_mic_sclk}]

#####################################################################
##Pmod Header JB
##Sch name = JB1
#####################################################################
set_property PACKAGE_PIN A14     [get_ports pmod_i2s_lrclk]
set_property IOSTANDARD LVCMOS33 [get_ports pmod_i2s_lrclk]
##Sch name = JB2
set_property PACKAGE_PIN A16     [get_ports pmod_i2s_sdat]
set_property IOSTANDARD LVCMOS33 [get_ports pmod_i2s_sdat]
#Sch name = JB4
set_property PACKAGE_PIN B16     [get_ports pmod_i2s_bclk]
set_property IOSTANDARD LVCMOS33 [get_ports pmod_i2s_bclk]
##Sch name = JB9
set_property PACKAGE_PIN C15     [get_ports pmod_i2s_mclk]
set_property IOSTANDARD LVCMOS33 [get_ports pmod_i2s_mclk]
##Sch name = JB10
set_property PACKAGE_PIN C16     [get_ports pmod_i2s_sd]
set_property IOSTANDARD LVCMOS33 [get_ports pmod_i2s_sd]

Personal tools