ADC state machine upgraded (reset added), ready for testing.
[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: out std_logic; -- RTS
26         gpio18: out std_logic; -- PWM0/PCMCLK
27         gpio27: out std_logic; -- SD1DAT3
28         gpio22: out std_logic; -- SD1CLK
29         gpio23: out std_logic; -- SD1CMD
30         gpio24: out std_logic; -- SD1DAT0
31         gpio10: in std_logic; -- SPI0MOSI
32         gpio9: out std_logic; -- SPI0MISO
33         gpio25: out 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,reset);
117         signal state : state_type;
118         signal adc_data: std_logic_vector(11 downto 0); --ADC income data
119         signal adc_reset : std_logic;
120         signal adc_rst_old : std_logic_vector(1 downto 0);
121         signal adc_address: std_logic_vector(8 downto 0);
122         signal adc_channels: std_logic_vector(35 downto 0);
123         
124         signal spiclk_old: std_logic_vector(1 downto 0); --pro detekci hrany SPI hodin
125         signal pwm_in, pwm_dir_in: std_logic;
126         signal gpio_clk: std_logic;
127         signal dat_reg : STD_LOGIC_VECTOR (95 downto 0); --shift register for spi
128         signal position: std_logic_vector(31 downto 0); --pozice z qcounteru
129         signal ce0_old: std_logic_vector(1 downto 0);
130         
131         
132         
133         --  attribute syn_noprune of gpio2 : signal is true;
134         --  attribute syn_preserve of gpio2 : signal is true;
135         --  attribute syn_keep of gpio2 : signal is true;
136         --  attribute syn_hier of gpio2 : signal is true;
137
138 begin
139         -- PLL as a reset generator
140         
141         --zesileni signalu GPIO CLK
142         copyclk2: CLKINT
143         port map (
144                 a => gpio4,
145                 y => gpio_clk
146         );
147         
148         
149         qcount: qcounter
150         port map (
151                 clock => gpio_clk,
152                 reset => '0',
153                 a0 => irc_a,
154                 b0 => irc_b,
155                 qcount => position,
156                 a_rise => open,
157                 a_fall => open,
158                 b_rise => open,
159                 b_fall => open,
160                 ab_event => open,
161                 ab_error => open
162         );
163         
164         
165         --   pll: pll50to200
166         --     port map (
167         --       powerdown => '1',
168         --       clka => pll_clkin,
169         --       gla => pll_clkout,
170         --       lock => pll_lock);
171         -- --  reset <= not pll_lock;
172         --   reset <= '0';                         -- TODO: apply reset for good failsafe
173                                            -- upon power-on
174         --   clock <= clkm;
175
176         dummy_unused <= gpio2 and gpio3  and gpio4 and
177                 gpio5 and gpio6 and
178                 gpio12 and gpio13 and gpio14 and
179                 gpio15 and gpio16 and gpio19 and
180                 gpio20 and gpio21 and gpio26 and
181                 stat(1) and stat(2) and stat(3) and
182                 hal_in(1) and hal_in(2) and hal_in(3) and
183                 irc_i and power_stat and 
184                 adc_miso and 
185                 rs485_rxd and
186                 can_rx and can_tx and
187                 dip_sw(1) and dip_sw(2) and dip_sw(3) and
188                 irc_a and irc_b and
189                 -- gpio17 and gpio18 and gpio27 and gpio22 and
190                 gpio8  and gpio11 and gpio7 and gpio10 and
191                 ext_scs1 and ext_scs2 and ext_miso and ext_mosi and ext_sclk and ext_scs0;
192                         
193         rs485_txd <= '1';
194         rs485_dir <= '0';
195
196
197         shdn(1) <= '0';
198         shdn(2) <= '0';
199         shdn(3) <= '1';
200
201         pwm(1) <= '0';
202         pwm(2) <= '0';
203         pwm(3) <= '0';
204
205         
206         process
207         begin
208                 --position is obtained on rising edge -> we should write it on next cycle
209                 wait until (gpio_clk'event and gpio_clk='1');
210                 
211                 --SCLK edge detection
212                 spiclk_old(0)<=gpio11;
213                 spiclk_old(1)<=spiclk_old(0);
214                 
215                 --SS edge detection
216                 ce0_old(0)<=gpio7;
217                 ce0_old(1)<=ce0_old(0);
218                 
219                 if (spiclk_old="01") then --rising edge, faze cteni
220                         if (gpio7 = '0') then             -- SPI CS must be selected
221                                 -- shift serial data into dat_reg on each rising edge
222                                 -- of SCK, MSB first
223                                 dat_reg(95 downto 0) <= dat_reg(94 downto 0) & gpio10;
224                                 end if;
225                 elsif (spiclk_old="10" ) then --falling edge, faze zapisu
226                         if (gpio7 = '0') then
227                                 gpio9 <= dat_reg(95); --zapisujeme nejdriv MSB
228                         end if;
229                 end if;
230                 
231                         
232                 --sestupna hrana SS, pripravime data pro prenos
233                 if (ce0_old = "10" ) then 
234                         dat_reg(95 downto 64) <= position(31 downto 0); --pozice
235                         dat_reg(63 downto 61) <= hal_in(1 to 3); --halovy sondy
236                         dat_reg(60 downto 36) <= (others => '1'); --let the rest fill with ones
237                         dat_reg(35 downto 0) <= adc_channels(35 downto 0); --current mesurments
238                 elsif (ce0_old = "01") then --rising edge of SS, we should read the data
239                         adc_reset<=dat_reg(95);
240                 end if;
241         end process;
242         
243         process 
244                 variable data_ready : std_logic;
245                 variable channel: std_logic_vector(1 downto 0);
246         begin
247                 wait until (gpio_clk'event and gpio_clk='1');
248                 case state is
249                         when reset=>
250                                 adc_scs<='0'; --active-high SS
251                                 data_ready:='0';
252                                 --addresse are CH(A2,A1,A0): CH0:(0,0,1),CH1:(1,0,1),CH2:(0,1,0)
253                                 adc_address<="001101010";
254                                 channel:="00";
255                         when f1=>
256                                 adc_sclk<='0'; --clk
257                                 adc_mosi<='1'; --start bit
258                                 state<=r1; --next state
259                         when r1=>       --rising edge
260                                 adc_sclk<='1';
261                                 adc_data(5)<=adc_miso;
262                                 state<=f2;
263                         when f2=> --2nd falling edge
264                                 adc_sclk<='0';
265                                 adc_mosi<=adc_address(8); --A2 address
266                                 state<=r2;
267                         when r2=> --rising edge
268                                 adc_sclk<='1';
269                                 adc_data(4)<=adc_miso;
270                                 state<=f3;
271                         when f3=> --3rd falling edge
272                                 adc_sclk<='0';
273                                 adc_mosi<=adc_address(7); --A1 address
274                                 state<=r3;
275                         when r3=> --rising edge
276                                 adc_sclk<='1';
277                                 adc_data(3)<=adc_miso;
278                                 state<=f4;      
279                         when f4=> --4th falling edge
280                                 adc_sclk<='0';
281                                 adc_mosi<=adc_address(6); --A0 address
282                                 --shift the addresses
283                                 adc_address(8 downto 0)<=adc_address(5 downto 0) & adc_address(8 downto 6);
284                                 state<=r4;
285                         when r4=> --rising edge
286                                 adc_sclk<='1';
287                                 adc_data(2)<=adc_miso;
288                                 state<=f5;      
289                         when f5=> --5th falling edge
290                                 adc_sclk<='0';
291                                 adc_mosi<='0'; --MODE (LOW -12bit)
292                                 state<=r5;
293                         when r5=> --rising edge
294                                 adc_sclk<='1';
295                                 adc_data(1)<=adc_miso;
296                                 state<=f6;      
297                         when f6=> --6th falling edge
298                                 adc_sclk<='0';
299                                 adc_mosi<='1'; --SGL/DIF (HIGH - SGL=Single Ended)
300                                 state<=r6;
301                         when r6=> --rising edge
302                                 adc_sclk<='1';
303                                 adc_data(0)<=adc_miso;
304                                 state<=f7;              
305                         when f7=> -- 7th falling edge
306                                 adc_sclk<='0';
307                                 adc_mosi<='0'; --PD1 (power down - PD1=PD0=0 -> power down between conversion)
308                                 state<=r7;
309                         when r7=> --rising edge, data ready
310                                 adc_sclk<='1';
311                                 if (data_ready='1') then
312                                         case channel is
313                                                 when "00"=>
314                                                         adc_channels(35 downto 24)<=adc_data(11 downto 0);
315                                                         channel:="01";
316                                                 when "01"=>
317                                                         adc_channels(23 downto 12)<=adc_data(11 downto 0);
318                                                         channel:="10";
319                                                 when "10"=>
320                                                         adc_channels(11 downto 0)<=adc_data(11 downto 0);
321                                                         channel:="00";
322                                         end case;
323                                 end if;
324                                 data_ready:='1';
325                                 state<=f8;      
326                         when f8=> --8th falling edge
327                                 adc_sclk<='0';
328                                 adc_mosi<='0'; --PD0
329                                 state<=r8;
330                         when r8=> --rising edge
331                                 adc_sclk<='1';
332                                 state<=f9;
333                         when f9=> --busy state between conversion, 9th falling edge
334                                 adc_sclk<='0';
335                                 state<=r9;
336                         when r9=>  --10th rising edge
337                                 adc_sclk<='1';
338                                 adc_data(11)<=adc_miso;
339                                 state<=f10;
340                         when f10=>
341                                 adc_sclk<='0';
342                                 state<=r10;
343                         when r10=>  --11th rising edge
344                                 adc_sclk<='1';
345                                 adc_data(10)<=adc_miso;
346                                 state<=f11;
347                         when f11=>
348                                 adc_sclk<='0';
349                                 state<=r11;
350                         when r11=>  --12th rising edge
351                                 adc_sclk<='1';
352                                 adc_data(9)<=adc_miso;
353                                 state<=f12;
354                         when f12=>
355                                 adc_sclk<='0';
356                                 state<=r12;
357                         when r12=>  --13th rising edge
358                                 adc_sclk<='1';
359                                 adc_data(8)<=adc_miso;
360                                 state<=f13;
361                         when f13=>
362                                 adc_sclk<='0';
363                                 state<=r13;
364                         when r13=>  --14th rising edge
365                                 adc_sclk<='1';
366                                 adc_data(7)<=adc_miso;
367                                 state<=f14;
368                         when f14=>
369                                 adc_sclk<='0';
370                                 state<=r14;
371                         when r14=> --15th rising edge
372                                 adc_sclk<='1';
373                                 adc_data(6)<=adc_miso;
374                                 adc_rst_old(0)<=adc_reset;
375                                 adc_rst_old(1)<=adc_rst_old(0);
376                                 if (adc_rst_old="01") then --we check rising edge of reset 
377                                         state<=reset;
378                                 else
379                                         state<=f1;
380                                 end if;
381                 end case;
382         end process;
383                         
384         
385                 
386 end behavioral;
387