7b09532e80b33b12352618327c7ca928b9d7da82
[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 port (
20         gpio2: in std_logic; -- SDA
21         gpio3: in std_logic; -- SCL
22         gpio4: in std_logic; -- CLK
23         gpio14: in std_logic; -- Tx
24         gpio15: in std_logic; -- Rx
25         gpio17: in std_logic; -- RTS
26         gpio18: in std_logic; -- PWM0/PCMCLK
27         gpio27: in std_logic; -- SD1DAT3
28         gpio22: in std_logic; -- SD1CLK
29         gpio23: in std_logic; -- SD1CMD
30         gpio24: in std_logic; -- SD1DAT0
31         gpio10: in std_logic; -- SPI0MOSI
32         gpio9: out std_logic; -- SPI0MISO
33         gpio25: in std_logic; -- SD1DAT1
34         gpio11: in std_logic; -- SPI0SCLK
35         gpio8: in std_logic; -- SPI0CE0
36         gpio7: in std_logic; -- SPI0CE1
37         gpio5: in std_logic; -- GPCLK1
38         gpio6: in std_logic; -- GPCLK2
39         gpio12: in std_logic; -- PWM0
40         gpio13: in std_logic; -- PWM1
41         gpio19: in std_logic; -- PWM1/SPI1MISO/PCMFS
42         gpio16: in std_logic; -- SPI1CE2
43         gpio26: in std_logic; -- SD1DAT2
44         gpio20: in std_logic; -- SPI1MOSI/PCMDIN/GPCLK0
45         gpio21: in std_logic; -- SPI1SCLK/PCMDOUT/GPCLK1
46         --
47         -- PWM
48         -- Each PWM signal has cooresponding shutdown
49         pwm: out std_logic_vector (1 to 3);
50         shdn: out std_logic_vector (1 to 3);
51         -- Fault/power stage status
52         stat: in std_logic_vector (1 to 3);
53         -- HAL inputs
54         hal_in: in std_logic_vector (1 to 3);
55         -- IRC inputs
56         irc_a: in std_logic;
57         irc_b: in std_logic;
58         irc_i: in std_logic;
59         -- Power status
60         power_stat: in std_logic;
61         -- ADC for current
62         adc_miso: in std_logic;
63         adc_mosi: out std_logic;
64         adc_sclk: out std_logic;
65         adc_scs: out std_logic;
66         -- Extarnal SPI
67         ext_miso: in std_logic; --master in slave out
68         ext_mosi: in std_logic; --master out slave in
69         ext_sclk: in std_logic;
70         ext_scs0: in std_logic;
71         ext_scs1: in std_logic;
72         ext_scs2: in std_logic;
73         -- RS-485 Transceiver
74         rs485_rxd: in std_logic;
75         rs485_txd: out std_logic;
76         rs485_dir: out std_logic;
77         -- CAN Transceiver
78         can_rx: in std_logic;
79         can_tx: in std_logic;
80         -- DIP switch
81         dip_sw: in std_logic_vector (1 to 3); --na desce je prohozene cislovanni
82         -- Unused terminal to keep design tools silent
83         dummy_unused : out std_logic
84 );
85 end rpi_mc_simple_dc;
86
87
88 architecture behavioral of rpi_mc_simple_dc is
89         attribute syn_noprune :boolean;
90         attribute syn_preserve :boolean;
91         attribute syn_keep :boolean;
92         attribute syn_hier :boolean;
93         -- Actel lib
94         -- component pll50to200
95         --   port (
96         --     powerdown, clka: in std_logic;
97         --     lock, gla: out std_logic
98         --   );
99         -- end component;
100         
101         component CLKINT
102                 port (A: in std_logic; Y: out std_logic);
103         end component;
104         
105         component qcounter
106         port (
107                 clock: in std_logic;
108                 reset: in std_logic;
109                 a0, b0: in std_logic;
110                 qcount: out std_logic_vector (31 downto 0);
111                 a_rise, a_fall, b_rise, b_fall, ab_event: out std_logic;
112                 ab_error: out std_logic
113         );
114         end component;
115
116         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);
117         signal state : state_type;
118         
119         type channel_type is (ch0, ch1, ch2);
120         
121         signal adc_data: std_logic_vector(11 downto 0); --ADC income data
122         signal adc_reset : std_logic;
123         signal adc_rst_old : std_logic_vector(1 downto 0);
124         signal adc_address: std_logic_vector(8 downto 0);
125         signal adc_channels: std_logic_vector(35 downto 0);
126         
127         signal spiclk_old: std_logic_vector(1 downto 0); --pro detekci hrany SPI hodin
128         --signal pwm_in, pwm_dir_in: std_logic;
129         signal gpio_clk: std_logic;
130         signal dat_reg : STD_LOGIC_VECTOR (95 downto 0); --shift register for spi
131         signal position: std_logic_vector(31 downto 0); --pozice z qcounteru
132         signal ce0_old: std_logic_vector(1 downto 0);
133         
134         
135         
136         --  attribute syn_noprune of gpio2 : signal is true;
137         --  attribute syn_preserve of gpio2 : signal is true;
138         --  attribute syn_keep of gpio2 : signal is true;
139         --  attribute syn_hier of gpio2 : signal is true;
140
141 begin
142         -- PLL as a reset generator
143         
144         --zesileni signalu GPIO CLK
145         copyclk2: CLKINT
146         port map (
147                 a => gpio4,
148                 y => gpio_clk
149         );
150         
151         
152         qcount: qcounter
153         port map (
154                 clock => gpio_clk,
155                 reset => '0',
156                 a0 => irc_a,
157                 b0 => irc_b,
158                 qcount => position,
159                 a_rise => open,
160                 a_fall => open,
161                 b_rise => open,
162                 b_fall => open,
163                 ab_event => open,
164                 ab_error => open
165         );
166         
167         
168         --   pll: pll50to200
169         --     port map (
170         --       powerdown => '1',
171         --       clka => pll_clkin,
172         --       gla => pll_clkout,
173         --       lock => pll_lock);
174         -- --  reset <= not pll_lock;
175         --   reset <= '0';                         -- TODO: apply reset for good failsafe
176                                            -- upon power-on
177         --   clock <= clkm;
178
179         dummy_unused <= gpio2 and gpio3  and gpio4 and
180                 gpio5 and gpio6 and
181                 gpio12 and gpio13 and gpio14 and
182                 gpio15 and gpio16 and gpio19 and
183                 gpio20 and gpio21 and gpio26 and
184                 stat(1) and stat(2) and stat(3) and
185                 hal_in(1) and hal_in(2) and hal_in(3) and
186                 irc_i and power_stat and 
187                 adc_miso and 
188                 rs485_rxd and
189                 can_rx and can_tx and
190                 dip_sw(1) and dip_sw(2) and dip_sw(3) and
191                 irc_a and irc_b and
192                 gpio17 and gpio18 and gpio27 and gpio22 and gpio23 and gpio24 and gpio25 and
193                 gpio8  and gpio11 and gpio7 and gpio10 and
194                 ext_scs1 and ext_scs2 and ext_miso and ext_mosi and ext_sclk and ext_scs0;
195                         
196         rs485_txd <= '1';
197         rs485_dir <= '0';
198
199
200         shdn(1) <= '0';
201         shdn(2) <= '0';
202         shdn(3) <= '1';
203
204         pwm(1) <= '0';
205         pwm(2) <= '0';
206         pwm(3) <= '0';
207
208         
209         process
210         begin
211                 --position is obtained on rising edge -> we should write it on next cycle
212                 wait until (gpio_clk'event and gpio_clk='1');
213                 
214                 --SCLK edge detection
215                 spiclk_old(0)<=gpio11;
216                 spiclk_old(1)<=spiclk_old(0);
217                 
218                 --SS edge detection
219                 ce0_old(0)<=gpio7;
220                 ce0_old(1)<=ce0_old(0);
221                 
222                 if (spiclk_old="01") then --rising edge, faze cteni
223                         if (gpio7 = '0') then             -- SPI CS must be selected
224                                 -- shift serial data into dat_reg on each rising edge
225                                 -- of SCK, MSB first
226                                 dat_reg(95 downto 0) <= dat_reg(94 downto 0) & gpio10;
227                                 end if;
228                 elsif (spiclk_old="10" ) then --falling edge, faze zapisu
229                         if (gpio7 = '0') then
230                                 gpio9 <= dat_reg(95); --zapisujeme nejdriv MSB
231                         end if;
232                 end if;
233                 
234                         
235                 --sestupna hrana SS, pripravime data pro prenos
236                 if (ce0_old = "10" ) then 
237                         dat_reg(95 downto 64) <= position(31 downto 0); --pozice
238                         dat_reg(63 downto 61) <= hal_in(1 to 3); --halovy sondy
239                         dat_reg(60 downto 36) <= (others => '1'); --let the rest fill with ones
240                         dat_reg(35 downto 0) <= adc_channels(35 downto 0); --current mesurments
241                         adc_reset<='0'; --remove reset flag, and wait on its rising edge
242                 elsif (ce0_old = "01") then --rising edge of SS, we should read the data
243                         adc_reset<=dat_reg(95);
244                 end if;
245         end process;
246         
247         process 
248                 variable data_ready : std_logic;
249                 variable channel: channel_type;
250                 variable reset_re: std_logic:='0';
251                 variable reset_count: integer:=0;
252         begin
253                 wait until (gpio_clk'event and gpio_clk='1');
254                 
255                 --reset rising edge detection
256                 adc_rst_old(0)<=adc_reset;
257                 adc_rst_old(1)<=adc_rst_old(0);
258                 
259                 if (adc_rst_old="01") then
260                         reset_re:='1';
261                 end if;
262                 
263                 case state is
264                         when reset=>
265                                 reset_re:='0'; --clear reset flag
266                                 adc_scs<='1'; --active-low SS
267                                 adc_sclk<='0'; --lower clock
268                                 data_ready:='0'; 
269                                 --addresse are CH(A2,A1,A0): CH0:(0,0,1),CH1:(1,0,1),CH2:(0,1,0)
270                                 adc_address<="001101010";
271                                 channel:=ch0;
272                                 adc_channels(35 downto 0)<=(others=>'1'); --for debug only - remove this line!
273                                 adc_data(11 downto 0)<=(others=>'1');
274                                 reset_count:=0;
275                                 state<=rst_wait;
276                         when rst_wait=>
277                                 if (reset_count<10) then
278                                         reset_count:=reset_count+1;
279                                         if (reset_count=7) then
280                                                 adc_scs<='0'; --give the adc some time to prepare before trensfer
281                                         end if;
282                                 else
283                                         state<=f1;
284                                 end if;
285                         when f1=> --1st 'fallin edge' - its not falling edge in any case-if rst clock is low before  
286                                 adc_sclk<='0'; --clk
287                                 adc_mosi<='1'; --start bit
288                                 state<=r1; --next state
289                         when r1=>       --1st rising edge (adc gets the start bit, we get date..)
290                                 adc_sclk<='1'; 
291                                 adc_data(5)<=adc_miso;
292                                 state<=f2;
293                         when f2=> --2nd falling edge
294                                 adc_sclk<='0';
295                                 adc_mosi<=adc_address(8); --A2 address
296                                 state<=r2;
297                         when r2=> --2nd rising edge (adc gets A2 address)
298                                 adc_sclk<='1';
299                                 adc_data(4)<=adc_miso;
300                                 state<=f3;
301                         when f3=> --3rd falling edge 
302                                 adc_sclk<='0';
303                                 adc_mosi<=adc_address(7); --A1 address
304                                 state<=r3;
305                         when r3=> --rising edge
306                                 adc_sclk<='1';
307                                 adc_data(3)<=adc_miso;
308                                 state<=f4;      
309                         when f4=> --4th falling edge
310                                 adc_sclk<='0';
311                                 adc_mosi<=adc_address(6); --A0 address
312                                 --shift the addresses
313                                 adc_address(8 downto 0)<=adc_address(5 downto 0) & adc_address(8 downto 6); 
314                                 state<=r4;
315                         when r4=> --rising edge
316                                 adc_sclk<='1';
317                                 adc_data(2)<=adc_miso;
318                                 state<=f5;      
319                         when f5=> --5th falling edge
320                                 adc_sclk<='0';
321                                 adc_mosi<='0'; --MODE (LOW -12bit)
322                                 state<=r5;
323                         when r5=> --rising edge
324                                 adc_sclk<='1';
325                                 adc_data(1)<=adc_miso;
326                                 state<=f6;      
327                         when f6=> --6th falling edge
328                                 adc_sclk<='0';
329                                 adc_mosi<='1'; --SGL/DIF (HIGH - SGL=Single Ended)
330                                 state<=r6;
331                         when r6=> --6th rising edge (we read last bit of conversion, adc gets SGL/DIF)
332                                 adc_sclk<='1';
333                                 adc_data(0)<=adc_miso;
334                                 state<=f7;              
335                         when f7=> -- 7th falling edge
336                                 adc_sclk<='0';
337                                 adc_mosi<='0'; --PD1 (power down - PD1=PD0=0 -> power down between conversion)
338                                 state<=r7;
339                         when r7=> --7th rising edge, data ready
340                                 adc_sclk<='1';
341                                 if (data_ready='1') then
342                                         case channel is
343                                                 when ch0=>
344                                                         adc_channels(35 downto 24)<=adc_data(11 downto 0);
345                                                         --adc_channels(35 downto 24)<=(others=>'0');
346                                                         channel:=ch1;
347                                                 when ch1=>
348                                                         adc_channels(23 downto 12)<=adc_data(11 downto 0);
349                                                         --adc_channels(23 downto 12)<=(others=>'1');
350                                                         channel:=ch2;
351                                                 when ch2=>
352                                                         adc_channels(11 downto 0)<=adc_data(11 downto 0);
353                                                         --adc_channels(11 downto 0)<=(others=>'0');
354                                                         channel:=ch0;
355                                         end case;
356                                 end if;
357                                 data_ready:='1';
358                                 state<=f8;      
359                         when f8=> --8th falling edge
360                                 adc_sclk<='0';
361                                 adc_mosi<='0'; --PD0
362                                 state<=r8;
363                         when r8=> --8th rising edge (adc gets PD0)
364                                 adc_sclk<='1';
365                                 state<=f9;
366                         when f9=> --9th falling edge busy state between conversion (we write nothing)
367                                 adc_sclk<='0';
368                                 state<=r9;
369                         when r9=>  --9th rising edge (we nor ads get nothing)
370                                 adc_sclk<='1';
371                                 state<=f10;
372                         when f10=> --10th falling edge
373                                 adc_sclk<='0';
374                                 state<=r10;
375                         when r10=>  --10th rising edge (we read 1. bit of conversion)
376                                 adc_sclk<='1';
377                                 adc_data(11)<=adc_miso;
378                                 state<=f11;
379                         when f11=>
380                                 adc_sclk<='0';
381                                 state<=r11;
382                         when r11=>  --11th rising edge
383                                 adc_sclk<='1';
384                                 adc_data(10)<=adc_miso;
385                                 state<=f12;
386                         when f12=>
387                                 adc_sclk<='0';
388                                 state<=r12;
389                         when r12=>  --12th rising edge
390                                 adc_sclk<='1';
391                                 adc_data(9)<=adc_miso;
392                                 state<=f13;
393                         when f13=>
394                                 adc_sclk<='0';
395                                 state<=r13;
396                         when r13=>  --13th rising edge
397                                 adc_sclk<='1';
398                                 adc_data(8)<=adc_miso;
399                                 state<=f14;
400                         when f14=>
401                                 adc_sclk<='0';
402                                 state<=r14;
403                         when r14=>  --14th rising edge
404                                 adc_sclk<='1';
405                                 adc_data(7)<=adc_miso;
406                                 state<=f15;
407                         when f15=>
408                                 adc_sclk<='0';
409                                 --for rising edge detection in next cycle
410                                 state<=r15;
411                         when r15=> --15th rising edge
412                                 adc_sclk<='1';
413                                 adc_data(6)<=adc_miso;
414                                 if (reset_re='1') then --we check rising edge of reset 
415                                         state<=reset;
416                                 else
417                                         state<=f1;
418                                 end if;
419                 end case;
420         end process;
421                         
422         
423                 
424 end behavioral;
425