]> rtime.felk.cvut.cz Git - fpga/rpi-motor-control.git/blob - pmsm-control/adc_reader.vhdl
Bug fix: Added data propagation to MISO on falling edge of SE signal.
[fpga/rpi-motor-control.git] / pmsm-control / adc_reader.vhdl
1 --
2 -- * Raspberry Pi BLDC/PMSM motor control design for RPi-MI-1 board *
3 -- SPI connected multichannel current ADC read and averaging
4 --
5 -- (c) 2015 Martin Prudek <prudemar@fel.cvut.cz>
6 -- Czech Technical University in Prague
7 --
8 -- Project supervision and original project idea
9 -- idea by Pavel Pisa <pisa@cmp.felk.cvut.cz>
10 --
11 -- Related RPi-MI-1 hardware is designed by Petr Porazil,
12 -- PiKRON Ltd  <http://www.pikron.com>
13 --
14 -- license: GNU LGPL and GPLv3+
15 --
16
17 library ieee;
18 use ieee.std_logic_1164.all;
19 use ieee.numeric_std.all;
20 use work.util.all;
21
22 entity adc_reader is
23 port (
24         clk: in std_logic;                                      --input clk
25         adc_reset: in std_logic;
26         adc_miso: in std_logic;                                 --spi master in slave out
27         adc_channels: out std_logic_vector (71 downto 0);       --consistent data of 3 channels
28         adc_sclk: out std_logic;                                --spi clk
29         adc_scs: out std_logic;                                 --spi slave select
30         adc_mosi: out std_logic;                                --spi master out slave in
31         measur_count: out std_logic_vector(8 downto 0)          --number of accumulated measurments
32         
33 );
34 end adc_reader;
35
36
37 architecture behavioral of adc_reader is
38         
39         
40         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);
41         signal state : state_type;
42         
43         type channel_type is (ch0, ch1, ch2);
44         
45         signal adc_data: std_logic_vector(11 downto 0); 
46         signal adc_rst_old : std_logic_vector(1 downto 0);
47         signal adc_address: std_logic_vector(2 downto 0);
48         signal cumul_data: std_logic_vector(71 downto 0);       --unconsistent data, containing different amounts of measurments
49         signal prepared_data: std_logic_vector(71 downto 0);    --consistent data, waiting for clk sync to propagate to output
50         signal m_count_sig: std_logic_vector(8 downto 0);       --measurments count waiting for clk to propagate to output
51         signal first_pass: std_logic;
52 begin
53         
54         
55         process 
56                 variable channel: channel_type;
57                 variable reset_re: std_logic:='0';
58                 variable reset_count: std_logic_vector (3 downto 0);
59         begin
60                 wait until (clk'event and clk='1');
61                 
62                 --rising edge detection of reset signal
63                 adc_rst_old(0)<=adc_reset;
64                 adc_rst_old(1)<=adc_rst_old(0);
65                 
66                 if (adc_rst_old="01") then
67                         reset_re:='1';
68                 end if;
69                 
70                 case state is
71                         when reset=>
72                                 reset_re:='0';                  --clear reset flag
73                                 adc_scs<='1';                   --active-low SS
74                                 adc_sclk<='0';                  --lower clock
75                                 first_pass<='1';                --mark data as unprepared
76                                 channel:=ch0;                   --prepare channel0
77                                 adc_data<=(others=>'0');        --null working data
78                                 cumul_data<=(others=>'0');      --null working data
79                                 prepared_data<=(others=>'0');   --null the output
80                                 adc_channels<=(others=>'0');    --null the output
81                                 measur_count<=(others=>'0');    --null the count
82                                 m_count_sig<=(others=>'0');     --null the count
83                                 adc_address<="001";             --set its address
84                                 reset_count:="0000";
85                                 state<=rst_wait;
86                         when rst_wait=>
87                                 if (reset_count/="1111") then
88                                         reset_count:=std_logic_vector(unsigned(reset_count)+1);
89                                         --give the adc some time to prepare before transfer
90                                         adc_scs<=not reset_count(3); 
91                                 else
92                                         state<=f1;
93                                 end if;
94                         when f1=> --1st 'fallin edge' - its not falling edge in any case-if rst clock is low before  
95                                 adc_sclk<='0'; --clk
96                                 adc_mosi<='1'; --start bit
97                                 state<=r1; --next state
98                         when r1=>       --1st rising edge (adc gets the start bit, we get date..)
99                                 adc_sclk<='1'; 
100                                 adc_data(5)<=adc_miso;
101                                 state<=f2;
102                         when f2=> --2nd falling edge
103                                 adc_sclk<='0';
104                                 adc_mosi<=adc_address(2); --A2 address
105                                 state<=r2;
106                         when r2=> --2nd rising edge (adc gets A2 address)
107                                 adc_sclk<='1';
108                                 adc_data(4)<=adc_miso;
109                                 state<=f3;
110                         when f3=> --3rd falling edge 
111                                 adc_sclk<='0';
112                                 adc_mosi<=adc_address(1); --A1 address
113                                 state<=r3;
114                         when r3=> --rising edge
115                                 adc_sclk<='1';
116                                 adc_data(3)<=adc_miso;
117                                 state<=f4;      
118                         when f4=> --4th falling edge
119                                 adc_sclk<='0';
120                                 adc_mosi<=adc_address(0); --A0 address 
121                                 state<=r4;
122                         when r4=> --rising edge
123                                 adc_sclk<='1';
124                                 adc_data(2)<=adc_miso;
125                                 state<=f5;      
126                         when f5=> --5th falling edge
127                                 adc_sclk<='0';
128                                 adc_mosi<='0'; --MODE (LOW -12bit)
129                                 state<=r5;
130                         when r5=> --rising edge
131                                 adc_sclk<='1';
132                                 adc_data(1)<=adc_miso;
133                                 state<=f6;      
134                         when f6=> --6th falling edge
135                                 adc_sclk<='0';
136                                 adc_mosi<='1'; --SGL/DIF (HIGH - SGL=Single Ended)
137                                 state<=r6;
138                         when r6=> --6th rising edge (we read last bit of conversion, adc gets SGL/DIF)
139                                 adc_sclk<='1';
140                                 adc_data(0)<=adc_miso;
141                                 state<=f7;              
142                         when f7=> -- 7th falling edge
143                                 adc_sclk<='0';
144                                 adc_mosi<='0'; --PD1 (power down - PD1=PD0=0 -> power down between conversion)
145                                 state<=r7;
146                         when r7=> --7th rising edge, data ready
147                                 adc_sclk<='1';
148                                 if (first_pass='0') then
149                                         --add the current current to sum and shift the register
150                                         cumul_data(71 downto 0)<=
151                                                 std_logic_vector(unsigned(cumul_data(47 downto 24))
152                                                         +unsigned(adc_data(11 downto 0)))
153                                                 & cumul_data(23 downto 0)
154                                                 & cumul_data(71 downto 48);
155                                 end if;
156                                 state<=f8;
157                         when f8=> --8th falling edge
158                                 adc_sclk<='0';
159                                 adc_mosi<='0'; --PD0
160                                 if (first_pass='0') then
161                                         case channel is
162                                                 when ch0=>
163                                                         adc_address<="101";     --ch1 address
164                                                         channel:=ch1;           --next channel code
165                                                 when ch1=>
166                                                         adc_address<="010";     --ch2 address
167                                                         channel:=ch2;           --next channel code
168                                                 when ch2=>
169                                                         --data order schould be: ch2 downto ch0 downto ch1
170                                                         prepared_data(71 downto 0)<=cumul_data(71 downto 0);
171                                                         m_count_sig<=std_logic_vector(unsigned(m_count_sig)+1);
172                                                         adc_address<="001";     --ch0 address
173                                                         channel:=ch0;           --next channel code
174                                         end case;
175                                 end if;
176                                 state<=r8;
177                         when r8=> --8th rising edge (adc gets PD0), we propagate our results to output
178                                 adc_sclk<='1';
179                                 adc_channels <= prepared_data;          --data
180                                 measur_count <= m_count_sig;            --count of measurments
181                                 first_pass<='0';                        --data in next cycle are usable
182                                 state<=f9;
183                         when f9=> --9th falling edge busy state between conversion (we write nothing)
184                                 adc_sclk<='0';
185                                 state<=r9;
186                         when r9=>  --9th rising edge (we nor ads get nothing)
187                                 adc_sclk<='1';
188                                 state<=f10;
189                         when f10=> --10th falling edge
190                                 adc_sclk<='0';
191                                 state<=r10;
192                         when r10=>  --10th rising edge (we read 1. bit of new conversion)
193                                 adc_sclk<='1';
194                                 adc_data(11)<=adc_miso;
195                                 state<=f11;
196                         when f11=>
197                                 adc_sclk<='0';
198                                 state<=r11;
199                         when r11=>  --11th rising edge
200                                 adc_sclk<='1';
201                                 adc_data(10)<=adc_miso;
202                                 state<=f12;
203                         when f12=>
204                                 adc_sclk<='0';
205                                 state<=r12;
206                         when r12=>  --12th rising edge
207                                 adc_sclk<='1';
208                                 adc_data(9)<=adc_miso;
209                                 state<=f13;
210                         when f13=>
211                                 adc_sclk<='0';
212                                 state<=r13;
213                         when r13=>  --13th rising edge
214                                 adc_sclk<='1';
215                                 adc_data(8)<=adc_miso;
216                                 state<=f14;
217                         when f14=>
218                                 adc_sclk<='0';
219                                 state<=r14;
220                         when r14=>  --14th rising edge
221                                 adc_sclk<='1';
222                                 adc_data(7)<=adc_miso;
223                                 state<=f15;
224                         when f15=>
225                                 adc_sclk<='0';
226                                 state<=r15;
227                         when r15=> --15th rising edge
228                                 adc_sclk<='1';
229                                 adc_data(6)<=adc_miso;
230                                 if (reset_re='1') then --we check rising edge of reset 
231                                         state<=reset;
232                                 else
233                                         state<=f1;
234                                 end if;
235                 end case;
236         end process;
237                         
238         
239                 
240 end behavioral;
241