diff --git a/Documentation/DeveloperInfo/FPGA_protocol.pdf b/Documentation/DeveloperInfo/FPGA_protocol.pdf index 0e4cacd..ff9ecda 100644 Binary files a/Documentation/DeveloperInfo/FPGA_protocol.pdf and b/Documentation/DeveloperInfo/FPGA_protocol.pdf differ diff --git a/Documentation/DeveloperInfo/FPGA_protocol.tex b/Documentation/DeveloperInfo/FPGA_protocol.tex index 40acb96..f3c0d3d 100644 --- a/Documentation/DeveloperInfo/FPGA_protocol.tex +++ b/Documentation/DeveloperInfo/FPGA_protocol.tex @@ -147,7 +147,7 @@ Initiate the reading of sampling data by sending the command word: \robits{3}{13}{reserved} \end{tikzpicture} \end{center} -Afterwards, read up to 19 words before setting NSS high. These 19 words will contain the sampling result (see section~\ref{result}), transmitted with the least significant word first. +Afterwards, read up to 20 words before setting NSS high. These 20 words will contain the sampling result (see section~\ref{result}), transmitted with the least significant word first. \subsection{Resuming a halted sweep} When the halt bit is set in the SweepConfig, the FPGA will configure the Source and LO as requested but will not start the settling timer (and subsequently the sampling process) until this resume command is issued. The halted sweep is indicated by the sweep halted bit in the status register. @@ -405,6 +405,42 @@ $$ PhaseInc = \frac{4096 * f_{IF2}}{SR_{ADC}} $$ For the the default IF frequency of $f_{IF2} = \SI{250}{\kilo\hertz}$ this evaluates to 10*Presc (see ADC prescaler register). \end{itemize} +\subsection{PGA gain settings: 0x06} +\label{reg:pgagain} +\begin{center} +\begin{tikzpicture} +\bitrect{16}{16-\bit} +\robits{0}{2}{reserved} +\rwbits{2}{1}{P2AG} +\rwbits{3}{1}{P1AG} +\robits{4}{4}{reserved} +\rwbits{8}{4}{Port 2 gain[3:0]} +\rwbits{12}{4}{Port 1 gain[3:0]} +\end{tikzpicture} +\end{center} +\begin{itemize} +\item \textbf{P2AG:} Autogain enable for ADC at port 2. During each sampling point, the first few initial ADC samples are evaluated and the gain of the PGA adjusted if necessary. Autogain only works correctly when a rectangular window is used. +\item \textbf{P1AG:} Autogain enable for ADC at port 1. +\item \textbf{Port 2 gain[3:0]:} Gain selection for port 2 PGA, only used when autogain is disabled. +\begin{center} +\begin{tabular}{ c|c } +Setting & Gain (V/V)\\ + \hline +0000 & 1\\ +0001 & 10\\ +0010 & 20\\ +0011 & 30\\ +0100 & 40\\ +0101 & 60\\ +0110 & 80\\ +0111 & 120\\ +1000 & 157\\ +1001--1111 & Reserved\\ +\end{tabular} +\end{center} +\item \textbf{Port 1 gain[3:0]:} Gain selection for port 1 PGA, only used when autogain is disabled. Same gain values available as for port 2. +\end{itemize} + \subsection{MAX2871 Default Values Registers: 0x08-0x0F} See datasheet of MAX2871 for bit descriptions. Bits for the fields N, FRAC, M, VCO and DIV\_A are "don't care" as they will be overwritten by the SweepConfig setting. \begin{center} @@ -562,6 +598,12 @@ Setting & Selected Band\\ Each point in the sweep generates two sampling results. The first one contains the measurement when the source was routed to Port 1, the second sampling result was taken when the source was routed to Port 2. \begin{center} \begin{tikzpicture} +\bitrect{16}{320-\bit} +\rwbits{0}{8}{reserved} +\robits{8}{4}{Port 2 gain [3:0]} +\rwbits{12}{4}{Port 1 gain [3:0]} +\end{tikzpicture} +\begin{tikzpicture} \bitrect{16}{304-\bit} \rwbits{0}{1}{SRC} \robits{1}{2}{reserved} @@ -646,4 +688,11 @@ Each point in the sweep generates two sampling results. The first one contains t \end{tikzpicture} \end{center} +\begin{itemize} +\item \textbf{Port 2 gain:} Used gain setting for port 2 if autoranging is enabled. Meaningless if autoranging is disabled. See section~\ref{reg:pgagain} for the mapping of gain factors to the bits. +\item \textbf{Port 1 gain:} Used gain setting for port 1 if autoranging is enabled. Meaningless if autoranging is disabled. See section~\ref{reg:pgagain} for the mapping of gain factors to the bits. +\item \textbf{SRC:} 0 if port 1 was excited during the measurement, 1 if port 2 was excited. +\item \textbf{POINT\_NUMBER[12:0]:} Indicates the sampling point in the sweep from which the result was acquired (used for verification purposes). +\end{itemize} + \end{document} \ No newline at end of file diff --git a/FPGA/VNA/MAX9939.vhd b/FPGA/VNA/MAX9939.vhd new file mode 100644 index 0000000..4ee7f32 --- /dev/null +++ b/FPGA/VNA/MAX9939.vhd @@ -0,0 +1,107 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 20:59:58 05/29/2021 +-- Design Name: +-- Module Name: MAX9939 - Behavioral +-- Project Name: +-- Target Devices: +-- Tool versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.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 MAX9939 is + Generic(CLK_DIV : integer); + Port ( CLK : in STD_LOGIC; + RESET : in STD_LOGIC; + GAIN : in STD_LOGIC_VECTOR (3 downto 0); + READY : out STD_LOGIC; + CS : out STD_LOGIC; + SCLK : out STD_LOGIC; + DIN : out STD_LOGIC); +end MAX9939; + +architecture Behavioral of MAX9939 is + signal div_cnt : integer range 0 to (CLK_DIV/2)-1; + signal chip_select : std_logic; + type States is (Idle, CLKlow, CLKhigh); + signal shift_register : std_logic_vector(7 downto 0); + signal bitcount : integer range 0 to 8; + signal state : States; + signal current_gain : std_logic_vector(3 downto 0); +begin + + READY <= chip_select; + CS <= chip_select; + + process(CLK, RESET) + begin + if(rising_edge(CLK)) then + DIN <= shift_register(0); + if(RESET = '1') then + state <= Idle; + chip_select <= '1'; + SCLK <= '0'; + current_gain <= "1111"; -- this is an invalid value, any valid value at GAIN input will trigger the transfer + else + case state is + when Idle => + SCLK <= '0'; + chip_select <= '1'; + if(current_gain /= GAIN) then + current_gain <= GAIN; + shift_register <= "000" & GAIN & "1"; + bitcount <= 0; + state <= CLKlow; + div_cnt <= 0; + end if; + when CLKlow => + SCLK <= '0'; + chip_select <= '0'; + if div_cnt = CLK_DIV/2 - 1 then + if bitcount = 8 then + state <= Idle; + else + bitcount <= bitcount + 1; + div_cnt <= 0; + state <= CLKhigh; + end if; + else + div_cnt <= div_cnt + 1; + end if; + when CLKhigh => + SCLK <= '1'; + chip_select <= '0'; + if div_cnt = CLK_DIV/2 - 1 then + div_cnt <= 0; + state <= CLKlow; + shift_register <= "0" & shift_register(7 downto 1); + else + div_cnt <= div_cnt + 1; + end if; + end case; + end if; + end if; + end process; + +end Behavioral; + diff --git a/FPGA/VNA/SPIConfig.vhd b/FPGA/VNA/SPIConfig.vhd index 62307c6..3e14215 100644 --- a/FPGA/VNA/SPIConfig.vhd +++ b/FPGA/VNA/SPIConfig.vhd @@ -37,7 +37,7 @@ entity SPICommands is MISO : out STD_LOGIC; NSS : in STD_LOGIC; NEW_SAMPLING_DATA : in STD_LOGIC; - SAMPLING_RESULT : in STD_LOGIC_VECTOR (303 downto 0); + SAMPLING_RESULT : in STD_LOGIC_VECTOR (319 downto 0); ADC_MINMAX : in STD_LOGIC_VECTOR(95 downto 0); SOURCE_UNLOCKED : in STD_LOGIC; LO_UNLOCKED : in STD_LOGIC; @@ -77,7 +77,13 @@ entity SPICommands is DFT_OUTPUT : in STD_LOGIC_VECTOR (191 downto 0); DFT_NEXT_OUTPUT : out STD_LOGIC; DFT_ENABLE : out STD_LOGIC; - + + -- ADC gain settings + PORT1_GAIN : out STD_LOGIC_VECTOR(3 downto 0); -- only used when autogain disabled + PORT2_GAIN : out STD_LOGIC_VECTOR(3 downto 0); -- only used when autogain disabled + PORT1_AUTOGAIN : out STD_LOGIC; + PORT2_AUTOGAIN : out STD_LOGIC; + DEBUG_STATUS : in STD_LOGIC_VECTOR(10 downto 0)); end SPICommands; @@ -116,7 +122,7 @@ architecture Behavioral of SPICommands is signal interrupt_mask : std_logic_vector(15 downto 0); signal interrupt_status : std_logic_vector(15 downto 0); - signal latched_result : std_logic_vector(287 downto 0); + signal latched_result : std_logic_vector(303 downto 0); signal sweepconfig_buffer : std_logic_vector(79 downto 0); begin SPI: spi_slave @@ -218,7 +224,7 @@ begin spi_buf_in <= DFT_OUTPUT(15 downto 0); dft_next <= '1'; when "110" => state <= ReadResult; - latched_result <= SAMPLING_RESULT(303 downto 16); + latched_result <= SAMPLING_RESULT(319 downto 16); spi_buf_in <= SAMPLING_RESULT(15 downto 0); unread_sampling_data <= '0'; when "111" => state <= ReadResult; -- can use same state as read result, but the latched data will contain the min/max ADC values @@ -247,6 +253,10 @@ begin EXCITE_PORT2 <= spi_buf_out(2); when 4 => ADC_PRESCALER <= spi_buf_out(7 downto 0); when 5 => ADC_PHASEINC <= spi_buf_out(11 downto 0); + when 6 => PORT1_GAIN <= spi_buf_out(3 downto 0); + PORT2_GAIN <= spi_buf_out(7 downto 4); + PORT1_AUTOGAIN <= spi_buf_out(12); + PORT2_AUTOGAIN <= spi_buf_out(13); when 8 => MAX2871_DEF_0(15 downto 0) <= spi_buf_out; when 9 => MAX2871_DEF_0(31 downto 16) <= spi_buf_out; when 10 => MAX2871_DEF_1(15 downto 0) <= spi_buf_out; @@ -272,7 +282,7 @@ begin when ReadResult => -- pass on next word of latched result spi_buf_in <= latched_result(15 downto 0); - latched_result <= "0000000000000000" & latched_result(287 downto 16); + latched_result <= "0000000000000000" & latched_result(303 downto 16); end case; end if; end if; diff --git a/FPGA/VNA/Sampling.vhd b/FPGA/VNA/Sampling.vhd index 0c752e2..847e05c 100644 --- a/FPGA/VNA/Sampling.vhd +++ b/FPGA/VNA/Sampling.vhd @@ -30,7 +30,10 @@ use IEEE.NUMERIC_STD.ALL; --use UNISIM.VComponents.all; entity Sampling is - Generic(CLK_CYCLES_PRE_DONE : integer); + Generic(CLK_CYCLES_PRE_DONE : integer; + AUTOGAIN_SAMPLES : integer; + AUTOGAIN_MAX : integer; + AUTOGAIN_MIN : integer); Port ( CLK : in STD_LOGIC; RESET : in STD_LOGIC; ADC_PRESCALER : in STD_LOGIC_VECTOR(7 downto 0); @@ -42,6 +45,7 @@ entity Sampling is NEW_SAMPLE : in STD_LOGIC; DONE : out STD_LOGIC; PRE_DONE : out STD_LOGIC; + USEDGAIN : out STD_LOGIC_VECTOR (15 downto 0); START : in STD_LOGIC; SAMPLES : in STD_LOGIC_VECTOR (12 downto 0); PORT1_I : out STD_LOGIC_VECTOR (47 downto 0); @@ -50,7 +54,13 @@ entity Sampling is PORT2_Q : out STD_LOGIC_VECTOR (47 downto 0); REF_I : out STD_LOGIC_VECTOR (47 downto 0); REF_Q : out STD_LOGIC_VECTOR (47 downto 0); - ACTIVE : out STD_LOGIC); + ACTIVE : out STD_LOGIC; + PORT1_GAIN : out STD_LOGIC_VECTOR (3 downto 0); + PORT1_GAIN_READY : in STD_LOGIC; + PORT1_AUTOGAIN : in STD_LOGIC; + PORT2_GAIN : out STD_LOGIC_VECTOR (3 downto 0); + PORT2_GAIN_READY : in STD_LOGIC; + PORT2_AUTOGAIN : in STD_LOGIC); end Sampling; architecture Behavioral of Sampling is @@ -104,6 +114,14 @@ END COMPONENT; signal mult_enable : std_logic; signal mult_accumulate : std_logic_vector(0 downto 0); + signal p1_gain : std_logic_vector(3 downto 0); + signal p2_gain : std_logic_vector(3 downto 0); + signal p1_max : integer range 0 to 65536; + signal p2_max : integer range 0 to 65536; + + signal autogain_cnt : integer range 0 to AUTOGAIN_SAMPLES + 1; + signal autogain_changed : std_logic; + type States is (Idle, Sampling, P1Q, P2I, P2Q, RI, RQ, SaveP1Q, SaveP2I, SaveP2Q, SaveRI, SaveRQ, Ready); signal state : States; begin @@ -134,6 +152,9 @@ begin -- sign extend b input of multiplier (sin/cos) mult_b(17 downto 16) <= mult_b(15) & mult_b(15); + PORT1_GAIN <= p1_gain; + PORT2_GAIN <= p2_gain; + process(CLK, RESET) begin if rising_edge(CLK) then @@ -148,6 +169,8 @@ begin phase <= (others => '0'); mult_enable <= '0'; mult_accumulate <= "0"; + p1_gain <= "0000"; + p2_gain <= "0000"; else -- when not idle, generate pulses for ADCs if state /= Idle then @@ -176,6 +199,9 @@ begin mult_accumulate <= "0"; if START = '1' then state <= Sampling; + -- reset peak detector for autogain + p1_max <= 0; + p2_max <= 0; samples_to_take <= to_integer(unsigned(SAMPLES & "0000")); end if; when Sampling => @@ -183,15 +209,48 @@ begin PRE_DONE <= '0'; ACTIVE <= '1'; mult_enable <= '0'; - if NEW_SAMPLE = '1' then + -- only accept new samples when the gain has been transferred to the PGA + if NEW_SAMPLE = '1' and PORT1_GAIN_READY = '1' and PORT2_GAIN_READY = '1' then sample_cnt <= sample_cnt + 1; + if autogain_cnt /= AUTOGAIN_SAMPLES + 1 then + autogain_cnt <= autogain_cnt + 1; + end if; + autogain_changed <= '0'; mult_enable <= '1'; mult_a <= PORT1; mult_b(15 downto 0) <= cosine; mult_c <= p1_I; + -- keep track of maximum value for autogain + if to_integer(signed(PORT1)) > p1_max then + p1_max <= to_integer(signed(PORT1)); + end if; + if to_integer(signed(PORT2)) > p2_max then + p2_max <= to_integer(signed(PORT2)); + end if; state <= P1Q; end if; when P1Q => + if autogain_cnt = AUTOGAIN_SAMPLES then + -- check signal range and adjust gain if enabled and necessary + if PORT1_AUTOGAIN = '1' and p1_max > AUTOGAIN_MAX and p1_gain /= "0000" then + -- signal too high, reduce gain + autogain_changed <= '1'; + p1_gain <= std_logic_vector(unsigned(p1_gain) - 1); + elsif PORT1_AUTOGAIN = '1' and p1_max < AUTOGAIN_MIN and p1_gain /= "1000" then + -- signal too low, increase gain + autogain_changed <= '1'; + p1_gain <= std_logic_vector(unsigned(p1_gain) + 1); + end if; + if PORT2_AUTOGAIN = '1' and p2_max > AUTOGAIN_MAX and p2_gain /= "0000" then + -- signal too high, reduce gain + autogain_changed <= '1'; + p2_gain <= std_logic_vector(unsigned(p2_gain) - 1); + elsif PORT2_AUTOGAIN = '1' and p2_max < AUTOGAIN_MIN and p2_gain /= "1000" then + -- signal too low, increase gain + autogain_changed <= '1'; + p2_gain <= std_logic_vector(unsigned(p2_gain) + 1); + end if; + end if; ACTIVE <= '1'; DONE <= '0'; PRE_DONE <= '0'; @@ -209,6 +268,13 @@ begin mult_b(15 downto 0) <= cosine; mult_c <= p2_I; state <= P2Q; + if autogain_changed = '1' then + -- reset autogain memory and restart sampling process + p1_max <= 0; + p2_max <= 0; + samples_to_take <= to_integer(unsigned(SAMPLES & "0000")); + state <= Sampling; + end if; when P2Q => ACTIVE <= '1'; DONE <= '0'; @@ -291,6 +357,7 @@ begin PORT2_Q <= p2_Q; REF_I <= r_I; REF_Q <= r_Q; + USEDGAIN <= "00000000" & p2_gain & p1_gain; state <= Idle; end case; end if; diff --git a/FPGA/VNA/Test_MAX9939.vhd b/FPGA/VNA/Test_MAX9939.vhd new file mode 100644 index 0000000..4b38c47 --- /dev/null +++ b/FPGA/VNA/Test_MAX9939.vhd @@ -0,0 +1,111 @@ +-------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 21:19:15 05/29/2021 +-- Design Name: +-- Module Name: /home/jan/Projekte/VNA2/FPGA/VNA/Test_MAX9939.vhd +-- Project Name: VNA +-- Target Device: +-- Tool versions: +-- Description: +-- +-- VHDL Test Bench Created by ISE for module: MAX9939 +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +-- Notes: +-- This testbench has been automatically generated using types std_logic and +-- std_logic_vector for the ports of the unit under test. Xilinx recommends +-- that these types always be used for the top-level I/O of a design in order +-- to guarantee that the testbench will bind correctly to the post-implementation +-- simulation model. +-------------------------------------------------------------------------------- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +--USE ieee.numeric_std.ALL; + +ENTITY Test_MAX9939 IS +END Test_MAX9939; + +ARCHITECTURE behavior OF Test_MAX9939 IS + + -- Component Declaration for the Unit Under Test (UUT) + + COMPONENT MAX9939 + GENERIC(CLK_DIV : integer); + PORT( + CLK : IN std_logic; + RESET : IN std_logic; + GAIN : IN std_logic_vector(3 downto 0); + READY : OUT std_logic; + CS : OUT std_logic; + SCLK : OUT std_logic; + DIN : OUT std_logic + ); + END COMPONENT; + + + --Inputs + signal CLK : std_logic := '0'; + signal RESET : std_logic := '1'; + signal GAIN : std_logic_vector(3 downto 0) := (others => '0'); + + --Outputs + signal READY : std_logic; + signal CS : std_logic; + signal SCLK : std_logic; + signal DIN : std_logic; + + -- Clock period definitions + constant CLK_period : time := 10 ns; + +BEGIN + + -- Instantiate the Unit Under Test (UUT) + uut: MAX9939 + GENERIC MAP(CLK_DIV => 10) + PORT MAP ( + CLK => CLK, + RESET => RESET, + GAIN => GAIN, + READY => READY, + CS => CS, + SCLK => SCLK, + DIN => DIN + ); + + -- Clock process definitions + CLK_process :process + begin + CLK <= '0'; + wait for CLK_period/2; + CLK <= '1'; + wait for CLK_period/2; + end process; + + + -- Stimulus process + stim_proc: process + begin + -- hold reset state for 100 ns. + wait for 100 ns; + RESET <= '0'; + + wait for CLK_period*10; + + -- insert stimulus here + wait for CLK_period*200; + GAIN <= "1010"; + + wait; + end process; + +END; diff --git a/FPGA/VNA/VNA.gise b/FPGA/VNA/VNA.gise index f25e55f..a014671 100644 --- a/FPGA/VNA/VNA.gise +++ b/FPGA/VNA/VNA.gise @@ -24,6 +24,7 @@ + @@ -41,6 +42,9 @@ + + + @@ -135,7 +139,7 @@ - + @@ -144,6 +148,7 @@ + @@ -152,6 +157,7 @@ + @@ -165,56 +171,91 @@ - + - + - + - - - - - + + + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + + + + - + - - - + + + @@ -224,7 +265,7 @@ - + @@ -253,7 +294,7 @@ - + @@ -271,11 +312,11 @@ - + - + @@ -284,7 +325,7 @@ - + @@ -300,7 +341,7 @@ - + @@ -314,7 +355,7 @@ - + @@ -368,7 +409,7 @@ - + diff --git a/FPGA/VNA/VNA.xise b/FPGA/VNA/VNA.xise index 7f1807b..4a9efc7 100644 --- a/FPGA/VNA/VNA.xise +++ b/FPGA/VNA/VNA.xise @@ -17,7 +17,7 @@ - + @@ -34,11 +34,11 @@ - + - + @@ -68,7 +68,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -120,7 +120,7 @@ - + @@ -146,6 +146,16 @@ + + + + + + + + + + @@ -405,8 +415,8 @@ - - + + @@ -424,7 +434,7 @@ - + @@ -476,7 +486,7 @@ - + diff --git a/FPGA/VNA/ipcore_dir/DFT_CLK.xco b/FPGA/VNA/ipcore_dir/DFT_CLK.xco new file mode 100644 index 0000000..3e4836e --- /dev/null +++ b/FPGA/VNA/ipcore_dir/DFT_CLK.xco @@ -0,0 +1,269 @@ +############################################################## +# +# Xilinx Core Generator version 14.6 +# Date: Mon Mar 15 20:29:12 2021 +# +############################################################## +# +# This file contains the customisation parameters for a +# Xilinx CORE Generator IP GUI. It is strongly recommended +# that you do not manually alter this file as it may cause +# unexpected and unsupported behavior. +# +############################################################## +# +# Generated from component: xilinx.com:ip:clk_wiz:3.6 +# +############################################################## +# +# BEGIN Project Options +SET addpads = false +SET asysymbol = true +SET busformat = BusFormatAngleBracketNotRipped +SET createndf = false +SET designentry = VHDL +SET device = xc6slx9 +SET devicefamily = spartan6 +SET flowvendor = Other +SET formalverification = false +SET foundationsym = false +SET implementationfiletype = Ngc +SET package = tqg144 +SET removerpms = false +SET simulationfiles = Behavioral +SET speedgrade = -2 +SET verilogsim = false +SET vhdlsim = true +# END Project Options +# BEGIN Select +SELECT Clocking_Wizard xilinx.com:ip:clk_wiz:3.6 +# END Select +# BEGIN Parameters +CSET calc_done=DONE +CSET clk_in_sel_port=CLK_IN_SEL +CSET clk_out1_port=CLK_OUT1 +CSET clk_out1_use_fine_ps_gui=false +CSET clk_out2_port=CLK_OUT2 +CSET clk_out2_use_fine_ps_gui=false +CSET clk_out3_port=CLK_OUT3 +CSET clk_out3_use_fine_ps_gui=false +CSET clk_out4_port=CLK_OUT4 +CSET clk_out4_use_fine_ps_gui=false +CSET clk_out5_port=CLK_OUT5 +CSET clk_out5_use_fine_ps_gui=false +CSET clk_out6_port=CLK_OUT6 +CSET clk_out6_use_fine_ps_gui=false +CSET clk_out7_port=CLK_OUT7 +CSET clk_out7_use_fine_ps_gui=false +CSET clk_valid_port=CLK_VALID +CSET clkfb_in_n_port=CLKFB_IN_N +CSET clkfb_in_p_port=CLKFB_IN_P +CSET clkfb_in_port=CLKFB_IN +CSET clkfb_in_signaling=SINGLE +CSET clkfb_out_n_port=CLKFB_OUT_N +CSET clkfb_out_p_port=CLKFB_OUT_P +CSET clkfb_out_port=CLKFB_OUT +CSET clkfb_stopped_port=CLKFB_STOPPED +CSET clkin1_jitter_ps=625.0 +CSET clkin1_ui_jitter=0.010 +CSET clkin2_jitter_ps=100.0 +CSET clkin2_ui_jitter=0.010 +CSET clkout1_drives=BUFG +CSET clkout1_requested_duty_cycle=50.000 +CSET clkout1_requested_out_freq=160 +CSET clkout1_requested_phase=0.000 +CSET clkout2_drives=BUFG +CSET clkout2_requested_duty_cycle=50.000 +CSET clkout2_requested_out_freq=100.000 +CSET clkout2_requested_phase=0.000 +CSET clkout2_used=false +CSET clkout3_drives=BUFG +CSET clkout3_requested_duty_cycle=50.000 +CSET clkout3_requested_out_freq=100.000 +CSET clkout3_requested_phase=0.000 +CSET clkout3_used=false +CSET clkout4_drives=BUFG +CSET clkout4_requested_duty_cycle=50.000 +CSET clkout4_requested_out_freq=100.000 +CSET clkout4_requested_phase=0.000 +CSET clkout4_used=false +CSET clkout5_drives=BUFG +CSET clkout5_requested_duty_cycle=50.000 +CSET clkout5_requested_out_freq=100.000 +CSET clkout5_requested_phase=0.000 +CSET clkout5_used=false +CSET clkout6_drives=BUFG +CSET clkout6_requested_duty_cycle=50.000 +CSET clkout6_requested_out_freq=100.000 +CSET clkout6_requested_phase=0.000 +CSET clkout6_used=false +CSET clkout7_drives=BUFG +CSET clkout7_requested_duty_cycle=50.000 +CSET clkout7_requested_out_freq=100.000 +CSET clkout7_requested_phase=0.000 +CSET clkout7_used=false +CSET clock_mgr_type=AUTO +CSET component_name=DFT_CLK +CSET daddr_port=DADDR +CSET dclk_port=DCLK +CSET dcm_clk_feedback=1X +CSET dcm_clk_out1_port=CLKFX +CSET dcm_clk_out2_port=CLK0 +CSET dcm_clk_out3_port=CLK0 +CSET dcm_clk_out4_port=CLK0 +CSET dcm_clk_out5_port=CLK0 +CSET dcm_clk_out6_port=CLK0 +CSET dcm_clkdv_divide=2.0 +CSET dcm_clkfx_divide=1 +CSET dcm_clkfx_multiply=10 +CSET dcm_clkgen_clk_out1_port=CLKFX +CSET dcm_clkgen_clk_out2_port=CLKFX +CSET dcm_clkgen_clk_out3_port=CLKFX +CSET dcm_clkgen_clkfx_divide=1 +CSET dcm_clkgen_clkfx_md_max=0.000 +CSET dcm_clkgen_clkfx_multiply=4 +CSET dcm_clkgen_clkfxdv_divide=2 +CSET dcm_clkgen_clkin_period=10.000 +CSET dcm_clkgen_notes=None +CSET dcm_clkgen_spread_spectrum=NONE +CSET dcm_clkgen_startup_wait=false +CSET dcm_clkin_divide_by_2=false +CSET dcm_clkin_period=62.500 +CSET dcm_clkout_phase_shift=NONE +CSET dcm_deskew_adjust=SYSTEM_SYNCHRONOUS +CSET dcm_notes=None +CSET dcm_phase_shift=0 +CSET dcm_pll_cascade=NONE +CSET dcm_startup_wait=false +CSET den_port=DEN +CSET din_port=DIN +CSET dout_port=DOUT +CSET drdy_port=DRDY +CSET dwe_port=DWE +CSET feedback_source=FDBK_AUTO +CSET in_freq_units=Units_MHz +CSET in_jitter_units=Units_UI +CSET input_clk_stopped_port=INPUT_CLK_STOPPED +CSET jitter_options=UI +CSET jitter_sel=No_Jitter +CSET locked_port=LOCKED +CSET mmcm_bandwidth=OPTIMIZED +CSET mmcm_clkfbout_mult_f=4.000 +CSET mmcm_clkfbout_phase=0.000 +CSET mmcm_clkfbout_use_fine_ps=false +CSET mmcm_clkin1_period=10.000 +CSET mmcm_clkin2_period=10.000 +CSET mmcm_clkout0_divide_f=4.000 +CSET mmcm_clkout0_duty_cycle=0.500 +CSET mmcm_clkout0_phase=0.000 +CSET mmcm_clkout0_use_fine_ps=false +CSET mmcm_clkout1_divide=1 +CSET mmcm_clkout1_duty_cycle=0.500 +CSET mmcm_clkout1_phase=0.000 +CSET mmcm_clkout1_use_fine_ps=false +CSET mmcm_clkout2_divide=1 +CSET mmcm_clkout2_duty_cycle=0.500 +CSET mmcm_clkout2_phase=0.000 +CSET mmcm_clkout2_use_fine_ps=false +CSET mmcm_clkout3_divide=1 +CSET mmcm_clkout3_duty_cycle=0.500 +CSET mmcm_clkout3_phase=0.000 +CSET mmcm_clkout3_use_fine_ps=false +CSET mmcm_clkout4_cascade=false +CSET mmcm_clkout4_divide=1 +CSET mmcm_clkout4_duty_cycle=0.500 +CSET mmcm_clkout4_phase=0.000 +CSET mmcm_clkout4_use_fine_ps=false +CSET mmcm_clkout5_divide=1 +CSET mmcm_clkout5_duty_cycle=0.500 +CSET mmcm_clkout5_phase=0.000 +CSET mmcm_clkout5_use_fine_ps=false +CSET mmcm_clkout6_divide=1 +CSET mmcm_clkout6_duty_cycle=0.500 +CSET mmcm_clkout6_phase=0.000 +CSET mmcm_clkout6_use_fine_ps=false +CSET mmcm_clock_hold=false +CSET mmcm_compensation=ZHOLD +CSET mmcm_divclk_divide=1 +CSET mmcm_notes=None +CSET mmcm_ref_jitter1=0.010 +CSET mmcm_ref_jitter2=0.010 +CSET mmcm_startup_wait=false +CSET num_out_clks=1 +CSET override_dcm=false +CSET override_dcm_clkgen=false +CSET override_mmcm=false +CSET override_pll=false +CSET platform=lin64 +CSET pll_bandwidth=OPTIMIZED +CSET pll_clk_feedback=CLKFBOUT +CSET pll_clkfbout_mult=49 +CSET pll_clkfbout_phase=0.000 +CSET pll_clkin_period=9.803 +CSET pll_clkout0_divide=5 +CSET pll_clkout0_duty_cycle=0.500 +CSET pll_clkout0_phase=0.000 +CSET pll_clkout1_divide=1 +CSET pll_clkout1_duty_cycle=0.500 +CSET pll_clkout1_phase=0.000 +CSET pll_clkout2_divide=1 +CSET pll_clkout2_duty_cycle=0.500 +CSET pll_clkout2_phase=0.000 +CSET pll_clkout3_divide=1 +CSET pll_clkout3_duty_cycle=0.500 +CSET pll_clkout3_phase=0.000 +CSET pll_clkout4_divide=1 +CSET pll_clkout4_duty_cycle=0.500 +CSET pll_clkout4_phase=0.000 +CSET pll_clkout5_divide=1 +CSET pll_clkout5_duty_cycle=0.500 +CSET pll_clkout5_phase=0.000 +CSET pll_compensation=SYSTEM_SYNCHRONOUS +CSET pll_divclk_divide=5 +CSET pll_notes=None +CSET pll_ref_jitter=0.010 +CSET power_down_port=POWER_DOWN +CSET prim_in_freq=16 +CSET prim_in_jitter=0.010 +CSET prim_source=No_buffer +CSET primary_port=CLK_IN1 +CSET primitive=MMCM +CSET primtype_sel=PLL_BASE +CSET psclk_port=PSCLK +CSET psdone_port=PSDONE +CSET psen_port=PSEN +CSET psincdec_port=PSINCDEC +CSET relative_inclk=REL_PRIMARY +CSET reset_port=RESET +CSET secondary_in_freq=100.000 +CSET secondary_in_jitter=0.010 +CSET secondary_port=CLK_IN2 +CSET secondary_source=Single_ended_clock_capable_pin +CSET ss_mod_freq=250 +CSET ss_mode=CENTER_HIGH +CSET status_port=STATUS +CSET summary_strings=empty +CSET use_clk_valid=false +CSET use_clkfb_stopped=false +CSET use_dyn_phase_shift=false +CSET use_dyn_reconfig=false +CSET use_freeze=false +CSET use_freq_synth=true +CSET use_inclk_stopped=false +CSET use_inclk_switchover=false +CSET use_locked=true +CSET use_max_i_jitter=false +CSET use_min_o_jitter=false +CSET use_min_power=false +CSET use_phase_alignment=true +CSET use_power_down=false +CSET use_reset=true +CSET use_spread_spectrum=false +CSET use_spread_spectrum_1=false +CSET use_status=false +# END Parameters +# BEGIN Extra information +MISC pkg_timestamp=2012-05-10T12:44:55Z +# END Extra information +GENERATE +# CRC: fd8e1b4c diff --git a/FPGA/VNA/ipcore_dir/DFT_CLK.xise b/FPGA/VNA/ipcore_dir/DFT_CLK.xise new file mode 100644 index 0000000..a96bc91 --- /dev/null +++ b/FPGA/VNA/ipcore_dir/DFT_CLK.xise @@ -0,0 +1,403 @@ + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/FPGA/VNA/ipcore_dir/result_bram.xise b/FPGA/VNA/ipcore_dir/result_bram.xise index 0abc844..dc81dae 100644 --- a/FPGA/VNA/ipcore_dir/result_bram.xise +++ b/FPGA/VNA/ipcore_dir/result_bram.xise @@ -17,11 +17,11 @@ - + - + @@ -29,357 +29,28 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - diff --git a/FPGA/VNA/top.bin b/FPGA/VNA/top.bin index 1a6d8e3..e01a468 100644 Binary files a/FPGA/VNA/top.bin and b/FPGA/VNA/top.bin differ diff --git a/FPGA/VNA/top.ucf b/FPGA/VNA/top.ucf index ab7be65..c1c05c8 100644 --- a/FPGA/VNA/top.ucf +++ b/FPGA/VNA/top.ucf @@ -62,6 +62,20 @@ NET "PORT1_SCLK" SLEW = FAST; NET "PORT2_SCLK" SLEW = FAST; NET "REF_SCLK" SLEW = FAST; +NET "P1_PGA_CS" IOSTANDARD = LVCMOS33; +NET "P1_PGA_SCLK" IOSTANDARD = LVCMOS33; +NET "P1_PGA_DIN" IOSTANDARD = LVCMOS33; +NET "P2_PGA_CS" IOSTANDARD = LVCMOS33; +NET "P2_PGA_SCLK" IOSTANDARD = LVCMOS33; +NET "P2_PGA_DIN" IOSTANDARD = LVCMOS33; + +NET "P1_PGA_CS" LOC = P134; +NET "P1_PGA_SCLK" LOC = P133; +NET "P1_PGA_DIN" LOC = P132; +NET "P2_PGA_CS" LOC = P131; +NET "P2_PGA_SCLK" LOC = P127; +NET "P2_PGA_DIN" LOC = P126; + NET "ATTENUATION[6]" LOC = P9; NET "ATTENUATION[5]" LOC = P10; NET "ATTENUATION[4]" LOC = P11; diff --git a/FPGA/VNA/top.vhd b/FPGA/VNA/top.vhd index 391a933..a574664 100644 --- a/FPGA/VNA/top.vhd +++ b/FPGA/VNA/top.vhd @@ -81,7 +81,13 @@ entity top is SOURCE_CE : out STD_LOGIC; REF_CONVSTART : out STD_LOGIC; REF_SDO : in STD_LOGIC; - REF_SCLK : out STD_LOGIC); + REF_SCLK : out STD_LOGIC; + P1_PGA_CS : out STD_LOGIC; + P1_PGA_SCLK : out STD_LOGIC; + P1_PGA_DIN : out STD_LOGIC; + P2_PGA_CS : out STD_LOGIC; + P2_PGA_SCLK : out STD_LOGIC; + P2_PGA_DIN : out STD_LOGIC); end top; architecture Behavioral of top is @@ -164,7 +170,10 @@ architecture Behavioral of top is END COMPONENT; COMPONENT Sampling - Generic(CLK_CYCLES_PRE_DONE : integer); + Generic(CLK_CYCLES_PRE_DONE : integer; + AUTOGAIN_SAMPLES : integer; + AUTOGAIN_MAX : integer; + AUTOGAIN_MIN : integer); PORT( CLK : IN std_logic; RESET : IN std_logic; @@ -179,13 +188,20 @@ architecture Behavioral of top is ADC_START : OUT std_logic; DONE : OUT std_logic; PRE_DONE : OUT std_logic; + USEDGAIN : out STD_LOGIC_VECTOR (15 downto 0); PORT1_I : OUT std_logic_vector(47 downto 0); PORT1_Q : OUT std_logic_vector(47 downto 0); PORT2_I : OUT std_logic_vector(47 downto 0); PORT2_Q : OUT std_logic_vector(47 downto 0); REF_I : OUT std_logic_vector(47 downto 0); REF_Q : OUT std_logic_vector(47 downto 0); - ACTIVE : OUT std_logic + ACTIVE : OUT std_logic; + PORT1_GAIN : out STD_LOGIC_VECTOR (3 downto 0); + PORT1_GAIN_READY : in STD_LOGIC; + PORT1_AUTOGAIN : in STD_LOGIC; + PORT2_GAIN : out STD_LOGIC_VECTOR (3 downto 0); + PORT2_GAIN_READY : in STD_LOGIC; + PORT2_AUTOGAIN : in STD_LOGIC ); END COMPONENT; COMPONENT MCP33131 @@ -205,6 +221,18 @@ architecture Behavioral of top is SCLK : OUT std_logic ); END COMPONENT; + COMPONENT MAX9939 + Generic(CLK_DIV : integer); + PORT( + CLK : IN std_logic; + RESET : IN std_logic; + GAIN : IN std_logic_vector(3 downto 0); + READY : OUT std_logic; + CS : OUT std_logic; + SCLK : OUT std_logic; + DIN : OUT std_logic + ); + END COMPONENT; COMPONENT MAX2871 Generic (CLK_DIV : integer); PORT( @@ -229,7 +257,7 @@ architecture Behavioral of top is MOSI : IN std_logic; NSS : IN std_logic; NEW_SAMPLING_DATA : IN std_logic; - SAMPLING_RESULT : IN std_logic_vector(303 downto 0); + SAMPLING_RESULT : IN std_logic_vector(319 downto 0); ADC_MINMAX : in STD_LOGIC_VECTOR(95 downto 0); SOURCE_UNLOCKED : IN std_logic; LO_UNLOCKED : IN std_logic; @@ -268,6 +296,10 @@ architecture Behavioral of top is DFT_OUTPUT : in STD_LOGIC_VECTOR (191 downto 0); DFT_NEXT_OUTPUT : out STD_LOGIC; DFT_ENABLE : out STD_LOGIC; + PORT1_GAIN : out STD_LOGIC_VECTOR(3 downto 0); + PORT2_GAIN : out STD_LOGIC_VECTOR(3 downto 0); + PORT1_AUTOGAIN : out STD_LOGIC; + PORT2_AUTOGAIN : out STD_LOGIC; DEBUG_STATUS : in STD_LOGIC_VECTOR (10 downto 0) ); END COMPONENT; @@ -353,7 +385,7 @@ architecture Behavioral of top is signal sampling_start : std_logic; signal sampling_samples : std_logic_vector(12 downto 0); signal sampling_user_samples : std_logic_vector(12 downto 0); - signal sampling_result : std_logic_vector(303 downto 0); + signal sampling_result : std_logic_vector(319 downto 0); signal sampling_window : std_logic_vector(1 downto 0); signal sampling_prescaler : std_logic_vector(7 downto 0); signal sampling_phaseinc : std_logic_vector(11 downto 0); @@ -419,6 +451,18 @@ architecture Behavioral of top is signal dft_next_output : std_logic; signal dft_enable : std_logic; signal dft_reset : std_logic; + + -- autogain signals + signal p1_autogain_enable : std_logic; + signal p2_autogain_enable : std_logic; + signal p1_gain_ready : std_logic; + signal p2_gain_ready : std_logic; + signal p1_gain_auto : std_logic_vector (3 downto 0); + signal p2_gain_auto : std_logic_vector (3 downto 0); + signal p1_gain_manual : std_logic_vector (3 downto 0); + signal p2_gain_manual : std_logic_vector (3 downto 0); + signal p1_gain : std_logic_vector (3 downto 0); + signal p2_gain : std_logic_vector (3 downto 0); begin -- Reference CLK LED @@ -562,6 +606,17 @@ begin CONVSTART => PORT1_CONVSTART, SCLK => PORT1_SCLK ); + Port1PGA: MAX9939 + GENERIC MAP(CLK_DIV => 21) + PORT MAP( + CLK => clk160, + RESET => int_reset, + GAIN => p1_gain, + READY => p1_gain_ready, + CS => P1_PGA_CS, + SCLK => P1_PGA_SCLK, + DIN => P1_PGA_DIN + ); Port2ADC: MCP33131 GENERIC MAP(CLK_DIV => 2, CONVCYCLES => 77) @@ -578,6 +633,17 @@ begin CONVSTART => PORT2_CONVSTART, SCLK => PORT2_SCLK ); + Port2PGA: MAX9939 + GENERIC MAP(CLK_DIV => 21) + PORT MAP( + CLK => clk160, + RESET => int_reset, + GAIN => p2_gain, + READY => p2_gain_ready, + CS => P2_PGA_CS, + SCLK => P2_PGA_SCLK, + DIN => P2_PGA_DIN + ); RefADC: MCP33131 GENERIC MAP(CLK_DIV => 2, CONVCYCLES => 77) @@ -612,7 +678,10 @@ begin ); Sampler: Sampling - GENERIC MAP(CLK_CYCLES_PRE_DONE => 0) + GENERIC MAP(CLK_CYCLES_PRE_DONE => 0, + AUTOGAIN_SAMPLES => 16, + AUTOGAIN_MIN => 7000, + AUTOGAIN_MAX => 140000) PORT MAP( CLK => clk160, RESET => sweep_reset, @@ -625,6 +694,7 @@ begin NEW_SAMPLE => windowing_ready, DONE => sampling_done, PRE_DONE => open, + USEDGAIN => sampling_result(319 downto 304), START => sampling_start, SAMPLES => sampling_samples, PORT1_I => sampling_result(287 downto 240), @@ -633,10 +703,20 @@ begin PORT2_Q => sampling_result(143 downto 96), REF_I => sampling_result(95 downto 48), REF_Q => sampling_result(47 downto 0), - ACTIVE => sampling_busy + ACTIVE => sampling_busy, + PORT1_GAIN => p1_gain_auto, + PORT1_GAIN_READY => p1_gain_ready, + PORT1_AUTOGAIN => p1_autogain_enable, + PORT2_GAIN => p2_gain_auto, + PORT2_GAIN_READY => p2_gain_ready, + PORT2_AUTOGAIN => p2_autogain_enable ); sweep_reset <= not aux3_sync; + + -- gain selection + p1_gain <= p1_gain_auto when p1_autogain_enable = '1' else p1_gain_manual; + p2_gain <= p2_gain_auto when p2_autogain_enable = '1' else p2_gain_manual; SweepModule: Sweep PORT MAP( CLK => clk160, @@ -748,6 +828,10 @@ begin DFT_OUTPUT => dft_output, DFT_NEXT_OUTPUT => dft_next_output, DFT_ENABLE => dft_enable, + PORT1_GAIN => p1_gain_manual, + PORT2_GAIN => p2_gain_manual, + PORT1_AUTOGAIN => p1_autogain_enable, + PORT2_AUTOGAIN => p2_autogain_enable, DEBUG_STATUS => debug );