Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

ADC and DAC interface for Spartan - 3A

Status
Not open for further replies.

NJ176

Newbie level 5
Joined
Jul 18, 2017
Messages
9
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
283
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;

 

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;

 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top