Mit einer DDFS-Einheit und einer PWM-Einheit lässt sich einfach eine PWM-Sinus-Ausgabe realisieren.
Dazu nehme ich die DDFS und die PWM und verbinde sie in der SinusPWM Entity zur gewünschten Funktion:
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
entity SinusPWM is
Port ( clk : in STD_LOGIC;
pwmout : out STD_LOGIC);
end SinusPWM;
architecture Behavioral of SinusPWM is
component DDFS is
Port ( CLK : in std_logic;
Freq_Data : in std_logic_vector (7 downto 0);
Dout : out std_logic_vector (7 downto 0));
end component;
component PWM is
Port ( clk : in std_logic;
pwmvalue : in std_logic_vector (7 downto 0);
pwmout : out std_logic);
end component;
signal sinus : std_logic_vector(7 downto 0);
signal sinusplusoffset : std_logic_vector(7 downto 0);
begin
I_ddfs : DDFS
port map( CLK => clk,
Freq_Data => x"cc",
Dout => sinus);
sinusplusoffset <= std_logic_vector(unsigned(sinus)+to_unsigned(128,8));
I_pwm : PWM
port map( CLK => clk,
pwmvalue => sinusplusoffset,
pwmout => pwmout);
end Behavioral;
Zusammen mit der recht übersichtlichen Testbench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb_sinusPWM_vhd IS
END tb_sinusPWM_vhd;
ARCHITECTURE behavior OF tb_sinusPWM_vhd IS
COMPONENT SinusPWM
PORT( clk : IN std_logic; pwmout : OUT std_logic);
END COMPONENT;
SIGNAL clk : std_logic := '0';
SIGNAL pwmout : std_logic;
BEGIN
uut: SinusPWM PORT MAP(clk => clk, pwmout => pwmout);
clk <= not clk after 10 ns;
END;
ergibt das dann diese Waveform
Hier die drei Quelldateien:
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
entity SinusPWM is
Port ( clk : in STD_LOGIC;
pwmout : out STD_LOGIC);
end SinusPWM;
architecture Behavioral of SinusPWM is
component DDFS is
Port ( CLK : in std_logic;
Freq_Data : in std_logic_vector (7 downto 0);
Dout : out std_logic_vector (7 downto 0));
end component;
component PWM is
Port ( clk : in std_logic;
pwmvalue : in std_logic_vector (7 downto 0);
pwmout : out std_logic);
end component;
signal sinus : std_logic_vector(7 downto 0);
signal sinusplusoffset : std_logic_vector(7 downto 0);
begin
I_ddfs : DDFS
port map( CLK => clk,
Freq_Data => x"cc",
Dout => sinus);
sinusplusoffset <= std_logic_vector(unsigned(sinus)+to_unsigned(128,8));
I_pwm : PWM
port map( CLK => clk,
pwmvalue => sinusplusoffset,
pwmout => pwmout);
end Behavioral;
-------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
Entity DDFS is
Port ( CLK : in std_logic;
Freq_Data : in std_logic_vector (7 downto 0);
Dout : out std_logic_vector (7 downto 0)
);
end DDFS;
Architecture RTL of DDFS is
signal Result : std_logic_vector (7 downto 0);
signal Accum : unsigned (20 downto 0) := (others=>'0');
alias Address : unsigned (6 downto 0) is Accum(Accum'high-1 downto Accum'high-7);
alias Sign : std_logic is Accum(Accum'high); -- MSB
begin
process begin
wait until rising_edge(CLK);
Accum <= Accum + unsigned(Freq_Data);
end process;
process (Address)
type Rom128x8 is array (0 to 127) of std_logic_vector (7 downto 0);
constant Sinus_Rom : Rom128x8 := (
x"00", x"03", x"06", x"09", x"0c", x"0f", x"12", x"15",
x"18", x"1b", x"1e", x"21", x"24", x"27", x"2a", x"2d",
x"30", x"33", x"36", x"39", x"3b", x"3e", x"41", x"43",
x"46", x"49", x"4b", x"4e", x"50", x"52", x"55", x"57",
x"59", x"5b", x"5e", x"60", x"62", x"64", x"66", x"67",
x"69", x"6b", x"6c", x"6e", x"70", x"71", x"72", x"74",
x"75", x"76", x"77", x"78", x"79", x"7a", x"7b", x"7b",
x"7c", x"7d", x"7d", x"7e", x"7e", x"7e", x"7e", x"7e",
x"7f", x"7e", x"7e", x"7e", x"7e", x"7e", x"7d", x"7d",
x"7c", x"7b", x"7b", x"7a", x"79", x"78", x"77", x"76",
x"75", x"74", x"72", x"71", x"70", x"6e", x"6c", x"6b",
x"69", x"67", x"66", x"64", x"62", x"60", x"5e", x"5b",
x"59", x"57", x"55", x"52", x"50", x"4e", x"4b", x"49",
x"46", x"43", x"41", x"3e", x"3b", x"39", x"36", x"33",
x"30", x"2d", x"2a", x"27", x"24", x"21", x"1e", x"1b",
x"18", x"15", x"12", x"0f", x"0c", x"09", x"06", x"03" );
begin
Result <= Sinus_Rom (to_integer(Address));
end process;
-- Output registers
-- ----------------
process begin
wait until rising_edge(CLK);
if (Sign='1')
then Dout <= Result;
else Dout <= std_logic_vector (- signed(Result));
end if;
end process;
end RTL;
-------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity PWM is
Port ( clk : in STD_LOGIC;
pwmvalue : in STD_LOGIC_VECTOR (7 downto 0);
pwmout : out STD_LOGIC := '0');
end PWM;
architecture Behavioral of PWM is
signal cnt : integer range 0 to 254 := 0;
begin
process begin
wait until rising_edge(clk);
-- Zähler
if (cnt<254) then cnt <= cnt+1;
else cnt <= 0;
end if;
end process;
-- Vergleicher
pwmout <= '0' when (cnt>=to_integer(unsigned(pwmvalue))) else '1';
end Behavioral;