wave: add square waveform generator
This commit is contained in:
130
wave/square.vhdl
Normal file
130
wave/square.vhdl
Normal file
@@ -0,0 +1,130 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user