X-Git-Url: https://rtime.felk.cvut.cz/gitweb/fpga/rpi-motor-control.git/blobdiff_plain/6e929536b290d817bd2473bcc158d1dab5ba1f55..41ad6fb58e07390cc1807e43d0de04d670c5719e:/pmsm-control/adc_reader.vhdl diff --git a/pmsm-control/adc_reader.vhdl b/pmsm-control/adc_reader.vhdl index 3a53446..219841c 100644 --- a/pmsm-control/adc_reader.vhdl +++ b/pmsm-control/adc_reader.vhdl @@ -1,4 +1,18 @@ - +-- +-- * Raspberry Pi BLDC/PMSM motor control design for RPi-MI-1 board * +-- SPI connected multichannel current ADC read and averaging +-- +-- (c) 2015 Martin Prudek +-- Czech Technical University in Prague +-- +-- Project supervision and original project idea +-- idea by Pavel Pisa +-- +-- Related RPi-MI-1 hardware is designed by Petr Porazil, +-- PiKRON Ltd +-- +-- license: GNU LGPL and GPLv3+ +-- library ieee; use ieee.std_logic_1164.all; @@ -7,13 +21,17 @@ use work.util.all; entity adc_reader is port ( - clk: in std_logic; --input clk - adc_reset: in std_logic; + clk: in std_logic; --synchronous master clk + divided_clk : in std_logic; --divided clk - value suitable to sourcing voltage + adc_reset: in std_logic; --synchronous reset on rising edge + adc_miso: in std_logic; --spi master in slave out - adc_channels: out std_logic_vector (35 downto 0); --consistent data of 3 channels adc_sclk: out std_logic; --spi clk adc_scs: out std_logic; --spi slave select - adc_mosi: out std_logic --spi master out slave in + adc_mosi: out std_logic; --spi master out slave in + + adc_channels: out std_logic_vector (71 downto 0); --consistent data of 3 channels + measur_count: out std_logic_vector(8 downto 0) --number of accumulated measurments ); end adc_reader; @@ -28,47 +46,54 @@ architecture behavioral of adc_reader is type channel_type is (ch0, ch1, ch2); signal adc_data: std_logic_vector(11 downto 0); - signal adc_rst_old : std_logic_vector(1 downto 0); - signal adc_address: std_logic_vector(8 downto 0); - + signal adc_rst_prev : std_logic; + signal adc_address: std_logic_vector(2 downto 0); + signal cumul_data: std_logic_vector(71 downto 0); --unconsistent data, containing different amounts of measurments + signal prepared_data: std_logic_vector(71 downto 0); --consistent data, waiting for clk sync to propagate to output + signal m_count_sig: std_logic_vector(8 downto 0); --measurments count waiting for clk to propagate to output + signal first_pass: std_logic; + signal div_clk_prev: std_logic; begin process - variable data_ready : std_logic; variable channel: channel_type; variable reset_re: std_logic:='0'; - variable reset_count: integer:=0; + variable reset_count: std_logic_vector (3 downto 0); begin wait until (clk'event and clk='1'); - --reset rising edge detection - adc_rst_old(0)<=adc_reset; - adc_rst_old(1)<=adc_rst_old(0); - - if (adc_rst_old="01") then + --rising edge detection of reset signal + adc_rst_prev<=adc_reset; + if (adc_rst_prev='0') and (adc_reset='1') then reset_re:='1'; end if; + --rising edge detection of divided clk signal + div_clk_prev<=divided_clk; + if (divided_clk='1') and (div_clk_prev='0') then + case state is when reset=> - reset_re:='0'; --clear reset flag - adc_scs<='1'; --active-low SS - adc_sclk<='0'; --lower clock - data_ready:='0'; - --addresse are CH(A2,A1,A0): CH0:(0,0,1),CH1:(1,0,1),CH2:(0,1,0) - adc_address<="001101010"; - channel:=ch0; - adc_channels(35 downto 0)<=(others=>'1'); --for debug only - remove this line! - adc_data(11 downto 0)<=(others=>'1'); - reset_count:=0; + reset_re:='0'; --clear reset flag + adc_scs<='1'; --active-low SS + adc_sclk<='0'; --lower clock + first_pass<='1'; --mark data as unprepared + channel:=ch0; --prepare channel0 + adc_data<=(others=>'0'); --null working data + cumul_data<=(others=>'0'); --null working data + prepared_data<=(others=>'0'); --null the output + adc_channels<=(others=>'0'); --null the output + measur_count<=(others=>'0'); --null the count + m_count_sig<=(others=>'0'); --null the count + adc_address<="001"; --set its address + reset_count:="0000"; state<=rst_wait; when rst_wait=> - if (reset_count<10) then - reset_count:=reset_count+1; - if (reset_count=7) then - adc_scs<='0'; --give the adc some time to prepare before trensfer - end if; + if (reset_count/="1111") then + reset_count:=std_logic_vector(unsigned(reset_count)+1); + --give the adc some time to prepare before transfer + adc_scs<=not reset_count(3); else state<=f1; end if; @@ -82,7 +107,7 @@ begin state<=f2; when f2=> --2nd falling edge adc_sclk<='0'; - adc_mosi<=adc_address(8); --A2 address + adc_mosi<=adc_address(2); --A2 address state<=r2; when r2=> --2nd rising edge (adc gets A2 address) adc_sclk<='1'; @@ -90,7 +115,7 @@ begin state<=f3; when f3=> --3rd falling edge adc_sclk<='0'; - adc_mosi<=adc_address(7); --A1 address + adc_mosi<=adc_address(1); --A1 address state<=r3; when r3=> --rising edge adc_sclk<='1'; @@ -98,9 +123,7 @@ begin state<=f4; when f4=> --4th falling edge adc_sclk<='0'; - adc_mosi<=adc_address(6); --A0 address - --shift the addresses - adc_address(8 downto 0)<=adc_address(5 downto 0) & adc_address(8 downto 6); + adc_mosi<=adc_address(0); --A0 address state<=r4; when r4=> --rising edge adc_sclk<='1'; @@ -128,30 +151,40 @@ begin state<=r7; when r7=> --7th rising edge, data ready adc_sclk<='1'; - if (data_ready='1') then + if (first_pass='0') then + --add the current current to sum and shift the register + cumul_data(71 downto 0)<= + std_logic_vector(unsigned(cumul_data(47 downto 24)) + +unsigned(adc_data(11 downto 0))) + & cumul_data(23 downto 0) + & cumul_data(71 downto 48); + end if; + state<=f8; + when f8=> --8th falling edge + adc_sclk<='0'; + adc_mosi<='0'; --PD0 + if (first_pass='0') then case channel is when ch0=> - adc_channels(35 downto 24)<=adc_data(11 downto 0); - --adc_channels(35 downto 24)<=(others=>'0'); - channel:=ch1; + adc_address<="101"; --ch1 address + channel:=ch1; --next channel code when ch1=> - adc_channels(23 downto 12)<=adc_data(11 downto 0); - --adc_channels(23 downto 12)<=(others=>'1'); - channel:=ch2; + adc_address<="010"; --ch2 address + channel:=ch2; --next channel code when ch2=> - adc_channels(11 downto 0)<=adc_data(11 downto 0); - --adc_channels(11 downto 0)<=(others=>'0'); - channel:=ch0; + --data order schould be: ch2 downto ch0 downto ch1 + prepared_data(71 downto 0)<=cumul_data(71 downto 0); + m_count_sig<=std_logic_vector(unsigned(m_count_sig)+1); + adc_address<="001"; --ch0 address + channel:=ch0; --next channel code end case; end if; - data_ready:='1'; - state<=f8; - when f8=> --8th falling edge - adc_sclk<='0'; - adc_mosi<='0'; --PD0 state<=r8; - when r8=> --8th rising edge (adc gets PD0) + when r8=> --8th rising edge (adc gets PD0), we propagate our results to output adc_sclk<='1'; + adc_channels <= prepared_data; --data + measur_count <= m_count_sig; --count of measurments + first_pass<='0'; --data in next cycle are usable state<=f9; when f9=> --9th falling edge busy state between conversion (we write nothing) adc_sclk<='0'; @@ -162,7 +195,7 @@ begin when f10=> --10th falling edge adc_sclk<='0'; state<=r10; - when r10=> --10th rising edge (we read 1. bit of conversion) + when r10=> --10th rising edge (we read 1. bit of new conversion) adc_sclk<='1'; adc_data(11)<=adc_miso; state<=f11; @@ -196,7 +229,6 @@ begin state<=f15; when f15=> adc_sclk<='0'; - --for rising edge detection in next cycle state<=r15; when r15=> --15th rising edge adc_sclk<='1'; @@ -207,6 +239,9 @@ begin state<=f1; end if; end case; + + end if; + end process;