Integration of mcpwm into toplevel entity.
[fpga/rpi-motor-control.git] / pmsm-control / rpi_mc_simple_dc.vhdl
1 --
2 -- * LXPWR slave part *
3 --  common sioreg & common counter for several ADC&PWM blocks
4 --
5 -- part of LXPWR motion control board (c) PiKRON Ltd
6 -- idea by Pavel Pisa PiKRON Ltd <pisa@cmp.felk.cvut.cz>
7 -- code by Marek Peca <mp@duch.cz>
8 -- 01/2013
9 --
10 -- license: GNU GPLv3
11 --
12
13 library ieee;
14 use ieee.std_logic_1164.all;
15 use ieee.numeric_std.all;
16 use work.util.all;
17
18 entity rpi_mc_simple_dc is
19 generic(
20         pwm_width : natural:=11
21         );
22 port (
23         gpio2: in std_logic; -- SDA
24         gpio3: in std_logic; -- SCL
25         gpio4: in std_logic; -- CLK
26         gpio14: in std_logic; -- Tx
27         gpio15: in std_logic; -- Rx
28         gpio17: in std_logic; -- RTS
29         gpio18: in std_logic; -- PWM0/PCMCLK
30         gpio27: in std_logic; -- SD1DAT3
31         gpio22: in std_logic; -- SD1CLK
32         gpio23: in std_logic; -- SD1CMD
33         gpio24: in std_logic; -- SD1DAT0
34         gpio10: in std_logic; -- SPI0MOSI
35         gpio9: out std_logic; -- SPI0MISO
36         gpio25: in std_logic; -- SD1DAT1
37         gpio11: in std_logic; -- SPI0SCLK
38         gpio8: in std_logic; -- SPI0CE0
39         gpio7: in std_logic; -- SPI0CE1
40         gpio5: in std_logic; -- GPCLK1
41         gpio6: in std_logic; -- GPCLK2
42         gpio12: in std_logic; -- PWM0
43         gpio13: in std_logic; -- PWM1
44         gpio19: in std_logic; -- PWM1/SPI1MISO/PCMFS
45         gpio16: in std_logic; -- SPI1CE2
46         gpio26: in std_logic; -- SD1DAT2
47         gpio20: in std_logic; -- SPI1MOSI/PCMDIN/GPCLK0
48         gpio21: in std_logic; -- SPI1SCLK/PCMDOUT/GPCLK1
49         --
50         -- PWM
51         -- Each PWM signal has cooresponding shutdown
52         pwm: out std_logic_vector (1 to 3);
53         shdn: out std_logic_vector (1 to 3);
54         -- Fault/power stage status
55         stat: in std_logic_vector (1 to 3);
56         -- HAL inputs
57         hal_in: in std_logic_vector (1 to 3);
58         -- IRC inputs
59         irc_a: in std_logic;
60         irc_b: in std_logic;
61         irc_i: in std_logic;
62         -- Power status
63         power_stat: in std_logic;
64         -- ADC for current
65         adc_miso: in std_logic;
66         adc_mosi: out std_logic;
67         adc_sclk: out std_logic;
68         adc_scs: out std_logic;
69         -- Extarnal SPI
70         ext_miso: in std_logic; --master in slave out
71         ext_mosi: in std_logic; --master out slave in
72         ext_sclk: in std_logic;
73         ext_scs0: in std_logic;
74         ext_scs1: in std_logic;
75         ext_scs2: in std_logic;
76         -- RS-485 Transceiver
77         rs485_rxd: in std_logic;
78         rs485_txd: out std_logic;
79         rs485_dir: out std_logic;
80         -- CAN Transceiver
81         can_rx: in std_logic;
82         can_tx: in std_logic;
83         -- DIP switch
84         dip_sw: in std_logic_vector (1 to 3); --na desce je prohozene cislovanni
85         -- Unused terminal to keep design tools silent
86         dummy_unused : out std_logic
87 );
88 end rpi_mc_simple_dc;
89
90
91 architecture behavioral of rpi_mc_simple_dc is
92         attribute syn_noprune :boolean;
93         attribute syn_preserve :boolean;
94         attribute syn_keep :boolean;
95         attribute syn_hier :boolean;
96         -- Actel lib
97         -- component pll50to200
98         --   port (
99         --     powerdown, clka: in std_logic;
100         --     lock, gla: out std_logic
101         --   );
102         -- end component;
103         
104         component CLKINT
105                 port (A: in std_logic; Y: out std_logic);
106         end component;
107         
108         component qcounter
109         port (
110                 clock: in std_logic;
111                 reset: in std_logic;
112                 a0, b0: in std_logic;
113                 qcount: out std_logic_vector (31 downto 0);
114                 a_rise, a_fall, b_rise, b_fall, ab_event: out std_logic;
115                 ab_error: out std_logic
116         );
117         end component;
118
119         component mcpwm is
120         generic (
121                 pwm_width: natural
122         );
123         port (
124                 clock: in std_logic;
125                 sync: in std_logic;                             --flag that counter "restarts-overflows"
126                 data_valid:in std_logic;                        --indicates data is consistent
127                 failsafe: in std_logic;                         --turn off both transistors
128                 en_p, en_n: in std_logic;                       --enable positive & enable shutdown
129                 match: in std_logic_vector (pwm_width-1 downto 0); --posion of counter when we swap output logic
130                 count: in std_logic_vector (pwm_width-1 downto 0); --we use an external counter
131                 out_p, out_n: out std_logic                     --pwm outputs: positive & shutdown
132                 --TODO add the rest of pwm signals, swap match to pwm_word
133         );
134         end component;
135         
136         
137         type state_type is (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,f15,r15,reset,rst_wait);
138         signal state : state_type;
139         
140         type channel_type is (ch0, ch1, ch2);
141         
142         signal adc_data: std_logic_vector(11 downto 0); --ADC income data
143         signal adc_reset : std_logic;
144         signal adc_rst_old : std_logic_vector(1 downto 0);
145         signal adc_address: std_logic_vector(8 downto 0);
146         signal adc_channels: std_logic_vector(35 downto 0);
147         
148         signal spiclk_old: std_logic_vector(1 downto 0); --pro detekci hrany SPI hodin
149         --signal pwm_in, pwm_dir_in: std_logic;
150         signal gpio_clk: std_logic;
151         signal dat_reg : STD_LOGIC_VECTOR (95 downto 0); --shift register for spi
152         signal position: std_logic_vector(31 downto 0); --pozice z qcounteru
153         signal ce0_old: std_logic_vector(1 downto 0);
154         
155         --pwm signals
156         constant pwm_n: natural := 3;                                   --number of pwm outputs
157         --number of ticks per pwm cycle, 2^11=2048
158         constant pwm_period : std_logic_vector (pwm_width-1 downto 0) := (others=>'1'); 
159         type pwm_res_type is array(1 to 3) of std_logic_vector (pwm_width-1 downto 0);
160         
161         signal pwm_match: pwm_res_type;                                 --point of reversion of pwm output, 0 to 2047
162         signal pwm_count: std_logic_vector (pwm_width-1 downto 0);      --counter, 0 to 2047
163         signal pwm_sync: std_logic;
164         signal pwm_en_p: std_logic_vector(1 to 3);
165         signal pwm_en_n: std_logic_vector(1 to 3);
166         
167         signal income_data_valid: std_logic;
168         
169         
170         --  attribute syn_noprune of gpio2 : signal is true;
171         --  attribute syn_preserve of gpio2 : signal is true;
172         --  attribute syn_keep of gpio2 : signal is true;
173         --  attribute syn_hier of gpio2 : signal is true;
174
175 begin
176         -- PLL as a reset generator
177         
178         --zesileni signalu GPIO CLK
179         copyclk2: CLKINT
180         port map (
181                 a => gpio4,
182                 y => gpio_clk
183         );
184         
185         
186         qcount: qcounter
187         port map (
188                 clock => gpio_clk,
189                 reset => '0',
190                 a0 => irc_a,
191                 b0 => irc_b,
192                 qcount => position,
193                 a_rise => open,
194                 a_fall => open,
195                 b_rise => open,
196                 b_fall => open,
197                 ab_event => open,
198                 ab_error => open
199         );
200         
201         pwm_block: for i in pwm_n downto 1 generate
202                 pwm_map: mcpwm
203                 generic map (
204                         pwm_width => pwm_width
205                 )
206                 port map (
207                         clock => gpio_clk,                              --50 Mhz clk from gpclk on raspberry
208                         sync => pwm_sync,                               --counter restarts
209                         data_valid => income_data_valid,                        
210                         failsafe => '0',
211                         --
212                         -- pwm config bits & match word
213                         --
214                         en_n => pwm_en_n(i),                            --enable positive pwm
215                         en_p => pwm_en_p(i),                            --enable "negative" ->activate shutdown
216                         match => pwm_match(i),
217                         count => pwm_count,
218                         -- outputs
219                         out_p => pwm(i),                                --positive signal
220                         out_n => shdn(i)                                --reverse signal is in shutdown mode
221                 );
222         end generate;
223         
224         
225         
226         --   pll: pll50to200
227         --     port map (
228         --       powerdown => '1',
229         --       clka => pll_clkin,
230         --       gla => pll_clkout,
231         --       lock => pll_lock);
232         -- --  reset <= not pll_lock;
233         --   reset <= '0';                         -- TODO: apply reset for good failsafe
234                                            -- upon power-on
235         --   clock <= clkm;
236
237         dummy_unused <= gpio2 and gpio3  and gpio4 and
238                 gpio5 and gpio6 and
239                 gpio12 and gpio13 and gpio14 and
240                 gpio15 and gpio16 and gpio19 and
241                 gpio20 and gpio21 and gpio26 and
242                 stat(1) and stat(2) and stat(3) and
243                 hal_in(1) and hal_in(2) and hal_in(3) and
244                 irc_i and power_stat and 
245                 adc_miso and 
246                 rs485_rxd and
247                 can_rx and can_tx and
248                 dip_sw(1) and dip_sw(2) and dip_sw(3) and
249                 irc_a and irc_b and
250                 gpio17 and gpio18 and gpio27 and gpio22 and gpio23 and gpio24 and gpio25 and
251                 gpio8  and gpio11 and gpio7 and gpio10 and
252                 ext_scs1 and ext_scs2 and ext_miso and ext_mosi and ext_sclk and ext_scs0;
253                         
254         rs485_txd <= '1';
255         rs485_dir <= '0';
256
257
258         --shdn(1) <= '0';
259         --shdn(2) <= '0';
260         --shdn(3) <= '1';
261
262         --pwm(1) <= '0';
263         --pwm(2) <= '0';
264         --pwm(3) <= '0';
265         
266         process
267         begin
268                 wait until (gpio_clk'event and gpio_clk='1');
269                 IF(pwm_count = pwm_period) THEN                         
270                 --end of period reached
271                         pwm_count <= (others=>'0');      --reset counter
272                         pwm_sync <= '1';                                -- inform PWM logic about new period start
273                 ELSE                                                    --end of period not reached
274                         pwm_count <= std_logic_vector(unsigned(pwm_count)+1);           --increment counter
275                         pwm_sync <= '0';
276                 END IF;
277         end process;
278         
279         process
280         begin
281                 --position is obtained on rising edge -> we should write it on next cycle
282                 wait until (gpio_clk'event and gpio_clk='1');
283                 
284                 --SCLK edge detection
285                 spiclk_old(0)<=gpio11;
286                 spiclk_old(1)<=spiclk_old(0);
287                 
288                 --SS edge detection
289                 ce0_old(0)<=gpio7;
290                 ce0_old(1)<=ce0_old(0);
291                 
292                 if (spiclk_old="01") then --rising edge, faze cteni
293                         if (gpio7 = '0') then             -- SPI CS must be selected
294                                 -- shift serial data into dat_reg on each rising edge
295                                 -- of SCK, MSB first
296                                 dat_reg(95 downto 0) <= dat_reg(94 downto 0) & gpio10;
297                                 end if;
298                 elsif (spiclk_old="10" ) then --falling edge, faze zapisu
299                         if (gpio7 = '0') then
300                                 gpio9 <= dat_reg(95); --zapisujeme nejdriv MSB
301                         end if;
302                 end if;
303                 
304                         
305                 --sestupna hrana SS, pripravime data pro prenos
306                 if (ce0_old = "10" ) then 
307                         income_data_valid<='0';
308                         dat_reg(95 downto 64) <= position(31 downto 0); --pozice
309                         dat_reg(63 downto 61) <= hal_in(1 to 3); --halovy sondy
310                         dat_reg(60 downto 36) <= (others => '1'); --let the rest fill with ones
311                         dat_reg(35 downto 0) <= adc_channels(35 downto 0); --current mesurments
312                         adc_reset<='0'; --remove reset flag, and wait on its rising edge
313                 elsif (ce0_old = "01") then --rising edge of SS, we should read the data
314                         adc_reset<=dat_reg(95);
315                         pwm_en_p(1 to 3)<=dat_reg(94 downto 92);
316                         pwm_en_n(1 to 3)<=dat_reg(91 downto 89);
317                         --11 bit pwm TODO: make it generic
318                         pwm_match(1)(pwm_width-1 downto 0)<=dat_reg(34 downto 24);
319                         pwm_match(2)(pwm_width-1 downto 0)<=dat_reg(22 downto 12);
320                         pwm_match(3)(pwm_width-1 downto 0)<=dat_reg(10 downto 0);
321                         income_data_valid<='1';
322                 end if;
323         end process;
324         
325         process 
326                 variable data_ready : std_logic;
327                 variable channel: channel_type;
328                 variable reset_re: std_logic:='0';
329                 variable reset_count: integer:=0;
330         begin
331                 wait until (gpio_clk'event and gpio_clk='1');
332                 
333                 --reset rising edge detection
334                 adc_rst_old(0)<=adc_reset;
335                 adc_rst_old(1)<=adc_rst_old(0);
336                 
337                 if (adc_rst_old="01") then
338                         reset_re:='1';
339                 end if;
340                 
341                 case state is
342                         when reset=>
343                                 reset_re:='0'; --clear reset flag
344                                 adc_scs<='1'; --active-low SS
345                                 adc_sclk<='0'; --lower clock
346                                 data_ready:='0'; 
347                                 --addresse are CH(A2,A1,A0): CH0:(0,0,1),CH1:(1,0,1),CH2:(0,1,0)
348                                 adc_address<="001101010";
349                                 channel:=ch0;
350                                 adc_channels(35 downto 0)<=(others=>'1'); --for debug only - remove this line!
351                                 adc_data(11 downto 0)<=(others=>'1');
352                                 reset_count:=0;
353                                 state<=rst_wait;
354                         when rst_wait=>
355                                 if (reset_count<10) then
356                                         reset_count:=reset_count+1;
357                                         if (reset_count=7) then
358                                                 adc_scs<='0'; --give the adc some time to prepare before trensfer
359                                         end if;
360                                 else
361                                         state<=f1;
362                                 end if;
363                         when f1=> --1st 'fallin edge' - its not falling edge in any case-if rst clock is low before  
364                                 adc_sclk<='0'; --clk
365                                 adc_mosi<='1'; --start bit
366                                 state<=r1; --next state
367                         when r1=>       --1st rising edge (adc gets the start bit, we get date..)
368                                 adc_sclk<='1'; 
369                                 adc_data(5)<=adc_miso;
370                                 state<=f2;
371                         when f2=> --2nd falling edge
372                                 adc_sclk<='0';
373                                 adc_mosi<=adc_address(8); --A2 address
374                                 state<=r2;
375                         when r2=> --2nd rising edge (adc gets A2 address)
376                                 adc_sclk<='1';
377                                 adc_data(4)<=adc_miso;
378                                 state<=f3;
379                         when f3=> --3rd falling edge 
380                                 adc_sclk<='0';
381                                 adc_mosi<=adc_address(7); --A1 address
382                                 state<=r3;
383                         when r3=> --rising edge
384                                 adc_sclk<='1';
385                                 adc_data(3)<=adc_miso;
386                                 state<=f4;      
387                         when f4=> --4th falling edge
388                                 adc_sclk<='0';
389                                 adc_mosi<=adc_address(6); --A0 address
390                                 --shift the addresses
391                                 adc_address(8 downto 0)<=adc_address(5 downto 0) & adc_address(8 downto 6); 
392                                 state<=r4;
393                         when r4=> --rising edge
394                                 adc_sclk<='1';
395                                 adc_data(2)<=adc_miso;
396                                 state<=f5;      
397                         when f5=> --5th falling edge
398                                 adc_sclk<='0';
399                                 adc_mosi<='0'; --MODE (LOW -12bit)
400                                 state<=r5;
401                         when r5=> --rising edge
402                                 adc_sclk<='1';
403                                 adc_data(1)<=adc_miso;
404                                 state<=f6;      
405                         when f6=> --6th falling edge
406                                 adc_sclk<='0';
407                                 adc_mosi<='1'; --SGL/DIF (HIGH - SGL=Single Ended)
408                                 state<=r6;
409                         when r6=> --6th rising edge (we read last bit of conversion, adc gets SGL/DIF)
410                                 adc_sclk<='1';
411                                 adc_data(0)<=adc_miso;
412                                 state<=f7;              
413                         when f7=> -- 7th falling edge
414                                 adc_sclk<='0';
415                                 adc_mosi<='0'; --PD1 (power down - PD1=PD0=0 -> power down between conversion)
416                                 state<=r7;
417                         when r7=> --7th rising edge, data ready
418                                 adc_sclk<='1';
419                                 if (data_ready='1') then
420                                         case channel is
421                                                 when ch0=>
422                                                         adc_channels(35 downto 24)<=adc_data(11 downto 0);
423                                                         --adc_channels(35 downto 24)<=(others=>'0');
424                                                         channel:=ch1;
425                                                 when ch1=>
426                                                         adc_channels(23 downto 12)<=adc_data(11 downto 0);
427                                                         --adc_channels(23 downto 12)<=(others=>'1');
428                                                         channel:=ch2;
429                                                 when ch2=>
430                                                         adc_channels(11 downto 0)<=adc_data(11 downto 0);
431                                                         --adc_channels(11 downto 0)<=(others=>'0');
432                                                         channel:=ch0;
433                                         end case;
434                                 end if;
435                                 data_ready:='1';
436                                 state<=f8;      
437                         when f8=> --8th falling edge
438                                 adc_sclk<='0';
439                                 adc_mosi<='0'; --PD0
440                                 state<=r8;
441                         when r8=> --8th rising edge (adc gets PD0)
442                                 adc_sclk<='1';
443                                 state<=f9;
444                         when f9=> --9th falling edge busy state between conversion (we write nothing)
445                                 adc_sclk<='0';
446                                 state<=r9;
447                         when r9=>  --9th rising edge (we nor ads get nothing)
448                                 adc_sclk<='1';
449                                 state<=f10;
450                         when f10=> --10th falling edge
451                                 adc_sclk<='0';
452                                 state<=r10;
453                         when r10=>  --10th rising edge (we read 1. bit of conversion)
454                                 adc_sclk<='1';
455                                 adc_data(11)<=adc_miso;
456                                 state<=f11;
457                         when f11=>
458                                 adc_sclk<='0';
459                                 state<=r11;
460                         when r11=>  --11th rising edge
461                                 adc_sclk<='1';
462                                 adc_data(10)<=adc_miso;
463                                 state<=f12;
464                         when f12=>
465                                 adc_sclk<='0';
466                                 state<=r12;
467                         when r12=>  --12th rising edge
468                                 adc_sclk<='1';
469                                 adc_data(9)<=adc_miso;
470                                 state<=f13;
471                         when f13=>
472                                 adc_sclk<='0';
473                                 state<=r13;
474                         when r13=>  --13th rising edge
475                                 adc_sclk<='1';
476                                 adc_data(8)<=adc_miso;
477                                 state<=f14;
478                         when f14=>
479                                 adc_sclk<='0';
480                                 state<=r14;
481                         when r14=>  --14th rising edge
482                                 adc_sclk<='1';
483                                 adc_data(7)<=adc_miso;
484                                 state<=f15;
485                         when f15=>
486                                 adc_sclk<='0';
487                                 --for rising edge detection in next cycle
488                                 state<=r15;
489                         when r15=> --15th rising edge
490                                 adc_sclk<='1';
491                                 adc_data(6)<=adc_miso;
492                                 if (reset_re='1') then --we check rising edge of reset 
493                                         state<=reset;
494                                 else
495                                         state<=f1;
496                                 end if;
497                 end case;
498         end process;
499                         
500         
501                 
502 end behavioral;
503