library ieee; use ieee.std_logic_unsigned.all; use ieee.std_logic_1164.all; entity ManchesterEncoder is port ( CLOCK_IN : in std_logic; -- Global input clock signal CE : in std_logic; -- Accept current data bits for next transmition RST : in std_logic; -- Global reset DATA_IN : in std_logic_vector(7 downto 0); -- Data bits PULSE_W : in std_logic_vector(7 downto 0); -- Output pulse width DATA_OUT : out std_logic; -- Manchaster encoded data CLOCK_OUT : out std_logic; -- Output clock signal BUSY : out std_logic -- Busy flag ); end ManchesterEncoder; architecture Encoder of ManchesterEncoder is type encoder_state is ( idle, process_data, initialise_variables, generate_data, reset_all ); signal act_state : encoder_state; signal nxt_state : encoder_state; signal clock_reference : std_logic; signal data_reference : std_logic; signal clock_ref_cnt : std_logic_vector(19 downto 0); signal data_ref_cnt : std_logic_vector(19 downto 0); signal clock_counter : std_logic_vector(19 downto 0); signal data_counter : std_logic_vector(19 downto 0); signal start : std_logic; signal done : std_logic; begin StateMachine : process( CLOCK_IN, CE, act_state, DATA_IN, PULSE_W, clock_counter, data_counter, clock_ref_cnt, data_ref_cnt, clock_reference, data_reference, done ) variable act_data_idx : std_logic_vector(3 downto 0); variable data_input : std_logic_vector(7 downto 0); variable pulse_width : std_logic_vector(7 downto 0); variable parity : std_logic; begin -- State machine implementation case act_state is when idle => clock_reference <= '0'; data_reference <= '0'; start <= '0'; done <= '1'; act_data_idx := "0000"; data_input := "00000000"; pulse_width := "00000000"; parity := '0'; clock_ref_cnt <= "00000000000000000000"; data_ref_cnt <= "00000000000000000000"; if ( CE = '1' ) then nxt_state <= process_data; else nxt_state <= idle; end if; when process_data => clock_reference <= '0'; data_reference <= '0'; start <= '0'; done <= '0'; act_data_idx := "0000"; data_input := DATA_IN; pulse_width := PULSE_W; parity := '0'; clock_ref_cnt <= "00000000000000000000"; data_ref_cnt <= "00000000000000000000"; if ( CE = '1' ) then nxt_state <= initialise_variables; else nxt_state <= reset_all; end if; when initialise_variables => clock_reference <= '0'; data_reference <= data_input(0); start <= '0'; done <= '0'; act_data_idx := "0000"; parity := data_input(0) xor data_input(1) xor data_input(2) xor data_input(3) xor data_input(4) xor data_input(5) xor data_input(6) xor data_input(7); data_ref_cnt <= pulse_width * "000111110100"; clock_ref_cnt <= pulse_width * "000011111010"; if ( CE = '1' ) then nxt_state <= generate_data; else nxt_state <= reset_all; end if; when generate_data => done <= '0'; start <= '1'; if ( clock_counter = clock_ref_cnt ) then clock_reference <= not clock_reference; end if; if ( data_counter = data_ref_cnt ) then act_data_idx := act_data_idx + 1; end if; case act_data_idx is when "0000" => data_reference <= data_input(0); when "0001" => data_reference <= data_input(1); when "0010" => data_reference <= data_input(2); when "0011" => data_reference <= data_input(3); when "0100" => data_reference <= data_input(4); when "0101" => data_reference <= data_input(5); when "0110" => data_reference <= data_input(6); when "0111" => data_reference <= data_input(7); when "1000" => data_reference <= parity; when others => data_reference <= '0'; end case; if ( act_data_idx = "1001" ) then done <= '1'; end if; if ( CE = '1' and done = '0' ) then nxt_state <= generate_data; else nxt_state <= reset_all; end if; when reset_all => clock_reference <= '0'; data_reference <= '0'; start <= '0'; done <= '1'; act_data_idx := "0000"; data_input := "00000000"; pulse_width := "00000000"; parity := '0'; clock_ref_cnt <= "00000000000000000000"; data_ref_cnt <= "00000000000000000000"; nxt_state <= idle; end case; -- Outputs if ( CLOCK_IN'event and CLOCK_IN = '1' ) then CLOCK_OUT <= clock_reference; DATA_OUT <= data_reference xor clock_reference; BUSY <= not done; end if; end process StateMachine; Counters : process( CLOCK_IN, CE, start, clock_counter, data_counter, clock_ref_cnt, data_ref_cnt ) begin if ( CLOCK_IN'event and CLOCK_IN = '1' ) then if ( CE = '1' and start = '1' ) then clock_counter <= clock_counter + 1; data_counter <= data_counter + 1; end if; end if; if ( clock_counter = clock_ref_cnt ) then clock_counter <= "00000000000000000000"; end if; if ( data_counter = data_ref_cnt ) then data_counter <= "00000000000000000000"; end if; end process Counters; Trigger : process( CLOCK_IN, RST ) begin if ( RST = '1' ) then act_state <= reset_all; elsif ( CLOCK_IN'event and CLOCK_IN = '1' ) then act_state <= nxt_state; end if; end process Trigger; end Encoder;