library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity servo is generic ( -- controls clock divider frequency divisor : positive := 771; -- adjusts center position of the servo trim : positive := 18; -- servo_period controls the output peroid -- and should be adjusted if "divisor" is changed servo_period : positive := 272 ); port ( clk, reset : in std_logic; servo_pos : in std_logic_vector(3 downto 0); servo_out : buffer std_logic ); end servo; architecture behavioral of servo is signal slow_clk : std_logic; signal slow_clk_count : std_logic_vector(10 downto 0); signal servo_counter : std_logic_vector(8 downto 0); begin -- a simple clock divider -- divides by (divisor x 2) 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 >= divisor 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; -- this process controls the width of the pulse -- being sent to the servo, -- proportional to servo_pos process (slow_clk) begin if reset = '0' then servo_counter <= (others => '0'); elsif slow_clk'event and slow_clk = '1' then -- servo_period controls the period -- of the signal which is sent to -- the servo if servo_counter >= servo_period then servo_counter <= (others => '0'); else servo_counter <= servo_counter + 1; end if; -- depending how far into the period -- we are output a '1' or a '0' if servo_counter < (servo_pos + trim) then servo_out <= '1'; else servo_out <= '0'; end if; end if; end process; end behavioral;