EmbDev.net

ADC_Module_SPI.vhd


Du wurdest von Mikrocontroller.net auf diese Seite weitergeleitet. Zurück zu Mikrocontroller.net
1
LIBRARY IEEE;
2
USE IEEE.STD_LOGIC_1164.ALL;
3
USE IEEE.NUMERIC_STD.ALL;
4
5
ENTITY ADC_Module_SPI IS
6
  PORT(
7
    CLK       :IN STD_LOGIC; -- external clock comes from FPGA 
8
    GO        : IN STD_LOGIC; -- to start the conversion by external key for example
9
    RESET     : IN STD_LOGIC; -- reset the system
10
    CS_n : OUT STD_LOGIC;  -- select line 
11
    SCLK : OUT STD_LOGIC; -- SPI clock for ADC conversion and transfer 
12
    BUSY      : IN STD_LOGIC; -- indicates if the conversion is complete or not
13
    EOC       : IN STD_LOGIC; -- indicate the end of conversion 
14
    iDOUT     : IN STD_LOGIC; -- SDOUT, data comes from the ADC 
15
    CNVST     : OUT STD_LOGIC; -- this line initiates the conversion
16
    AD_RESET  : OUT STD_LOGIC;  -- reset the ADC module
17
    DATA_AOUT : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); -- data comes from the channel A   
18
    DATA_BOUT : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)-- data comes from the channel B
19
    
20
    
21
  );
22
END ADC_Module_SPI;
23
24
25
ARCHITECTURE ADC_ARCH OF ADC_Module_SPI IS
26
TYPE ADC_STATE IS (IDLE,START,CONV_A,CONV_B,CATCH);     --Define the FSM(Finite State Machine)'s state
27
SIGNAL STATE_START,STATE_NEXT   : ADC_STATE;     
28
SIGNAL BUSY_R                : STD_LOGIC := 'Z';  --BUSY_R => to judge the rising edge of BUSY
29
SIGNAL EOC_R                 : STD_LOGIC := 'Z';  --EOC_R => to judge the rising edge of EOC
30
SIGNAL BUSY_D,EOC_D          : STD_LOGIC := 'Z';  --BUSY_D,EOC_D => to save the signal BUSY and EOC
31
SIGNAL DATA_ATEMP,DATA_BTEMP : STD_LOGIC_VECTOR(15 DOWNTO 0);  -- to save the AD reading data from two channel
32
signal go_en: STD_LOGIC;
33
signal iCLK: STD_LOGIC;
34
35
BEGIN
36
CLKPLL: SPICLK port map (CLK, iCLK);
37
38
  with go_en select
39
    SCLK <= iCLK when '1',  -- generate the ADC clock 
40
        '1'  when '0',
41
        '1'  when others;  
42
Start_ADC_proc: process(GO)
43
  begin  
44
    if(GO = '1') then 
45
       go_en <= '1'; -- go_en is low when the push button is pressed or reset is high 
46
    else 
47
       go_en <= '0'; -- if the push-button is not pressed, the level is high 
48
    end if;
49
end process Start_ADC_proc;
50
51
  PROCESS(iCLK,RESET) 
52
  
53
  VARIABLE CONV_AC  : INTEGER := 0;
54
  VARIABLE CONV_AFC : INTEGER := 16; -- cont the number of the cycles during the Channel A conversion
55
  VARIABLE CONV_BC  : INTEGER := 0;
56
  VARIABLE CONV_BFC : INTEGER := 16; -- cont the number of the cycles during the Channel B conversion
57
  
58
  BEGIN
59
    IF (RESET='1') THEN        -- when reset is selected 
60
      AD_RESET <= '1';      -- the ADC is reset 
61
      CONV_AC := 0;        
62
      CONV_BC  := 0;       
63
      STATE_START <= IDLE;    -- The state machine enter to the idle mode 
64
      DATA_ATEMP <= (OTHERS => '0');
65
      DATA_BTEMP <= (OTHERS => '0');
66
    ELSIF (iCLK'EVENT AND iCLK ='1') THEN      --when the iCLK is rising edge and do the following thing
67
      STATE_START <= STATE_NEXT;             
68
      BUSY_D <= BUSY;  -- save the actual state of the busy signal 
69
      EOC_D  <= EOC;   -- save the actual state of EOC signal 
70
      BUSY_R <= (NOT BUSY_D) AND BUSY;    -- this line is mainly for the rising edge detector for BUSY,
71
      EOC_R  <= (NOT EOC_D) AND EOC;      -- this line is mainly for the rising edge detector for EOC , 
72
      CASE STATE_START IS                   --the finite state machine with five states
73
      
74
        WHEN IDLE =>                   -- in the IDLE state  
75
          IF go_en='1' THEN          --when you start, turn off the AD_reset,and make the CNVST to high
76
            AD_RESET <= '0';       -- the reset ADC signal is disabled by putting it high 
77
            CNVST <= '1';          -- the conversion can start
78
            STATE_NEXT <= START;   -- the next state take the value start 
79
          ELSE
80
            STATE_NEXT <= IDLE;
81
          END IF;
82
          
83
        WHEN START =>                   -- in the Start state  when is conversion can be started 
84
          CNVST <='0';  
85
          IF BUSY_R='1' THEN          --when BUSY rising, change the state, rising edge is detected 
86
            STATE_NEXT <= CONV_A;    -- the CONV state is activated in the next rising edge of SCLK  
87
          END IF;
88
          
89
        WHEN CONV_A =>
90
          IF BUSY ='1' THEN    -- when the busy signal is always high, that means the conversion is occurring 
91
                                   
92
            IF CONV_AC = CONV_AFC THEN     
93
              STATE_NEXT <= CONV_B;       -- The conversion of channel A is complete, the next step is to convert the channel A    
94
            ELSE     
95
              DATA_ATEMP <= DATA_ATEMP(14 downto 0) & iDOUT;
96
              CONV_AC := CONV_AC +1; 
97
                            STATE_NEXT <= CONV_A;   
98
            END IF;
99
          END IF;
100
          
101
        WHEN CONV_B =>
102
          IF BUSY ='1' THEN    -- when the busy signal is always high, that means the conversion is occurring 
103
                                   
104
            IF CONV_BC = CONV_BFC THEN        
105
              STATE_NEXT <= CATCH;       -- The conversion of channel B is complete 
106
            ELSE     
107
              IF EOC_R='1' THEN    -- if busy=1 and a rising edge is detected on EOC_R, that means the channel B is ready to be converted and sent     
108
                  DATA_BTEMP <= DATA_BTEMP(14 downto 0) & iDOUT;
109
                CONV_BC := CONV_BC +1;
110
                STATE_NEXT <= CONV_B;             
111
              END IF;
112
            END IF;
113
          END IF;
114
        WHEN CATCH =>                         --reading the two channel data 
115
                
116
          DATA_AOUT <= DATA_ATEMP;
117
          DATA_BOUT <= DATA_ATEMP;
118
            
119
            STATE_NEXT <= IDLE;
120
      END CASE;
121
    END IF;
122
  END PROCESS;
123
  
124
END ADC_ARCH;