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