]> rtime.felk.cvut.cz Git - fpga/virtex2/msp_motion.git/blob - msp_motion.vhd
Keeping hierarchy during hardware synthesis.
[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_gen : 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   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     generic map (
320       AXIS_CNT   => 1,
321       AXIS_CNT_W => 1)
322     port map (
323       CLK_I      => mclk,
324       RST_I      => puc,
325       MCC_AXIS_O => open,
326       MCC_DONE_O => open,
327       MCC_EN_I   => '1',
328       MCC_EXEC_I => PWM_OW,
329       MCC_ERR_O  => open,
330       MCC_ACK_I  => MCC_ACK,
331       MCC_STB_O  => MCC_STB);
332   
333   mcc_1 : entity work.mcc
334     generic map (
335       LUT_DAT_W => PWM_W,
336       LUT_ADR_W => LUT_ADR_W)
337     port map (
338       ACK_O      => MCC_ACK,
339       CLK_I      => mclk,
340       RST_I      => puc,
341       STB_I      => MCC_STB,
342       LUT_STB_O  => LUT_STB,
343       LUT_ADR_O  => LUT_ADR,
344       LUT_DAT_I  => LUT_DAT_O,
345       IRC_DAT_I  => QCNT (15 downto 0),
346       PWM_DAT_O  => PWM_DAT,
347       PWM1_STB_O => PWM1_STB,
348       PWM2_STB_O => PWM2_STB,
349       PWM3_STB_O => PWM3_STB,
350       IRF_ACK_I  => IRF_ACK,
351       IRF_ADR_O  => IRF_ADR,
352       IRF_DAT_I  => IRF_DAT_O,
353       IRF_DAT_O  => IRF_DAT_I,
354       IRF_STB_O  => IRF_STB,
355       IRF_WE_O   => IRF_WE);
356
357   wave_table_1 : entity work.wave_table
358     generic map (
359       DAT_W     => PWM_W,
360       ADR_W     => LUT_ADR_W,
361       INIT_FILE => LUT_INIT)
362     port map (
363       ACK_O => open,
364       ADR_I => LUT_ADR,
365       CLK_I => mclk,
366       DAT_I => conv_std_logic_vector(0, PWM_W),
367       DAT_O => LUT_DAT_O,
368       STB_I => LUT_STB,
369       WE_I  => '0');
370
371
372   ------------------------------------------------------------------------------
373   -- PWM and IRC
374   ------------------------------------------------------------------------------
375   -- PWM counter is shared by all PWM generators. Generator contains only
376   -- comparator and desired value.
377   pwm_counter : entity work.counter
378     generic map (
379       WIDTH => PWM_W,
380       MAX   => 2**PWM_W - 2)
381     port map (
382       clk      => mclk,
383       clk_en   => '1',
384       reset    => puc,
385       count    => PWM_CNT,
386       event_ow => PWM_OW);
387
388     pwm_1 : entity work.pwm
389     generic map (
390       PWM_WIDTH => PWM_W)
391     port map (
392       clk     => mclk,
393       reset   => puc,
394       din     => PWM_DAT,
395       sel     => '1',
396       we      => PWM1_STB,
397       pwm_cnt => PWM_CNT,
398       pwm_cyc => PWM_OW,
399       pwm     => PWM1_OUT);
400
401   pwm_2 : entity work.pwm
402     generic map (
403       PWM_WIDTH => PWM_W)
404     port map (
405       clk     => mclk,
406       reset   => puc,
407       din     => PWM_DAT,
408       sel     => '1',
409       we      => PWM2_STB,
410       pwm_cnt => PWM_CNT,
411       pwm_cyc => PWM_OW,
412       pwm     => PWM2_OUT);
413   
414   pwm_3 : entity work.pwm
415     generic map (
416       PWM_WIDTH => PWM_W)
417     port map (
418       clk     => mclk,
419       reset   => puc,
420       din     => PWM_DAT,
421       sel     => '1',
422       we      => PWM3_STB,
423       pwm_cnt => PWM_CNT,
424       pwm_cyc => PWM_OW,
425       pwm     => PWM3_OUT);
426
427   -- PWM signals mapped to FPGA outputs, EN forced to '1'
428   PWM0    <= not PWM1_OUT;
429   PWM0_EN <= '1';
430   PWM1    <= not PWM2_OUT;
431   PWM1_EN <= '1';
432   PWM2    <= not PWM3_OUT;
433   PWM2_EN <= '1';
434
435   -- PWM is signalized on LEDs
436   LED0    <= PWM1_OUT;
437   LED1    <= PWM2_OUT;
438   LED2    <= PWM3_OUT;
439
440   qcounter_1 : entity work.qcounter
441     port map (
442       clock    => mclk,
443       reset    => puc,
444       a0       => IRC_A,
445       b0       => IRC_B,
446       qcount   => QCNT,
447       a_rise   => open,
448       a_fall   => open,
449       b_rise   => open,
450       b_fall   => open,
451       ab_event => open,
452       ab_error => open);
453
454   
455 end rtl;
456