Project

General

Profile

Download (8.2 KB) Statistics
| Branch: | Tag: | Revision:
1 c62f5734 Christian Daniel
---------------------------------------------------------------------------------------------------
2
-- Filename    : usbrx_ad7357.vhd
3
-- Project     : OsmoSDR FPGA Firmware
4
-- Purpose     : AD7357 Interface
5
---------------------------------------------------------------------------------------------------
6
7
-----------------------------------------------------------------------------------
8
-- Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany --
9
-- written by Matthias Kleffel                                                   --
10
--                                                                               --
11
-- This program is free software; you can redistribute it and/or modify          --
12
-- it under the terms of the GNU General Public License as published by          --
13
-- the Free Software Foundation as version 3 of the License, or                  --
14
--                                                                               --
15
-- This program is distributed in the hope that it will be useful,               --
16
-- but WITHOUT ANY WARRANTY; without even the implied warranty of                --
17
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  --
18
-- GNU General Public License V3 for more details.                               --
19
--                                                                               --
20
-- You should have received a copy of the GNU General Public License             --
21
-- along with this program. If not, see <http://www.gnu.org/licenses/>.          --
22
-----------------------------------------------------------------------------------
23
24
library ieee;
25
	use ieee.std_logic_1164.all;
26
	use ieee.numeric_std.all;
27
library xp2;
28
	use xp2.all;
29
	use xp2.components.all;
30
library work;
31
	use work.all;
32
	use work.mt_toolbox.all;
33
	use work.usbrx.all;
34
35
entity usbrx_ad7357 is
36
	port(
37
		-- common
38
		clk        : in  std_logic;
39
		reset      : in  std_logic;
40
41
		-- config
42
		config     : in  usbrx_adc_config_t;
43
	
44
		-- ADC interface
45
		adc_cs     : out std_logic;
46
		adc_sck    : out std_logic;
47
		adc_sd1    : in  std_logic;
48
		adc_sd2    : in  std_logic;
49
		
50
		-- output
51
		out_clk    : out std_logic;
52
		out_i      : out unsigned(13 downto 0);
53
		out_q      : out unsigned(13 downto 0)
54
	);
55
end usbrx_ad7357;
56
57
architecture rtl of usbrx_ad7357 is
58
59
	-- internal types
60
	type state_t is (S_ACQUISITION, S_CONVERT);
61
	
62
	-- main status
63
	signal state   : state_t;
64
	signal counter : unsigned(7 downto 0);
65
	
66
	-- SCK generator
67
	signal cg_div    : unsigned(7 downto 0);
68
	signal cg_count  : unsigned(7 downto 0);
69
	signal cg_phase  : std_logic;
70
	signal cg_ddr_a  : std_logic;
71
	signal cg_ddr_b  : std_logic;
72
	signal cg_renxt  : std_logic;
73
	signal cg_redge  : std_logic;
74
75
	-- chip select (+ delayed versions)
76
	signal css : std_logic_vector(3 downto 0);
77
	
78
	-- latch input on rising/falling edge of current cycle
79
	-- (+ delayed versions)
80
	signal latch_r : std_logic_vector(3 downto 0);
81
	signal latch_f : std_logic_vector(3 downto 0);
82
	
83
	-- input register stage #1
84
	signal sd1_s1r : std_logic; -- SD1 - rising edge
85
	signal sd1_s1f : std_logic; -- SD1 - falling edge
86
	signal sd2_s1r : std_logic; -- SD2 - rising edge
87
	signal sd2_s1f : std_logic; -- SD2 - falling edge
88
	
89
	-- input register stage #2
90
	signal sd1_s2r : std_logic; -- SD1 - rising edge
91
	signal sd1_s2f : std_logic; -- SD1 - falling edge
92
	signal sd2_s2r : std_logic; -- SD2 - rising edge
93
	signal sd2_s2f : std_logic; -- SD2 - falling edge
94
	
95
	-- input shift registers
96
	signal sreg1 : std_logic_vector(13 downto 0);
97
	signal sreg2 : std_logic_vector(13 downto 0);
98
	
99
	-- output latches
100
	signal onew  : std_logic;
101
	signal oreg1 : std_logic_vector(13 downto 0);
102
	signal oreg2 : std_logic_vector(13 downto 0);
103
104
begin
105
	
106
	-- SCL clock generator logic
107
	process(clk)
108
	begin
109
		if rising_edge(clk) then
110
			-- set default values
111
			cg_renxt <= '0';
112
			cg_redge <= cg_renxt;
