Difference between revisions of "PWM"
(One intermediate revision by one other user not shown) | |||
Line 56: | Line 56: | ||
entity PWM is | entity PWM is | ||
port ( | port ( | ||
− | clk : in std_logic; -- 50MHz : higher than dog and cat frequency | + | clk : in std_logic; -- 50MHz : higher than dog and cat frequency, a multiple of clk_ref |
clk_ref : in std_logic; -- 1MHz : same one as sound chip clk | clk_ref : in std_logic; -- 1MHz : same one as sound chip clk | ||
PWM_in : in std_logic_vector (7 downto 0) := "00000000"; | PWM_in : in std_logic_vector (7 downto 0) := "00000000"; | ||
Line 97: | Line 97: | ||
PWM_out <= PWM_Accumulator(8); | PWM_out <= PWM_Accumulator(8); | ||
end PWM_arch; | end PWM_arch; | ||
+ | |||
+ | [[Category:Hardware]] |
Latest revision as of 07:29, 11 March 2018
Pulse Width Modulation, is a DAC (Digital Analog Convertor) using only numerical components (outputting only 0v or 5v values)
Using an entry clock, you output several signals 0v or 5v in order to result an average fix value between 0v and 5v, for sample 2.3v. Changing like it the speed of a small electric motor (speeding it up or slowing it down) as you want but using at its inputs only two values : 0v or 5v.
Using a quicker clock, you can generate analog signal, like sound music.
pwm.vhd
library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.ALL; -- http://www.fpga4fun.com/PWM_DAC.html entity PWM is port ( clk : in std_logic; -- 1MHz : same one as sound chip clk PWM_in : in std_logic_vector (7 downto 0) := "00000000"; PWM_out : out std_logic ); end PWM; architecture PWM_arch of PWM is signal PWM_Accumulator : std_logic_vector(8 downto 0):=(others=>'0'); -- sim XXXXXXXXX begin process begin wait until rising_edge(clk); PWM_Accumulator <= ("0" & PWM_Accumulator(7 downto 0)) + ("0" & PWM_in); end process; PWM_out <= PWM_Accumulator(8); end PWM_arch;
Ok, let's go further, let's target 2.5v using only 0v and 5v, with a stupid slow clock, you result in a sequence like this : 05050505050505v. It has a bad border effect : it's a noise ! 2.5v normaly doesn't produce sound by here, but using this simple PWM it does.
This problem is solved here : this is an original homemade PWM component enabling Arkanoid not producing noises instead of silents, don't ask me how I solved it two years ago but it does :
pwm.vhd - currently used in FPGAmstrad project
-- {@{@{@{@{@{@ -- {@{@{@{@{@{@{@{@ This code is covered by CoreAmstrad synthesis r004 -- {@ {@{@ {@ A core of Amstrad CPC 6128 running on MiST-board platform -- {@{@{@{@{@{@{@{@ -- {@ {@{@{@{@ {@ CoreAmstrad is implementation of FPGAmstrad on MiST-board -- {@{@ {@{@ Contact : renaudhelias@gmail.com -- {@{@{@{@{@{@{@{@ @see http://github.com/mist-devel/mist-board/wiki -- {@{@{@{@{@{@ @see FPGAmstrad at CPCWiki -- -- -------------------------------------------------------------------------------- -- FPGAmstrad_amstrad_motherboard.PWM patched for luxurious output quality -- clk : a big clock, upper than dog sound frequency, here 17MHz -- clk_ref : clock matching with PWM_in data, here YM2149.CLK (Yamaha chip clock) -------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.ALL; -- http://www.fpga4fun.com/PWM_DAC.html entity PWM is port ( clk : in std_logic; -- 50MHz : higher than dog and cat frequency, a multiple of clk_ref clk_ref : in std_logic; -- 1MHz : same one as sound chip clk PWM_in : in std_logic_vector (7 downto 0) := "00000000"; PWM_out : out std_logic ); end PWM; architecture PWM_arch of PWM is signal PWM_Accumulator : std_logic_vector(8 downto 0):=(others=>'0'); -- sim XXXXXXXXX signal PWM_iRef:std_logic_vector(7 downto 0); signal PWM_i:std_logic_vector(7 downto 0); begin process(clk_ref) variable PWM_mem : std_logic_vector(7 downto 0):=x"00"; begin if rising_edge(clk_ref) then PWM_mem:=PWM_in; PWM_iRef<=PWM_mem; end if; end process; process(clk) variable PWM_mem : std_logic_vector(7 downto 0):=x"00"; begin if rising_edge(clk) then PWM_mem:=PWM_iRef; PWM_i<=PWM_mem; end if; end process; process(clk) begin if rising_edge(clk) then PWM_Accumulator <= ("0" & PWM_Accumulator(7 downto 0)) + ("0" & PWM_i); end if; end process; PWM_out <= PWM_Accumulator(8); end PWM_arch;