library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity steering_servo is generic ( -- pwd_period controls the output peroid -- of the pulse width modulator, -- pwm_duty_cycle and pwm_counter width -- should be adjusted if this generic is altered trim : positive := 18; pwm_period : positive := 272 ); port ( -- clk is rising edge sensitive -- reset and enable are active high clk, enable, reset : in std_logic; servo_pos : in std_logic_vector(3 downto 0); servo_out : buffer std_logic ); end steering_servo; architecture behavioral of steering_servo is signal pwm_counter : std_logic_vector(8 downto 0); signal slow_clk : std_logic; signal slow_clk_count : std_logic_vector(10 downto 0); signal duty_cycle : std_logic_vector(8 downto 0); signal zero : std_logic_vector(3 downto 0); begin zero <= "0111"; -- provides a clock of 16.3262 kHz process (clk) begin if reset = '0' then slow_clk_count <= (others => '0'); slow_clk <= '0'; elsif clk'event and clk = '1' then if slow_clk_count >= 771 then slow_clk_count <= (others => '0'); slow_clk <= not slow_clk; else slow_clk_count <= slow_clk_count + 1; end if; end if; end process; process (slow_clk) begin if reset = '0' then pwm_counter <= (others => '0'); duty_cycle <= zero + trim; elsif slow_clk'event and slow_clk = '1' then -- if our counter has exceeded the desired -- period then restart it if pwm_counter >= pwm_period then pwm_counter <= (others => '0'); else pwm_counter <= pwm_counter + 1; end if; -- if enabled adjust the servo position -- as required -- else set it to zero position if enable = '1' then duty_cycle <= (servo_pos + trim); end if; -- output a 1 for the duty cycle and -- output 0 otherwise if pwm_counter < duty_cycle then servo_out <= '1'; else servo_out <= '0'; end if; end if; end process; end behavioral;