]> rtime.felk.cvut.cz Git - fpga/rpi-motor-control.git/blobdiff - pmsm-control/rpi_mc_simple_dc.vhdl
Tested version of ADC.
[fpga/rpi-motor-control.git] / pmsm-control / rpi_mc_simple_dc.vhdl
index d1810c68b1357a8230ee585bda4a6857ab4b698a..7b09532e80b33b12352618327c7ca928b9d7da82 100644 (file)
@@ -16,72 +16,72 @@ use ieee.numeric_std.all;
 use work.util.all;
 
 entity rpi_mc_simple_dc is
 use work.util.all;
 
 entity rpi_mc_simple_dc is
-       port (
-               gpio2: in std_logic; -- SDA
-               gpio3: in std_logic; -- SCL
-               gpio4: out std_logic; -- CLK
-               gpio14: in std_logic; -- Tx
-               gpio15: in std_logic; -- Rx
-               gpio17: out std_logic; -- RTS
-               gpio18: out std_logic; -- PWM0/PCMCLK
-               gpio27: out std_logic; -- SD1DAT3
-               gpio22: out std_logic; -- SD1CLK
-               gpio23: out std_logic; -- SD1CMD
-               gpio24: out std_logic; -- SD1DAT0
-               gpio10: in std_logic; -- SPI0MOSI
-               gpio9: out std_logic; -- SPI0MISO
-               gpio25: out std_logic; -- SD1DAT1
-               gpio11: in std_logic; -- SPI0SCLK
-               gpio8: in std_logic; -- SPI0CE0
-               gpio7: in std_logic; -- SPI0CE1
-               gpio5: in std_logic; -- GPCLK1
-               gpio6: in std_logic; -- GPCLK2
-               gpio12: in std_logic; -- PWM0
-               gpio13: in std_logic; -- PWM1
-               gpio19: in std_logic; -- PWM1/SPI1MISO/PCMFS
-               gpio16: in std_logic; -- SPI1CE2
-               gpio26: in std_logic; -- SD1DAT2
-               gpio20: in std_logic; -- SPI1MOSI/PCMDIN/GPCLK0
-               gpio21: in std_logic; -- SPI1SCLK/PCMDOUT/GPCLK1
-               --
-               -- PWM
-               -- Each PWM signal has cooresponding shutdown
-               pwm: out std_logic_vector (1 to 3);
-               shdn: out std_logic_vector (1 to 3);
-               -- Fault/power stage status
-               stat: in std_logic_vector (1 to 3);
-               -- HAL inputs
-               hal_in: in std_logic_vector (1 to 3);
-               -- IRC inputs
-               irc_a: in std_logic;
-               irc_b: in std_logic;
-               irc_i: in std_logic;
-               -- Power status
-               power_stat: in std_logic;
-               -- ADC for current
-               adc_miso: in std_logic;
-               adc_mosi: in std_logic;
-               adc_sclk: in std_logic;
-               adc_scs: in std_logic;
-               -- Extarnal SPI
-               ext_miso: in std_logic; --master in slave out
-               ext_mosi: in std_logic; --master out slave in
-               ext_sclk: in std_logic;
-               ext_scs0: in std_logic;
-               ext_scs1: in std_logic;
-               ext_scs2: in std_logic;
-               -- RS-485 Transceiver
-               rs485_rxd: in std_logic;
-               rs485_txd: out std_logic;
-               rs485_dir: out std_logic;
-               -- CAN Transceiver
-               can_rx: in std_logic;
-               can_tx: in std_logic;
-               -- DIP switch
-               dip_sw: in std_logic_vector (1 to 3); --na desce je prohozene cislovanni
-               -- Unused terminal to keep design tools silent
-               dummy_unused : out std_logic
-       );
+port (
+       gpio2: in std_logic; -- SDA
+       gpio3: in std_logic; -- SCL
+       gpio4: in std_logic; -- CLK
+       gpio14: in std_logic; -- Tx
+       gpio15: in std_logic; -- Rx
+       gpio17: in std_logic; -- RTS
+       gpio18: in std_logic; -- PWM0/PCMCLK
+       gpio27: in std_logic; -- SD1DAT3
+       gpio22: in std_logic; -- SD1CLK
+       gpio23: in std_logic; -- SD1CMD
+       gpio24: in std_logic; -- SD1DAT0
+       gpio10: in std_logic; -- SPI0MOSI
+       gpio9: out std_logic; -- SPI0MISO
+       gpio25: in std_logic; -- SD1DAT1
+       gpio11: in std_logic; -- SPI0SCLK
+       gpio8: in std_logic; -- SPI0CE0
+       gpio7: in std_logic; -- SPI0CE1
+       gpio5: in std_logic; -- GPCLK1
+       gpio6: in std_logic; -- GPCLK2
+       gpio12: in std_logic; -- PWM0
+       gpio13: in std_logic; -- PWM1
+       gpio19: in std_logic; -- PWM1/SPI1MISO/PCMFS
+       gpio16: in std_logic; -- SPI1CE2
+       gpio26: in std_logic; -- SD1DAT2
+       gpio20: in std_logic; -- SPI1MOSI/PCMDIN/GPCLK0
+       gpio21: in std_logic; -- SPI1SCLK/PCMDOUT/GPCLK1
+       --
+       -- PWM
+       -- Each PWM signal has cooresponding shutdown
+       pwm: out std_logic_vector (1 to 3);
+       shdn: out std_logic_vector (1 to 3);
+       -- Fault/power stage status
+       stat: in std_logic_vector (1 to 3);
+       -- HAL inputs
+       hal_in: in std_logic_vector (1 to 3);
+       -- IRC inputs
+       irc_a: in std_logic;
+       irc_b: in std_logic;
+       irc_i: in std_logic;
+       -- Power status
+       power_stat: in std_logic;
+       -- ADC for current
+       adc_miso: in std_logic;
+       adc_mosi: out std_logic;
+       adc_sclk: out std_logic;
+       adc_scs: out std_logic;
+       -- Extarnal SPI
+       ext_miso: in std_logic; --master in slave out
+       ext_mosi: in std_logic; --master out slave in
+       ext_sclk: in std_logic;
+       ext_scs0: in std_logic;
+       ext_scs1: in std_logic;
+       ext_scs2: in std_logic;
+       -- RS-485 Transceiver
+       rs485_rxd: in std_logic;
+       rs485_txd: out std_logic;
+       rs485_dir: out std_logic;
+       -- CAN Transceiver
+       can_rx: in std_logic;
+       can_tx: in std_logic;
+       -- DIP switch
+       dip_sw: in std_logic_vector (1 to 3); --na desce je prohozene cislovanni
+       -- Unused terminal to keep design tools silent
+       dummy_unused : out std_logic
+);
 end rpi_mc_simple_dc;
 
 
 end rpi_mc_simple_dc;
 
 
