From 8868a09a07f7a10180e26500fe13e80bbcba8b13 Mon Sep 17 00:00:00 2001 From: rs <> Date: Sun, 14 Dec 2025 16:38:59 -0600 Subject: [PATCH] Add I2S control signal generator --- libraries/dsp/i2s_ctrl.vhd | 122 +++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 libraries/dsp/i2s_ctrl.vhd diff --git a/libraries/dsp/i2s_ctrl.vhd b/libraries/dsp/i2s_ctrl.vhd new file mode 100644 index 0000000..32825a4 --- /dev/null +++ b/libraries/dsp/i2s_ctrl.vhd @@ -0,0 +1,122 @@ +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; -- 2.43.0