+ Post New Thread
Results 1 to 2 of 2
  1. #1
    Newbie level 5
    Points: 89, Level: 1

    Join Date
    Jul 2017
    Posts
    9
    Helped
    0 / 0
    Points
    89
    Level
    1

    ADC and DAC interface for Spartan - 3A

    Hello!

    I am trying to interface the ADC and DAC of the spartan - 3A starter kit. I have written a code but when I implemented it, result is not correct. I have directed the first 8 MSBs on an LED to see the output. All the LEDs are always on, however the first LED (MSB) turns on and off when the switch Start_AD_CONV.

    I am not sure if my clock frequency is proper or the there is an issue with the ADC state.

    Could anyone help me figure this out?

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;
     
    entity ADC is
    port    (   enable              : in std_logic;     --switch enable for start preamp and adc
                clk_div             : in std_logic;
                start_AD_CONV       : in std_logic;     --switch enable for start adc
                SPI_MISO                : in std_logic;
                AD_CONV             : out std_logic;    --SPI-bus for ADC
                ADC1                    : inout std_logic_vector(13 downto 0); --VINA
                ADC2                    : out std_logic_vector(13 downto 0); --VINB
                AMP_CS              : out std_logic;    --SPI-bus for preamp
                SPI_MOSI                : out std_logic;
                SPI_SCK             : out std_logic;
                DAC_CS              : out std_logic;
                AMP_SHDN                : out std_logic;    --preamp
                DAC_CLR             : out std_logic     --dac
            );
    end ADC;
     
    architecture Behavioral of ADC is
     
        type state_type is (amp_state, adc_state, dac_state);
        type amp_state_type is (IDLE, START, HI, LO);
        type adc_state_type is (IDLE_AD, START_AD,LO_AD,HI_AD,FINE_AD);
        type dac_state_type is (da_idle, da_send, da_sck1, da_loop, da_end);
        signal state: state_type := amp_state;
        signal amp_state_reg: amp_state_type := IDLE;
        signal adc_state_reg: adc_state_type := IDLE_AD;
        signal dac_state_reg: dac_state_type := da_idle;
        signal sck_reg: std_logic:='0';
        signal da_data_reg: std_logic_vector (31 downto 0) := "00000000001100000000000000000000"; -- signal for the DAC
        signal da_bit_reg : natural range 0 to 32;
        signal ADC_COPY: std_logic_vector (13 downto 0) := (others => '0');         -- a copy of the ADC-value to use for the DAC
     
    begin
     
    --START PROCESS PREAMP - ADC - DAC
    process(clk_div)
        variable count: integer range 0 to 16;  -- 14 bits for 1 ADC channel+2 for zero
        variable counter : integer range 0 to 34; -- 34 SPI_SCK clockchanges for an entire ADC-loop
        variable gaincount: integer range 0 to 7;   -- 8 bits preampsignal
        constant gain_temp: std_logic_vector (7 downto 0):= "00010001"; -- biggest range of preamp
    begin
        if clk_div'event and clk_div ='1' then
            case state is
            --START AMP CYCLE
                when amp_state =>
                    DAC_CS <= '1';      --non active SPI-bus for DAC
                    case amp_state_reg is
                        when IDLE =>
                            gaincount:=7;
                            if enable = '1' then
                                amp_state_reg <= START;
                            else
                                AMP_SHDN <= '1';
                                AMP_CS <= '1';
                                amp_state_reg <= IDLE;
                            end if;
                            
                        when START =>
                            AMP_SHDN <= '0';
                            sck_reg <= '0';
                            SPI_MOSI <= '0';
                            counter := 0;
                            AMP_CS <= '0';
                            amp_state_reg <= HI;
                            
                        when HI =>
                            sck_reg <= '1';
                            counter := counter+1;                -- The counter was set to 0    
                            SPI_MOSI <= gain_temp(gaincount); -- gaincount is set to be 7
                            amp_state_reg <= LO;
                            
                        when LO =>
                            if counter = 8 then                     -- When 8 bit transferred
                                AMP_SHDN <= '1';                        -- Shut the amp 
                                AMP_state_reg <= IDLE;              -- Go to IDLE state
                                SPI_MOSI <= '0';                        -- Set all the outgoing data to zero
                                AMP_CS <= '1';                          -- Basically, do the tasks assigned by the state IDLE
                                gaincount := 7;
                                sck_reg <= '0';
                                state <= adc_state;                 -- When done communication, go to ADC
                            else
                                sck_reg <= '0';                     -- If counter less than 8 
                                gaincount := gaincount-1;           -- Decrease the gain count (from 7 to 6 and so on)
                                amp_state_reg <= HI;                    -- Go to HI to do the serial transfer
                            end if;
                            
                        when others =>                                  -- Any other situation - Go to IDLE
                            amp_state_reg <= IDLE;
                            
                    end case;
                    
                --START ADC CYCLE
                when adc_state =>
                    DAC_CS <= '1';
                    case adc_state_reg is
                        when IDLE_AD =>
                            counter := 0;
                            sck_reg <= '0';
                            AD_CONV <= '0';
                            if enable = '0' then
                                state <= amp_state;
                            else
                                if start_AD_CONV = '1' then
                                    adc_state_reg <= START_AD;
                                    AD_CONV <= '1';
                                else
                                    adc_state_reg <= IDLE_AD;
                                end if;
                            end if;
                            
                        when START_AD =>
                            sck_reg <= '0';
                            AD_CONV <= '0';
                            count := 16;
                            adc_state_reg <=LO_AD;
                            
                        when LO_AD =>
                            sck_reg<='0';
                            if count > 0 then                   -- Count is initialized to 16
                                count := count-1;
                            end if;
                            counter := counter+1;           -- Counter was set to 0
                            adc_state_reg <= HI_AD;
                            
                        when HI_AD =>
                            sck_reg <= '1';
                            if counter <= 2 then
                                adc_state_reg <= LO_AD;
                            elsif counter > 2 and counter <= 16 then
                                ADC1(count) <= SPI_MISO;
                                adc_state_reg <= LO_AD;
                            elsif counter > 16 and counter <= 18 then
                                count:=14;
                                adc_state_reg <= LO_AD;
                            elsif counter > 18 and counter <=32 then
                                ADC2(count) <= SPI_MISO;
                                adc_state_reg <= LO_AD;
                            elsif counter = 33 then
                                adc_state_reg <= LO_AD;
                            else
                                adc_state_reg <= FINE_AD;
                            end if;
                            
                        when FINE_AD =>
                            counter := 0;
                            count := 16;
                            sck_reg <= '0';
                            ADC_COPY <= ADC1;
                            AD_CONV <= '0';
                            adc_state_reg <= IDLE_AD;
                            state <= dac_state;
                            
                        when others =>
                            adc_state_reg <= IDLE_AD;
                            
                    end case;
                    
                --START DAC CYCLE
                when dac_state =>
                    case dac_state_reg is
                        when da_idle =>
                            AMP_CS <= '1';
                            AD_CONV <= '0';
                            DAC_CS <= '0';
                            DAC_CLR <= '0';
                            sck_reg <= '0';
                            da_bit_reg <= 32;
                            da_data_reg <= "00000000"&"0011"&"0000"&ADC_COPY(13 downto 2)&"0000";
                            dac_state_reg <= da_send;
                            
                        when da_send =>
                            DAC_CLR<='1';
                            SPI_MOSI <= da_data_reg(da_bit_reg);  -- da_bit_reg <= 32;
                            dac_state_reg <= da_sck1;
                            
                        when da_sck1 =>
                            sck_reg <= '1';
                            da_bit_reg <= da_bit_reg-1;             -- Reduce the da_bit_reg by 1 every time the state
                            dac_state_reg <= da_loop;
                        
                        when da_loop =>
                            sck_reg <= '0';
                            if da_bit_reg > 0 then
                                dac_state_reg <= da_send;
                            else
                                dac_state_reg <= da_end;
                            end if;
                            
                        when da_end =>
                            dac_cs <= '1';
                            sck_reg <= '0';
                            dac_state_reg <= da_idle;
                            state <= amp_state;
                        
                        when others =>
                            dac_state_reg <= da_idle;
                            
                    end case;
                    
                when others =>
                    state <= amp_state;
            end case;
        end if;
    end process;
     
    SPI_SCK <= sck_reg;
    end Behavioral;

    •   Alt10th August 2017, 11:02

      advertising

        
       

  2. #2
    Newbie level 5
    Points: 89, Level: 1

    Join Date
    Jul 2017
    Posts
    9
    Helped
    0 / 0
    Points
    89
    Level
    1

    Re: ADC and DAC interface for Spartan - 3A

    Apologies, that was the old code. This is the one I am using.

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;
     
    -- Uncomment the following library declaration if using
    -- arithmetic functions with Signed or Unsigned values
    --use IEEE.NUMERIC_STD.ALL;
     
    -- Uncomment the following library declaration if instantiating
    -- any Xilinx primitives in this code.
    --library UNISIM;
    --use UNISIM.VComponents.all;
     
    entity F_ADC_DAC is
        Port ( Enable : in  STD_LOGIC;
               clk_div : in  STD_LOGIC;
               Start_AD_CONV : in  STD_LOGIC;
               SPI_MISO : in  STD_LOGIC;
               AD_CONV : out  STD_LOGIC;
               AMP_CS : out  STD_LOGIC;
               SPI_MOSI : out  STD_LOGIC;
               SPI_SCK : out  STD_LOGIC;
               AMP_SHDN : out  STD_LOGIC;
               DAC_CS : out  STD_LOGIC;
               DAC_CLR : out  STD_LOGIC);
    end F_ADC_DAC;
     
    architecture Behavioral of F_ADC_DAC is
     
    type state_type is (amp_state, adc_state, dac_state);
    type amp_state_type is (IDLE, START, HI, LO);
    type adc_state_type is (IDLE_AD, START_AD,LO_AD,HI_AD,FINE_AD);
    type dac_state_type is (da_idle, da_send, da_sck1, da_loop, da_end);
    signal state: state_type := amp_state;
    signal amp_state_reg: amp_state_type := IDLE;
    signal adc_state_reg: adc_state_type := IDLE_AD;
    signal dac_state_reg: dac_state_type := da_idle;
    signal sck_reg: std_logic:='0';
    signal ADC1 : std_logic_vector (13 downto 0);
    signal ADC2 : std_logic_Vector (13 downto 0);
    signal da_data_reg: std_logic_vector (31 downto 0) := "00000000001100000000000000000000"; -- signal for the DAC
    signal da_bit_reg : natural range 0 to 32;
    signal ADC_COPY: std_logic_vector (13 downto 0) := (others => '0'); -- a copy of the ADC-value to use for the DAC
    signal clk_sample : STD_LOGIC := '0'; -- Clock Sample is initalized to zero
    signal counter1 : integer range 0 to 34; -- Counter up to 34
    signal risingedge : std_logic := '1'; -- For clock of rising edge
    begin
     
    -- 1.5MHz clock
    clock_divider : process (clk_div) -- Clock divider process
    begin
     if(rising_edge(clk_div)) then -- Process triggered by clk_div
    if(counter1 = 33) then -- To obtain a clock frequency of 1.5MHz=50/33
    risingedge <= risingedge xor '1'; -- Alternate the rising edge 
    clk_sample <= clk_sample xor '1'; -- Alternate the clock sample 
    counter1 <= 0; -- Initilaize the counter to 33 to reiterate 
    else
    counter1 <= counter1 + 1; -- Else, increment the counter till 33
    end if;
    SPI_SCK <= clk_sample;
    end if; 
    end process;
     
     
    --START PROCESS PREAMP - ADC - DAC
    process(clk_div)
    variable count: integer range 0 to 16; -- 14 bits for 1 ADC channel+2 for zero
    variable counter
    : integer range 0 to 34; -- 34 SPI_SCK clockchanges for an entire ADC-loop
    variable gaincount: integer range 0 to 7; -- 8 bits preampsignal
    constant gain_temp: std_logic_vector (7 downto 0):= "00010001"; -- biggest range of preamp
    begin
    if clk_sample'event and clk_sample ='1' then
    case state is
    --START AMP CYCLE
    when amp_state =>
    DAC_CS <= '1'; --non active SPI-bus for DAC
    case amp_state_reg is
    when IDLE =>
    gaincount:=7;
    if enable = '1' then
    amp_state_reg <= START;
    else
    AMP_SHDN <= '1';
    AMP_CS <= '1';
    amp_state_reg <= IDLE;
    end if;
     
    when START =>
    AMP_SHDN <= '0';
    sck_reg <= '0';
    SPI_MOSI <= '0';
    counter := 0;
    AMP_CS <= '0';
    amp_state_reg <= HI;
     
    when HI =>
    sck_reg <= '1';
    counter := counter+1; -- The counter was set to 0
    SPI_MOSI <= gain_temp(gaincount); -- gaincount is set to be 7
    amp_state_reg <= LO;
     
    when LO =>
    if counter = 8 then -- When 8 bit transferred
    AMP_SHDN <= '1'; -- Shut the amp 
    AMP_state_reg <= IDLE; -- Go to IDLE state
    SPI_MOSI <= '0'; -- Set all the outgoing data to zero
    AMP_CS <= '1'; -- Basically, do the tasks assigned by the state IDLE
    gaincount := 7;
    sck_reg <= '0';
    state <= adc_state; -- When done communication, go to ADC
    else
    sck_reg <= '0'; -- If counter less than 8 
    gaincount := gaincount-1; -- Decrease the gain count (from 7 to 6 and so on)
    amp_state_reg <= HI; -- Go to HI to do the serial transfer
    end if;
     
    when others => -- Any other situation - Go to IDLE
    amp_state_reg <= IDLE;
     
    end case;
     
    --START ADC CYCLE
    when adc_state =>
    DAC_CS <= '1';
    case adc_state_reg is
    when IDLE_AD =>
    counter := 0;
    sck_reg <= '0';
    AD_CONV <= '0';
    if enable = '0' then
    state <= amp_state;
    else
    if start_AD_CONV = '1' then
    adc_state_reg <= START_AD;
    AD_CONV <= '1';
    else
    adc_state_reg <= IDLE_AD;
    end if;
    end if;
     
    when START_AD =>
    sck_reg <= '0';
    AD_CONV <= '0';
    count := 16;
    adc_state_reg <=LO_AD;
     
    when LO_AD =>
    sck_reg<='0';
    if count > 0 then -- Count is initialized to 16
    count := count-1;
    end if;
    counter := counter+1; -- Counter was set to 0
    adc_state_reg <= HI_AD;
     
    when HI_AD =>
    sck_reg <= '1';
    if counter <= 2 then
    adc_state_reg <= LO_AD;
    elsif counter > 2 and counter <= 16 then
    ADC1(count) <= SPI_MISO;
    adc_state_reg <= LO_AD;
    elsif counter > 16 and counter <= 18 then
    count:=14;
    adc_state_reg <= LO_AD;
    elsif counter > 18 and counter <=32 then
    ADC2(count) <= SPI_MISO;
    adc_state_reg <= LO_AD;
    elsif counter = 33 then
    adc_state_reg <= LO_AD;
    else
    adc_state_reg <= FINE_AD;
    end if;
     
    when FINE_AD =>
    counter := 0;
    count := 16;
    sck_reg <= '0';
    ADC_COPY <= ADC1;
    AD_CONV <= '0';
    adc_state_reg <= IDLE_AD;
    state <= dac_state;
     
    when others =>
    adc_state_reg <= IDLE_AD;
     
    end case;
     
    --START DAC CYCLE
    when dac_state =>
    case dac_state_reg is
    when da_idle =>
    AMP_CS <= '1';
    AD_CONV <= '0';
    DAC_CS <= '0';
    sck_reg <= '0';
    da_bit_reg <= 32;
    da_data_reg <= "00000000"&"0011"&"0000"&ADC_COPY(13 downto 2)&"0000";
    dac_state_reg <= da_send;
     
    when da_send =>
    SPI_MOSI <= da_data_reg(da_bit_reg);  -- da_bit_reg <= 32;
    dac_state_reg <= da_sck1;
     
    when da_sck1 =>
    sck_reg <= '1';
    da_bit_reg <= da_bit_reg-1; -- Reduce the da_bit_reg by 1 every time the state
    dac_state_reg <= da_loop;
     
    when da_loop =>
    sck_reg <= '0';
    if da_bit_reg > 0 then
    dac_state_reg <= da_send;
    else
    dac_state_reg <= da_end;
    end if;
     
    when da_end =>
    dac_cs <= '1';
    sck_reg <= '0';
    dac_state_reg <= da_idle;
    state <= amp_state;
     
    when others =>
    dac_state_reg <= da_idle;
     
    end case;
     
    when others =>
    state <= amp_state;
    end case;
    end if;
    end process;
     
     
    end Behavioral;



--[[ ]]--