Jump to content
  • 0

Audio with PmodI2S with ZYBO


Kampi

Question

Hello,

I receive my I2C Audio PMOD (http://store.digilentinc.com/pmodi2s-stereo-audio-output/) today and I want to use it with my ZYBO.
My I2S transmitter look like this:

library ieee;
use ieee.std_logic_1164.all;

entity I2S_Transmitter is
    generic (  
        DATA_WIDTH : integer := 32
    );
    port (
        Clock   :   in  STD_LOGIC;
        MCLK    :   out STD_LOGIC;
        Data_In :   in STD_LOGIC_VECTOR(DATA_WIDTH - 1 downto 0); 
        LRCLK   :   Out  STD_LOGIC;
        DOUT    :   out STD_LOGIC;
        Reset   :   in  STD_LOGIC;
        Empty   :   out STD_LOGIC
    );
end entity;

architecture I2S_Transmitter_Arch of I2S_Transmitter is

    signal InputBuffer  :   std_logic_vector(DATA_WIDTH - 1 downto 0) := (others => '0');
    signal Empty_Signal :   std_logic := '1';
    
    signal DOUT_D1      :   std_logic := '0';
    signal WS           :   std_logic := '0';
    signal Counter      :   integer := 0;

begin
 
LRCLK_Logic:
        process (Clock)
        begin
            if(falling_edge(Clock)) then
                if(Reset = '1') then
                    Counter <= 0;
                    WS <= '1';
                else
                            
                    Counter <= Counter + 1;
                    
                    if(Counter > (DATA_WIDTH / 2 - 1)) then
                        WS <= '1';
                    else
                        WS <= '0';
                    end if;
                    
                    if(Counter = (DATA_WIDTH - 1)) then
                        Counter <= 0;
                    end if;
                end if; 
            end if;
        end process;
    
Load_and_shift_out_Data:
        process(Clock)
        begin
            if(falling_edge(Clock)) then
                if(Reset = '1') then
                    InputBuffer <= (others => '0');
                    Empty_Signal <= '1';
                else
                    if(Empty_Signal = '1') then
                        InputBuffer <= Data_In;
                        Empty_Signal <= '0';
                    else
                        InputBuffer <= InputBuffer((DATA_WIDTH - 2) downto 0) & '0';   
                        DOUT_D1 <= InputBuffer(DATA_WIDTH - 1);
                    end if;        
                    
                    if(Counter = (DATA_WIDTH - 1)) then
                        Empty_Signal <= '1';
                    end if;     
                end if;
            end if;
        end process;

    MCLK <= Clock;
    LRCLK <= WS;
    DOUT <= DOUT_D1;
    Empty <= Empty_Signal;

end architecture I2S_Transmitter_Arch;

With this Testbench:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity I2S_Transmitter_TB is
--  Port ( );
end I2S_Transmitter_TB;

architecture I2S_Transmitter_TB_Arch of I2S_Transmitter_TB is

    signal MCLK     :   std_logic;
    signal WS       :   std_logic := '0';
    signal SCK      :   std_logic := '1';
    signal DOUT     :   std_logic;
    signal Empty    :   std_logic := '0';
    signal Reset    :   std_logic := '0';
    signal Data_In  :   std_logic_vector(31 downto 0) := (others => '0');
    
    -- 8,192 MHz Clock
    constant clk_period:    Time := 122 ns;
    constant ws_period:     Time := 16 * clk_period;

begin

DUT:
    entity work.i2s_transmitter
        port map (
            LRCLK => WS,
            MCLK => MCLK,
            Data_In => Data_In,
            Clock => SCK,
            DOUT => DOUT,
            Empty => Empty,
            Reset => Reset
        );
CLOCK:

    process
    begin
        wait for clk_period / 2;
        SCK <= not SCK;
    end process;

STIMULUS:

    process
    begin
        Data_In <= x"507B507B";
        Reset <= '1';
        wait for 10 us;
        Reset <= '0';
        wait for 10 us;
        Data_In <= (others => '0');
        wait for 30 ms;
        Reset <= '1';
        wait for 5 ms;
        
    end process;

end I2S_Transmitter_TB_Arch;

I use Port JC on my ZYBO and this is my XDC-File:

# Clock
set_property PACKAGE_PIN L16 [get_ports Clock_In]
set_property IOSTANDARD LVCMOS33 [get_ports Clock_In]

set_property PACKAGE_PIN V15 [get_ports MCLK]
set_property IOSTANDARD LVCMOS33 [get_ports MCLK]

set_property PACKAGE_PIN W15 [get_ports LRCLK]
set_property IOSTANDARD LVCMOS33 [get_ports LRCLK]

set_property PACKAGE_PIN T10 [get_ports DOUT]
set_property IOSTANDARD LVCMOS33 [get_ports DOUT]

set_property IOSTANDARD LVCMOS33 [get_ports DEM]
set_property PACKAGE_PIN T11 [get_ports DEM]

The clock frequency for MCLK is 8,192MHz, generated with a MMCM. I´ve connected this speaker (http://store.digilentinc.com/speaker/) to the PMOD, but I doesn´t hear any sound. Why?
Thank you for help!

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

  • 0

If I get a chance I'll simulate it this weekend.... but chances are that it is the mismatch of the DAC output impedance and the speaker impedance. The speaker is 4 ohm, and the DAC is for driving 10k ohm loads. Have you got some powered speakers you can test with?

For an un-amplifed speaker you might want to use PMOD-AMP3 ( http://store.digilentinc.com/pmodamp3-stereo-power-amplifier ) which is also I2S. As it is a bridged class-D amplifier you can't connect a PMOD-AMP3 to an external power amp but it is ideally suited to to the 4 ohm speaker.

Also, sending the clock directly to a pin isn't best practices (but should work for this application). Have a look for "clock forwarding" in http://www.xilinx.com/support/documentation/user_guides/ug471_7Series_SelectIO.pdf at around page 128.

Edited by hamster
Link to comment
Share on other sites

  • 0

Hello,

thanks for your reply. I don´t have self powered speakers, so I have to buy some :(.... I think I could use . The PMOD-AMP3 looks like a good alternative, but it has I²C for configuration and I want to test I²S alone and without I²C configuration. Otherwise I could choose the audio codec on my ZYBO (which will be the next step after I²S is running).

Link to comment
Share on other sites

  • 0
On 5/12/2016 at 11:59 PM, Kampi said:

Hello,

thanks for your reply. I don´t have self powered speakers, so I have to buy some :(.... I think I could use . The PMOD-AMP3 looks like a good alternative, but it has I²C for configuration and I want to test I²S alone and without I²C configuration. Otherwise I could choose the audio codec on my ZYBO (which will be the next step after I²S is running).

Super late on this, but I am posting just in case anyone reads this in the future. AMP3 does indeed have an I2C config mode, but it also has a simple mode that requires no configuration aside from setting some jumpers. You pass it a few clocks, and the I2S serial data, and its off you go. No I2C required

Link to comment
Share on other sites

  • 0

Not sure if it heps, but I wonder, how the PLL setting should cooperate with I2S.(?)

Typically you will get or drive the MCLOCK from / to the board with 64xBCLK. This is for instance someting like 12,288 MHz. One chance is to obtain a BLCK and use a PLL to generate an internal multiple of it to get e.g. S/PDIF (BMC) working.

If you want to produce I2S or S/PDIF from the PCB and do not have an oscilator with 24.576...  you can try to produce a 25MHz Clock with a first PLL and then use a 29/59 to obtain a 12,288 with some 20 ppm error only!  One can even use a little load to the OSC to pull it and synch it to an coming clock this way.

Link to comment
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
×
×
  • Create New...