From: Vladimir Burian Date: Sat, 12 Feb 2011 22:46:34 +0000 (+0100) Subject: + PWM output capability. X-Git-Url: http://rtime.felk.cvut.cz/gitweb/fpga/virtex2/uart.git/commitdiff_plain/e46674ac277a1a88f8e0bcab9d52e683b1603fee + PWM output capability. Added 2 new entities: counter and omsp_pwm. Instances of these are inserted in the top-level. --- diff --git a/counter.vhd b/counter.vhd new file mode 100644 index 0000000..cfb698a --- /dev/null +++ b/counter.vhd @@ -0,0 +1,49 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +-------------------------------------------------------------------------------- +-- General counter which count width and maximum value can be set by generic +-- attributes. +-------------------------------------------------------------------------------- + +entity counter is + generic ( + WIDTH : integer := 16; + MAX : integer := 2**16 - 1); + port ( + clk : in std_logic; + reset : in std_ulogic; + count : out std_logic_vector (WIDTH-1 downto 0)); +end counter; + +-------------------------------------------------------------------------------- + +architecture behavioral of counter is + + signal cnt : std_logic_vector (WIDTH-1 downto 0); + +-------------------------------------------------------------------------------- + +begin + + count <= cnt; + + + process (clk, reset) is + begin + if reset = '1' then + cnt <= (others => '0'); + + elsif clk'event and clk = '1' then + if cnt = CONV_STD_LOGIC_VECTOR(MAX, WIDTH) then + cnt <= (others => '0'); + else + cnt <= cnt + 1; + end if; + end if; + end process; + +end behavioral; + diff --git a/omsp_pwm.vhd b/omsp_pwm.vhd new file mode 100644 index 0000000..24afa76 --- /dev/null +++ b/omsp_pwm.vhd @@ -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; + diff --git a/openMSP430_uart.prj b/openMSP430_uart.prj index 5d3418b..6d4283c 100644 --- a/openMSP430_uart.prj +++ b/openMSP430_uart.prj @@ -24,6 +24,9 @@ vhdl work uart/fifo.vhd vhdl work uart/baud_gen.vhd vhdl work uart/uart.vhd +vhdl work counter.vhd +vhdl work omsp_pwm.vhd + vhdl work omsp_quadcount.vhd vhdl work quadcount/dff.vhdl vhdl work quadcount/qcounter.vhdl diff --git a/openMSP430_uart.ucf b/openMSP430_uart.ucf index e28d6b5..a17400a 100644 --- a/openMSP430_uart.ucf +++ b/openMSP430_uart.ucf @@ -24,3 +24,10 @@ NET "ROT_A" LOC = "J2" | PULLDOWN; # pin 03 NET "ROT_B" LOC = "K2" | PULLDOWN; # pin 05 NET "ROT_PRESS" LOC = "E4" | PULLDOWN; # pin 07 +#==============================================================================# +# PWM output # +#==============================================================================# +# Connected to the header J7 (LVDS TX STATUS). + +NET "PWM" LOC = "C1"; # pin 01 + diff --git a/openMSP430_uart.vhd b/openMSP430_uart.vhd index bdd92f6..7537c6f 100644 --- a/openMSP430_uart.vhd +++ b/openMSP430_uart.vhd @@ -14,7 +14,9 @@ entity openMSP430_uart is ROT_FEED : out std_logic; ROT_A : in std_logic; ROT_B : in std_logic; - ROT_PRESS : in std_logic + ROT_PRESS : in std_logic; + + PWM : out std_logic ); end openMSP430_uart; @@ -110,6 +112,33 @@ architecture rtl of openMSP430_uart is ); end component; + component omsp_pwm is + generic ( + ADDR : integer; + PWM_WIDTH : integer); + port ( + 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_cnt : in std_logic_vector (15 downto 0); + pwm : out std_logic); + end component omsp_pwm; + + component counter is + generic ( + WIDTH : integer; + MAX : integer); + port ( + clk : in std_logic; + reset : in std_ulogic; + count : out std_logic_vector (WIDTH-1 downto 0)); + end component counter; + + signal mclk : std_logic; signal puc : std_logic; @@ -142,6 +171,9 @@ architecture rtl of openMSP430_uart is signal uart_dout : std_logic_vector (15 downto 0); signal uart_irq : std_logic; + signal omsp_pwm_dout : std_logic_vector (15 downto 0); + + signal pwm_cnt : std_logic_vector (15 downto 0); -------------------------------------------------------------------------------- @@ -246,10 +278,33 @@ begin txd => TXD ); + omsp_pwm_1 : omsp_pwm + generic map ( + ADDR => 16#0160#, + PWM_WIDTH => 16) + port map ( + mclk => mclk, + puc => puc, + per_addr => per_addr, + per_en => per_en, + per_wen => per_wen, + per_din => per_din, + per_dout => omsp_pwm_dout, + pwm_cnt => pwm_cnt, + pwm => PWM); + counter_1 : counter + generic map ( + WIDTH => 16, + MAX => 2**16 - 2) + port map ( + clk => mclk, + reset => puc, + count => pwm_cnt); + -------------------------------------------------------------------------------- - per_dout <= uart_dout or omsp_quadcount_dout; + per_dout <= uart_dout or omsp_quadcount_dout or omsp_pwm_dout; irq <= (6 => uart_irq, 7 => omsp_quadcount_irq,