library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- some kind of square wave generator, writing 16-bit samples -- to a memory address using DMA periodically entity square is port ( clk : in std_logic; rst : in std_logic; -- bus slave interface s_we : in std_logic; s_addr : in std_logic_vector(15 downto 0); s_din : in std_logic_vector(15 downto 0); -- bus master interface (DMA!!) m_busy : in std_logic; m_we : out std_logic; m_addr : out std_logic_vector(15 downto 0); m_dout : out std_logic_vector(15 downto 0) ); end square; -- -- Mem layout: -- 0x00: 16-bit unsigned period (units of 256 clock cycles) -- 0x02: 16-bit unsigned high value -- 0x04: 16-bit unsigned low value -- 0x06: 16-bit output address -- 0x08: flags: [enabled] architecture Behavioral of square is -- all registers signal period, hi_val, lo_val, out_addr: std_logic_vector(15 downto 0); signal enabled: std_logic; signal counter: unsigned(23 downto 0); signal active: std_logic; begin -- counter process -- drives counter, active process(clk, rst) begin if rst = '1' then counter <= to_unsigned(0, 24); active <= '0'; elsif rising_edge(clk) then active <= '0'; counter <= to_unsigned(0, 24); if enabled = '1' and unsigned(period) /= 0 then if counter(22 downto 7) = unsigned(period) then active <= '1'; else counter <= counter + 1; end if; end if; end if; end process; -- signal generation -- drives m_we, m_addr, m_dout process(clk, rst) variable high: std_logic; variable deferred: std_logic; begin if rst = '1' then m_we <= '0'; m_addr <= x"0000"; m_dout <= x"0000"; high := '0'; deferred := '0'; elsif rising_edge(clk) then m_we <= '0'; if enabled = '1' then if active = '1' and m_busy = '1' then deferred := '1'; elsif m_busy = '0' and (deferred = '1' or active = '1') then m_we <= '1'; m_addr <= out_addr; if high = '1' then m_dout <= hi_val; else m_dout <= lo_val; end if; high := not high; deferred := '0'; end if; end if; end if; end process; -- Bus slave process -- drives period, value, out_addr, enabled process(clk, rst) begin if rst = '1' then period <= x"0000"; hi_val <= x"0000"; lo_val <= x"0000"; out_addr <= x"0000"; enabled <= '0'; elsif rising_edge(clk) then if s_we = '1' then case s_addr(3 downto 0) is when x"0" => period <= s_din; when x"2" => hi_val <= s_din; when x"4" => lo_val <= s_din; when x"6" => out_addr <= s_din; when x"8" => enabled <= s_din(0); when others => end case; end if; end if; end process; end Behavioral;