--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+
+entity i2s_ctrl is
+ port (
+ rst_i: in std_logic;
+ clk_50: in std_logic; -- 50 MHz
+
+ ws: out std_logic;
+ sck: out std_logic -- 44.1028*16*2 kHz (good enough for government work)
+ );
+end i2s_ctrl;
+
+
+architecture behavioral of i2s_ctrl is
+
+ signal clk_orig: std_logic; -- Output from DCM
+ signal clk_int: std_logic; -- DCM output after clock buffer
+
+ signal sck_orig: std_logic; -- Further clock division
+ signal sck_int: std_logic; -- Final I2S SCK after clock buffer
+
+ signal ws_tick: std_logic; -- For WS generation
+ signal ws_reg: std_logic := '0';
+
+begin
+
+ e_dcm: dcm_sp
+ generic map (
+ CLK_FEEDBACK => "NONE",
+ --CLKDV_DIVIDE => 1,
+ CLKFX_DIVIDE => 31,
+ CLKFX_MULTIPLY => 7,
+ CLKIN_DIVIDE_BY_2 => true,
+ CLKIN_PERIOD => 20.0,
+ --CLKOUT_PHASE_SHIFT => "NONE",
+ --DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
+ --FACTORY_JF =>
+ --PHASE_SHIFT => 0,
+ DFS_FREQUENCY_MODE => "LOW",
+ --DLL_FREQUENCY_MODE => "LOW",
+ --DSS_MODE => "NONE",
+ --DUTY_CYCLE_CORRECTION => false,
+ STARTUP_WAIT => true
+ )
+ port map (
+ CLKIN => clk_50,
+ CLKFB => '0',
+ DSSEN => '0',
+ RST => rst_i,
+ PSINCDEC => '0',
+ PSEN => '0',
+ PSCLK => '0',
+ CLK0 => open,
+ CLK90 => open,
+ CLK180 => open,
+ CLK270 => open,
+ CLK2X => open,
+ CLK2X180 => open,
+ CLKDV => open,
+ CLKFX => clk_orig,
+ CLKFX180 => open,
+ LOCKED => open,
+ STATUS => open,
+ PSDONE => open
+ );
+
+ e_clkbuf: bufg
+ port map (
+ I => clk_orig,
+ O => clk_int
+ );
+
+ e_sck_gen: srl16
+ generic map (INIT => x"0003")
+ port map (
+ D => sck_orig,
+ CLK => clk_int,
+ A0 => '1',
+ A1 => '1',
+ A2 => '0',
+ A3 => '0',
+ Q => sck_orig
+ );
+
+ e_sck_buf: bufg
+ port map (
+ I => sck_orig,
+ O => sck_int
+ );
+
+ e_ws_count: srlc16
+ generic map (INIT => x"0001")
+ port map (
+ D => ws_tick,
+ CLK => sck_int,
+ A0 => '0',
+ A1 => '0',
+ A2 => '0',
+ A3 => '0',
+ Q => open,
+ Q15 => ws_tick
+ );
+
+ process (sck_int, ws_tick, ws_reg)
+ begin
+ if rising_edge(sck_int) then
+ if ws_tick = '1' then
+ ws_reg <= not ws_reg;
+ end if;
+ end if;
+ end process;
+
+ ws <= ws_reg;
+ sck <= sck_int;
+
+end behavioral;