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

entity pdmout is
  port
  (
    clk     : in std_logic;
    rst     : in std_logic;

    -- hardware
    out_pin  : out std_logic;

    -- bus interface
    we      : in std_logic;
    addr    : in std_logic_vector(15 downto 0);
    din     : in std_logic_vector(15 downto 0)
  );
end pdmout;

--
-- Mem layout:
--  0x00: 16-bit unsigned amplitude
--  0x02: flags: [enabled]

architecture Behavioral of pdmout is

  signal sample: std_logic_vector(15 downto 0);
  signal feedback: signed(16 downto 0);
  signal enabled: std_logic;

begin

  -- PDM process
  -- drives pin_out, feedback
  process(clk, rst)
  begin

    if rst = '1' then
      feedback <= to_signed(0, 17);
      out_pin <= '0';
    elsif rising_edge(clk) then
      if feedback > 0 then
        out_pin <= '1';
        feedback <= feedback + signed("0" & sample) - ("0" & x"ffff");
      else
        out_pin <= '0';
        feedback <= feedback + signed("0" & sample);
      end if;
    end if;

  end process;

  -- Bus process
  -- drives sample, enabled
  process(clk, rst)
  begin

    if rst = '1' then
      sample <= x"0000";
      enabled <= '0';
    elsif rising_edge(clk) then
      case addr(3 downto 0) is
        when x"0" =>
          if we = '1' then
            sample <= din;
          end if;
        when x"2" =>
          if we = '1' then
            enabled <= din(0);
          end if;
        when others =>
      end case;
    end if;

  end process;

end Behavioral;
