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