------------------------------------------------------------------------------- -- file: busin.vhd -- -- Module: busin -- -- Revision history: -- 19Dec2009 DF Copied from ESC4:rcin, rewrote a bit -- 20Mar2010 DF Fixed control polarity, changed switch byte to 'A' -- -- Description: Decodes bus data into switch and pwm commands. -- -- The bus input is an 8-bit entity containing two types of information: -- Channel is in bit 0 and mode is in bit 7 on the falling edge of Load\. -- Data are in bits 0-7 on the rising edge of Load\. -- -- Data format: -- -- Motor command: 0x00 is full reverse, 0x80 stopped, 0xff full forward. -- We use 1's complement to avoid speed=0x80 when data=0x00. -- -- data speed dir -- 0x00 0x7f 1 -- 0x40 0x3f 1 -- 0x7f 0x00 1 -- 0x80 0x00 0 -- 0xc0 0x40 0 -- 0xff 0x7f 0 -- -- Switch command: -- 0xaa active -- anything else off -- -- Switch 1 is active =0 closed, switch 2 is active =1 open. -- -- The phase input identifies when to issue the start pulse to each pwm. -- If slot = phase, then phase is active. -- The two pwm engines alternate start pulses, one every other phase rising edge. -- -- The work to be performed by this module is: -- -- convert phase and slot into start(2..1) -- -- convert data and load_i into speed, dir and load(2..1) and switch(2..1) -- -- --------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; --use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity busin is port ( clock_i : in std_logic; reset_i : in std_logic; -- bus interface data_i : in std_logic_vector(7 downto 0); load_i : in std_logic; slot_i : in std_logic; phase_i : in std_logic; -- pwm engine interface dir : out std_logic; speed : out std_logic_vector(6 downto 0); load : out std_logic_vector(2 downto 1); start : out std_logic_vector(2 downto 1); -- output data switch1_o : out std_logic; switch2_o : out std_logic ); end busin; architecture behavioral of busin is signal load_is, load_was : std_logic; signal phase_is, phase_was : std_logic; signal last_pwm, next_last_pwm : std_logic; signal chan, next_chan : std_logic; signal mode, next_mode : std_logic; signal switch1, next_switch1 : std_logic; signal switch2, next_switch2 : std_logic; begin BUSIN_SYNC_PROCESS: process (clock_i, reset_i) begin if (reset_i = '1') then chan <= '0'; mode <= '0'; switch1 <= '0'; switch2 <= '0'; last_pwm <= '0'; load_was <= '0'; load_is <= '0'; phase_was <= '0'; phase_is <= '0'; elsif (clock_i'event and clock_i = '1') then chan <= next_chan; mode <= next_mode; switch1 <= next_switch1; switch2 <= next_switch2; last_pwm <= next_last_pwm; -- resync load and phase for edge detection load_is <= not(load_i); -- invert it since active low input load_was <= load_is; phase_is <= (phase_i xor slot_i); -- invert it depending on slot phase_was <= phase_is; end if; end process BUSIN_SYNC_PROCESS; BUSIN_COMB_PROCESS: process (data_i, load_is, load_was, switch1, chan, mode, switch2, last_pwm, phase_is, phase_was) begin next_chan <= chan; next_mode <= mode; next_switch1 <= switch1; next_switch2 <= switch2; next_last_pwm <= last_pwm; load <= (others=>'0'); start <= (others=>'0'); -- Create start pulse to the correct PWM engine if (phase_is = '1' and phase_was = '0' and last_pwm = '0') then start <= "10"; next_last_pwm <= '1'; elsif (phase_is = '1' and phase_was = '0' and last_pwm = '1') then start <= "01"; next_last_pwm <= '0'; end if; -- Invert speed if reverse if (data_i(7) = '1') then speed <= data_i(6 downto 0); -- forward dir <= '1'; else speed <= not(data_i(6 downto 0)); -- reverse dir <= '0'; end if; -- capture channel number on start of load pulse if (load_is = '1' and load_was = '0') then next_chan <= data_i(0); -- which channel next_mode <= data_i(7); -- 0 for pwm, 1 for switches end if; -- Create speed update flag to the correct PWM engine if (load_is = '0' and load_was = '1' and mode = '0') then case chan is when '0' => load <= "01"; when '1' => load <= "10"; when others => load <= "00"; end case; end if; -- set a switch if requested by ASCII 'A' data if (load_is = '0' and load_was = '1' and mode = '1' and chan = '0') then if (data_i = "01000001") then next_switch1 <= '1'; else next_switch1 <= '0'; end if; elsif (load_is = '0' and load_was = '1' and mode = '1' and chan = '1') then if (data_i = "01000001") then next_switch2 <= '1'; else next_switch2 <= '0'; end if; end if; switch1_o <= not(switch1); -- inverted since active is 0 on wire switch2_o <= switch2; end process BUSIN_COMB_PROCESS; end behavioral;