library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity DS_dac3 is
    port (
        clk     : in  std_logic;
        reset   : in  std_logic;                      -- active high synchronous reset
        data_in : in  signed(15 downto 0);
        pdm_out : out std_logic
    );
end entity DS_dac3;

architecture behavioral of DS_dac3 is

    -- Integrators
    signal int1_reg, int1_next : signed(18 downto 0);
    signal int2_reg, int2_next : signed(18 downto 0);

    -- Quantizer output (registered)
    signal quant_reg : std_logic;

    -- Input synchronizer
    signal data_in_sync1 : signed(15 downto 0);
    signal data_in_sync2 : signed(15 downto 0);

    -- LFSR for dither (your proven good polynomial)
    signal lfsr : std_logic_vector(15 downto 0) := x"ACE1";
    signal lfsr_fb : std_logic;

    -- Dither added to quantizer input (± approx 0.5 LSB of the 1-bit quantizer)
    signal dither : signed(18 downto 0);

    -- Signal after adding dither to second integrator
    signal quant_input : signed(18 downto 0);

    -- Feedback
    constant FB_LEVEL : signed(18 downto 0) := to_signed(32768, 19);
    signal feedback   : signed(18 downto 0);

begin

    ------------------------------------------------------------------------
    -- Input synchronizer
    ------------------------------------------------------------------------
    sync_process: process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                data_in_sync1 <= (others => '0');
                data_in_sync2 <= (others => '0');
            else
                data_in_sync1 <= data_in;
                data_in_sync2 <= data_in_sync1;
            end if;
        end if;
    end process;

    ------------------------------------------------------------------------
    -- LFSR - runs every clock cycle
    ------------------------------------------------------------------------
    lfsr_fb <= lfsr(15) xor lfsr(13) xor lfsr(12) xor lfsr(10);

    process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                lfsr <= x"ACE1";
            else
                lfsr <= lfsr(14 downto 0) & lfsr_fb;
            end if;
        end if;
    end process;

    ------------------------------------------------------------------------
    -- Rectangular dither ≈ ±16384 (half quantizer step)
    -- Uses 15 bits to avoid zero state, scaled up by 2 bits for headroom
    ------------------------------------------------------------------------
    dither <= signed(lfsr(14 downto 0) & "00") - to_signed(16384, 19);

    ------------------------------------------------------------------------
    -- State registers and quantizer
    ------------------------------------------------------------------------
    state_update: process(clk)
    begin
        if rising_edge(clk) then
            if reset = '1' then
                int1_reg    <= (others => '0');
                int2_reg    <= (others => '0');
                quant_reg   <= '0';
                quant_input <= (others => '0');
            else
                int1_reg    <= int1_next;
                int2_reg    <= int2_next;
                quant_input <= int1_reg + dither;          -- add dither here
                quant_reg   <= quant_input(18);           -- simple MSB indexing
            end if;
        end if;
    end process;

    ------------------------------------------------------------------------
    -- Combinational feedback (simple conditional signal - fully supported)
    ------------------------------------------------------------------------
    feedback_proc: process(quant_reg)
    begin
        if quant_reg = '1' then
            feedback <= FB_LEVEL;
        else
            feedback <= -FB_LEVEL;
        end if;
    end process;

    ------------------------------------------------------------------------
    -- Next-state logic (pure combinational, no conditionals in arithmetic)
    ------------------------------------------------------------------------
    int1_next <= int1_reg + resize(data_in_sync2, 19) - feedback;
    int2_next <= int2_reg + int1_next;

    ------------------------------------------------------------------------
    -- Output
    ------------------------------------------------------------------------
    pdm_out <= not quant_reg;
    -- pdm_out <= not quant_reg;  -- uncomment if you need inverted polarity

end architecture behavioral;