@@ -101,11 +101,38 @@ architecture behavioral of rpi_mc_simple_dc is
        component CLKINT
                port (A: in std_logic; Y: out std_logic);
        end component;
        component CLKINT
                port (A: in std_logic; Y: out std_logic);
        end component;
+       
+       component qcounter
+       port (
+               clock: in std_logic;
+               reset: in std_logic;
+               a0, b0: in std_logic;
+               qcount: out std_logic_vector (31 downto 0);
+               a_rise, a_fall, b_rise, b_fall, ab_event: out std_logic;
+               ab_error: out std_logic
+       );
+       end component;
 
 
-       signal pwm_in, pwm_dir_in: std_logic;
-       signal spi_clk: std_logic;
-       signal dat_reg : STD_LOGIC_VECTOR (7 downto 0):=(others=>'0'); --registr pro SPI
-
+       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);
+       signal state : state_type;
+       
+       type channel_type is (ch0, ch1, ch2);
+       
+       signal adc_data: std_logic_vector(11 downto 0); --ADC income data
+       signal adc_reset : std_logic;
+       signal adc_rst_old : std_logic_vector(1 downto 0);
+       signal adc_address: std_logic_vector(8 downto 0);
+       signal adc_channels: std_logic_vector(35 downto 0);
+       
+       signal spiclk_old: std_logic_vector(1 downto 0); --pro detekci hrany SPI hodin
+       --signal pwm_in, pwm_dir_in: std_logic;
+       signal gpio_clk: std_logic;
+       signal dat_reg : STD_LOGIC_VECTOR (95 downto 0); --shift register for spi
+       signal position: std_logic_vector(31 downto 0); --pozice z qcounteru
+       signal ce0_old: std_logic_vector(1 downto 0);
+       
+       
+       
        --  attribute syn_noprune of gpio2 : signal is true;
        --  attribute syn_preserve of gpio2 : signal is true;
        --  attribute syn_keep of gpio2 : signal is true;
        --  attribute syn_noprune of gpio2 : signal is true;
        --  attribute syn_preserve of gpio2 : signal is true;
        --  attribute syn_keep of gpio2 : signal is true;
