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