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