wave: axi4-compliant wave
This commit is contained in:
46
wave/pdm.vhdl
Normal file
46
wave/pdm.vhdl
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
entity 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 pdm;
|
||||||
|
|
||||||
|
architecture Behavioral of pdm is
|
||||||
|
|
||||||
|
signal feedback: signed(16 downto 0);
|
||||||
|
|
||||||
|
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) and enabled = '1' 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;
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
175
wave/wave.vhdl
Normal file
175
wave/wave.vhdl
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
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;
|
||||||
165
wave/wave_test.vhdl
Normal file
165
wave/wave_test.vhdl
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use std.textio.all;
|
||||||
|
|
||||||
|
entity wave_test is
|
||||||
|
end wave_test;
|
||||||
|
|
||||||
|
architecture rtl of wave_test is
|
||||||
|
|
||||||
|
component 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 component;
|
||||||
|
|
||||||
|
signal finished, clk, rst, rstn: std_logic := '0';
|
||||||
|
|
||||||
|
signal arvalid, arready, awvalid, awready: std_logic;
|
||||||
|
signal rresp, rvalid, rready, bresp, bvalid, bready: std_logic;
|
||||||
|
signal wstrb: std_logic_vector(3 downto 0);
|
||||||
|
signal araddr, rdata, awaddr, wdata: std_logic_vector(31 downto 0);
|
||||||
|
|
||||||
|
signal pdmout: std_logic;
|
||||||
|
|
||||||
|
constant period: integer := 7 * 256;
|
||||||
|
constant half_time: time := 1280 ns * period;
|
||||||
|
|
||||||
|
begin
|
||||||
|
rstn <= not rst;
|
||||||
|
dut: wave port map(aclk => clk, aresetn => rstn,
|
||||||
|
arvalid => arvalid, arready => arready, awvalid => awvalid, awready => awready,
|
||||||
|
rresp => rresp, rvalid => rvalid, rready => rready, bresp => bresp, bvalid => bvalid, bready => bready,
|
||||||
|
wstrb => wstrb, araddr => araddr, rdata => rdata, awaddr => awaddr, wdata => wdata,
|
||||||
|
pdmout => pdmout
|
||||||
|
);
|
||||||
|
|
||||||
|
-- tick tock
|
||||||
|
process
|
||||||
|
begin
|
||||||
|
if finished = '0' then
|
||||||
|
clk <= not clk;
|
||||||
|
wait for 5 ns;
|
||||||
|
else
|
||||||
|
clk <= '0';
|
||||||
|
wait;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
process
|
||||||
|
begin
|
||||||
|
rst <= '1';
|
||||||
|
|
||||||
|
arvalid <= '0';
|
||||||
|
awvalid <= '0';
|
||||||
|
wstrb <= "0000";
|
||||||
|
|
||||||
|
wait for 1 ns;
|
||||||
|
-- assert(='0') report "Fail rst" severity error;
|
||||||
|
|
||||||
|
rst <= '0';
|
||||||
|
|
||||||
|
wait for 10 ns;
|
||||||
|
|
||||||
|
awvalid <= '1';
|
||||||
|
awaddr <= x"00000000"; -- enable
|
||||||
|
wstrb <= "1111";
|
||||||
|
wdata <= x"00000001";
|
||||||
|
bready <= '1';
|
||||||
|
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(bvalid = '1') report "Write error" severity error;
|
||||||
|
assert(bresp = '0') report "Write fail" severity error;
|
||||||
|
assert(awready = '1') report "Write error" severity error;
|
||||||
|
|
||||||
|
awaddr <= x"00000004"; -- period
|
||||||
|
wdata <= std_logic_vector(to_unsigned(period, 32));
|
||||||
|
|
||||||
|
wait for 10 ns;
|
||||||
|
|
||||||
|
-- read back
|
||||||
|
wstrb <= "0000";
|
||||||
|
awvalid <= '0';
|
||||||
|
arvalid <= '1';
|
||||||
|
araddr <= x"00000004";
|
||||||
|
rready <= '1';
|
||||||
|
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(unsigned(rdata) = period) report "Period readback failed" severity error;
|
||||||
|
|
||||||
|
arvalid <= '0';
|
||||||
|
awvalid <= '1';
|
||||||
|
wstrb <= "1111";
|
||||||
|
|
||||||
|
awaddr <= x"00000008"; -- high
|
||||||
|
wdata <= x"00008000";
|
||||||
|
|
||||||
|
wait for 10 ns;
|
||||||
|
|
||||||
|
awaddr <= x"0000000c"; -- low
|
||||||
|
wdata <= x"00004000";
|
||||||
|
|
||||||
|
wait for 10 ns;
|
||||||
|
|
||||||
|
wstrb <= "0000";
|
||||||
|
awvalid <= '0';
|
||||||
|
|
||||||
|
wait for 30 ns;
|
||||||
|
assert(pdmout = '1') report "wrong pdmout" severity error;
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(pdmout = '0') report "wrong pdmout" severity error;
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(pdmout = '0') report "wrong pdmout" severity error;
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(pdmout = '1') report "wrong pdmout" severity error;
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(pdmout = '0') report "wrong pdmout" severity error;
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(pdmout = '0') report "wrong pdmout" severity error;
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(pdmout = '0') report "wrong pdmout" severity error;
|
||||||
|
wait for 10 ns;
|
||||||
|
assert(pdmout = '1') report "wrong pdmout" severity error;
|
||||||
|
|
||||||
|
wait for 100 us;
|
||||||
|
|
||||||
|
assert false report "Test done." severity note;
|
||||||
|
|
||||||
|
finished <= '1';
|
||||||
|
wait;
|
||||||
|
|
||||||
|
end process;
|
||||||
|
end rtl;
|
||||||
Reference in New Issue
Block a user