]> rtime.felk.cvut.cz Git - fpga/virtex2/msp_motion.git/blob - msp_motion.vhd
use of incremental encoder index signal for phase table alignment
[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   signal reset_p : std_logic;
45
46   ------------------------------------------------------------------------------
47   -- OpenMSP430 softcore MCU module
48   ------------------------------------------------------------------------------
49   signal mclk      : std_logic;
50   signal puc       : std_logic;
51   -- External data bus
52   signal dmem_addr : std_logic_vector (11 downto 0);
53   signal dmem_ce   : std_logic;
54   signal dmem_we   : std_logic;
55   signal dmem_din  : std_logic_vector (15 downto 0);
56   signal dmem_dout : std_logic_vector (15 downto 0);
57   -- Peripheral bus
58   signal per_din   : std_logic_vector (15 downto 0);
59   signal per_dout  : std_logic_Vector (15 downto 0);
60   signal per_wen   : std_logic_vector (1 downto 0);
61   signal per_wen16 : std_logic;
62   signal per_en    : std_logic;
63   signal per_addr  : std_logic_vector (7 downto 0);
64   -- Interrupt
65   --signal irq       : std_logic_vector (13 downto 0) := (others => '0');
66   signal irq       : std_logic_vector (13 downto 0);
67   signal irq_acc   : std_logic_vector (13 downto 0);
68
69   ------------------------------------------------------------------------------
70   -- MCU peripherals
71   ------------------------------------------------------------------------------
72   -- GPIO
73   signal GPIO_IN    : std_logic_vector (15 downto 0);
74   signal GPIO_OUT   : std_logic_vector (15 downto 0);
75   signal GPIO_DAT_O : std_logic_vector (15 downto 0);
76   signal GPIO_SEL   : std_logic;
77   -- Qcounter MCU interface
78   signal QCNT_DAT_O : std_logic_vector (15 downto 0);
79   signal QCNT_SEL   : std_logic;
80   -- Motor feedback IRQ generator
81   signal MOTOR_IRQ  : std_logic;
82   -- Event register
83   signal EVENT_DAT_O : std_logic_vector (15 downto 0);
84   signal EVENT_SEL   : std_logic;
85   signal event_i         : std_logic_vector (15 downto 0);
86   signal event_o         : std_logic_vector (15 downto 0);
87
88   -- Edge detector
89   signal EDGE_DAT_O                     : std_logic_vector (15 downto 0);
90   signal EDGE_DETECT_SEL        : std_logic;
91   signal event_in                       : std_logic_vector (15 downto 0);
92   signal edge_detect_o          : std_logic_vector (15 downto 0);
93   signal rst_edge                       : std_logic;
94
95   -- Qcounter capture
96   signal CAPTURE_SEL : std_logic;
97   signal CAPTURE_DAT : std_logic_vector (15 downto 0);
98   -- IRC index detection
99   signal INDEX_DETECT_DAT_O : std_logic_vector (15 downto 0);  
100   signal INDEX_DETECT_SEL : std_logic;
101
102   ------------------------------------------------------------------------------
103   -- Dual-port shared memory
104   ------------------------------------------------------------------------------
105   -- These signals of A-port (MCU) enables creation of external data encoder and
106   -- multiplexer in a case of multiple devices connected to the external data
107   -- bus. Otherwise useless.
108   signal DPA_DAT_O   : std_logic_vector (15 downto 0);
109   signal DPA_SEL     : std_logic;
110   signal DPA_STB     : std_logic;
111   -- Auxiliary register used to generate IRF_ACK
112   signal IRF_ACK_REG : std_logic := '0';
113   -- Auxiliary signal used to form B-port address
114   signal DPB_ADR     : std_logic_vector (9 downto 0);
115
116   ------------------------------------------------------------------------------
117   -- Motion Control Chain
118   ------------------------------------------------------------------------------
119   -- Constants
120   constant PWM_W     : integer := 10;
121   constant LUT_ADR_W : integer := 11;
122   constant LUT_INIT  : string  := "sin1000.lut";
123   
124   -- Bus interface to the shared memory
125   signal IRF_ACK   : std_logic;
126   signal IRF_ADR   : std_logic_vector (4 downto 0);
127   signal IRF_DAT_I : std_logic_vector (15 downto 0);
128   signal IRF_DAT_O : std_logic_vector (15 downto 0);
129   signal IRF_STB   : std_logic;
130   signal IRF_WE    : std_logic;
131   -- Wave look-up table
132   signal LUT_ADR   : std_logic_vector (LUT_ADR_W-1 downto 0);
133   signal LUT_DAT_O : std_logic_vector (PWM_W-1 downto 0);
134   signal LUT_STB   : std_logic;
135   -- MCC execution control
136   signal MCC_ACK   : std_logic;
137   signal MCC_STB   : std_logic;
138
139   ------------------------------------------------------------------------------
140   -- PWM and IRC
141   ------------------------------------------------------------------------------
142   signal PWM_CNT  : std_logic_vector (PWM_W-1 downto 0);
143   signal PWM_OW   : std_logic;          -- PWM counter overflow
144   -- PWM interface to the MCC
145   signal PWM_DAT  : std_logic_vector (PWM_W-1 downto 0);
146   signal PWM1_STB : std_logic;
147   signal PWM2_STB : std_logic;
148   signal PWM3_STB : std_logic;
149   -- PWM outputs
150   signal PWM1_OUT : std_logic;
151   signal PWM2_OUT : std_logic;
152   signal PWM3_OUT : std_logic;
153   -- IRC value
154   signal QCNT     : std_logic_vector (31 downto 0);
155   -- IRC capturing
156   signal IRC_INDEX_DFF   : std_logic;   -- IRC_INDEX aligned with global clock
157   signal IRC_INDEX_EVENT : std_logic;
158   
159 --------------------------------------------------------------------------------
160
161 begin
162   
163   ------------------------------------------------------------------------------
164   -- OpenMSP430 softcore MCU module
165   ------------------------------------------------------------------------------
166   openMSP430_1 : entity work.openMSP430_8_32_mul_dbus
167     port map (
168       dco_clk                  => CLK_24MHz,
169       lfxt_clk                 => '0',
170       reset_n                  => '1',
171       rxd                      => RXD,
172       txd                      => TXD,
173       per_addr                 => per_addr,
174       per_din                  => per_din,
175       per_dout                 => per_dout,
176       per_wen                  => per_wen,
177       per_en                   => per_en,
178       nmi                      => '0',
179       irq                      => irq,
180       irq_acc                  => irq_acc,
181       aclk_en                  => open,
182       smclk_en                 => open,
183       mclk                     => mclk,
184       puc                      => open,
185       dmem_addr                => dmem_addr,
186       dmem_ce                  => dmem_ce,
187       dmem_we                  => dmem_we,
188       dmem_din                 => dmem_din,
189       dmem_dout                => dmem_dout);
190
191   puc     <= '0';
192   reset_p <= not RESET;
193
194   STARTUP_VIRTEX2_inst : STARTUP_VIRTEX2
195     port map (
196       CLK => open,
197       -- Clock input for start-up sequence
198       GSR => reset_p, -- Global Set/Reset input (GSR cannot be used for the port name)
199       GTS => open); -- Global 3-state input (GTS cannot be used for the port name)
200
201
202   -- External data bus address decoder and data multiplexer.
203   ------------------------------------------------------------------------------
204   -- When connection more memories, be aware that 'dmem_dout' can vary only when
205   -- reading cycle is performed. I.e. mux variable must be registered.
206   dmem_dout <= DPA_DAT_O;
207   
208   DPA_SEL <= '1' when dmem_addr (11 downto 10) = "00" else '0';
209   DPA_STB <= dmem_ce and DPA_SEL;
210
211   -- Peripheral bus address decoder and data multiplexer.
212   ------------------------------------------------------------------------------
213   per_dout <= GPIO_DAT_O when GPIO_SEL = '1' else
214               QCNT_DAT_O when QCNT_SEL = '1' else
215               EVENT_DAT_O when EVENT_SEL = '1' else
216               CAPTURE_DAT when CAPTURE_SEL = '1' else
217                           EDGE_DAT_O when EDGE_DETECT_SEL = '1' else
218               (others => '0');          -- MUST be 0 when nothing is addressed
219   
220   GPIO_SEL <= '1' when per_addr(7 downto 2) = 16#0140#/2/4 else '0';
221   QCNT_SEL <= '1' when per_addr(7 downto 1) = 16#0148#/2/2 else '0';
222   EVENT_SEL <= '1' when per_addr(7 downto 0) = 16#014C#/2  else '0';
223   CAPTURE_SEL <= '1' when per_addr(7 downto 1) = 16#0150#/2/2 else '0';
224   EDGE_DETECT_SEL <= '1' when per_addr(7 downto 0) = 16#0154#/2 else '0';
225
226   per_wen16 <= per_wen(0) and per_wen(1);
227
228   -- Interrupt signals
229   ------------------------------------------------------------------------------
230   irq (13 downto 1) <= (others => '0');
231
232   motor_irq_gen : process (mclk, puc) is
233   begin
234     if rising_edge (mclk) then
235       if puc = '1' or irq_acc (0) = '1' then
236         irq (0) <= '0';
237       elsif MOTOR_IRQ = '1' then
238         irq (0) <= '1';
239       end if;
240     end if;
241   end process;
242
243   
244   ------------------------------------------------------------------------------
245   -- MCU peripherals
246   ------------------------------------------------------------------------------
247   GPIO_IN(0) <= HAL0;
248   GPIO_IN(1) <= HAL1;
249   GPIO_IN(2) <= HAL2;
250   GPIO_IN(3) <= IRC_INDEX;
251
252   gpio_0 : entity work.gpio
253     generic map (
254       W => 16)
255     port map (
256       ACK_O  => open,
257       ADR_I  => per_addr (1 downto 0),
258       CLK_I  => mclk,
259       DAT_I  => per_din,
260       DAT_O  => GPIO_DAT_O,
261       RST_I  => puc,
262       SEL_I  => GPIO_SEL,
263       STB_I  => per_en,
264       WE_I   => per_wen16,
265       GPIO_I => GPIO_IN,
266       GPIO_O => GPIO_OUT);
267
268   qcounter_mcu16_0 : entity work.qcounter_mcu16
269     port map (
270       ACK_O  => open,
271       ADR_I  => per_addr (0),
272       CLK_I  => mclk,
273       DAT_O  => QCNT_DAT_O,
274       SEL_I  => QCNT_SEL,
275       STB_I  => per_en,
276       QCOUNT => QCNT);
277
278   -- Motor feedback IRQ generator
279   -- f_motor_irq approx. 1 kHz
280   irq_counter_1 : entity work.counter
281     generic map (
282       WIDTH => 5,
283       MAX   => 22)
284     port map (
285       clk      => mclk,
286       clk_en   => PWM_OW,
287       reset    => puc,
288       count    => open,
289       event_ow => MOTOR_IRQ);
290
291
292   event_io_0 : entity work.event_rwc
293         port map (
294        -- Peripheral bus interface
295     ACK_O  => open,
296     CLK_I  => mclk,
297     DAT_I  => per_din,
298     DAT_O  => EVENT_DAT_O,
299     RST_I  => puc,
300     SEL_I  => EVENT_SEL,
301     STB_I  => per_en,
302     WE_I   => per_wen16,
303     -- Event port pins
304     EVENT_I => event_i,
305     EVENT_O => event_o);
306
307   event_i(0)      <= (not IRC_INDEX_DFF) and (not event_o(0));
308   IRC_INDEX_EVENT <= event_i(0);
309
310
311   edge_detector_0 : entity work.edge_detector
312           port map (
313                 -- Peripheral bus interface
314                 ACK_O => open,
315                 CLK_I => mclk,
316                 DAT_I => per_din,
317                 DAT_O => EDGE_DAT_O,
318                 RST_I => puc,
319                 SEL_I => EDGE_DETECT_SEL,
320                 STB_I => per_en,
321                 WE_I  => per_wen16,
322                 -- Event port pins
323                 EVENT_I => event_in);
324
325
326   --rst_edge <= '0' when per_addr()
327   event_in(0) <= IRC_INDEX_DFF; 
328
329   irc_index_dff_0 : entity work.dff
330     port map (
331       clock => mclk,
332       d     => IRC_INDEX,
333       q     => IRC_INDEX_DFF);
334
335   capture_reg16_0 : entity work.capture_reg16
336     port map (
337       ACK_O     => open,
338       ADR_I     => per_addr (0 downto 0),
339       CLK_I     => mclk,
340       DAT_O     => CAPTURE_DAT,
341       SEL_I     => CAPTURE_SEL,
342       STB_I     => per_en,
343       EVENT_I   => IRC_INDEX_EVENT,
344       CAPTURE_I => QCNT);
345
346   ------------------------------------------------------------------------------
347   -- Dual-port shared memory
348   ------------------------------------------------------------------------------
349   -- Shared memory between MCU and MCC (size: 16+2 bits x 1k).
350   -- Port A (MCU side) has a priority of writing.
351   shared_mem : RAMB16_S18_S18
352     generic map (
353       WRITE_MODE_A => "READ_FIRST",
354       WRITE_MODE_B => "WRITE_FIRST")
355     port map (
356       -- A-Port (MCU)
357       ADDRA => dmem_addr (9 downto 0),
358       CLKA  => mclk,
359       DIA   => dmem_din,
360       DIPA  => "00",
361       DOA   => DPA_DAT_O,
362       DOPA  => open,
363       ENA   => DPA_STB,
364       SSRA  => '0',
365       WEA   => dmem_we,
366       -- B-Port (MCC)
367       ADDRB => DPB_ADR,
368       CLKB  => mclk,
369       DIB   => IRF_DAT_I,
370       DIPB  => "00",
371       DOB   => IRF_DAT_O,
372       DOPB  => open,
373       ENB   => IRF_STB,
374       SSRB  => '0',
375       WEB   => IRF_WE);
376
377   -- B-Port address (10 bits) constructed from IRF_ADR (5 bits). Upper addr bits
378   -- are forced to '0', but in a case of several axes these can be used to
379   -- address memory space of the appropriate one.
380   DPB_ADR (9 downto 5) <= (others => '0');
381   DPB_ADR (4 downto 0) <= IRF_ADR;
382   
383   -- Generation of IRF acknowledge signal for MCC.
384   IRF_ACK <= IRF_STB and (IRF_WE or IRF_ACK_REG);
385
386   -- IRF_ACK_REG signalizes that data is present on IRF_DAT_O when reading.
387   irf_read : process (mclk, puc) is
388   begin
389     if rising_edge(mclk) then
390       if puc = '1' then
391         IRF_ACK_REG <= '0';
392       else
393         IRF_ACK_REG <= IRF_STB  and not IRF_WE;
394       end if;
395     end if;
396   end process;
397
398   
399   ------------------------------------------------------------------------------
400   -- Motion Control Chain
401   ------------------------------------------------------------------------------
402   mcc_exec_1 : entity work.mcc_exec
403     generic map (
404       AXIS_CNT   => 1,
405       AXIS_CNT_W => 1)
406     port map (
407       CLK_I      => mclk,
408       RST_I      => puc,
409       MCC_AXIS_O => open,
410       MCC_DONE_O => open,
411       MCC_EN_I   => '1',
412       MCC_EXEC_I => PWM_OW,
413       MCC_ERR_O  => open,
414       MCC_ACK_I  => MCC_ACK,
415       MCC_STB_O  => MCC_STB);
416   
417   mcc_1 : entity work.mcc
418     generic map (
419       LUT_DAT_W => PWM_W,
420       LUT_ADR_W => LUT_ADR_W)
421     port map (
422       ACK_O      => MCC_ACK,
423       CLK_I      => mclk,
424       RST_I      => puc,
425       STB_I      => MCC_STB,
426       LUT_STB_O  => LUT_STB,
427       LUT_ADR_O  => LUT_ADR,
428       LUT_DAT_I  => LUT_DAT_O,
429       IRC_DAT_I  => QCNT (15 downto 0),
430       PWM_DAT_O  => PWM_DAT,
431       PWM1_STB_O => PWM1_STB,
432       PWM2_STB_O => PWM2_STB,
433       PWM3_STB_O => PWM3_STB,
434       IRF_ACK_I  => IRF_ACK,
435       IRF_ADR_O  => IRF_ADR,
436       IRF_DAT_I  => IRF_DAT_O,
437       IRF_DAT_O  => IRF_DAT_I,
438       IRF_STB_O  => IRF_STB,
439       IRF_WE_O   => IRF_WE);
440
441   wave_table_1 : entity work.wave_table
442     generic map (
443       DAT_W     => PWM_W,
444       ADR_W     => LUT_ADR_W,
445       INIT_FILE => LUT_INIT)
446     port map (
447       ACK_O => open,
448       ADR_I => LUT_ADR,
449       CLK_I => mclk,
450       DAT_I => conv_std_logic_vector(0, PWM_W),
451       DAT_O => LUT_DAT_O,
452       STB_I => LUT_STB,
453       WE_I  => '0');
454
455
456   ------------------------------------------------------------------------------
457   -- PWM and IRC
458   ------------------------------------------------------------------------------
459   -- PWM counter is shared by all PWM generators. Generator contains only
460   -- comparator and desired value.
461   pwm_counter : entity work.counter
462     generic map (
463       WIDTH => PWM_W,
464       MAX   => 2**PWM_W - 2)
465     port map (
466       clk      => mclk,
467       clk_en   => '1',
468       reset    => puc,
469       count    => PWM_CNT,
470       event_ow => PWM_OW);
471
472     pwm_1 : entity work.pwm
473     generic map (
474       PWM_WIDTH => PWM_W)
475     port map (
476       clk     => mclk,
477       reset   => puc,
478       din     => PWM_DAT,
479       sel     => '1',
480       we      => PWM1_STB,
481       pwm_cnt => PWM_CNT,
482       pwm_cyc => PWM_OW,
483       pwm     => PWM1_OUT);
484
485   pwm_2 : entity work.pwm
486     generic map (
487       PWM_WIDTH => PWM_W)
488     port map (
489       clk     => mclk,
490       reset   => puc,
491       din     => PWM_DAT,
492       sel     => '1',
493       we      => PWM2_STB,
494       pwm_cnt => PWM_CNT,
495       pwm_cyc => PWM_OW,
496       pwm     => PWM2_OUT);
497   
498   pwm_3 : entity work.pwm
499     generic map (
500       PWM_WIDTH => PWM_W)
501     port map (
502       clk     => mclk,
503       reset   => puc,
504       din     => PWM_DAT,
505       sel     => '1',
506       we      => PWM3_STB,
507       pwm_cnt => PWM_CNT,
508       pwm_cyc => PWM_OW,
509       pwm     => PWM3_OUT);
510
511   -- PWM signals mapped to FPGA outputs, EN forced to '1'
512   PWM0    <= not PWM1_OUT;
513   PWM0_EN <= '1';
514   PWM1    <= not PWM2_OUT;
515   PWM1_EN <= '1';
516   PWM2    <= not PWM3_OUT;
517   PWM2_EN <= '1';
518
519   -- PWM is signalized on LEDs
520   LED0    <= PWM1_OUT;
521   LED1    <= PWM2_OUT;
522   LED2    <= PWM3_OUT;
523
524   qcounter_1 : entity work.qcounter
525     port map (
526       clock    => mclk,
527       reset    => puc,
528       a0       => IRC_A,
529       b0       => IRC_B,
530       qcount   => QCNT,
531       a_rise   => open,
532       a_fall   => open,
533       b_rise   => open,
534       b_fall   => open,
535       ab_event => open,
536       ab_error => open);
537
538   
539 end rtl;
540