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