]> rtime.felk.cvut.cz Git - fpga/virtex2/msp_motion.git/commitdiff
PWM (MCC) connected to MCU
authorVladimir Burian <buriavl2@fel.cvut.cz>
Sun, 17 Apr 2011 09:16:20 +0000 (11:16 +0200)
committerVladimir Burian <buriavl2@fel.cvut.cz>
Sun, 17 Apr 2011 09:16:20 +0000 (11:16 +0200)
MCC is connected to MCU through dual-port BRAM. PWM outputs and IRC input
is connected to MCC. MCC is executed once per PWM period when PWM counter
overflows.

msp_motion.prj
msp_motion.vhd

index cc4dec7a84ac019c236280ba38bff10f97435abf..03a97658058fc04b7e2b14f2393477e8c7b3e421 100644 (file)
@@ -33,6 +33,34 @@ verilog work openmsp430/top/top_8_32_mul_dbus/openMSP430_defines.v
 vhdl    work openmsp430/top/top_8_32_mul_dbus/openMSP430_8_32_mul_dbus.vhd
 
 
+#==============================================================================#
+# Motion Control Chain - MCC                                                   #
+#==============================================================================#
+
+vhdl    work pwm/counter.vhd
+vhdl    work pwm/pwm.vhd
+vhdl    work pwm/wave_table.vhd
+vhdl    work pwm/vector_gen.vhd
+vhdl    work pwm/priority_encoder.vhd
+vhdl    work pwm/mcc_master.vhd
+vhdl    work pwm/sequencer.vhd
+vhdl    work pwm/multiplier.vhd
+vhdl    work pwm/vector_scale.vhd
+vhdl    work pwm/pwm_dump.vhd
+vhdl    work pwm/irc_dump.vhd
+vhdl    work pwm/irc_base.vhd
+vhdl    work pwm/mcc.vhd
+vhdl    work pwm/mcc_exec.vhd
+
+
+#==============================================================================#
+# Quadcount - IRC                                                              #
+#==============================================================================#
+
+vhdl    work quadcount/dff.vhd
+vhdl    work quadcount/qcounter.vhd
+
+
 #==============================================================================#
 # Top-level design file                                                        #
 #==============================================================================#
index c5aef7d052d6b5e846a3babc36c3344ddc62de10..b1c213ee29569c2df0fe75e651e6b5cd7e8c8f90 100644 (file)
@@ -3,6 +3,9 @@ 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
@@ -38,9 +41,71 @@ 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);
   
 --------------------------------------------------------------------------------
 
@@ -68,11 +133,206 @@ begin
       smclk_en                 => open,
       mclk                     => mclk,
       puc                      => puc,
-      dmem_addr                => open,
-      dmem_ce                  => open,
-      dmem_we                  => open,
-      dmem_din                 => open,
-      dmem_dout                => (others => '0'));
+      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;