113
			latch_r <= latch_r(latch_r'left-1 downto 0) & '0';
114
			latch_f <= latch_f(latch_f'left-1 downto 0) & '0';
115
			
116
			-- get config
117
			cg_div <= config.clkdiv;
118
	
119
			-- get operation mode
120
			if cg_div=0 or cg_div=1 then
121
				--> full speed, just pass through clock
122
				cg_ddr_a   <= '0';
123
				cg_ddr_b   <= '1';
124
				cg_renxt   <= '1';
125
				latch_f(0) <= '1';
126
			else
127
				--> divided clock, update divider-logic
128
				if cg_count=0 then
129
					-- toggle clock on FE in middle of cycle 
130
					cg_count   <= cg_div - 2;
131
					cg_phase   <= not cg_phase;
132
					cg_ddr_a   <= cg_phase;
133
					cg_ddr_b   <= not cg_phase;
134
					cg_renxt   <= not cg_phase;
135
					latch_r(0) <= cg_phase;
136
				elsif cg_count=1 then
137
					-- toggle clock on RE after this cycle
138
					cg_count   <= cg_div - 1;
139
					cg_phase   <= '0'; --not cg_phase;
140
					cg_ddr_a   <= '1'; --cg_phase;
141
					cg_ddr_b   <= '1'; --cg_phase;
142
					latch_f(0) <= '1';
143
				else
144
					-- leave clock unchanged
145
					cg_count <= cg_count - 2;
146
					cg_ddr_a <= cg_phase;
147
					cg_ddr_b <= cg_phase;
148
				end if;
149
				
150
				-- failsafe
151
				if cg_count=1 and cg_div(0)='0' then
152
					cg_count <= cg_div - 2;
153
				end if;
154
				
155
			end if;
156
			
157
			-- handle reset
158
			if reset='1' then
159
				cg_div   <= (others=>'1');
160
				cg_count <= (others=>'0');
161
				cg_phase <= '0';
162
				cg_renxt <= '0';
163
				cg_redge <= '0';
164
				cg_ddr_a <= '1';
165
				cg_ddr_b <= '1';
166
				latch_r  <= (others=>'0');
167
				latch_f  <= (others=>'0');
168
			end if;
169
		end if;
170
	end process;
171
	
172
	-- output register for SCLK
173
	oddr: ODDRXC
174
		port map (
175
			clk => clk,
176
			rst => reset,
177
			da  => cg_ddr_a,
178
			db  => cg_ddr_b,
179
			q   => adc_sck
180
		);
181
	
182
	-- main control logig
183
	process(clk)
184
	begin
185
		if rising_edge(clk) then
186
			-- set default values
187
			css <= css(css'left-1 downto 0) & css(0);
188
				
189
			-- update status
190
			case state is
191
				when S_ACQUISITION =>
192
					-- doing ACQUISITION, wait until ready to start conversion
193
					if cg_redge='1' then
194
						-- new SCLK cycle, check if wait-counter has ellapsed
195
						counter <= counter - 1;
196
						if counter<=1 then
197
							--> counter ellapsed, start conversion
198
							state   <= S_CONVERT;
199
							counter <= to_unsigned(15,counter'length);
200
							css(0)  <= '0';
201
						end if;
202
					end if;
203
					
204
				when S_CONVERT =>
205
					-- doing conversion, wait until all bits are clocked out
206
					if cg_redge='1' then
207
						-- new SCLK cycle, check if bit-counter has ellapsed
208
						counter <= counter - 1;
209
						if counter=0 then
210
							-- all bits received, return to ACQUISITION state
211
							state   <= S_ACQUISITION;
212
							counter <= config.acqlen;
213
							css(0)  <= '1';
214
						end if;
215
					end if;
216
			end case;
217
			
218
			-- handle reset
219
			if reset='1' then
220
				state   <= S_ACQUISITION; -- TODO
221
				counter <= (others=>'0');
222
				css     <= (others=>'1');
223
			end if;
224
		end if;
225
	end process;
226
	
227
	-- output chip-select
228
	adc_cs <= css(0);
229
230
	-- input capture registers
231
	iddr1: IDDRXC
232
		port map (
233
			clk => clk,
234
			rst => '0',
235
			ce  => '1',
236
			d   => adc_sd1,
237
			qa  => sd1_s1r,
238
			qb  => sd1_s1f
239
		);
240
	iddr2: IDDRXC
241
		port map (
242
			clk => clk,
243
			rst => '0',
244
			ce  => '1',
245
			d   => adc_sd2,
246
			qa  => sd2_s1r,
247
			qb  => sd2_s1f
248
		);
249
	
250
	-- input data handling
251
	process(clk)
252
	begin
253
		if rising_edge(clk) then
254
			-- set default valies
255
			onew <= '0';
256
			
257
			-- register input-bits once more
258
			sd1_s2r <= sd1_s1r;
259
			sd1_s2f <= sd1_s1f;
260
			sd2_s2r <= sd2_s1r;
261
			sd2_s2f <= sd2_s1f;
262
			
263
			-- update shift-registers
264
			if latch_r(3)='1' then
265
				sreg1 <= sreg1(12 downto 0) & sd1_s2r;
266
				sreg2 <= sreg2(12 downto 0) & sd2_s2r;
267
			elsif latch_f(3)='1' then
268
				sreg1 <= sreg1(12 downto 0) & sd1_s2f;
269
				sreg2 <= sreg2(12 downto 0) & sd2_s2f;
270
			end if;
271
		
272
			-- latch away shift-register when requested
273
			if css(2)='1' and css(3)='0' then
274
				onew  <= '1';
275
				oreg1 <= sreg1;
276
				oreg2 <= sreg2;
277
			end if;
278
			
279
			-- handle reset
280
			if reset='1' then
281
				sd1_s2r <= '0';
282
				sd1_s2f <= '0';
283
				sd2_s2r <= '0';
284
				sd2_s2f <= '0';
285
				sreg1 <= (others=>'0');
286
				sreg2 <= (others=>'0');
287
				oreg1 <= (others=>'0');
288
				oreg2 <= (others=>'0');
289
				onew  <= '0';
290
			end if;
291
		end if;
292
	end process;
293
	
294
	-- set output
295
	out_clk <= onew;
296
	out_i <= unsigned(oreg1);
297
	out_q <= unsigned(oreg2);
298
		
299
end rtl;
Add picture from clipboard (Maximum size: 48.8 MB)