]> rtime.felk.cvut.cz Git - fpga/virtex2/msp_motion.git/blob - msp_motion.vhd
MCU interface to Qcount (32-bit output)
[fpga/virtex2/msp_motion.git] / msp_motion.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.std_logic_arith.all;
4 use ieee.std_logic_unsigned.all;
5
6 library unisim;
7 use unisim.vcomponents.all;
8
9 --------------------------------------------------------------------------------
10
11 entity msp_motion is
12   port (
13     -- Clock & reset
14     CLK_24MHz : in  std_logic;
15     RESET     : in  std_logic;
16     -- RS232
17     RXD       : in  std_logic;
18     TXD       : out std_logic;
19     -- LED
20     LED0      : out std_logic;
21     LED1      : out std_logic;
22     LED2      : out std_logic;
23     -- PWM
24     PWM0      : out std_logic;
25     PWM0_EN   : out std_logic;
26     PWM1      : out std_logic;
27     PWM1_EN   : out std_logic;
28     PWM2      : out std_logic;
29     PWM2_EN   : out std_logic;
30     -- IRC
31     IRC_INDEX : in  std_logic;
32     IRC_A     : in  std_logic;
33     IRC_B     : in  std_logic;
34     -- HALL
35     HAL0      : in  std_logic;
36     HAL1      : in  std_logic;
37     HAL2      : in  std_logic);
38 end msp_motion;
39
40 --------------------------------------------------------------------------------
41
42 architecture rtl of msp_motion is
43
44   ------------------------------------------------------------------------------
45   -- OpenMSP430 softcore MCU module
46   ------------------------------------------------------------------------------
47   signal mclk      : std_logic;
48   signal puc       : std_logic;
49   -- External data bus
50   signal dmem_addr : std_logic_vector (11 downto 0);
51   signal dmem_ce   : std_logic;
52   signal dmem_we   : std_logic;
53   signal dmem_din  : std_logic_vector (15 downto 0);
54   signal dmem_dout : std_logic_vector (15 downto 0);
55   -- Peripheral bus
56   signal per_din   : std_logic_vector (15 downto 0);
57   signal per_dout  : std_logic_Vector (15 downto 0);
58   signal per_wen   : std_logic_vector (1 downto 0);
59   signal per_wen16 : std_logic;
60   signal per_en    : std_logic;
61   signal per_addr  : std_logic_vector (7 downto 0);
62
63   ------------------------------------------------------------------------------
64   -- MCU peripherals
65   ------------------------------------------------------------------------------
66   -- GPIO
67   signal GPIO_IN    : std_logic_vector (15 downto 0);
68   signal GPIO_OUT   : std_logic_vector (15 downto 0);
69   signal GPIO_DAT_O : std_logic_vector (15 downto 0);
70   signal GPIO_SEL   : std_logic;
71   -- Qcounter MCU interface
72   signal QCNT_DAT_O : std_logic_vector (15 downto 0);
73   signal QCNT_SEL   : std_logic;
74   
75   ------------------------------------------------------------------------------
76   -- Dual-port shared memory
77   ------------------------------------------------------------------------------
78   -- These signals of A-port (MCU) enables creation of external data encoder and
79   -- multiplexer in a case of multiple devices connected to the external data
80   -- bus. Otherwise useless.
81   signal DPA_DAT_O   : std_logic_vector (15 downto 0);
82   signal DPA_SEL     : std_logic;
83   signal DPA_STB     : std_logic;
84   -- Auxiliary register used to generate IRF_ACK
85   signal IRF_ACK_REG : std_logic;
86   -- Auxiliary signal used to form B-port address
87   signal DPB_ADR     : std_logic_vector (9 downto 0);
88
89   ------------------------------------------------------------------------------
90   -- Motion Control Chain
91   ------------------------------------------------------------------------------
92   -- Constants
93   constant PWM_W     : integer := 10;
94   constant LUT_ADR_W : integer := 11;
95   constant LUT_INIT  : string  := "sin1000.lut";
96   
97   -- Bus interface to the shared memory
98   signal IRF_ACK   : std_logic;
99   signal IRF_ADR   : std_logic_vector (4 downto 0);
100   signal IRF_DAT_I : std_logic_vector (15 downto 0);
101   signal IRF_DAT_O : std_logic_vector (15 downto 0);
102   signal IRF_STB   : std_logic;
103   signal IRF_WE    : std_logic;
104   -- Wave look-up table
105   signal LUT_ADR   : std_logic_vector (LUT_ADR_W-1 downto 0);
106   signal LUT_DAT_O : std_logic_vector (PWM_W-1 downto 0);
107   signal LUT_STB   : std_logic;
108   -- MCC execution control
109   signal MCC_ACK   : std_logic;
110   signal MCC_STB   : std_logic;
111
112   ------------------------------------------------------------------------------
113   -- PWM and IRC
114   ------------------------------------------------------------------------------
115   signal PWM_CNT  : std_logic_vector (PWM_W-1 downto 0);
116   signal PWM_OW   : std_logic;          -- PWM counter overflow
117   -- PWM interface to the MCC
118   signal PWM_DAT  : std_logic_vector (PWM_W-1 downto 0);
119   signal PWM1_STB : std_logic;
120   signal PWM2_STB : std_logic;
121   signal PWM3_STB : std_logic;
122   -- PWM outputs
123   signal PWM1_OUT : std_logic;
124   signal PWM2_OUT : std_logic;
125   signal PWM3_OUT : std_logic;
126   -- IRC value
127   signal QCNT     : std_logic_vector (31 downto 0);
128   
129 --------------------------------------------------------------------------------
130
131 begin
132   
133   ------------------------------------------------------------------------------
134   -- OpenMSP430 softcore MCU module
135   ------------------------------------------------------------------------------
136   openMSP430_1 : entity work.openMSP430_8_32_mul_dbus
137     port map (
138       dco_clk                  => CLK_24MHz,
139       lfxt_clk                 => '0',
140       reset_n                  => RESET,
141       rxd                      => RXD,
142       txd                      => TXD,
143       per_addr                 => per_addr,
144       per_din                  => per_din,
145       per_dout                 => per_dout,
146       per_wen                  => per_wen,
147       per_en                   => per_en,
148       nmi                      => '0',
149       irq                      => (others => '0'),
150       irq_acc                  => open,
151       aclk_en                  => open,
152       smclk_en                 => open,
153       mclk                     => mclk,
154       puc                      => puc,
155       dmem_addr                => dmem_addr,
156       dmem_ce                  => dmem_ce,
157       dmem_we                  => dmem_we,
158       dmem_din                 => dmem_din,
159       dmem_dout                => dmem_dout);
160
161   -- External data bus address decoder and data multiplexer.
162   ------------------------------------------------------------------------------
163   -- This statement leads to priority encoder (which should be avoided), but for
164   -- a small mux it doesn't matter and it's better readable.
165   dmem_dout <= DPA_DAT_O when DPA_SEL = '1' else
166                (others => 'X');
167   
168   DPA_SEL <= '1' when dmem_addr (11 downto 10) = "00" else '0';
169   DPA_STB <= dmem_ce and DPA_SEL;
170
171   -- Peripheral bus address decoder and data multiplexer.
172   ------------------------------------------------------------------------------
173   per_dout <= GPIO_DAT_O when GPIO_SEL = '1' else
174               QCNT_DAT_O when QCNT_SEL = '1' else
175               (others => '0');          -- MUST be 0 when nothing is addressed
176   
177   GPIO_SEL <= '1' when per_addr(7 downto 2) = 16#0140#/2/4 else '0';
178   QCNT_SEL <= '1' when per_addr(7 downto 1) = 16#0148#/2/2 else '0';
179
180
181   ------------------------------------------------------------------------------
182   -- MCU peripherals
183   ------------------------------------------------------------------------------
184   GPIO_IN(0) <= HAL0;
185   GPIO_IN(1) <= HAL1;
186   GPIO_IN(2) <= HAL2;
187   GPIO_IN(3) <= IRC_INDEX;
188
189   gpio_0 : entity work.gpio
190     generic map (
191       W => 16)
192     port map (
193       ACK_O  => open,
194       ADR_I  => per_addr (1 downto 0),
195       CLK_I  => mclk,
196       DAT_I  => per_din,
197       DAT_O  => GPIO_DAT_O,
198       RST_I  => puc,
199       SEL_I  => GPIO_SEL,
200       STB_I  => per_en,
201       WE_I   => per_wen16,
202       GPIO_I => GPIO_IN,
203       GPIO_O => GPIO_OUT);
204
205   qcounter_mcu16_0 : entity work.qcounter_mcu16
206     port map (
207       ACK_O  => open,
208       ADR_I  => per_addr (0),
209       CLK_I  => mclk,
210       DAT_O  => QCNT_DAT_O,
211       SEL_I  => QCNT_SEL,
212       STB_I  => per_en,
213       QCOUNT => QCNT);
214
215
216   ------------------------------------------------------------------------------
217   -- Dual-port shared memory
218   ------------------------------------------------------------------------------
219   -- Shared memory between MCU and MCC (size: 16+2 bits x 1k).
220   -- Port A (MCU side) has a priority of writing.
221   shared_mem : RAMB16_S18_S18
222     generic map (
223       WRITE_MODE_A => "READ_FIRST",
224       WRITE_MODE_B => "WRITE_FIRST")
225     port map (
226       -- A-Port (MCU)
227       ADDRA => dmem_addr (9 downto 0),
228       CLKA  => mclk,
229       DIA   => dmem_din,
230       DIPA  => "00",
231       DOA   => DPA_DAT_O,
232       DOPA  => open,
233       ENA   => DPA_STB,
234       SSRA  => '0',
235       WEA   => dmem_we,
236       -- B-Port (MCC)
237       ADDRB => DPB_ADR,
238       CLKB  => mclk,
239       DIB   => IRF_DAT_I,
240       DIPB  => "00",
241       DOB   => IRF_DAT_O,
242       DOPB  => open,
243       ENB   => IRF_STB,
244       SSRB  => '0',
245       WEB   => IRF_WE);
246
247   -- B-Port address (10 bits) constructed from IRF_ADR (5 bits). Upper addr bits
248   -- are forced to '0', but in a case of several axes these can be used to
249   -- address memory space of the appropriate one.
250   DPB_ADR (9 downto 5) <= (others => '0');
251   DPB_ADR (4 downto 0) <= IRF_ADR;
252   
253   -- Generation of IRF acknowledge signal for MCC.
254   IRF_ACK <= IRF_STB and (IRF_WE or IRF_ACK_REG);
255
256   -- IRF_ACK_REG signalizes that data is present on IRF_DAT_O when reading.
257   irf_read : process (mclk, puc) is
258   begin
259     if rising_edge(mclk) then
260       if puc = '1' then
261         IRF_ACK_REG <= '0';
262       else
263         IRF_ACK_REG <= IRF_STB  and not IRF_WE;
264       end if;
265     end if;
266   end process;
267
268   
269   ------------------------------------------------------------------------------
270   -- Motion Control Chain
271   ------------------------------------------------------------------------------
272   mcc_exec_1 : entity work.mcc_exec
273     port map (
274       CLK_I      => mclk,
275       RST_I      => puc,
276       MCC_EN_I   => '1',
277       MCC_EXEC_I => PWM_OW,
278       MCC_ERR_O  => open,
279       MCC_ACK_I  => MCC_ACK,
280       MCC_STB_O  => MCC_STB);
281   
282   mcc_1 : entity work.mcc
283     generic map (
284       LUT_DAT_W => PWM_W,
285       LUT_ADR_W => LUT_ADR_W)
286     port map (
287       ACK_O      => MCC_ACK,
288       CLK_I      => mclk,
289       RST_I      => puc,
290       STB_I      => MCC_STB,
291       LUT_STB_O  => LUT_STB,
292       LUT_ADR_O  => LUT_ADR,
293       LUT_DAT_I  => LUT_DAT_O,
294       IRC_DAT_I  => QCNT (15 downto 0),
295       PWM_DAT_O  => PWM_DAT,
296       PWM1_STB_O => PWM1_STB,
297       PWM2_STB_O => PWM2_STB,
298       PWM3_STB_O => PWM3_STB,
299       IRF_ACK_I  => IRF_ACK,
300       IRF_ADR_O  => IRF_ADR,
301       IRF_DAT_I  => IRF_DAT_O,
302       IRF_DAT_O  => IRF_DAT_I,
303       IRF_STB_O  => IRF_STB,
304       IRF_WE_O   => IRF_WE);
305
306   wave_table_1 : entity work.wave_table
307     generic map (
308       DAT_W     => PWM_W,
309       ADR_W     => LUT_ADR_W,
310       INIT_FILE => LUT_INIT)
311     port map (
312       ACK_O => open,
313       ADR_I => LUT_ADR,
314       CLK_I => mclk,
315       DAT_I => conv_std_logic_vector(0, PWM_W),
316       DAT_O => LUT_DAT_O,
317       STB_I => LUT_STB,
318       WE_I  => '0');
319
320
321   ------------------------------------------------------------------------------
322   -- PWM and IRC
323   ------------------------------------------------------------------------------
324   -- PWM counter is shared by all PWM generators. Generator contains only
325   -- comparator and desired value.
326   counter_1 : entity work.counter
327     generic map (
328       WIDTH => PWM_W,
329       MAX   => 2**PWM_W - 2)
330     port map (
331       clk      => mclk,
332       clk_en   => '1',
333       reset    => puc,
334       count    => PWM_CNT,
335       event_ow => PWM_OW);
336
337     pwm_1 : entity work.pwm
338     generic map (
339       PWM_WIDTH => PWM_W)
340     port map (
341       clk     => mclk,
342       reset   => puc,
343       din     => PWM_DAT,
344       we      => PWM1_STB,
345       pwm_cnt => PWM_CNT,
346       pwm_cyc => PWM_OW,
347       pwm     => PWM1_OUT);
348
349   pwm_2 : entity work.pwm
350     generic map (
351       PWM_WIDTH => PWM_W)
352     port map (
353       clk     => mclk,
354       reset   => puc,
355       din     => PWM_DAT,
356       we      => PWM2_STB,
357       pwm_cnt => PWM_CNT,
358       pwm_cyc => PWM_OW,
359       pwm     => PWM2_OUT);
360   
361   pwm_3 : entity work.pwm
362     generic map (
363       PWM_WIDTH => PWM_W)
364     port map (
365       clk     => mclk,
366       reset   => puc,
367       din     => PWM_DAT,
368       we      => PWM3_STB,
369       pwm_cnt => PWM_CNT,
370       pwm_cyc => PWM_OW,
371       pwm     => PWM3_OUT);
372
373   -- PWM signals mapped to FPGA outputs, EN forced to '1'
374   PWM0    <= PWM1_OUT;
375   PWM0_EN <= '1';
376   PWM1    <= PWM2_OUT;
377   PWM1_EN <= '1';
378   PWM2    <= PWM3_OUT;
379   PWM2_EN <= '1';
380   -- PWM is signalized on LEDs
381   LED0    <= PWM1_OUT;
382   LED1    <= PWM2_OUT;
383   LED2    <= PWM3_OUT;
384
385   qcounter_1 : entity work.qcounter
386     port map (
387       clock    => mclk,
388       reset    => puc,
389       a0       => IRC_A,
390       b0       => IRC_B,
391       qcount   => QCNT,
392       a_rise   => open,
393       a_fall   => open,
394       b_rise   => open,
395       b_fall   => open,
396       ab_event => open,
397       ab_error => open);
398
399   
400 end rtl;
401