131 lines
2.8 KiB
VHDL
131 lines
2.8 KiB
VHDL
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);
|
|
|
|
begin
|
|
|
|
-- counter process
|
|
-- drives counter
|
|
process(clk, rst)
|
|
begin
|
|
|
|
if rst = '1' then
|
|
counter <= to_unsigned(0, 24);
|
|
elsif rising_edge(clk) then
|
|
if enabled = '0' or counter(22 downto 7) = unsigned(period) then
|
|
counter <= to_unsigned(0, 24);
|
|
else
|
|
counter <= counter + 1;
|
|
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 counter = 0 and m_busy = '1' then
|
|
deferred := '1';
|
|
elsif deferred = '1' or (counter = 0 and m_busy = '0') 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;
|