• 0
Sign in to follow this  
GregyPooh

Pmodi2s Stereo Output Pmod - How Can I Get This Thing To Work?

Question

I cannot, for the life of me, get this: http://www.digilentinc.com/Data/Products/PMOD-I2S/PmodI2S_rm.pdf work.

I'm fairly confident I have the clocks at the correct frequencies.

 

And I've tried sending a square wave at about 12kHz ranging from
max amplitude: 0111111111111111
to min amplitude: 1000000000000000
(2's compliment). 

But when I plug in my headphones, I do not hear anything... Does this thing need an amplifier? 
Any help would be greatly appreciated!

Share this post


Link to post
Share on other sites

4 answers to this question

Recommended Posts

  • 0

Hi,

 

I've hauled my PMOD I2S out of the cupboard, and got it going on my Basys3, under Vivado

 

First, the I2S interface

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Description: Generate I2S audio stream
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
 
entity i2s_output is
    Port ( clk            : in  STD_LOGIC;
           -- Interface to the source of the audio
           data_l         : in  STD_LOGIC_VECTOR (15 downto 0);
           data_r         : in  STD_LOGIC_VECTOR (15 downto 0);
           data_accepted  : out  STD_LOGIC;
           
           -- Interface out to the DAC
           i2s_sd    : out  STD_LOGIC;
           i2s_lrclk : out  STD_LOGIC;
           i2s_sclk  : out  STD_LOGIC;
           i2s_mclk  : out  STD_LOGIC);
end i2s_output;
 
architecture Behavioral of i2s_output is
   signal step      : unsigned(8 downto 0)  := (others => '0');
   signal shift_out : std_logic_vector(16 downto 0) := (others => '0');
   signal hold_r    : std_logic_vector(15 downto 0) := (others => '0');
begin
   -- Set the output signals 
   i2s_lrclk <= std_logic(step(8));
   i2s_sclk  <= std_logic(step(3));
   i2s_sd    <= shift_out(shift_out'high);
 
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 => i2s_mclk,   -- 1-bit DDR output
      C  => clk,  -- 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
   );
 
   
process(clk)
   begin
      if rising_edge(clk) then
         -- Default to telling the source to wait
         data_accepted <= '0';
         
         if step = "111111111" then
            -- start sending the left sample, and signal the source
            -- that we have started sending both channels
            shift_out(15 downto 0) <= data_l;
            hold_r                 <= data_r;
            data_accepted          <= '1';
         elsif step = "011111111" then
              -- switch to sending the right sample
              shift_out(15 downto 0) <= hold_r;
         elsif step(3 downto 0) = "1111" then
                -- Just send the next bit.
               shift_out <= shift_out(shift_out'high-1 downto 0) & '1';
         end if;
         step <= step + 1;
      end if;
   end process;
 
end Behavioral;

Second, the top level source

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity i2s_test_top is
    Port ( clk100 : in STD_LOGIC;           
            -- Interface out to the DAC
            JA : out std_logic_vector(3 downto 0));
    end i2s_test_top;
 
architecture Behavioral of i2s_test_top is
    component i2s_output is
    Port ( clk            : in  STD_LOGIC;
           -- Interface to the source of the audio
           data_l         : in  STD_LOGIC_VECTOR (15 downto 0);
           data_r         : in  STD_LOGIC_VECTOR (15 downto 0);
           data_accepted  : out  STD_LOGIC;
           
           -- Interface out to the DAC
           i2s_sd    : out  STD_LOGIC;
           i2s_lrclk : out  STD_LOGIC;
           i2s_sclk  : out  STD_LOGIC;
           i2s_mclk  : out  STD_LOGIC);
    end component;
    
    signal clk      : std_logic := '0';
    signal toggle   : std_logic := '0';
    signal accepted : std_logic;
    signal data     : STD_LOGIC_VECTOR (15 downto 0) := x"C000";    
    signal count    : unsigned(7 downto 0) := (others => '0');
begin
    
i_output: i2s_output  Port map (
       clk    => clk,
       -- Interface to the source of the audio
       data_l        => data,
       data_r        => data, 
       data_accepted => accepted,
       
       i2s_mclk      => ja(0),
       i2s_lrclk     => ja(1),
       i2s_sclk      => ja(2),
       i2s_sd        => ja(3)
   );
       
p_clk: process(clk)
    begin
        if rising_edge(clk) then
            if accepted = '1' then 
                if count = 99 then
                    count <= (others => '0');
                    data(15) <= not data(15);
                else
                    count <= count + 1;
                end if;
            end if;
        end if;
    end process;
 
p_clk100: process(clk100)
    begin
        if rising_edge(clk100) then
            if toggle = '1' then
                clk <= not clk; 
            end if;
            toggle <= not toggle;
        end if;
    end process;
end Behavioral;

Third, the constraints:

## Clock signal
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]
 
##Pmod Header JA
#Sch name = JA1
set_property PACKAGE_PIN J1 [get_ports {JA[0]}] 
   set_property IOSTANDARD LVCMOS33 [get_ports {JA[0]}]
set_property PACKAGE_PIN L2 [get_ports {JA[1]}] 
   set_property IOSTANDARD LVCMOS33 [get_ports {JA[1]}]
set_property PACKAGE_PIN J2 [get_ports {JA[2]}] 
  set_property IOSTANDARD LVCMOS33 [get_ports {JA[2]}]
set_property PACKAGE_PIN G2 [get_ports {JA[3]}] 
   set_property IOSTANDARD LVCMOS33 [get_ports {JA[3]}]

As it is running at 25Mhz, and using a 512 clocks per frame the audio rate will be 48,828 samples per second.

 

As the top level module drives it with a square wave taking 200 sample, it should be a buzz of 244.14Hz:

 

post-35-0-95457300-1416816807_thumb.jpg

 

It looks quite noise, but that is actually because of the filtering on the edges - they contain no frequencies over 24kHz or so and so they 'ring' a little:

 

post-35-0-18845300-1416816936_thumb.jpg

Share this post


Link to post
Share on other sites
  • 0

As an additional side note, if you want to use the PmodI2S, you will need to use one of the newer FPGAs as opposed to a chipKIT board. Most of the chipKIT boards, aside from the chipKIT WiFire, are only able to run at 80 MHz which is unfortunately simply not fast enough to generate the master clock signal that the PmodI2S requires in addition to performing other actions (such as sending audio data).

 

In terms of numbers, for those who are interested, the reason for this is because the slowest master clock signal that the PmodI2S can receive (according to the on-board chips datasheet here) is 8.192 MHz, which is equivalent to about 122 ns between clock edges. On the chipKIT boards, with a processor clock rate of 80 MHz, they are are only able to utilize their timer register clock for core services for half the time (40 MHz).  This is a difference of 25 ns between clock edges, implying that every 5 clock "ticks" the master clock signal for the PmodIS will need to be triggered. Unfortunately, switching the voltage state of the digital pin driving the master clock and running a counter to keep track of the other needed clocks (such as the LRCK) takes more than 5 clock cycles to complete. This means that once the processor enters an interrupt service routine to "tick" the master clock and increase the counter of the other clocks, it will essentially never leave the ISR since more than 5 clock cycles passed while performing the functions within the ISR.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this