176 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
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;
 |