]> rtime.felk.cvut.cz Git - fpga/virtex2/uart.git/blobdiff - omsp_pwm.vhd
+ PWM output capability.
[fpga/virtex2/uart.git] / omsp_pwm.vhd
diff --git a/omsp_pwm.vhd b/omsp_pwm.vhd
new file mode 100644 (file)
index 0000000..24afa76
--- /dev/null
@@ -0,0 +1,96 @@
+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 with 16-bit MCU interface.
+--
+-- PWM bit width is configurable by PWM_WIDTH generic parameter and must be in
+-- range of 1 to 16. Default is 16.
+--
+-- 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.
+--
+-- MCU interface consist of one r/w 16-bit register holding PWM value.
+--------------------------------------------------------------------------------
+
+entity omsp_pwm is
+  generic (
+    ADDR      : integer := 16#0160#;
+    PWM_WIDTH : integer := 16);
+  port (
+    -- MCU peripheral interface
+    mclk     : in  std_logic;
+    puc      : in  std_logic;
+    per_addr : in  std_logic_vector (7 downto 0);
+    per_en   : in  std_logic;
+    per_wen  : in  std_logic_vector (1 downto 0);
+    per_din  : in  std_logic_vector (15 downto 0);
+    per_dout : out std_logic_vector (15 downto 0);
+    -- PWM interface
+    pwm_cnt  : in  std_logic_vector (PWM_WIDTH-1 downto 0);
+    pwm      : out std_logic);
+end omsp_pwm;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of omsp_pwm is
+
+  signal pwm_value : std_logic_vector (15 downto 0);
+  
+  signal pwm_sel : boolean;
+  
+--------------------------------------------------------------------------------
+
+begin
+
+  pwm_sel <= (per_addr = ADDR/2) and (per_en = '1');
+
+  per_dout <= pwm_value when pwm_sel else
+              (others => '0');
+  
+
+  -- Peripheral registers
+  process (mclk, puc)
+  begin
+    if puc = '1' then
+      pwm_value <= (others => '0');
+
+    elsif rising_edge(mclk) and pwm_sel then
+      if per_wen (0) = '1' then
+        pwm_value (7 downto 0) <= per_din (7 downto 0);
+      end if;
+      
+      if per_wen (1) = '1' then
+        pwm_value (15 downto 8) <= per_din (15 downto 8);
+      end if;
+    end if;
+  end process;
+
+
+  -- Generation of the PWM signal
+  process (mclk, puc)
+  begin
+    if puc = '1' then
+      pwm <= '0';
+      
+    elsif mclk'event and mclk = '1' then
+      if pwm_cnt < pwm_value then
+        pwm <= '1';
+      else
+        pwm <= '0';
+      end if;
+    end if;
+  end process;
+
+end behavioral;
+