PWM

From CPCWiki - THE Amstrad CPC encyclopedia!
Revision as of 09:21, 5 March 2017 by Freemac (Talk | contribs)

Jump to: navigation, search

Pulse Width Modulation, is a DAC (Digital Analog Convertor) using only numerical components (outputting only 0v or 5v values)
Using a entry clock, you output a signal 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 as you want but using at input 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;
   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 is a bad border effect : it 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 https://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;
   clk_ref : in std_logic;
   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;