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