]> rtime.felk.cvut.cz Git - fpga/pwm.git/blobdiff - pwm.vhd
Added counter and pwm modules.
[fpga/pwm.git] / pwm.vhd
diff --git a/pwm.vhd b/pwm.vhd
new file mode 100644 (file)
index 0000000..4cfcc29
--- /dev/null
+++ b/pwm.vhd
@@ -0,0 +1,89 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+--------------------------------------------------------------------------------
+-- This entity is a generator of PWM signal.
+--
+-- PWM bit width is configurable by PWM_WIDTH generic parameter.
+--
+-- In practice, to generate PWM signal component must be fed by a counter vector
+-- (pwm_cnt input) of appropriate width and also period! (One counter can be
+-- used by several PWM generators and generated signals are then synchronized.)
+--
+-- The period of the input counter vector should be by 1 smaller than the count
+-- of all possible PWM values, i.e. counter vector should never reaches the
+-- maximum possible PWM value, and counting should start from 0. E.g. when full
+-- range of PWM values is used, binary counter should be reset just one step
+-- before it overflows. In such a case, when PWM value is maximal, output keeps
+-- log. 1.
+--
+-- PWM value is buffered and any change is propageted to the output by the next
+-- pwm period - 'pwm_cyc' must by feed.
+--------------------------------------------------------------------------------
+
+entity pwm is
+  generic (
+    PWM_WIDTH : integer);
+  port (
+    clk     : in  std_logic;
+    reset   : in  std_logic;
+    din     : in  std_logic_vector (PWM_WIDTH-1 downto 0);
+    we      : in  std_logic;
+    -- PWM interface
+    pwm_cnt : in  std_logic_vector (PWM_WIDTH-1 downto 0);
+    pwm_cyc : in  std_logic;            -- Indicate new pwm period
+    pwm     : out std_logic);
+end pwm;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of pwm is
+
+  -- Register accessible from bus
+  signal reg : std_logic_vector (PWM_WIDTH-1 downto 0);
+  -- Compare value during pwm cycle, loaded from 'reg' when new period begins.
+  signal cmp : std_logic_vector (PWM_WIDTH-1 downto 0);
+  
+--------------------------------------------------------------------------------
+
+begin
+
+  -- Peripheral register
+  PWM_REGISTER : process (clk, reset)
+  begin
+    if reset = '1' then
+      reg <= (others => '0');
+
+    elsif rising_edge(clk) then
+      if we = '1' then
+        reg <= din;
+      end if;
+    end if;
+  end process;
+
+
+  -- Generation of PWM signal
+  -- When 'pwm_cyc' is high then new 'cmp' is loaded and 'counter' is reset 
+  -- with next clk edge. Pwm output is delayed by one clock.
+  PWM_GEN : process (clk, reset)
+  begin
+    if reset = '1' then
+      pwm <= '0';
+      
+    elsif rising_edge(clk) then
+      if pwm_cyc = '1' then
+        cmp <= reg;
+      end if;
+      
+      if pwm_cnt < cmp then
+        pwm <= '1';
+      else
+        pwm <= '0';
+      end if;
+    end if;
+  end process;
+
+end behavioral;
+