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;
 |