@@ -113,11 +140,31 @@ architecture behavioral of rpi_mc_simple_dc is
 
 begin
        -- PLL as a reset generator
 
 begin
        -- PLL as a reset generator
-       copyclk: CLKINT
+       
+       --zesileni signalu GPIO CLK
+       copyclk2: CLKINT
        port map (
        port map (
-               a => gpio11,
-               y => spi_clk
+               a => gpio4,
+               y => gpio_clk
        );
        );
+       
+       
+       qcount: qcounter
+       port map (
+               clock => gpio_clk,
+               reset => '0',
+               a0 => irc_a,
+               b0 => irc_b,
+               qcount => position,
+               a_rise => open,
+               a_fall => open,
+               b_rise => open,
+               b_fall => open,
+               ab_event => open,
+               ab_error => open
+       );
+       
+       
        --   pll: pll50to200
        --     port map (
        --       powerdown => '1',
        --   pll: pll50to200
        --     port map (
        --       powerdown => '1',
@@ -129,7 +176,7 @@ begin
                                            -- upon power-on
        --   clock <= clkm;
 
                                            -- upon power-on
        --   clock <= clkm;
 
-       dummy_unused <= gpio2 and gpio3  and
+       dummy_unused <= gpio2 and gpio3  and gpio4 and
                gpio5 and gpio6 and
                gpio12 and gpio13 and gpio14 and
                gpio15 and gpio16 and gpio19 and
                gpio5 and gpio6 and
                gpio12 and gpio13 and gpio14 and
                gpio15 and gpio16 and gpio19 and
@@ -137,20 +184,18 @@ begin
                stat(1) and stat(2) and stat(3) and
                hal_in(1) and hal_in(2) and hal_in(3) and
                irc_i and power_stat and 
                stat(1) and stat(2) and stat(3) and
                hal_in(1) and hal_in(2) and hal_in(3) and
                irc_i and power_stat and 
-               adc_miso and adc_mosi and adc_sclk and adc_scs and
+               adc_miso and 
                rs485_rxd and
                can_rx and can_tx and
                dip_sw(1) and dip_sw(2) and dip_sw(3) and
                irc_a and irc_b and
                rs485_rxd and
                can_rx and can_tx and
                dip_sw(1) and dip_sw(2) and dip_sw(3) and
                irc_a and irc_b and
-               -- gpio17 and gpio18 and gpio27 and gpio22 and
+               gpio17 and gpio18 and gpio27 and gpio22 and gpio23 and gpio24 and gpio25 and
                gpio8  and gpio11 and gpio7 and gpio10 and
                ext_scs1 and ext_scs2 and ext_miso and ext_mosi and ext_sclk and ext_scs0;
                        
        rs485_txd <= '1';
        rs485_dir <= '0';
 
                gpio8  and gpio11 and gpio7 and gpio10 and
                ext_scs1 and ext_scs2 and ext_miso and ext_mosi and ext_sclk and ext_scs0;
                        
        rs485_txd <= '1';
        rs485_dir <= '0';
 
-       --gpio24 <= dip_sw(1); --na desce je prohozene cislovani
 
        shdn(1) <= '0';
        shdn(2) <= '0';
 
        shdn(1) <= '0';
        shdn(2) <= '0';
@@ -160,31 +205,221 @@ begin
        pwm(2) <= '0';
        pwm(3) <= '0';
 
        pwm(2) <= '0';
        pwm(3) <= '0';
 
-
-  
-       process (spi_clk) --nufunguje preo piny 11,17,27 funguje pro 4,18,22,ext_sclk,10
+       
+       process
        begin
        begin
-               --if (gpio11'event and gpio11 = '1') then  -- rising edge of SCK
-               if (rising_edge(spi_clk)) then 
+               --position is obtained on rising edge -> we should write it on next cycle
+               wait until (gpio_clk'event and gpio_clk='1');
+               
+               --SCLK edge detection
+               spiclk_old(0)<=gpio11;
+               spiclk_old(1)<=spiclk_old(0);
+               
+               --SS edge detection
+               ce0_old(0)<=gpio7;
+               ce0_old(1)<=ce0_old(0);
+               
+               if (spiclk_old="01") then --rising edge, faze cteni
                        if (gpio7 = '0') then             -- SPI CS must be selected
                                -- shift serial data into dat_reg on each rising edge
                                -- of SCK, MSB first
                        if (gpio7 = '0') then             -- SPI CS must be selected
                                -- shift serial data into dat_reg on each rising edge
                                -- of SCK, MSB first
-                               dat_reg(7 downto 0) <= dat_reg(6 downto 0) & gpio10;
-                
-                               gpio4 <= dat_reg(7);
-                               gpio17 <= dat_reg(6);
-                               gpio18 <= dat_reg(5);
-                               gpio27 <= dat_reg(4);
-                               gpio22 <= dat_reg(3);
-                               gpio23 <= dat_reg(2);
-                               gpio24 <= dat_reg(1);
-                               gpio25 <= dat_reg(0);
-       
-                       end if;
-               elsif (falling_edge(spi_clk)) then
+                               dat_reg(95 downto 0) <= dat_reg(94 downto 0) & gpio10;
+                               end if;
+               elsif (spiclk_old="10" ) then --falling edge, faze zapisu
                        if (gpio7 = '0') then
                        if (gpio7 = '0') then
-                               gpio9 <= dat_reg(7); --zapisujeme nejdriv MSB
+                               gpio9 <= dat_reg(95); --zapisujeme nejdriv MSB
                        end if;
                end if;
                        end if;
                end if;
+               
+                       
+               --sestupna hrana SS, pripravime data pro prenos
+               if (ce0_old = "10" ) then 
+                       dat_reg(95 downto 64) <= position(31 downto 0); --pozice
+                       dat_reg(63 downto 61) <= hal_in(1 to 3); --halovy sondy
+                       dat_reg(60 downto 36) <= (others => '1'); --let the rest fill with ones
+                       dat_reg(35 downto 0) <= adc_channels(35 downto 0); --current mesurments
+                       adc_reset<='0'; --remove reset flag, and wait on its rising edge
+               elsif (ce0_old = "01") then --rising edge of SS, we should read the data
+                       adc_reset<=dat_reg(95);
+               end if;
+       end process;
+       
+       process 
+               variable data_ready : std_logic;
+               variable channel: channel_type;
+               variable reset_re: std_logic:='0';
+               variable reset_count: integer:=0;
+       begin
+               wait until (gpio_clk'event and gpio_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
+                       reset_re:='1';
+               end if;
+               
+               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;
+                               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;
+                               else
+                                       state<=f1;
+                               end if;
+                       when f1=> --1st 'fallin edge' - its not falling edge in any case-if rst clock is low before  
+                               adc_sclk<='0'; --clk
+                               adc_mosi<='1'; --start bit
+                               state<=r1; --next state
+                       when r1=>       --1st rising edge (adc gets the start bit, we get date..)
+                               adc_sclk<='1'; 
+                               adc_data(5)<=adc_miso;
+                               state<=f2;
+                       when f2=> --2nd falling edge
+                               adc_sclk<='0';
+                               adc_mosi<=adc_address(8); --A2 address
+                               state<=r2;
+                       when r2=> --2nd rising edge (adc gets A2 address)
+                               adc_sclk<='1';
+                               adc_data(4)<=adc_miso;
+                               state<=f3;
+                       when f3=> --3rd falling edge 
+                               adc_sclk<='0';
+                               adc_mosi<=adc_address(7); --A1 address
+                               state<=r3;
+                       when r3=> --rising edge
+                               adc_sclk<='1';
+                               adc_data(3)<=adc_miso;
+                               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); 
+                               state<=r4;
+                       when r4=> --rising edge
+                               adc_sclk<='1';
+                               adc_data(2)<=adc_miso;
+                               state<=f5;      
+                       when f5=> --5th falling edge
+                               adc_sclk<='0';
+                               adc_mosi<='0'; --MODE (LOW -12bit)
+                               state<=r5;
+                       when r5=> --rising edge
+                               adc_sclk<='1';
+                               adc_data(1)<=adc_miso;
+                               state<=f6;      
+                       when f6=> --6th falling edge
+                               adc_sclk<='0';
+                               adc_mosi<='1'; --SGL/DIF (HIGH - SGL=Single Ended)
+                               state<=r6;
+                       when r6=> --6th rising edge (we read last bit of conversion, adc gets SGL/DIF)
+                               adc_sclk<='1';
+                               adc_data(0)<=adc_miso;
+                               state<=f7;              
+                       when f7=> -- 7th falling edge
+                               adc_sclk<='0';
+                               adc_mosi<='0'; --PD1 (power down - PD1=PD0=0 -> power down between conversion)
+                               state<=r7;
+                       when r7=> --7th rising edge, data ready
+                               adc_sclk<='1';
+                               if (data_ready='1') 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;
+                                               when ch1=>
+                                                       adc_channels(23 downto 12)<=adc_data(11 downto 0);
+                                                       --adc_channels(23 downto 12)<=(others=>'1');
+                                                       channel:=ch2;
+                                               when ch2=>
+                                                       adc_channels(11 downto 0)<=adc_data(11 downto 0);
+                                                       --adc_channels(11 downto 0)<=(others=>'0');
+                                                       channel:=ch0;
+                                       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)
+                               adc_sclk<='1';
+                               state<=f9;
+                       when f9=> --9th falling edge busy state between conversion (we write nothing)
+                               adc_sclk<='0';
+                               state<=r9;
+                       when r9=>  --9th rising edge (we nor ads get nothing)
+                               adc_sclk<='1';
+                               state<=f10;
+                       when f10=> --10th falling edge
+                               adc_sclk<='0';
+                               state<=r10;
+                       when r10=>  --10th rising edge (we read 1. bit of conversion)
+                               adc_sclk<='1';
+                               adc_data(11)<=adc_miso;
+                               state<=f11;
+                       when f11=>
+                               adc_sclk<='0';
+                               state<=r11;
+                       when r11=>  --11th rising edge
+                               adc_sclk<='1';
+                               adc_data(10)<=adc_miso;
+                               state<=f12;
+                       when f12=>
+                               adc_sclk<='0';
+                               state<=r12;
+                       when r12=>  --12th rising edge
+                               adc_sclk<='1';
+                               adc_data(9)<=adc_miso;
+                               state<=f13;
+                       when f13=>
+                               adc_sclk<='0';
+                               state<=r13;
+                       when r13=>  --13th rising edge
+                               adc_sclk<='1';
+                               adc_data(8)<=adc_miso;
+                               state<=f14;
+                       when f14=>
+                               adc_sclk<='0';
+                               state<=r14;
+                       when r14=>  --14th rising edge
+                               adc_sclk<='1';
+                               adc_data(7)<=adc_miso;
+                               state<=f15;
+                       when f15=>
+                               adc_sclk<='0';
+                               --for rising edge detection in next cycle
+                               state<=r15;
+                       when r15=> --15th rising edge
+                               adc_sclk<='1';
+                               adc_data(6)<=adc_miso;
+                               if (reset_re='1') then --we check rising edge of reset 
+                                       state<=reset;
+                               else
+                                       state<=f1;
+                               end if;
+               end case;
        end process;
        end process;
+                       
+       
+               
 end behavioral;
 end behavioral;
+