library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library unisim; use unisim.vcomponents.all; -------------------------------------------------------------------------------- entity msp_motion is port ( -- Clock & reset CLK_24MHz : in std_logic; RESET : in std_logic; -- RS232 RXD : in std_logic; TXD : out std_logic; -- LED LED0 : out std_logic; LED1 : out std_logic; LED2 : out std_logic; -- PWM PWM0 : out std_logic; PWM0_EN : out std_logic; PWM1 : out std_logic; PWM1_EN : out std_logic; PWM2 : out std_logic; PWM2_EN : out std_logic; -- IRC IRC_INDEX : in std_logic; IRC_A : in std_logic; IRC_B : in std_logic; -- HALL HAL0 : in std_logic; HAL1 : in std_logic; HAL2 : in std_logic); end msp_motion; -------------------------------------------------------------------------------- architecture rtl of msp_motion is ------------------------------------------------------------------------------ -- OpenMSP430 softcore MCU module ------------------------------------------------------------------------------ signal mclk : std_logic; signal puc : std_logic; -- External data bus signal dmem_addr : std_logic_vector (11 downto 0); signal dmem_ce : std_logic; signal dmem_we : std_logic; signal dmem_din : std_logic_vector (15 downto 0); signal dmem_dout : std_logic_vector (15 downto 0); ------------------------------------------------------------------------------ -- Dual-port shared memory ------------------------------------------------------------------------------ -- These signals of A-port (MCU) enables creation of external data encoder and -- multiplexer in a case of multiple devices connected to the external data -- bus. Otherwise useless. signal DPA_DAT_O : std_logic_vector (15 downto 0); signal DPA_SEL : std_logic; signal DPA_STB : std_logic; -- Auxiliary register used to generate IRF_ACK signal IRF_ACK_REG : std_logic; -- Auxiliary signal used to form B-port address signal DPB_ADR : std_logic_vector (9 downto 0); ------------------------------------------------------------------------------ -- Motion Control Chain ------------------------------------------------------------------------------ -- Constants constant PWM_W : integer := 10; constant LUT_ADR_W : integer := 11; constant LUT_INIT : string := "sin1000.lut"; -- Bus interface to the shared memory signal IRF_ACK : std_logic; signal IRF_ADR : std_logic_vector (4 downto 0); signal IRF_DAT_I : std_logic_vector (15 downto 0); signal IRF_DAT_O : std_logic_vector (15 downto 0); signal IRF_STB : std_logic; signal IRF_WE : std_logic; -- Wave look-up table signal LUT_ADR : std_logic_vector (LUT_ADR_W-1 downto 0); signal LUT_DAT_O : std_logic_vector (PWM_W-1 downto 0); signal LUT_STB : std_logic; -- MCC execution control signal MCC_ACK : std_logic; signal MCC_STB : std_logic; ------------------------------------------------------------------------------ -- PWM and IRC ------------------------------------------------------------------------------ signal PWM_CNT : std_logic_vector (PWM_W-1 downto 0); signal PWM_OW : std_logic; -- PWM counter overflow -- PWM interface to the MCC signal PWM_DAT : std_logic_vector (PWM_W-1 downto 0); signal PWM1_STB : std_logic; signal PWM2_STB : std_logic; signal PWM3_STB : std_logic; -- PWM outputs signal PWM1_OUT : std_logic; signal PWM2_OUT : std_logic; signal PWM3_OUT : std_logic; -- IRC value signal QCNT : std_logic_vector (31 downto 0); -------------------------------------------------------------------------------- begin ------------------------------------------------------------------------------ -- OpenMSP430 softcore MCU module ------------------------------------------------------------------------------ openMSP430_1 : entity work.openMSP430_8_32_mul_dbus port map ( dco_clk => CLK_24MHz, lfxt_clk => '0', reset_n => RESET, rxd => RXD, txd => TXD, per_addr => open, per_din => open, per_dout => (others => '0'), per_wen => open, per_en => open, nmi => '0', irq => (others => '0'), irq_acc => open, aclk_en => open, smclk_en => open, mclk => mclk, puc => puc, dmem_addr => dmem_addr, dmem_ce => dmem_ce, dmem_we => dmem_we, dmem_din => dmem_din, dmem_dout => dmem_dout); -- External data bus address decoder and data multiplexer. ------------------------------------------------------------------------------ -- This statement leads to priority encoder (which should be avoided), but for -- a small mux it doesn't matter and it's better readable. dmem_dout <= DPA_DAT_O when DPA_SEL = '1' else (others => 'X'); DPA_SEL <= '1' when dmem_addr (11 downto 10) = "00" else '0'; DPA_STB <= dmem_ce and DPA_SEL; ------------------------------------------------------------------------------ -- Dual-port shared memory ------------------------------------------------------------------------------ -- Shared memory between MCU and MCC (size: 16+2 bits x 1k). -- Port A (MCU side) has a priority of writing. shared_mem : RAMB16_S18_S18 generic map ( WRITE_MODE_A => "READ_FIRST", WRITE_MODE_B => "WRITE_FIRST") port map ( -- A-Port (MCU) ADDRA => dmem_addr (9 downto 0), CLKA => mclk, DIA => dmem_din, DIPA => "00", DOA => DPA_DAT_O, DOPA => open, ENA => DPA_STB, SSRA => '0', WEA => dmem_we, -- B-Port (MCC) ADDRB => DPB_ADR, CLKB => mclk, DIB => IRF_DAT_I, DIPB => "00", DOB => IRF_DAT_O, DOPB => open, ENB => IRF_STB, SSRB => '0', WEB => IRF_WE); -- B-Port address (10 bits) constructed from IRF_ADR (5 bits). Upper addr bits -- are forced to '0', but in a case of several axes these can be used to -- address memory space of the appropriate one. DPB_ADR (9 downto 5) <= (others => '0'); DPB_ADR (4 downto 0) <= IRF_ADR; -- Generation of IRF acknowledge signal for MCC. IRF_ACK <= IRF_STB and (IRF_WE or IRF_ACK_REG); -- IRF_ACK_REG signalizes that data is present on IRF_DAT_O when reading. irf_read : process (mclk, puc) is begin if rising_edge(mclk) then if puc = '1' then IRF_ACK_REG <= '0'; else IRF_ACK_REG <= IRF_STB and not IRF_WE; end if; end if; end process; ------------------------------------------------------------------------------ -- Motion Control Chain ------------------------------------------------------------------------------ mcc_exec_1 : entity work.mcc_exec port map ( CLK_I => mclk, RST_I => puc, MCC_EN_I => '1', MCC_EXEC_I => PWM_OW, MCC_ERR_O => open, MCC_ACK_I => MCC_ACK, MCC_STB_O => MCC_STB); mcc_1 : entity work.mcc generic map ( LUT_DAT_W => PWM_W, LUT_ADR_W => LUT_ADR_W) port map ( ACK_O => MCC_ACK, CLK_I => mclk, RST_I => puc, STB_I => MCC_STB, LUT_STB_O => LUT_STB, LUT_ADR_O => LUT_ADR, LUT_DAT_I => LUT_DAT_O, IRC_DAT_I => QCNT (15 downto 0), PWM_DAT_O => PWM_DAT, PWM1_STB_O => PWM1_STB, PWM2_STB_O => PWM2_STB, PWM3_STB_O => PWM3_STB, IRF_ACK_I => IRF_ACK, IRF_ADR_O => IRF_ADR, IRF_DAT_I => IRF_DAT_O, IRF_DAT_O => IRF_DAT_I, IRF_STB_O => IRF_STB, IRF_WE_O => IRF_WE); wave_table_1 : entity work.wave_table generic map ( DAT_W => PWM_W, ADR_W => LUT_ADR_W, INIT_FILE => LUT_INIT) port map ( ACK_O => open, ADR_I => LUT_ADR, CLK_I => mclk, DAT_I => conv_std_logic_vector(0, PWM_W), DAT_O => LUT_DAT_O, STB_I => LUT_STB, WE_I => '0'); ------------------------------------------------------------------------------ -- PWM and IRC ------------------------------------------------------------------------------ -- PWM counter is shared by all PWM generators. Generator contains only -- comparator and desired value. counter_1 : entity work.counter generic map ( WIDTH => PWM_W, MAX => 2**PWM_W - 2) port map ( clk => mclk, clk_en => '1', reset => puc, count => PWM_CNT, event_ow => PWM_OW); pwm_1 : entity work.pwm generic map ( PWM_WIDTH => PWM_W) port map ( clk => mclk, reset => puc, din => PWM_DAT, we => PWM1_STB, pwm_cnt => PWM_CNT, pwm_cyc => PWM_OW, pwm => PWM1_OUT); pwm_2 : entity work.pwm generic map ( PWM_WIDTH => PWM_W) port map ( clk => mclk, reset => puc, din => PWM_DAT, we => PWM2_STB, pwm_cnt => PWM_CNT, pwm_cyc => PWM_OW, pwm => PWM2_OUT); pwm_3 : entity work.pwm generic map ( PWM_WIDTH => PWM_W) port map ( clk => mclk, reset => puc, din => PWM_DAT, we => PWM3_STB, pwm_cnt => PWM_CNT, pwm_cyc => PWM_OW, pwm => PWM3_OUT); -- PWM signals mapped to FPGA outputs, EN forced to '1' PWM0 <= PWM1_OUT; PWM0_EN <= '1'; PWM1 <= PWM2_OUT; PWM1_EN <= '1'; PWM2 <= PWM3_OUT; PWM2_EN <= '1'; -- PWM is signalized on LEDs LED0 <= PWM1_OUT; LED1 <= PWM2_OUT; LED2 <= PWM3_OUT; qcounter_1 : entity work.qcounter port map ( clock => mclk, reset => puc, a0 => IRC_A, b0 => IRC_B, qcount => QCNT, a_rise => open, a_fall => open, b_rise => open, b_fall => open, ab_event => open, ab_error => open); end rtl;