library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- some kind of square wave generator, with PDM output entity wave is port ( -- AXI4 slave interface aclk : in std_logic; aresetn : in std_logic; -- read addr araddr : in std_logic_vector(31 downto 0); arvalid : in std_logic; arready : out std_logic; -- read data rdata : out std_logic_vector(31 downto 0); rresp : out std_logic; rvalid : out std_logic; rready : in std_logic; -- write addr awaddr : in std_logic_vector(31 downto 0); awvalid : in std_logic; awready : out std_logic; -- write data wdata : in std_logic_vector(31 downto 0); wstrb : in std_logic_vector(3 downto 0); -- write resp bresp : out std_logic; bvalid : out std_logic; bready : in std_logic; -- PDM output! pdmout : out std_logic ); end wave; -- -- Mem layout: -- 0x00: control: [bit0: enabled] -- 0x04: 32-bit unsigned period (in clock cycles) -- 0x08: 16-bit unsigned high value (high 16 bits ignored) -- 0x0c: 16-bit unsigned low value (high 16 bits ignored) architecture Behavioral of wave is component pdm is port ( clk : in std_logic; rst : in std_logic; -- hardware out_pin : out std_logic; -- input interface enabled : in std_logic; sample : in std_logic_vector(15 downto 0) ); end component; -- all registers signal period, hi_val, lo_val, sample: std_logic_vector(15 downto 0); signal enabled, rst, onwrite: std_logic; signal counter: unsigned(23 downto 0); begin arready <= '1'; awready <= '1'; rst <= not aresetn; pdm0: pdm port map(clk => aclk, rst => rst, out_pin => pdmout, sample => sample, enabled => enabled); -- main process -- drives counter, sample process(aclk, aresetn) variable high: std_logic; begin if aresetn = '0' then counter <= to_unsigned(0, 24); sample <= x"0000"; high := '0'; elsif rising_edge(aclk) then counter <= to_unsigned(0, 24); if high = '1' then sample <= hi_val; else sample <= lo_val; end if; if enabled = '1' and unsigned(period) /= 0 and onwrite = '0' then if counter(22 downto 7) = unsigned(period) - 1 and counter(6 downto 0) = x"7f" then high := not high; else counter <= counter + 1; end if; end if; end if; end process; -- Bus slave process -- drives period, value, out_addr, enabled, onwrite process(aclk, aresetn) -- 00: control, 01: period, 02: high, 03: low variable waddr: std_logic_vector(2 downto 0); variable raddr: std_logic_vector(2 downto 0); begin if aresetn = '0' then period <= x"0000"; hi_val <= x"0000"; lo_val <= x"0000"; enabled <= '0'; waddr := "000"; elsif rising_edge(aclk) then rvalid <= '0'; rdata <= x"00000000"; rresp <= '0'; bvalid <= '0'; bresp <= '0'; onwrite <= '0'; if arvalid = '1' then raddr := araddr(4 downto 2); end if; if awvalid = '1' then waddr := awaddr(4 downto 2); end if; if arvalid = '1' then case waddr(1 downto 0) is when "00" => rdata(0) <= enabled; when "01" => rdata(23 downto 8) <= period; when "10" => rdata(15 downto 0) <= hi_val; when "11" => rdata(15 downto 0) <= lo_val; when others => end case; rvalid <= '1'; end if; if unsigned(wstrb) > 0 then case waddr(1 downto 0) is when "00" => enabled <= wdata(0); when "01" => period <= wdata(23 downto 8); when "10" => hi_val <= wdata(15 downto 0); when "11" => lo_val <= wdata(15 downto 0); when others => end case; bvalid <= '1'; onwrite <= '1'; end if; end if; end process; end Behavioral;