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