diff --git a/Documentation/DeveloperInfo/FPGA_protocol.pdf b/Documentation/DeveloperInfo/FPGA_protocol.pdf
index e93a2bc..0e4cacd 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 10b061a..9660519 100644
--- a/Documentation/DeveloperInfo/FPGA_protocol.tex
+++ b/Documentation/DeveloperInfo/FPGA_protocol.tex
@@ -448,30 +448,6 @@ In addition to the single bin DFT configured through the ADC prescaler and phase
The DFT has a fixed number of bins (64), but the frequencies these bins correspond to can be changed.
-\subsubsection{Number of samples: 0x10}
-\label{reg:dft-nsamples}
-\begin{center}
-\begin{tikzpicture}
-\bitrect{16}{16-\bit}
-\rwbits{0}{16}{DFT\_SAMPLES[15:0]}
-\end{tikzpicture}
-\end{center}
-\begin{itemize}
-\item \textbf{DFT\_SAMPLES[15:0]:} Amount of samples the DFT should take. This should always match the number of samples configured with the Samples Per Point register (see~\ref{reg:spp}).
-\end{itemize}
-
-\subsubsection{Window increment: 0x11}
-\begin{center}
-\begin{tikzpicture}
-\bitrect{16}{16-\bit}
-\rwbits{0}{16}{DFT\_WINDOW\_INC[15:0]}
-\end{tikzpicture}
-\end{center}
-\begin{itemize}
-\item \textbf{DFT\_WINDOW\_INC[15:0]:} Window increment value after each sample. This should always be set in such a way, that the window is iterated over exactly once after all samples configured with DFT\_SAMPLES (see \ref{reg:dft-nsamples}) have been taken.
-$$ TODO: formula $$
-\end{itemize}
-
\subsubsection{DFT\_FIRST\_BIN: 0x12}
\begin{center}
\begin{tikzpicture}
diff --git a/FPGA/VNA/DFT.vhd b/FPGA/VNA/DFT.vhd
index 46a5666..9a90d40 100644
--- a/FPGA/VNA/DFT.vhd
+++ b/FPGA/VNA/DFT.vhd
@@ -36,11 +36,9 @@ entity DFT is
PORT1 : in STD_LOGIC_VECTOR (15 downto 0);
PORT2 : in STD_LOGIC_VECTOR (15 downto 0);
NEW_SAMPLE : in STD_LOGIC;
- NSAMPLES : in STD_LOGIC_VECTOR (15 downto 0);
+ NSAMPLES : in STD_LOGIC_VECTOR (12 downto 0);
BIN1_PHASEINC : in STD_LOGIC_VECTOR (15 downto 0);
DIFFBIN_PHASEINC : in STD_LOGIC_VECTOR (15 downto 0);
- WINDOW_INC : in STD_LOGIC_VECTOR (15 downto 0);
- WINDOW_TYPE : in STD_LOGIC_VECTOR (1 downto 0);
RESULT_READY : out STD_LOGIC;
OUTPUT : out STD_LOGIC_VECTOR (191 downto 0);
NEXT_OUTPUT : in STD_LOGIC);
@@ -85,6 +83,17 @@ COMPONENT SinCosMult
p : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
);
END COMPONENT;
+COMPONENT DSP_SLICE
+ PORT (
+ clk : IN STD_LOGIC;
+ ce : IN STD_LOGIC;
+ sel : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
+ a : IN STD_LOGIC_VECTOR(17 DOWNTO 0);
+ b : IN STD_LOGIC_VECTOR(17 DOWNTO 0);
+ c : IN STD_LOGIC_VECTOR(47 DOWNTO 0);
+ p : OUT STD_LOGIC_VECTOR(47 DOWNTO 0)
+ );
+END COMPONENT;
COMPONENT window
PORT(
CLK : IN std_logic;
@@ -105,7 +114,8 @@ END COMPONENT;
--signal port2_real_read : std_logic_vector(47 downto 0);
--signal port2_imag_read : std_logic_vector(47 downto 0);
- signal sample_cnt : integer range 0 to 65535;
+ signal sample_cnt : integer range 0 to 131072;
+ signal samples_to_take : integer range 0 to 131072;
signal bin_cnt : integer range 0 to BINS+2;
signal read_address : integer range 0 to BINS-1;
@@ -116,35 +126,38 @@ END COMPONENT;
signal ram_in : std_logic_vector(191 downto 0);
signal ram_out : std_logic_vector(191 downto 0);
- type States is (WaitingForSample, WaitMult, WaitMult2, PhaseReady, WindowingReady, WaitSinCos, Busy, Ready);
+ type States is (WaitingForSample, WaitMult, WaitSinCos, Busy, Ready);
signal state : States;
signal port1_latch : std_logic_vector(15 downto 0);
signal port2_latch : std_logic_vector(15 downto 0);
- signal window_index : std_logic_vector(15 downto 0);
-
- signal window_value : std_logic_vector(15 downto 0);
-
signal phase : std_logic_vector(31 downto 0);
signal phase_inc : std_logic_vector(31 downto 0);
signal sine : std_logic_vector(15 downto 0);
signal cosine : std_logic_vector(15 downto 0);
- signal mult1_a : std_logic_vector(15 downto 0);
- signal mult1_b : std_logic_vector(15 downto 0);
- signal mult1_p : std_logic_vector(31 downto 0);
+ signal mult1_a : std_logic_vector(17 downto 0);
+ signal mult1_b : std_logic_vector(17 downto 0);
+ signal mult1_c : std_logic_vector(47 downto 0);
+ signal mult1_p : std_logic_vector(47 downto 0);
- signal mult2_a : std_logic_vector(15 downto 0);
- signal mult2_b : std_logic_vector(15 downto 0);
- signal mult2_p : std_logic_vector(31 downto 0);
+ signal mult2_a : std_logic_vector(17 downto 0);
+ signal mult2_b : std_logic_vector(17 downto 0);
+ signal mult2_c : std_logic_vector(47 downto 0);
+ signal mult2_p : std_logic_vector(47 downto 0);
- signal mult3_a : std_logic_vector(15 downto 0);
- signal mult3_b : std_logic_vector(15 downto 0);
- signal mult3_p : std_logic_vector(31 downto 0);
+ signal mult3_a : std_logic_vector(17 downto 0);
+ signal mult3_b : std_logic_vector(17 downto 0);
+ signal mult3_c : std_logic_vector(47 downto 0);
+ signal mult3_p : std_logic_vector(47 downto 0);
- signal mult4_a : std_logic_vector(15 downto 0);
- signal mult4_b : std_logic_vector(15 downto 0);
- signal mult4_p : std_logic_vector(31 downto 0);
+ signal mult4_a : std_logic_vector(17 downto 0);
+ signal mult4_b : std_logic_vector(17 downto 0);
+ signal mult4_c : std_logic_vector(47 downto 0);
+ signal mult4_p : std_logic_vector(47 downto 0);
+
+ signal mult_enable : std_logic;
+ signal mult_accumulate : std_logic_vector(0 downto 0);
begin
LookupTable : SinCos
@@ -154,72 +167,75 @@ begin
cosine => cosine,
sine => sine
);
- Mult1 : SinCosMult
+ Mult1 : DSP_SLICE
PORT MAP (
clk => CLK,
+ ce => mult_enable,
+ sel => mult_accumulate,
a => mult1_a,
b => mult1_b,
+ c => mult1_c,
p => mult1_p
);
- Mult2 : SinCosMult
+ Mult2 : DSP_SLICE
PORT MAP (
clk => CLK,
+ ce => mult_enable,
+ sel => mult_accumulate,
a => mult2_a,
b => mult2_b,
+ c => mult2_c,
p => mult2_p
);
- Mult3 : SinCosMult
+ Mult3 : DSP_SLICE
PORT MAP (
clk => CLK,
+ ce => mult_enable,
+ sel => mult_accumulate,
a => mult3_a,
b => mult3_b,
+ c => mult3_c,
p => mult3_p
);
- Mult4 : SinCosMult
+ Mult4 : DSP_SLICE
PORT MAP (
clk => CLK,
+ ce => mult_enable,
+ sel => mult_accumulate,
a => mult4_a,
b => mult4_b,
+ c => mult4_c,
p => mult4_p
);
- WindowROM: window PORT MAP(
- CLK => CLK,
- INDEX => window_index(15 downto 9),
- WINDOW_TYPE => WINDOW_TYPE,
- VALUE => window_value
- );
--- result_ram: dft_result
--- GENERIC MAP(depth => BINS)
--- PORT MAP(
--- CLK => CLK,
--- READ_ADDRESS => read_address,
--- WRITE_ADDRESS => write_address,
--- DATA_IN => ram_in,
--- DATA_OUT => ram_out,
--- WE => we
--- );
-
-your_instance_name : result_bram
- PORT MAP (
- clka => CLK,
- wea => we,
- addra => write_address_vector,
- dina => ram_in,
- clkb => CLK,
- addrb => read_address_vector,
- doutb => ram_out
- );
+ result_ram: result_bram
+ PORT MAP (
+ clka => CLK,
+ wea => we,
+ addra => write_address_vector,
+ dina => ram_in,
+ clkb => CLK,
+ addrb => read_address_vector,
+ doutb => ram_out
+ );
read_address_vector <= std_logic_vector(to_unsigned(read_address, 6));
write_address_vector <= std_logic_vector(to_unsigned(write_address, 6));
OUTPUT <= ram_out;
+ mult1_c <= ram_out(191 downto 144);
+ mult2_c <= ram_out(143 downto 96);
+ mult3_c <= ram_out(95 downto 48);
+ mult4_c <= ram_out(47 downto 0);
+
+ ram_in <= mult1_p & mult2_p & mult3_p & mult4_p;
+
process(CLK, RESET)
begin
if rising_edge(CLK) then
if RESET = '1' then
- window_index <= (others => '0');
+ mult_enable <= '0';
+ mult_accumulate <= "0";
sample_cnt <= 0;
RESULT_READY <= '0';
read_address <= 0;
@@ -227,108 +243,124 @@ your_instance_name : result_bram
we <= "0";
state <= WaitingForSample;
else
+ samples_to_take <= to_integer(unsigned(NSAMPLES & "0000")) - 1;
case state is
when WaitingForSample =>
we <= "0";
+ mult_enable <= '0';
+ mult_accumulate <= "0";
+ read_address <= 0;
+ write_address <= 0;
if NEW_SAMPLE = '1' then
-- calculate phase for initial bin
- -- TODO this should use unsigned multiplication
- mult1_a <= std_logic_vector(to_unsigned(sample_cnt, 16));
- mult1_b <= BIN1_PHASEINC;
- mult2_a <= std_logic_vector(to_unsigned(sample_cnt, 16));
- mult2_b <= DIFFBIN_PHASEINC;
- -- window ADC data
- mult3_a <= PORT1;
- mult3_b <= window_value;
- mult4_a <= PORT2;
- mult4_b <= window_value;
+ mult1_a <= std_logic_vector(to_unsigned(sample_cnt, 18));
+ mult1_b <= "00" & BIN1_PHASEINC;
+ mult2_a <= std_logic_vector(to_unsigned(sample_cnt, 18));
+ mult2_b <= "00" & DIFFBIN_PHASEINC;
state <= WaitMult;
- read_address <= 0;
+ bin_cnt <= 0;
+ mult_enable <= '1';
end if;
when WaitMult =>
RESULT_READY <= '0';
we <= "0";
- state <= WaitMult2;
- when WaitMult2 =>
- RESULT_READY <= '0';
- we <= "0";
- state <= PhaseReady;
- when PhaseReady =>
- RESULT_READY <= '0';
- we <= "0";
- -- initial phase is ready
- phase <= mult1_p(15 downto 0) & "0000000000000000";
- phase_inc <= mult2_p(23 downto 0) & "00000000";
- state <= WindowingReady;
- when WindowingReady =>
- RESULT_READY <= '0';
- we <= "0";
- phase <= std_logic_vector(unsigned(phase)+unsigned(phase_inc));
- port1_latch <= mult3_p(31 downto 16);
- port2_latch <= mult4_p(31 downto 16);
- bin_cnt <= 0;
- state <= WaitSinCos;
- when WaitSinCos =>
- phase <= std_logic_vector(unsigned(phase)+unsigned(phase_inc));
- RESULT_READY <= '0';
- we <= "0";
+ mult_enable <= '1';
+ mult_accumulate <= "0";
+ read_address <= 0;
+ write_address <= 0;
if bin_cnt < 4 then
bin_cnt <= bin_cnt + 1;
else
bin_cnt <= 0;
+ mult_enable <= '0';
+ state <= WaitSinCos;
+ phase <= mult1_p(15 downto 0) & "0000000000000000";
+ phase_inc <= mult2_p(23 downto 0) & "00000000";
+ port1_latch <= PORT1;
+ port2_latch <= PORT2;
+ end if;
+ when WaitSinCos =>
+ phase <= std_logic_vector(unsigned(phase)+unsigned(phase_inc));
+ RESULT_READY <= '0';
+ we <= "0";
+ mult_enable <= '0';
+ mult_accumulate <= "0";
+ read_address <= 0;
+ write_address <= 0;
+ if bin_cnt < 6 then
+ bin_cnt <= bin_cnt + 1;
+ else
+ bin_cnt <= 0;
+ mult_enable <= '1';
+ read_address <= 1;
+ -- sign extended multiplication
+ mult1_a <= port1_latch(15) & port1_latch(15) & port1_latch;
+ mult1_b <= sine(15) & sine(15) & sine;
+ mult2_a <= port1_latch(15) & port1_latch(15) & port1_latch;
+ mult2_b <= cosine(15) & cosine(15) & cosine;
+ mult3_a <= port2_latch(15) & port2_latch(15) & port2_latch;
+ mult3_b <= sine(15) & sine(15) & sine;
+ mult4_a <= port2_latch(15) & port2_latch(15) & port2_latch;
+ mult4_b <= cosine(15) & cosine(15) & cosine;
state <= BUSY;
+ if sample_cnt = 0 then
+ mult_accumulate <= "0";
+ else
+ mult_accumulate <= "1";
+ end if;
end if;
when BUSY =>
+ mult_enable <= '1';
+ if sample_cnt = 0 then
+ mult_accumulate <= "0";
+ else
+ mult_accumulate <= "1";
+ end if;
RESULT_READY <= '0';
phase <= std_logic_vector(unsigned(phase)+unsigned(phase_inc));
- mult1_a <= port1_latch;
- mult1_b <= sine;
- mult2_a <= port1_latch;
- mult2_b <= cosine;
- mult3_a <= port2_latch;
- mult3_b <= sine;
- mult4_a <= port2_latch;
- mult4_b <= cosine;
+ -- sign extended multiplication
+ mult1_a <= port1_latch(15) & port1_latch(15) & port1_latch;
+ mult1_b <= sine(15) & sine(15) & sine;
+ mult2_a <= port1_latch(15) & port1_latch(15) & port1_latch;
+ mult2_b <= cosine(15) & cosine(15) & cosine;
+ mult3_a <= port2_latch(15) & port2_latch(15) & port2_latch;
+ mult3_b <= sine(15) & sine(15) & sine;
+ mult4_a <= port2_latch(15) & port2_latch(15) & port2_latch;
+ mult4_b <= cosine(15) & cosine(15) & cosine;
if bin_cnt >= 3 then
- -- multiplier result is available, accumulate
+ -- multiplier result is available, advance write address
we <= "1";
write_address <= bin_cnt - 3;
- ram_in <= std_logic_vector(signed(ram_out(191 downto 144))+signed(mult1_p))
- & std_logic_vector(signed(ram_out(143 downto 96))+signed(mult2_p))
- & std_logic_vector(signed(ram_out(95 downto 48))+signed(mult3_p))
- & std_logic_vector(signed(ram_out(47 downto 0))+signed(mult4_p));
else
we <= "0";
+ write_address <= 0;
end if;
if bin_cnt >= BINS+2 then
read_address <= 0;
- if sample_cnt < unsigned(NSAMPLES) then
+ if sample_cnt < samples_to_take then
sample_cnt <= sample_cnt + 1;
state <= WaitingForSample;
- window_index <= std_logic_vector(unsigned(window_index)+unsigned(WINDOW_INC));
else
state <= Ready;
end if;
else
bin_cnt <= bin_cnt + 1;
- if bin_cnt >= 1 then
- read_address <= bin_cnt - 1;
+ if bin_cnt < BINS - 2 then
+ read_address <= bin_cnt + 2;
end if;
end if;
when Ready =>
we <= "0";
RESULT_READY <= '1';
+ write_address <= 0;
if NEXT_OUTPUT = '1' then
- -- reset last entry to prepare for next DFT
- write_address <= read_address;
- ram_in <= (others => '0');
- we <= "1";
-- fetch next entry from RAM
if read_address < BINS - 1 then
read_address <= read_address + 1;
else
RESULT_READY <= '0';
sample_cnt <= 0;
+ mult_enable <= '0';
state <= WaitingForSample;
read_address <= 0;
end if;
diff --git a/FPGA/VNA/ResetDelay.vhd b/FPGA/VNA/ResetDelay.vhd
index 6ef1028..bb8c1d0 100644
--- a/FPGA/VNA/ResetDelay.vhd
+++ b/FPGA/VNA/ResetDelay.vhd
@@ -40,16 +40,17 @@ architecture Behavioral of ResetDelay is
signal clk_cnt : integer range 0 to CLK_DELAY-1;
begin
- OUT_RESET <= '1' when IN_RESET = '1' or clk_cnt < CLK_DELAY-1 else '0';
-
process(CLK, IN_RESET)
begin
if rising_edge(CLK) then
if IN_RESET = '1' then
clk_cnt <= 0;
+ OUT_RESET <= '1';
else
if clk_cnt < CLK_DELAY-1 then
clk_cnt <= clk_cnt + 1;
+ else
+ OUT_RESET <= '0';
end if;
end if;
end if;
diff --git a/FPGA/VNA/SPIConfig.vhd b/FPGA/VNA/SPIConfig.vhd
index 183eeff..62307c6 100644
--- a/FPGA/VNA/SPIConfig.vhd
+++ b/FPGA/VNA/SPIConfig.vhd
@@ -71,10 +71,8 @@ entity SPICommands is
SWEEP_RESUME : out STD_LOGIC;
-- DFT signals
- DFT_NSAMPLES : out STD_LOGIC_VECTOR (15 downto 0);
DFT_BIN1_PHASEINC : out STD_LOGIC_VECTOR (15 downto 0);
DFT_DIFFBIN_PHASEINC : out STD_LOGIC_VECTOR (15 downto 0);
- DFT_WINDOW_INC : out STD_LOGIC_VECTOR (15 downto 0);
DFT_RESULT_READY : in STD_LOGIC;
DFT_OUTPUT : in STD_LOGIC_VECTOR (191 downto 0);
DFT_NEXT_OUTPUT : out STD_LOGIC;
@@ -103,7 +101,7 @@ architecture Behavioral of SPICommands is
signal spi_buf_in : std_logic_vector(15 downto 0);
signal spi_complete : std_logic;
signal word_cnt : integer range 0 to 19;
- type SPI_states is (Invalid, WriteSweepConfig, ReadResult, WriteRegister, ReadTest);
+ type SPI_states is (FirstWord, WriteSweepConfig, ReadResult, WriteRegister);
signal state : SPI_states;
signal selected_register : integer range 0 to 31;
@@ -166,11 +164,10 @@ begin
ADC_PHASEINC <= std_logic_vector(to_unsigned(1120, 12));
RESET_MINMAX <= '0';
INTERRUPT_ASSERTED <= '0';
+ latched_result <= (others => '0');
- DFT_NSAMPLES <= (others => '0');
DFT_BIN1_PHASEINC <= (others => '0');
DFT_DIFFBIN_PHASEINC <= (others => '0');
- DFT_WINDOW_INC <= (others => '0');
dft_next <= '0';
last_NSS <= '1';
else
@@ -198,19 +195,21 @@ begin
if NSS = '0' and last_NSS = '1' then
word_cnt <= 0;
spi_buf_in <= interrupt_status;
+ state <= FirstWord;
elsif spi_complete = '1' then
word_cnt <= word_cnt + 1;
- if word_cnt = 0 then
+ case state is
+ when FirstWord =>
-- initial word determines action
case spi_buf_out(15 downto 13) is
when "000" => state <= WriteSweepConfig;
-- also extract the point number
SWEEP_ADDRESS <= spi_buf_out(12 downto 0);
- when "001" => state <= Invalid;
+ when "001" => state <= FirstWord;
SWEEP_RESUME <= '1';
- when "010" => state <= ReadTest;
+ when "010" => state <= FirstWord;
spi_buf_in <= "1111000010100101";
- when "011" => state <= Invalid;
+ when "011" => state <= FirstWord;
RESET_MINMAX <= '1';
when "100" => state <= WriteRegister;
selected_register <= to_integer(unsigned(spi_buf_out(4 downto 0)));
@@ -225,60 +224,56 @@ begin
when "111" => state <= ReadResult; -- can use same state as read result, but the latched data will contain the min/max ADC values
latched_result(79 downto 0) <= ADC_MINMAX(95 downto 16);
spi_buf_in <= ADC_MINMAX(15 downto 0);
- when others => state <= Invalid;
+ when others => state <= FirstWord;
end case;
- else
- if state = WriteRegister then
- -- write received data into previously selected register
- case selected_register is
- when 0 => interrupt_mask <= spi_buf_out;
- when 1 => SWEEP_POINTS <= spi_buf_out(12 downto 0);
- when 2 => NSAMPLES <= spi_buf_out(12 downto 0);
- when 3 => PORTSWITCH_EN <= spi_buf_out(0);
- PORT1_EN <= spi_buf_out(15);
- PORT2_EN <= spi_buf_out(14);
- REF_EN <= spi_buf_out(13);
- AMP_SHDN <= not spi_buf_out(12);
- SOURCE_RF_EN <= spi_buf_out(11);
- LO_RF_EN <= spi_buf_out(10);
- LEDS <= not spi_buf_out(9 downto 7);
- WINDOW_SETTING <= spi_buf_out(6 downto 5);
- SOURCE_CE_EN <= spi_buf_out(4);
- LO_CE_EN <= spi_buf_out(3);
- EXCITE_PORT1 <= spi_buf_out(1);
- 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 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;
- when 11 => MAX2871_DEF_1(31 downto 16) <= spi_buf_out;
- when 12 => MAX2871_DEF_3(15 downto 0) <= spi_buf_out;
- when 13 => MAX2871_DEF_3(31 downto 16) <= spi_buf_out;
- when 14 => MAX2871_DEF_4(15 downto 0) <= spi_buf_out;
- when 15 => MAX2871_DEF_4(31 downto 16) <= spi_buf_out;
- when 16 => DFT_NSAMPLES <= spi_buf_out;
- when 17 => DFT_WINDOW_INC <= spi_buf_out;
- when 18 => DFT_BIN1_PHASEINC <= spi_buf_out;
- when 19 => DFT_DIFFBIN_PHASEINC <= spi_buf_out;
- when others =>
- end case;
- selected_register <= selected_register + 1;
- elsif state = WriteSweepConfig then
- if word_cnt = 6 then
- -- Sweep config data is complete pass on
- SWEEP_DATA <= sweepconfig_buffer & spi_buf_out;
- sweep_config_write <= '1';
- else
- -- shift next word into buffer
- sweepconfig_buffer <= sweepconfig_buffer(63 downto 0) & spi_buf_out;
- end if;
- elsif state = ReadResult then
- -- pass on next word of latched result
- spi_buf_in <= latched_result(15 downto 0);
- latched_result <= "0000000000000000" & latched_result(287 downto 16);
+ when WriteRegister =>
+ -- write received data into previously selected register
+ case selected_register is
+ when 0 => interrupt_mask <= spi_buf_out;
+ when 1 => SWEEP_POINTS <= spi_buf_out(12 downto 0);
+ when 2 => NSAMPLES <= spi_buf_out(12 downto 0);
+ when 3 => PORTSWITCH_EN <= spi_buf_out(0);
+ PORT1_EN <= spi_buf_out(15);
+ PORT2_EN <= spi_buf_out(14);
+ REF_EN <= spi_buf_out(13);
+ AMP_SHDN <= not spi_buf_out(12);
+ SOURCE_RF_EN <= spi_buf_out(11);
+ LO_RF_EN <= spi_buf_out(10);
+ LEDS <= not spi_buf_out(9 downto 7);
+ WINDOW_SETTING <= spi_buf_out(6 downto 5);
+ SOURCE_CE_EN <= spi_buf_out(4);
+ LO_CE_EN <= spi_buf_out(3);
+ EXCITE_PORT1 <= spi_buf_out(1);
+ 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 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;
+ when 11 => MAX2871_DEF_1(31 downto 16) <= spi_buf_out;
+ when 12 => MAX2871_DEF_3(15 downto 0) <= spi_buf_out;
+ when 13 => MAX2871_DEF_3(31 downto 16) <= spi_buf_out;
+ when 14 => MAX2871_DEF_4(15 downto 0) <= spi_buf_out;
+ when 15 => MAX2871_DEF_4(31 downto 16) <= spi_buf_out;
+ when 18 => DFT_BIN1_PHASEINC <= spi_buf_out;
+ when 19 => DFT_DIFFBIN_PHASEINC <= spi_buf_out;
+ when others =>
+ end case;
+ selected_register <= selected_register + 1;
+ when WriteSweepConfig =>
+ if word_cnt = 6 then
+ -- Sweep config data is complete pass on
+ SWEEP_DATA <= sweepconfig_buffer & spi_buf_out;
+ sweep_config_write <= '1';
+ else
+ -- shift next word into buffer
+ sweepconfig_buffer <= sweepconfig_buffer(63 downto 0) & spi_buf_out;
end if;
- end if;
+ 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);
+ end case;
end if;
end if;
end if;
diff --git a/FPGA/VNA/Sampling.vhd b/FPGA/VNA/Sampling.vhd
index 7cc30ab..f1b2287 100644
--- a/FPGA/VNA/Sampling.vhd
+++ b/FPGA/VNA/Sampling.vhd
@@ -44,7 +44,6 @@ entity Sampling is
PRE_DONE : out STD_LOGIC;
START : in STD_LOGIC;
SAMPLES : in STD_LOGIC_VECTOR (12 downto 0);
- WINDOW_TYPE : in STD_LOGIC_VECTOR (1 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);
@@ -94,16 +93,6 @@ END COMPONENT;
signal sine : std_logic_vector(15 downto 0);
signal cosine : std_logic_vector(15 downto 0);
- signal windowed_sine : std_logic_vector(31 downto 0);
- signal windowed_cosine : std_logic_vector(31 downto 0);
-
- signal window_index : std_logic_vector(6 downto 0);
- signal window_value : std_logic_vector(15 downto 0);
- signal window_sample_cnt : integer range 0 to 8191;
- signal window_index_inc : integer range 0 to 8;
- signal window_sample_compare : integer range 0 to 8191;
- signal window_sample_cnt_inc : integer range 0 to 8;
-
signal mult1_I : std_logic_vector(31 downto 0);
signal mult1_Q : std_logic_vector(31 downto 0);
signal mult2_I : std_logic_vector(31 downto 0);
@@ -132,66 +121,45 @@ begin
PORT MAP (
clk => CLK,
a => PORT1,
- b => windowed_cosine(31 downto 16),
+ b => cosine,
p => mult1_I
);
Port1_Q_Mult : SinCosMult
PORT MAP (
clk => CLK,
a => PORT1,
- b => windowed_sine(31 downto 16),
+ b => sine,
p => mult1_Q
);
Port2_I_Mult : SinCosMult
PORT MAP (
clk => CLK,
a => PORT2,
- b => windowed_cosine(31 downto 16),
+ b => cosine,
p => mult2_I
);
Port2_Q_Mult : SinCosMult
PORT MAP (
clk => CLK,
a => PORT2,
- b => windowed_sine(31 downto 16),
+ b => sine,
p => mult2_Q
);
Ref_I_Mult : SinCosMult
PORT MAP (
clk => CLK,
a => REF,
- b => windowed_cosine(31 downto 16),
+ b => cosine,
p => multR_I
);
Ref_Q_Mult : SinCosMult
PORT MAP (
clk => CLK,
a => REF,
- b => windowed_sine(31 downto 16),
+ b => sine,
p => multR_Q
);
- Sine_Mult : SinCosMult
- PORT MAP (
- clk => CLK,
- a => window_value,
- b => sine,
- p => windowed_sine
- );
- Cosine_Mult : SinCosMult
- PORT MAP (
- clk => CLK,
- a => window_value,
- b => cosine,
- p => windowed_cosine
- );
- WindowROM: window PORT MAP(
- CLK => CLK,
- INDEX => window_index,
- WINDOW_TYPE => WINDOW_TYPE,
- VALUE => window_value
- );
-
process(CLK, RESET)
begin
if rising_edge(CLK) then
@@ -203,8 +171,6 @@ begin
ACTIVE <= '0';
clk_cnt <= 0;
sample_cnt <= 0;
- window_sample_cnt <= 0;
- window_index <= (others => '0');
phase <= (others => '0');
else
-- when not idle, generate pulses for ADCs
@@ -244,25 +210,6 @@ begin
if START = '1' then
state <= Sampling;
samples_to_take <= to_integer(unsigned(SAMPLES & "0000") - 1);
- window_sample_compare <= to_integer(unsigned(SAMPLES) - 1);
- case SAMPLES is
- when "0000000000001" =>
- -- 16 samples, increment on every sample by 8
- window_sample_cnt_inc <= 1;
- window_index_inc <= 8;
- when "0000000000010" | "0000000000011" =>
- -- 32-48 samples, increment by 4
- window_sample_cnt_inc <= 2;
- window_index_inc <= 4;
- when "0000000000100" | "0000000000101" | "0000000000110" | "0000000000111"=>
- -- 64-112 samples, increment by 2
- window_sample_cnt_inc <= 4;
- window_index_inc <= 2;
- when others =>
- -- 128 or more samples, increment by 1
- window_sample_cnt_inc <= 8;
- window_index_inc <= 1;
- end case;
end if;
when Sampling =>
DONE <= '0';
@@ -294,13 +241,6 @@ begin
else
state <= Ready;
end if;
- -- keep track of window index
- if window_sample_cnt < window_sample_compare then
- window_sample_cnt <= window_sample_cnt + window_sample_cnt_inc;
- else
- window_sample_cnt <= window_sample_cnt - window_sample_compare;
- window_index <= std_logic_vector( unsigned(window_index) + window_index_inc );
- end if;
when Ready =>
ACTIVE <= '1';
DONE <= '1';
diff --git a/FPGA/VNA/Sweep.vhd b/FPGA/VNA/Sweep.vhd
index 3e2fc3e..3c81251 100644
--- a/FPGA/VNA/Sweep.vhd
+++ b/FPGA/VNA/Sweep.vhd
@@ -82,45 +82,41 @@ architecture Behavioral of Sweep is
signal state : Point_states;
signal settling_cnt : unsigned(15 downto 0);
signal settling_time : unsigned(15 downto 0);
+ signal config_reg : std_logic_vector(95 downto 0);
begin
CONFIG_ADDRESS <= std_logic_vector(point_cnt);
-- assemble registers
-- source register 0: N divider and fractional division value
- SOURCE_REG_0 <= MAX2871_DEF_0(31) & "000000000" & CONFIG_DATA(6 downto 0) & CONFIG_DATA(27 downto 16) & "000";
+ SOURCE_REG_0 <= MAX2871_DEF_0(31) & "000000000" & config_reg(6 downto 0) & config_reg(27 downto 16) & "000";
-- source register 1: Modulus value
- SOURCE_REG_1 <= MAX2871_DEF_1(31 downto 15) & CONFIG_DATA(39 downto 28) & "001";
+ SOURCE_REG_1 <= MAX2871_DEF_1(31 downto 15) & config_reg(39 downto 28) & "001";
-- source register 3: VCO selection
- SOURCE_REG_3 <= CONFIG_DATA(12 downto 7) & MAX2871_DEF_3(25 downto 3) & "011";
+ SOURCE_REG_3 <= config_reg(12 downto 7) & MAX2871_DEF_3(25 downto 3) & "011";
-- output power A passed on from default registers, output B disabled
- SOURCE_REG_4 <= MAX2871_DEF_4(31 downto 23) & CONFIG_DATA(15 downto 13) & MAX2871_DEF_4(19 downto 9) & "000" & MAX2871_DEF_4(5 downto 3) & "100";
+ SOURCE_REG_4 <= MAX2871_DEF_4(31 downto 23) & config_reg(15 downto 13) & MAX2871_DEF_4(19 downto 9) & "000" & MAX2871_DEF_4(5 downto 3) & "100";
-- LO register 0: N divider and fractional division value
- LO_REG_0 <= MAX2871_DEF_0(31) & "000000000" & CONFIG_DATA(54 downto 48) & CONFIG_DATA(75 downto 64) & "000";
+ LO_REG_0 <= MAX2871_DEF_0(31) & "000000000" & config_reg(54 downto 48) & config_reg(75 downto 64) & "000";
-- LO register 1: Modulus value
- LO_REG_1 <= MAX2871_DEF_1(31 downto 15) & CONFIG_DATA(87 downto 76) & "001";
+ LO_REG_1 <= MAX2871_DEF_1(31 downto 15) & config_reg(87 downto 76) & "001";
-- LO register 3: VCO selection
- LO_REG_3 <= CONFIG_DATA(60 downto 55) & MAX2871_DEF_3(25 downto 3) & "011";
+ LO_REG_3 <= config_reg(60 downto 55) & MAX2871_DEF_3(25 downto 3) & "011";
-- both outputs enabled at +5dbm
- LO_REG_4 <= MAX2871_DEF_4(31 downto 23) & CONFIG_DATA(63 downto 61) & MAX2871_DEF_4(19 downto 9) & "111111100";
+ LO_REG_4 <= MAX2871_DEF_4(31 downto 23) & config_reg(63 downto 61) & MAX2871_DEF_4(19 downto 9) & "111111100";
- ATTENUATOR <= CONFIG_DATA(46 downto 40);
- SOURCE_FILTER <= CONFIG_DATA(89 downto 88);
- BAND_SELECT <= CONFIG_DATA(47);
-
- settling_time <= to_unsigned(2048, 16) when CONFIG_DATA(94 downto 93) = "00" else -- 20us
- to_unsigned(6144, 16) when CONFIG_DATA(94 downto 93) = "01" else -- 60us
- to_unsigned(18432, 16) when CONFIG_DATA(94 downto 93) = "10" else -- 180us
- to_unsigned(55296, 16); -- 540us
+ ATTENUATOR <= config_reg(46 downto 40);
+ SOURCE_FILTER <= config_reg(89 downto 88);
+ BAND_SELECT <= config_reg(47);
- NSAMPLES <= USER_NSAMPLES when CONFIG_DATA(92 downto 90) = "000" else
- std_logic_vector(to_unsigned(6, 13)) when CONFIG_DATA(92 downto 90) = "001" else
- std_logic_vector(to_unsigned(19, 13)) when CONFIG_DATA(92 downto 90) = "010" else
- std_logic_vector(to_unsigned(57, 13)) when CONFIG_DATA(92 downto 90) = "011" else
- std_logic_vector(to_unsigned(190, 13)) when CONFIG_DATA(92 downto 90) = "100" else
- std_logic_vector(to_unsigned(571, 13)) when CONFIG_DATA(92 downto 90) = "101" else
- std_logic_vector(to_unsigned(1904, 13)) when CONFIG_DATA(92 downto 90) = "110" else
+ NSAMPLES <= USER_NSAMPLES when config_reg(92 downto 90) = "000" else
+ std_logic_vector(to_unsigned(6, 13)) when config_reg(92 downto 90) = "001" else
+ std_logic_vector(to_unsigned(19, 13)) when config_reg(92 downto 90) = "010" else
+ std_logic_vector(to_unsigned(57, 13)) when config_reg(92 downto 90) = "011" else
+ std_logic_vector(to_unsigned(190, 13)) when config_reg(92 downto 90) = "100" else
+ std_logic_vector(to_unsigned(571, 13)) when config_reg(92 downto 90) = "101" else
+ std_logic_vector(to_unsigned(1904, 13)) when config_reg(92 downto 90) = "110" else
std_logic_vector(to_unsigned(5712, 13));
DEBUG_STATUS(10 downto 8) <= "000" when state = TriggerSetup else
@@ -135,7 +131,9 @@ begin
DEBUG_STATUS(6) <= PLL_RELOAD_DONE and PLL_LOCKED;
DEBUG_STATUS(5) <= SAMPLING_BUSY;
DEBUG_STATUS(4 downto 0) <= (others => '1');
-
+
+ config_reg <= CONFIG_DATA;
+
process(CLK, RESET)
begin
if rising_edge(CLK) then
@@ -154,21 +152,25 @@ begin
state <= SettingUp;
end if;
when SettingUp =>
- -- highest bit in CONFIG_DATA determines whether the sweep should be halted prior to sampling
- SWEEP_HALTED <= CONFIG_DATA(95);
+ -- highest bit in config_reg determines whether the sweep should be halted prior to sampling
+ SWEEP_HALTED <= config_reg(95);
RELOAD_PLL_REGS <= '0';
+ case config_reg(94 downto 93) is
+ when "00" => settling_time <= to_unsigned(2048, 16); -- 20us
+ when "01" => settling_time <= to_unsigned(6144, 16); -- 60us
+ when "10" => settling_time <= to_unsigned(18432, 16); -- 180us
+ when others => settling_time <= to_unsigned(55296, 16); -- 540us
+ end case;
+ settling_cnt <= settling_time;
if PLL_RELOAD_DONE = '1' and PLL_LOCKED = '1' then
-- check if halted sweep is resumed
- if CONFIG_DATA(95) = '0' or SWEEP_RESUME = '1' then
+ if config_reg(95) = '0' or SWEEP_RESUME = '1' then
SWEEP_HALTED <= '0';
if EXCITE_PORT1 = '1' then
state <= SettlingPort1;
- elsif EXCITE_PORT2 = '1' then
- state <= SettlingPort2;
else
- state <= Done;
+ state <= SettlingPort2;
end if;
- settling_cnt <= settling_time;
end if;
end if;
when SettlingPort1 =>
@@ -192,7 +194,7 @@ begin
else
state <= NextPoint;
end if;
- settling_cnt <= unsigned(SETTLING_TIME);
+ settling_cnt <= settling_time;
end if;
when SettlingPort2 =>
PORT_SELECT <= '0';
diff --git a/FPGA/VNA/Test_DFT.vhd b/FPGA/VNA/Test_DFT.vhd
index e4d7f8f..2bd28ad 100644
--- a/FPGA/VNA/Test_DFT.vhd
+++ b/FPGA/VNA/Test_DFT.vhd
@@ -47,11 +47,9 @@ ARCHITECTURE behavior OF Test_DFT IS
PORT1 : IN std_logic_vector(15 downto 0);
PORT2 : IN std_logic_vector(15 downto 0);
NEW_SAMPLE : IN std_logic;
- NSAMPLES : in STD_LOGIC_VECTOR (15 downto 0);
+ NSAMPLES : in STD_LOGIC_VECTOR (12 downto 0);
BIN1_PHASEINC : IN std_logic_vector(15 downto 0);
DIFFBIN_PHASEINC : IN std_logic_vector(15 downto 0);
- WINDOW_INC : IN std_logic_vector(15 downto 0);
- WINDOW_TYPE : IN std_logic_vector(1 downto 0);
RESULT_READY : OUT std_logic;
OUTPUT : out STD_LOGIC_VECTOR (191 downto 0);
NEXT_OUTPUT : IN std_logic
@@ -67,10 +65,8 @@ ARCHITECTURE behavior OF Test_DFT IS
signal NEW_SAMPLE : std_logic := '0';
signal BIN1_PHASEINC : std_logic_vector(15 downto 0) := (others => '0');
signal DIFFBIN_PHASEINC : std_logic_vector(15 downto 0) := (others => '0');
- signal WINDOW_INC : std_logic_vector(15 downto 0) := (others => '0');
- signal WINDOW_TYPE : std_logic_vector(1 downto 0) := (others => '0');
signal NEXT_OUTPUT : std_logic := '0';
- signal NSAMPLES : STD_LOGIC_VECTOR (15 downto 0);
+ signal NSAMPLES : STD_LOGIC_VECTOR (12 downto 0);
--Outputs
signal RESULT_READY : std_logic;
@@ -93,8 +89,6 @@ BEGIN
NSAMPLES => NSAMPLES,
BIN1_PHASEINC => BIN1_PHASEINC,
DIFFBIN_PHASEINC => DIFFBIN_PHASEINC,
- WINDOW_INC => WINDOW_INC,
- WINDOW_TYPE => WINDOW_TYPE,
RESULT_READY => RESULT_READY,
OUTPUT => OUTPUT,
NEXT_OUTPUT => NEXT_OUTPUT
@@ -119,7 +113,6 @@ BEGIN
PORT2 <= "0100000000000000";
BIN1_PHASEINC <= "0100000000000000";
DIFFBIN_PHASEINC <= "0010000000000000";
- WINDOW_INC <= "0000100000000000";
NSAMPLES <= "0000000000000011";
wait for 100 ns;
RESET <= '0';
@@ -128,7 +121,7 @@ BEGIN
wait for CLK_period;
NEW_SAMPLE <= '0';
while True loop
- wait for CLK_period * 111;
+ wait for CLK_period * 79;
NEW_SAMPLE <= '1';
wait for CLK_period;
NEW_SAMPLE <= '0';
diff --git a/FPGA/VNA/Test_Windowing.vhd b/FPGA/VNA/Test_Windowing.vhd
new file mode 100644
index 0000000..58517e4
--- /dev/null
+++ b/FPGA/VNA/Test_Windowing.vhd
@@ -0,0 +1,135 @@
+--------------------------------------------------------------------------------
+-- Company:
+-- Engineer:
+--
+-- Create Date: 18:37:51 11/06/2020
+-- Design Name:
+-- Module Name: /home/jan/Projekte/VNA2/FPGA/VNA/Test_Windowing.vhd
+-- Project Name: VNA
+-- Target Device:
+-- Tool versions:
+-- Description:
+--
+-- VHDL Test Bench Created by ISE for module: Windowing
+--
+-- 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_Windowing IS
+END Test_Windowing;
+
+ARCHITECTURE behavior OF Test_Windowing IS
+
+ -- Component Declaration for the Unit Under Test (UUT)
+
+ COMPONENT Windowing
+ PORT(
+ CLK : IN std_logic;
+ RESET : IN std_logic;
+ WINDOW_TYPE : IN std_logic_vector(1 downto 0);
+ PORT1_RAW : IN std_logic_vector(15 downto 0);
+ PORT2_RAW : IN std_logic_vector(15 downto 0);
+ REF_RAW : IN std_logic_vector(15 downto 0);
+ ADC_READY : IN std_logic;
+ PORT1_WINDOWED : OUT std_logic_vector(15 downto 0);
+ PORT2_WINDOWED : OUT std_logic_vector(15 downto 0);
+ REF_WINDOWED : OUT std_logic_vector(15 downto 0);
+ WINDOWING_DONE : OUT std_logic;
+ NSAMPLES : IN std_logic_vector(12 downto 0)
+ );
+ END COMPONENT;
+
+
+ --Inputs
+ signal CLK : std_logic := '0';
+ signal RESET : std_logic := '0';
+ signal WINDOW_TYPE : std_logic_vector(1 downto 0) := (others => '0');
+ signal PORT1_RAW : std_logic_vector(15 downto 0) := (others => '0');
+ signal PORT2_RAW : std_logic_vector(15 downto 0) := (others => '0');
+ signal REF_RAW : std_logic_vector(15 downto 0) := (others => '0');
+ signal ADC_READY : std_logic := '0';
+ signal NSAMPLES : std_logic_vector(12 downto 0) := (others => '0');
+
+ --Outputs
+ signal PORT1_WINDOWED : std_logic_vector(15 downto 0);
+ signal PORT2_WINDOWED : std_logic_vector(15 downto 0);
+ signal REF_WINDOWED : std_logic_vector(15 downto 0);
+ signal WINDOWING_DONE : std_logic;
+
+ -- Clock period definitions
+ constant CLK_period : time := 10 ns;
+
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: Windowing PORT MAP (
+ CLK => CLK,
+ RESET => RESET,
+ WINDOW_TYPE => WINDOW_TYPE,
+ PORT1_RAW => PORT1_RAW,
+ PORT2_RAW => PORT2_RAW,
+ REF_RAW => REF_RAW,
+ ADC_READY => ADC_READY,
+ PORT1_WINDOWED => PORT1_WINDOWED,
+ PORT2_WINDOWED => PORT2_WINDOWED,
+ REF_WINDOWED => REF_WINDOWED,
+ WINDOWING_DONE => WINDOWING_DONE,
+ NSAMPLES => NSAMPLES
+ );
+
+ -- 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;
+
+ wait for CLK_period*10;
+
+ -- insert stimulus here
+ WINDOW_TYPE <= "10";
+ NSAMPLES <= "0000000010001";
+ PORT1_RAW <= "0000000010000000";
+ PORT2_RAW <= "0000000100000000";
+ REF_RAW <= "0000001000000000";
+ ADC_READY <= '0';
+ RESET <= '1';
+ wait for CLK_period;
+ RESET <= '0';
+ for i in 0 to 271 loop
+ wait for CLK_period*111;
+ ADC_READY <= '1';
+ wait for CLK_period;
+ ADC_READY <= '0';
+ end loop;
+
+ wait;
+ end process;
+
+END;
diff --git a/FPGA/VNA/VNA.gise b/FPGA/VNA/VNA.gise
index 2642c8c..955d340 100644
--- a/FPGA/VNA/VNA.gise
+++ b/FPGA/VNA/VNA.gise
@@ -39,9 +39,7 @@
-
-
@@ -51,7 +49,12 @@
+
+
+
+
+
@@ -68,7 +71,6 @@
-
@@ -129,7 +131,7 @@
-
+
@@ -154,22 +156,25 @@
-
+
+
-
+
-
+
-
+
+
+
@@ -180,7 +185,7 @@
-
+
@@ -206,7 +211,9 @@
-
+
+
+
@@ -216,7 +223,7 @@
-
+
@@ -224,22 +231,20 @@
-
-
+
+
-
-
+
-
+
-
@@ -249,9 +254,11 @@
-
+
+
+
@@ -278,8 +285,9 @@
-
+
+
@@ -295,11 +303,11 @@
-
+
-
+
@@ -308,7 +316,7 @@
-
+
@@ -322,7 +330,7 @@
-
+
@@ -336,7 +344,7 @@
-
+
@@ -390,7 +398,7 @@
-
+
diff --git a/FPGA/VNA/VNA.xise b/FPGA/VNA/VNA.xise
index ec70abb..1327387 100644
--- a/FPGA/VNA/VNA.xise
+++ b/FPGA/VNA/VNA.xise
@@ -17,14 +17,14 @@
-
+
-
+
@@ -34,22 +34,22 @@
-
+
-
+
-
+
-
+
-
+
@@ -64,15 +64,15 @@
-
+
-
+
-
+
@@ -100,7 +100,7 @@
-
+
@@ -114,7 +114,7 @@
-
+
@@ -127,23 +127,33 @@
-
-
+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -159,6 +169,9 @@
+
+
+
@@ -226,8 +239,8 @@
-
-
+
+
@@ -345,7 +358,7 @@
-
+
@@ -403,8 +416,8 @@
-
-
+
+
@@ -422,7 +435,7 @@
-
+
@@ -454,7 +467,7 @@
-
+
@@ -474,7 +487,7 @@
-
+
diff --git a/FPGA/VNA/Windowing.vhd b/FPGA/VNA/Windowing.vhd
new file mode 100644
index 0000000..8271d3f
--- /dev/null
+++ b/FPGA/VNA/Windowing.vhd
@@ -0,0 +1,201 @@
+----------------------------------------------------------------------------------
+-- Company:
+-- Engineer:
+--
+-- Create Date: 18:18:17 11/06/2020
+-- Design Name:
+-- Module Name: Windowing - 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 Windowing is
+ Port ( CLK : in STD_LOGIC;
+ RESET : in STD_LOGIC;
+ WINDOW_TYPE : in STD_LOGIC_VECTOR (1 downto 0);
+ PORT1_RAW : in STD_LOGIC_VECTOR (15 downto 0);
+ PORT2_RAW : in STD_LOGIC_VECTOR (15 downto 0);
+ REF_RAW : in STD_LOGIC_VECTOR (15 downto 0);
+ ADC_READY : in STD_LOGIC;
+ PORT1_WINDOWED : out STD_LOGIC_VECTOR (15 downto 0);
+ PORT2_WINDOWED : out STD_LOGIC_VECTOR (15 downto 0);
+ REF_WINDOWED : out STD_LOGIC_VECTOR (15 downto 0);
+ WINDOWING_DONE : out STD_LOGIC;
+ NSAMPLES : in STD_LOGIC_VECTOR (12 downto 0));
+end Windowing;
+
+architecture Behavioral of Windowing is
+COMPONENT window
+PORT(
+ CLK : IN std_logic;
+ INDEX : IN std_logic_vector(6 downto 0);
+ WINDOW_TYPE : IN std_logic_vector(1 downto 0);
+ VALUE : OUT std_logic_vector(15 downto 0)
+ );
+END COMPONENT;
+COMPONENT DSP_SLICE
+ PORT (
+ clk : IN STD_LOGIC;
+ ce : IN STD_LOGIC;
+ sel : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
+ a : IN STD_LOGIC_VECTOR(17 DOWNTO 0);
+ b : IN STD_LOGIC_VECTOR(17 DOWNTO 0);
+ c : IN STD_LOGIC_VECTOR(47 DOWNTO 0);
+ p : OUT STD_LOGIC_VECTOR(47 DOWNTO 0)
+ );
+END COMPONENT;
+ signal window_index : std_logic_vector(6 downto 0);
+ signal window_value : std_logic_vector(15 downto 0);
+ signal window_sample_cnt : integer range -8 to 8191;
+ signal window_index_inc : integer range 0 to 8;
+ signal window_sample_compare : integer range 0 to 8191;
+ signal window_sample_cnt_inc : integer range 0 to 8;
+
+ signal mult_a : std_logic_vector(17 downto 0);
+ signal mult_b : std_logic_vector(17 downto 0);
+ signal mult_p : std_logic_vector(47 downto 0);
+ signal mult_enable : std_logic;
+
+ type states is (CalcWindowInc, WaitingForADC, CalcPort1, CalcPort2, CalcRef, MultDelay1, MultDelay2, StorePort1, StorePort2, StoreRef);
+ signal state : states;
+begin
+
+ Mult : DSP_SLICE
+ PORT MAP (
+ clk => CLK,
+ ce => mult_enable,
+ sel => "0",
+ a => mult_a,
+ b => mult_b,
+ c => (others => '0'),
+ p => mult_p
+ );
+ WindowROM: window PORT MAP(
+ CLK => CLK,
+ INDEX => window_index,
+ WINDOW_TYPE => WINDOW_TYPE,
+ VALUE => window_value
+ );
+ -- sign extend multiplier inputs
+ mult_a(17 downto 16) <= mult_a(15) & mult_a(15);
+ mult_b(17 downto 16) <= mult_b(15) & mult_b(15);
+
+ mult_a(15 downto 0) <= window_value;
+
+ process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ WINDOWING_DONE <= '0';
+ state <= CalcWindowInc;
+ mult_enable <= '0';
+ mult_b(15 downto 0) <= (others => '0');
+ window_index <= (others => '0');
+ window_sample_cnt <= 0;
+ window_sample_compare <= to_integer(unsigned(NSAMPLES));
+ else
+ case state is
+ when CalcWindowInc =>
+ case window_sample_compare is
+ when 1 =>
+ -- 16 samples, increment on every sample by 8
+ window_sample_cnt_inc <= 1;
+ window_index_inc <= 8;
+ when 2 to 3 =>
+ -- 32-48 samples, increment by 4
+ window_sample_cnt_inc <= 2;
+ window_index_inc <= 4;
+ when 4 to 7 =>
+ -- 64-112 samples, increment by 2
+ window_sample_cnt_inc <= 4;
+ window_index_inc <= 2;
+ when others =>
+ -- 128 or more samples, increment by 1
+ window_sample_cnt_inc <= 8;
+ window_index_inc <= 1;
+ end case;
+ state <= WaitingForADC;
+ when WaitingForADC =>
+ WINDOWING_DONE <= '0';
+ mult_enable <= '0';
+ mult_b(15 downto 0) <= (others => '0');
+ if ADC_READY = '1' then
+ state <= CalcPort1;
+ end if;
+ when CalcPort1 =>
+ WINDOWING_DONE <= '0';
+ mult_enable <= '1';
+ mult_b(15 downto 0) <= PORT1_RAW;
+ state <= CalcPort2;
+ when CalcPort2 =>
+ WINDOWING_DONE <= '0';
+ mult_enable <= '1';
+ mult_b(15 downto 0) <= PORT2_RAW;
+ state <= CalcRef;
+ when CalcRef =>
+ WINDOWING_DONE <= '0';
+ mult_enable <= '1';
+ mult_b(15 downto 0) <= REF_RAW;
+ state <= MultDelay1;
+ when MultDelay1 =>
+ WINDOWING_DONE <= '0';
+ mult_enable <= '1';
+ mult_b(15 downto 0) <= (others => '0');
+ state <= MultDelay2;
+ when MultDelay2 =>
+ WINDOWING_DONE <= '0';
+ mult_enable <= '1';
+ mult_b(15 downto 0) <= (others => '0');
+ state <= StorePort1;
+ when StorePort1 =>
+ WINDOWING_DONE <= '0';
+ mult_enable <= '1';
+ mult_b(15 downto 0) <= (others => '0');
+ PORT1_WINDOWED <= mult_p(30 downto 15);
+ state <= StorePort2;
+ when StorePort2 =>
+ WINDOWING_DONE <= '0';
+ mult_enable <= '1';
+ mult_b(15 downto 0) <= (others => '0');
+ PORT2_WINDOWED <= mult_p(30 downto 15);
+ state <= StoreRef;
+ when StoreRef =>
+ WINDOWING_DONE <= '1';
+ mult_enable <= '0';
+ mult_b(15 downto 0) <= (others => '0');
+ REF_WINDOWED <= mult_p(30 downto 15);
+ -- update window increment
+ if window_sample_cnt + window_sample_cnt_inc < window_sample_compare then
+ window_sample_cnt <= window_sample_cnt + window_sample_cnt_inc;
+ else
+ window_sample_cnt <= window_sample_cnt + window_sample_cnt_inc - window_sample_compare;
+ window_index <= std_logic_vector( unsigned(window_index) + window_index_inc );
+ end if;
+ state <= WaitingForADC;
+ end case;
+ end if;
+ end if;
+ end process;
+
+end Behavioral;
+
diff --git a/FPGA/VNA/dft_result.vhd b/FPGA/VNA/dft_result.vhd
deleted file mode 100644
index e4388f7..0000000
--- a/FPGA/VNA/dft_result.vhd
+++ /dev/null
@@ -1,56 +0,0 @@
-----------------------------------------------------------------------------------
--- Company:
--- Engineer:
---
--- Create Date: 22:01:17 11/03/2020
--- Design Name:
--- Module Name: dft_result - 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 dft_result is
- Generic (depth : integer);
- Port ( CLK : in STD_LOGIC;
- READ_ADDRESS : in integer range 0 to depth-1;
- WRITE_ADDRESS : in integer range 0 to depth-1;
- DATA_IN : in STD_LOGIC_VECTOR (191 downto 0);
- DATA_OUT : out STD_LOGIC_VECTOR (191 downto 0);
- WE : in STD_LOGIC);
-end dft_result;
-
-architecture rtl of dft_result is
- type memory is array(depth-1 downto 0) of std_logic_vector(191 downto 0);
- signal ram : memory;
-begin
- process(CLK)
- begin
- if rising_edge(CLK) then
- DATA_OUT <= ram(READ_ADDRESS);
- if(WE = '1') then
- ram(WRITE_ADDRESS) <= DATA_IN;
- end if;
- end if;
- end process;
-end rtl;
-
diff --git a/FPGA/VNA/ipcore_dir/DSP48.xco b/FPGA/VNA/ipcore_dir/DSP48.xco
new file mode 100644
index 0000000..face7fc
--- /dev/null
+++ b/FPGA/VNA/ipcore_dir/DSP48.xco
@@ -0,0 +1,136 @@
+##############################################################
+#
+# Xilinx Core Generator version 14.6
+# Date: Fri Nov 6 13:56:17 2020
+#
+##############################################################
+#
+# 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:xbip_dsp48_macro:2.1
+#
+##############################################################
+#
+# 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 DSP48_Macro xilinx.com:ip:xbip_dsp48_macro:2.1
+# END Select
+# BEGIN Parameters
+CSET a_binarywidth=0
+CSET a_width=18
+CSET areg_1=false
+CSET areg_2=false
+CSET areg_3=true
+CSET areg_4=true
+CSET b_binarywidth=0
+CSET b_width=18
+CSET breg_1=false
+CSET breg_2=false
+CSET breg_3=true
+CSET breg_4=true
+CSET c_binarywidth=0
+CSET c_width=48
+CSET cinreg_1=false
+CSET cinreg_2=false
+CSET cinreg_3=false
+CSET cinreg_4=false
+CSET cinreg_5=false
+CSET component_name=DSP48
+CSET concat_binarywidth=0
+CSET concat_width=48
+CSET concatreg_3=false
+CSET concatreg_4=false
+CSET concatreg_5=false
+CSET creg_1=false
+CSET creg_2=false
+CSET creg_3=true
+CSET creg_4=true
+CSET creg_5=true
+CSET d_binarywidth=0
+CSET d_width=18
+CSET dreg_1=false
+CSET dreg_2=false
+CSET dreg_3=false
+CSET gui_behaviour=Coregen
+CSET has_a_ce=false
+CSET has_a_sclr=false
+CSET has_acout=false
+CSET has_b_ce=false
+CSET has_b_sclr=false
+CSET has_bcout=false
+CSET has_c_ce=false
+CSET has_c_sclr=false
+CSET has_carrycascout=false
+CSET has_carryout=false
+CSET has_ce=true
+CSET has_concat_ce=false
+CSET has_concat_sclr=false
+CSET has_d_ce=false
+CSET has_d_sclr=false
+CSET has_m_ce=false
+CSET has_m_sclr=false
+CSET has_p_ce=false
+CSET has_p_sclr=false
+CSET has_pcout=false
+CSET has_sclr=false
+CSET has_sel_ce=false
+CSET has_sel_sclr=false
+CSET instruction1=A*B
+CSET instruction2=A*B+C
+CSET instruction3=#
+CSET instruction4=#
+CSET instruction5=#
+CSET instruction6=#
+CSET instruction7=#
+CSET instruction8=#
+CSET instruction_list=#
+CSET mreg_5=true
+CSET opreg_1=false
+CSET opreg_2=false
+CSET opreg_3=true
+CSET opreg_4=true
+CSET opreg_5=true
+CSET output_properties=Full_Precision
+CSET p_binarywidth=0
+CSET p_full_width=48
+CSET p_width=48
+CSET pcin_binarywidth=0
+CSET pipeline_options=Automatic
+CSET preg_6=true
+CSET show_filtered=false
+CSET tier_1=false
+CSET tier_2=false
+CSET tier_3=false
+CSET tier_4=false
+CSET tier_5=false
+CSET tier_6=false
+CSET use_dsp48=true
+# END Parameters
+# BEGIN Extra information
+MISC pkg_timestamp=2012-11-05T14:23:53Z
+# END Extra information
+GENERATE
+# CRC: 2ca4f824
diff --git a/FPGA/VNA/ipcore_dir/DSP48.xise b/FPGA/VNA/ipcore_dir/DSP48.xise
new file mode 100644
index 0000000..4da40c6
--- /dev/null
+++ b/FPGA/VNA/ipcore_dir/DSP48.xise
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FPGA/VNA/ipcore_dir/DSP_SLICE.xco b/FPGA/VNA/ipcore_dir/DSP_SLICE.xco
new file mode 100644
index 0000000..b39e78b
--- /dev/null
+++ b/FPGA/VNA/ipcore_dir/DSP_SLICE.xco
@@ -0,0 +1,136 @@
+##############################################################
+#
+# Xilinx Core Generator version 14.6
+# Date: Fri Nov 6 13:57:46 2020
+#
+##############################################################
+#
+# 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:xbip_dsp48_macro:2.1
+#
+##############################################################
+#
+# 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 DSP48_Macro xilinx.com:ip:xbip_dsp48_macro:2.1
+# END Select
+# BEGIN Parameters
+CSET a_binarywidth=0
+CSET a_width=18
+CSET areg_1=false
+CSET areg_2=false
+CSET areg_3=true
+CSET areg_4=true
+CSET b_binarywidth=0
+CSET b_width=18
+CSET breg_1=false
+CSET breg_2=false
+CSET breg_3=true
+CSET breg_4=true
+CSET c_binarywidth=0
+CSET c_width=48
+CSET cinreg_1=false
+CSET cinreg_2=false
+CSET cinreg_3=false
+CSET cinreg_4=false
+CSET cinreg_5=false
+CSET component_name=DSP_SLICE
+CSET concat_binarywidth=0
+CSET concat_width=48
+CSET concatreg_3=false
+CSET concatreg_4=false
+CSET concatreg_5=false
+CSET creg_1=false
+CSET creg_2=false
+CSET creg_3=true
+CSET creg_4=true
+CSET creg_5=true
+CSET d_binarywidth=0
+CSET d_width=18
+CSET dreg_1=false
+CSET dreg_2=false
+CSET dreg_3=false
+CSET gui_behaviour=Coregen
+CSET has_a_ce=false
+CSET has_a_sclr=false
+CSET has_acout=false
+CSET has_b_ce=false
+CSET has_b_sclr=false
+CSET has_bcout=false
+CSET has_c_ce=false
+CSET has_c_sclr=false
+CSET has_carrycascout=false
+CSET has_carryout=false
+CSET has_ce=true
+CSET has_concat_ce=false
+CSET has_concat_sclr=false
+CSET has_d_ce=false
+CSET has_d_sclr=false
+CSET has_m_ce=false
+CSET has_m_sclr=false
+CSET has_p_ce=false
+CSET has_p_sclr=false
+CSET has_pcout=false
+CSET has_sclr=false
+CSET has_sel_ce=false
+CSET has_sel_sclr=false
+CSET instruction1=A*B
+CSET instruction2=A*B+C
+CSET instruction3=#
+CSET instruction4=#
+CSET instruction5=#
+CSET instruction6=#
+CSET instruction7=#
+CSET instruction8=#
+CSET instruction_list=#
+CSET mreg_5=true
+CSET opreg_1=false
+CSET opreg_2=false
+CSET opreg_3=true
+CSET opreg_4=true
+CSET opreg_5=true
+CSET output_properties=Full_Precision
+CSET p_binarywidth=0
+CSET p_full_width=48
+CSET p_width=48
+CSET pcin_binarywidth=0
+CSET pipeline_options=Automatic
+CSET preg_6=true
+CSET show_filtered=false
+CSET tier_1=false
+CSET tier_2=false
+CSET tier_3=false
+CSET tier_4=false
+CSET tier_5=false
+CSET tier_6=false
+CSET use_dsp48=true
+# END Parameters
+# BEGIN Extra information
+MISC pkg_timestamp=2012-11-05T14:23:53Z
+# END Extra information
+GENERATE
+# CRC: 57648294
diff --git a/FPGA/VNA/ipcore_dir/DSP_SLICE.xise b/FPGA/VNA/ipcore_dir/DSP_SLICE.xise
new file mode 100644
index 0000000..b4222ea
--- /dev/null
+++ b/FPGA/VNA/ipcore_dir/DSP_SLICE.xise
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FPGA/VNA/top.bin b/FPGA/VNA/top.bin
index a47191b..6ad41ec 100644
Binary files a/FPGA/VNA/top.bin and b/FPGA/VNA/top.bin differ
diff --git a/FPGA/VNA/top.vhd b/FPGA/VNA/top.vhd
index d382670..41b0f72 100644
--- a/FPGA/VNA/top.vhd
+++ b/FPGA/VNA/top.vhd
@@ -145,6 +145,24 @@ architecture Behavioral of top is
DEBUG_STATUS : out STD_LOGIC_VECTOR (10 downto 0)
);
END COMPONENT;
+
+ COMPONENT Windowing
+ PORT(
+ CLK : IN std_logic;
+ RESET : IN std_logic;
+ WINDOW_TYPE : IN std_logic_vector(1 downto 0);
+ PORT1_RAW : IN std_logic_vector(15 downto 0);
+ PORT2_RAW : IN std_logic_vector(15 downto 0);
+ REF_RAW : IN std_logic_vector(15 downto 0);
+ ADC_READY : IN std_logic;
+ NSAMPLES : IN std_logic_vector(12 downto 0);
+ PORT1_WINDOWED : OUT std_logic_vector(15 downto 0);
+ PORT2_WINDOWED : OUT std_logic_vector(15 downto 0);
+ REF_WINDOWED : OUT std_logic_vector(15 downto 0);
+ WINDOWING_DONE : OUT std_logic
+ );
+ END COMPONENT;
+
COMPONENT Sampling
Generic(CLK_CYCLES_PRE_DONE : integer);
PORT(
@@ -158,7 +176,6 @@ architecture Behavioral of top is
NEW_SAMPLE : IN std_logic;
START : IN std_logic;
SAMPLES : IN std_logic_vector(12 downto 0);
- WINDOW_TYPE : in STD_LOGIC_VECTOR (1 downto 0);
ADC_START : OUT std_logic;
DONE : OUT std_logic;
PRE_DONE : OUT std_logic;
@@ -245,10 +262,8 @@ architecture Behavioral of top is
RESET_MINMAX : out STD_LOGIC;
SWEEP_HALTED : in STD_LOGIC;
SWEEP_RESUME : out STD_LOGIC;
- DFT_NSAMPLES : out STD_LOGIC_VECTOR (15 downto 0);
DFT_BIN1_PHASEINC : out STD_LOGIC_VECTOR (15 downto 0);
DFT_DIFFBIN_PHASEINC : out STD_LOGIC_VECTOR (15 downto 0);
- DFT_WINDOW_INC : out STD_LOGIC_VECTOR (15 downto 0);
DFT_RESULT_READY : in STD_LOGIC;
DFT_OUTPUT : in STD_LOGIC_VECTOR (191 downto 0);
DFT_NEXT_OUTPUT : out STD_LOGIC;
@@ -265,11 +280,9 @@ architecture Behavioral of top is
PORT1 : IN std_logic_vector(15 downto 0);
PORT2 : IN std_logic_vector(15 downto 0);
NEW_SAMPLE : IN std_logic;
- NSAMPLES : IN std_logic_vector(15 downto 0);
+ NSAMPLES : IN std_logic_vector(12 downto 0);
BIN1_PHASEINC : IN std_logic_vector(15 downto 0);
DIFFBIN_PHASEINC : IN std_logic_vector(15 downto 0);
- WINDOW_INC : IN std_logic_vector(15 downto 0);
- WINDOW_TYPE : IN std_logic_vector(1 downto 0);
NEXT_OUTPUT : IN std_logic;
RESULT_READY : OUT std_logic;
OUTPUT : OUT std_logic_vector(191 downto 0)
@@ -329,6 +342,11 @@ architecture Behavioral of top is
signal adc_minmax : std_logic_vector(95 downto 0);
signal adc_reset_minmax : std_logic;
+ signal port1_windowed : std_logic_vector(15 downto 0);
+ signal port2_windowed : std_logic_vector(15 downto 0);
+ signal ref_windowed : std_logic_vector(15 downto 0);
+ signal windowing_ready : std_logic;
+
-- Sampling signals
signal sampling_busy : std_logic;
signal sampling_done : std_logic;
@@ -394,10 +412,8 @@ architecture Behavioral of top is
signal intr : std_logic;
-- DFT signals
- signal dft_nsamples : std_logic_vector (15 downto 0);
signal dft_bin1_phaseinc : std_logic_vector (15 downto 0);
signal dft_diffbin_phaseinc : std_logic_vector (15 downto 0);
- signal dft_window_inc : std_logic_vector (15 downto 0);
signal dft_ready : std_logic;
signal dft_output : std_logic_vector (191 downto 0);
signal dft_next_output : std_logic;
@@ -579,6 +595,22 @@ begin
SCLK => REF_SCLK
);
+
+ Windower: Windowing PORT MAP(
+ CLK => clk160,
+ RESET => sampling_start,
+ WINDOW_TYPE => sampling_window,
+ PORT1_RAW => adc_port1_data,
+ PORT2_RAW => adc_port2_data,
+ REF_RAW => adc_ref_data,
+ ADC_READY => adc_port1_ready,
+ PORT1_WINDOWED => port1_windowed,
+ PORT2_WINDOWED => port2_windowed,
+ REF_WINDOWED => ref_windowed,
+ WINDOWING_DONE => windowing_ready,
+ NSAMPLES => sampling_samples
+ );
+
Sampler: Sampling
GENERIC MAP(CLK_CYCLES_PRE_DONE => 0)
PORT MAP(
@@ -586,16 +618,15 @@ begin
RESET => sweep_reset,
ADC_PRESCALER => sampling_prescaler,
PHASEINC => sampling_phaseinc,
- PORT1 => adc_port1_data,
- PORT2 => adc_port2_data,
- REF => adc_ref_data,
+ PORT1 => port1_windowed,
+ PORT2 => port2_windowed,
+ REF => ref_windowed,
ADC_START => adc_trigger_sample,
- NEW_SAMPLE => adc_port1_ready,
+ NEW_SAMPLE => windowing_ready,
DONE => sampling_done,
PRE_DONE => open,
START => sampling_start,
SAMPLES => sampling_samples,
- WINDOW_TYPE => sampling_window,
PORT1_I => sampling_result(287 downto 240),
PORT1_Q => sampling_result(239 downto 192),
PORT2_I => sampling_result(191 downto 144),
@@ -614,7 +645,7 @@ begin
CONFIG_ADDRESS => sweep_config_address,
CONFIG_DATA => sweep_config_data,
USER_NSAMPLES => sampling_user_samples,
- NSAMPLES => sampling_user_samples,
+ NSAMPLES => sampling_samples,
SAMPLING_BUSY => sampling_busy,
SAMPLING_DONE => sampling_done,
START_SAMPLING => sampling_start,
@@ -691,7 +722,7 @@ begin
SWEEP_ADDRESS => sweep_config_write_address,
SWEEP_WRITE => sweep_config_write,
SWEEP_POINTS => sweep_points,
- NSAMPLES => sampling_samples,
+ NSAMPLES => sampling_user_samples,
PORT1_EN => port1mix_en,
PORT2_EN => port2mix_en,
REF_EN => refmix_en,
@@ -711,10 +742,8 @@ begin
SWEEP_RESUME => sweep_resume,
EXCITE_PORT1 => sweep_excite_port1,
EXCITE_PORT2 => sweep_excite_port2,
- DFT_NSAMPLES => dft_nsamples,
DFT_BIN1_PHASEINC => dft_bin1_phaseinc,
DFT_DIFFBIN_PHASEINC => dft_diffbin_phaseinc,
- DFT_WINDOW_INC => dft_window_inc,
DFT_RESULT_READY => dft_ready,
DFT_OUTPUT => dft_output,
DFT_NEXT_OUTPUT => dft_next_output,
@@ -728,14 +757,12 @@ begin
PORT MAP(
CLK => clk160,
RESET => dft_reset,
- PORT1 => adc_port1_data,
- PORT2 => adc_port2_data,
- NEW_SAMPLE => adc_port1_ready,
- NSAMPLES => dft_nsamples,
+ PORT1 => port1_windowed,
+ PORT2 => port2_windowed,
+ NEW_SAMPLE => windowing_ready,
+ NSAMPLES => sampling_samples,
BIN1_PHASEINC => dft_bin1_phaseinc,
DIFFBIN_PHASEINC => dft_diffbin_phaseinc,
- WINDOW_INC => dft_window_inc,
- WINDOW_TYPE => sampling_window,
RESULT_READY => dft_ready,
OUTPUT => dft_output,
NEXT_OUTPUT => dft_next_output
diff --git a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
index b686adb..7997810 100644
--- a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
+++ b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
@@ -12,6 +12,7 @@
static FPGA::HaltedCallback halted_cb;
static uint16_t SysCtrlReg = 0x0000;
static uint16_t ISRMaskReg = 0x0000;
+static uint32_t ADC_samplerate;
using namespace FPGAHAL;
@@ -27,6 +28,9 @@ void FPGA::WriteRegister(FPGA::Reg reg, uint16_t value) {
Low(CS);
HAL_SPI_Transmit(&FPGA_SPI, (uint8_t*) cmd, 4, 100);
High(CS);
+ if(reg == Reg::ADCPrescaler) {
+ ADC_samplerate = Clockrate / value;
+ }
}
bool FPGA::Configure(Flash *f, uint32_t start_address, uint32_t bitstream_size) {
@@ -371,6 +375,23 @@ void FPGA::ResumeHaltedSweep() {
High(CS);
}
+void FPGA::SetupDFT(uint32_t f_firstBin, uint32_t f_binSpacing) {
+ // see FPGA protocol for formulas
+ uint16_t firstBin = f_firstBin * (1ULL << 16) / ADC_samplerate;
+ uint16_t binSpacing = f_binSpacing * (1ULL << 24) / ADC_samplerate;
+ WriteRegister(Reg::DFTFirstBin, firstBin);
+ WriteRegister(Reg::DFTFreqSpacing, binSpacing);
+}
+
+void FPGA::StopDFT() {
+ DisableInterrupt(Interrupt::DFTReady);
+}
+
+void FPGA::StartDFT() {
+ StopDFT();
+ EnableInterrupt(Interrupt::DFTReady);
+}
+
FPGA::DFTResult FPGA::ReadDFTResult() {
uint8_t cmd[2] = {0xA0, 0x00};
uint8_t recv[24];
diff --git a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
index 07cafce..cae5e3e 100644
--- a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
+++ b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
@@ -7,6 +7,7 @@ namespace FPGA {
static constexpr uint16_t MaxPoints = 4501;
static constexpr uint16_t DFTbins = 64;
+static constexpr uint32_t Clockrate = 102400000UL;
enum class Reg {
InterruptMask = 0x00,
@@ -23,8 +24,6 @@ enum class Reg {
MAX2871Def3MSB = 0x0D,
MAX2871Def4LSB = 0x0E,
MAX2871Def4MSB = 0x0F,
- DFTSamples = 0x10,
- DFTWindowInc = 0x11,
DFTFirstBin = 0x12,
DFTFreqSpacing = 0x13,
};
@@ -124,6 +123,9 @@ void WriteSweepConfig(uint16_t pointnum, bool lowband, uint32_t *SourceRegs, uin
uint8_t attenuation, uint64_t frequency, SettlingTime settling, Samples samples, bool halt = false, LowpassFilter filter = LowpassFilter::Auto);
using ReadCallback = void(*)(const SamplingResult &result);
bool InitiateSampleRead(ReadCallback cb);
+void SetupDFT(uint32_t f_firstBin, uint32_t f_binSpacing);
+void StopDFT();
+void StartDFT();
DFTResult ReadDFTResult();
ADCLimits GetADCLimits();
void ResetADCLimits();
diff --git a/Software/VNA_embedded/Application/Drivers/Si5351C.cpp b/Software/VNA_embedded/Application/Drivers/Si5351C.cpp
index 34576cd..3997afb 100644
--- a/Software/VNA_embedded/Application/Drivers/Si5351C.cpp
+++ b/Software/VNA_embedded/Application/Drivers/Si5351C.cpp
@@ -315,29 +315,31 @@ void Si5351C::FindOptimalDivider(uint32_t f_pll, uint32_t f, uint32_t &P1,
// see https://www.silabs.com/documents/public/application-notes/AN619.pdf (page 3/6)
uint32_t a = f_pll / f;
int32_t f_rem = f_pll - f * a;
- uint32_t best_b, best_c;
- uint32_t best_deviation = UINT32_MAX;
- for (uint32_t c = (1UL << 20) - 1; c >= (1UL << 19); c--) {
- uint32_t guess_b = (uint64_t) f_rem * c / f;
- for (uint32_t b = guess_b; b <= guess_b + 1; b++) {
- int32_t f_div = (uint64_t) f * b / c;
- uint32_t deviation = abs(f_rem - f_div);
- if (deviation < best_deviation) {
- best_b = b;
- best_c = c;
- best_deviation = deviation;
- if (deviation == 0) {
- break;
- }
- }
- }
- if (best_deviation == 0) {
- break;
- }
- }
- LOG_DEBUG(
- "Optimal divider for %luHz/%luHz is: a=%lu, b=%lu, c=%lu (%luHz deviation)",
- f_pll, f, a, best_b, best_c, best_deviation);
+ // always using the highest modulus divider results in less than 1Hz deviation for all frequencies, that is good enough
+ uint32_t best_c = (1UL << 20) - 1;
+ uint32_t best_b = (uint64_t) f_rem * best_c / f;
+// uint32_t best_deviation = UINT32_MAX;
+// for (uint32_t c = (1UL << 20) - 1; c >= (1UL << 19); c--) {
+// uint32_t guess_b = (uint64_t) f_rem * c / f;
+// for (uint32_t b = guess_b; b <= guess_b + 1; b++) {
+// int32_t f_div = (uint64_t) f * b / c;
+// uint32_t deviation = abs(f_rem - f_div);
+// if (deviation < best_deviation) {
+// best_b = b;
+// best_c = c;
+// best_deviation = deviation;
+// if (deviation <= 3) {
+// break;
+// }
+// }
+// }
+// if (best_deviation <= 3) {
+// break;
+// }
+// }
+// LOG_DEBUG(
+// "Optimal divider for %luHz/%luHz is: a=%lu, b=%lu, c=%lu (%luHz deviation)",
+// f_pll, f, a, best_b, best_c, best_deviation);
// convert to Si5351C parameters
uint32_t floor = 128 * best_b / best_c;
P1 = 128 * a + floor - 512;
diff --git a/Software/VNA_embedded/Application/Hardware.cpp b/Software/VNA_embedded/Application/Hardware.cpp
index d7e1ebf..b788a8b 100644
--- a/Software/VNA_embedded/Application/Hardware.cpp
+++ b/Software/VNA_embedded/Application/Hardware.cpp
@@ -131,10 +131,6 @@ bool HW::Init() {
// Set phase increment according to
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, HW::DFTphaseInc);
- // Enable new data and sweep halt interrupt
- FPGA::EnableInterrupt(FPGA::Interrupt::NewData);
- FPGA::EnableInterrupt(FPGA::Interrupt::SweepHalted);
-
Exti::SetCallback(FPGA_INTR_GPIO_Port, FPGA_INTR_Pin, Exti::EdgeType::Rising, Exti::Pull::Down, FPGA_Interrupt);
// Initialize PLLs and build VCO maps
diff --git a/Software/VNA_embedded/Application/Hardware.hpp b/Software/VNA_embedded/Application/Hardware.hpp
index 6ace39a..2522051 100644
--- a/Software/VNA_embedded/Application/Hardware.hpp
+++ b/Software/VNA_embedded/Application/Hardware.hpp
@@ -2,6 +2,7 @@
#include
#include "Protocol.hpp"
+#include "FPGA/FPGA.hpp"
#define USE_DEBUG_PINS
@@ -31,10 +32,9 @@ static constexpr uint32_t LO1_minFreq = 25000000;
static constexpr uint32_t MaxSamples = 130944;
static constexpr uint32_t MinSamples = 16;
static constexpr uint32_t PLLRef = 100000000;
-static constexpr uint16_t MaxPoints = 4501;
-static constexpr uint8_t ADCprescaler = 102400000UL / ADCSamplerate;
-static_assert(ADCprescaler * ADCSamplerate == 102400000UL, "ADCSamplerate can not be reached exactly");
+static constexpr uint8_t ADCprescaler = FPGA::Clockrate / ADCSamplerate;
+static_assert(ADCprescaler * ADCSamplerate == FPGA::Clockrate, "ADCSamplerate can not be reached exactly");
static constexpr uint16_t DFTphaseInc = 4096 * IF2 / ADCSamplerate;
static_assert(DFTphaseInc * ADCSamplerate == 4096 * IF2, "DFT can not be computed for 2.IF");
@@ -43,7 +43,7 @@ static constexpr Protocol::DeviceLimits Limits = {
.maxFreq = 6000000000,
.minIFBW = ADCSamplerate / MaxSamples,
.maxIFBW = ADCSamplerate / MinSamples,
- .maxPoints = MaxPoints,
+ .maxPoints = FPGA::MaxPoints,
.cdbm_min = -4000,
.cdbm_max = 0,
.minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples),
diff --git a/Software/VNA_embedded/Application/Manual.cpp b/Software/VNA_embedded/Application/Manual.cpp
index 42cb1e2..41061f7 100644
--- a/Software/VNA_embedded/Application/Manual.cpp
+++ b/Software/VNA_embedded/Application/Manual.cpp
@@ -73,6 +73,9 @@ void Manual::Setup(Protocol::ManualControl m) {
FPGA::Enable(FPGA::Periphery::ExcitePort2, m.PortSwitch == 1);
FPGA::Enable(FPGA::Periphery::PortSwitch);
+ // Enable new data and sweep halt interrupt
+ FPGA::EnableInterrupt(FPGA::Interrupt::NewData);
+
active = true;
FPGA::StartSweep();
}
diff --git a/Software/VNA_embedded/Application/SpectrumAnalyzer.cpp b/Software/VNA_embedded/Application/SpectrumAnalyzer.cpp
index 78e5625..9f53e94 100644
--- a/Software/VNA_embedded/Application/SpectrumAnalyzer.cpp
+++ b/Software/VNA_embedded/Application/SpectrumAnalyzer.cpp
@@ -11,6 +11,8 @@
#define LOG_MODULE "SA"
#include "Log.h"
+using namespace HWHAL;
+
static Protocol::SpectrumAnalyzerSettings s;
static uint32_t pointCnt;
static uint32_t points;
@@ -21,10 +23,11 @@ static Protocol::PacketInfo p;
static bool active = false;
static uint32_t lastLO2;
static uint32_t actualRBW;
+static bool usingDFT;
+static uint16_t DFTpoints;
+static bool negativeDFT; // if true, a positive frequency shift at input results in a negative shift at the 2.IF. Handle DFT accordingly
-static float port1Measurement, port2Measurement;
-
-using namespace HWHAL;
+static float port1Measurement[FPGA::DFTbins], port2Measurement[FPGA::DFTbins];
static void StartNextSample() {
uint64_t freq = s.f_start + (s.f_stop - s.f_start) * pointCnt / (points - 1);
@@ -34,16 +37,20 @@ static void StartNextSample() {
case 0:
default:
// reset minimum amplitudes in first signal ID step
- port1Measurement = std::numeric_limits::max();
- port2Measurement = std::numeric_limits::max();
+ for (uint16_t i = 0; i < DFTpoints; i++) {
+ port1Measurement[i] = std::numeric_limits::max();
+ port2Measurement[i] = std::numeric_limits::max();
+ }
// Use default LO frequencies
LO1freq = freq + HW::IF1;
LO2freq = HW::IF1 - HW::IF2;
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, 112);
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, 1120);
+ negativeDFT = true;
break;
case 1:
LO2freq = HW::IF1 - HW::IF2;
+ negativeDFT = false;
// Shift first LO to other side
// depending on the measurement frequency this is not possible or additive mixing has to be used
if(freq >= HW::IF1 + HW::LO1_minFreq) {
@@ -59,13 +66,15 @@ static void StartNextSample() {
signalIDstep++;
/* no break */
case 2:
- // Shift both LOs to other side
+ // Shift second LOs to other side
LO1freq = freq + HW::IF1;
LO2freq = HW::IF1 + HW::IF2;
+ negativeDFT = false;
break;
case 3:
+ // Shift both LO to other side
LO2freq = HW::IF1 + HW::IF2;
- // Shift second LO to other side
+ negativeDFT = true;
// depending on the measurement frequency this is not possible or additive mixing has to be used
if(freq >= HW::IF1 + HW::LO1_minFreq) {
// frequency is high enough to shift 1.LO below measurement frequency
@@ -81,6 +90,7 @@ static void StartNextSample() {
/* no break */
case 4:
// Use default frequencies with different ADC samplerate to remove images in final IF
+ negativeDFT = true;
LO1freq = freq + HW::IF1;
LO2freq = HW::IF1 - HW::IF2;
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, 120);
@@ -96,6 +106,17 @@ static void StartNextSample() {
Si5351.SetCLK(SiChannel::Port2LO2, LO2freq, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
lastLO2 = LO2freq;
}
+ if (usingDFT) {
+ uint32_t spacing = (s.f_stop - s.f_start) / (points - 1);
+ uint32_t start = HW::IF2;
+ if(negativeDFT) {
+ // needs to look below the start frequency, shift start
+ start -= spacing * (DFTpoints - 1);
+ }
+ FPGA::SetupDFT(start, spacing);
+ FPGA::StartDFT();
+ }
+
// Configure the sampling in the FPGA
FPGA::WriteSweepConfig(0, 0, Source.GetRegisters(), LO1.GetRegisters(), 0,
0, FPGA::SettlingTime::us20, FPGA::Samples::SPPRegister, 0,
@@ -111,9 +132,6 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
s = settings;
HW::SetMode(HW::Mode::SA);
FPGA::SetMode(FPGA::Mode::FPGA);
- FPGA::DisableInterrupt(FPGA::Interrupt::NewData);
- FPGA::DisableInterrupt(FPGA::Interrupt::SweepHalted);
- FPGA::EnableInterrupt(FPGA::Interrupt::DFTReady);
// in almost all cases a full sweep requires more points than the FPGA can handle at a time
// individually start each point and do the sweep in the uC
FPGA::SetNumberOfPoints(1);
@@ -148,12 +166,17 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
FPGA::Enable(FPGA::Periphery::Port1Mixer);
FPGA::Enable(FPGA::Periphery::Port2Mixer);
- // Configure DFT
- LOG_INFO("DFT samples: %lu", sampleNum);
- FPGA::WriteRegister(FPGA::Reg::DFTSamples, sampleNum - 1);
- FPGA::WriteRegister(FPGA::Reg::DFTWindowInc, 65536 / sampleNum);
- FPGA::WriteRegister(FPGA::Reg::DFTFirstBin, 17920);
- FPGA::WriteRegister(FPGA::Reg::DFTFreqSpacing, 1147);
+ // automatically select DFT mode for lower RBWs
+ usingDFT = actualRBW <= 1000;
+
+ if (usingDFT) {
+ DFTpoints = FPGA::DFTbins; // use full DFT in FPGA
+ FPGA::DisableInterrupt(FPGA::Interrupt::NewData);
+ } else {
+ DFTpoints = 1; // can only measure one point at a time
+ FPGA::StopDFT();
+ FPGA::EnableInterrupt(FPGA::Interrupt::NewData);
+ }
lastLO2 = 0;
active = true;
@@ -166,26 +189,39 @@ bool SA::MeasurementDone(const FPGA::SamplingResult &result) {
}
FPGA::AbortSweep();
- uint16_t i=0;
- while(FPGA::GetStatus() & (uint16_t) FPGA::Interrupt::DFTReady) {
- auto dft = FPGA::ReadDFTResult();
- dft.P1 /= sampleNum;
- dft.P2 /= sampleNum;
- LOG_INFO("DFT %d: %lu, %lu", i, (uint32_t) dft.P1, (uint32_t) dft.P2);
- Log_Flush();
- i++;
- }
- FPGA::DisableInterrupt(FPGA::Interrupt::DFTReady);
- FPGA::EnableInterrupt(FPGA::Interrupt::DFTReady);
+ for(uint16_t i=0;i(result.P1I, result.P1Q));
+ port2 = abs(std::complex(result.P2I, result.P2Q));
+ }
+ port1 /= sampleNum;
+ port2 /= sampleNum;
- float port1 = abs(std::complex(result.P1I, result.P1Q))/sampleNum;
- float port2 = abs(std::complex(result.P2I, result.P2Q))/sampleNum;
- if(port1 < port1Measurement) {
- port1Measurement = port1;
+ uint16_t index = i;
+ if (negativeDFT) {
+ // bin order is reversed
+ index = DFTpoints - i - 1;
+ }
+
+ if(port1 < port1Measurement[index]) {
+ port1Measurement[index] = port1;
+ }
+ if(port2 < port2Measurement[index]) {
+ port2Measurement[index] = port2;
+ }
}
- if(port2 < port2Measurement) {
- port2Measurement = port2;
+
+ if (usingDFT) {
+ FPGA::StopDFT();
+ // will be started again in StartNextSample
}
+
// trigger work function
return true;
}
@@ -196,74 +232,76 @@ void SA::Work() {
}
if(!s.SignalID || signalIDstep >= 4) {
// this measurement point is done, handle result according to detector
- uint16_t binIndex = pointCnt / binSize;
- uint32_t pointInBin = pointCnt % binSize;
- bool lastPointInBin = pointInBin >= binSize - 1;
- auto det = (Detector) s.Detector;
- if(det == Detector::Normal) {
- det = binIndex & 0x01 ? Detector::PosPeak : Detector::NegPeak;
- }
- switch(det) {
- case Detector::PosPeak:
- if(pointInBin == 0) {
- p.spectrumResult.port1 = std::numeric_limits::min();
- p.spectrumResult.port2 = std::numeric_limits::min();
+ for(uint16_t i=0;i= binSize - 1;
+ auto det = (Detector) s.Detector;
+ if(det == Detector::Normal) {
+ det = binIndex & 0x01 ? Detector::PosPeak : Detector::NegPeak;
}
- if(port1Measurement > p.spectrumResult.port1) {
- p.spectrumResult.port1 = port1Measurement;
+ switch(det) {
+ case Detector::PosPeak:
+ if(pointInBin == 0) {
+ p.spectrumResult.port1 = std::numeric_limits::min();
+ p.spectrumResult.port2 = std::numeric_limits::min();
+ }
+ if(port1Measurement[i] > p.spectrumResult.port1) {
+ p.spectrumResult.port1 = port1Measurement[i];
+ }
+ if(port2Measurement[i] > p.spectrumResult.port2) {
+ p.spectrumResult.port2 = port2Measurement[i];
+ }
+ break;
+ case Detector::NegPeak:
+ if(pointInBin == 0) {
+ p.spectrumResult.port1 = std::numeric_limits::max();
+ p.spectrumResult.port2 = std::numeric_limits::max();
+ }
+ if(port1Measurement[i] < p.spectrumResult.port1) {
+ p.spectrumResult.port1 = port1Measurement[i];
+ }
+ if(port2Measurement[i] < p.spectrumResult.port2) {
+ p.spectrumResult.port2 = port2Measurement[i];
+ }
+ break;
+ case Detector::Sample:
+ if(pointInBin <= binSize / 2) {
+ // still in first half of bin, simply overwrite
+ p.spectrumResult.port1 = port1Measurement[i];
+ p.spectrumResult.port2 = port2Measurement[i];
+ }
+ break;
+ case Detector::Average:
+ if(pointInBin == 0) {
+ p.spectrumResult.port1 = 0;
+ p.spectrumResult.port2 = 0;
+ }
+ p.spectrumResult.port1 += port1Measurement[i];
+ p.spectrumResult.port2 += port2Measurement[i];
+ if(lastPointInBin) {
+ // calculate average
+ p.spectrumResult.port1 /= binSize;
+ p.spectrumResult.port2 /= binSize;
+ }
+ break;
+ case Detector::Normal:
+ // nothing to do, normal detector handled by PosPeak or NegPeak in each sample
+ break;
}
- if(port2Measurement > p.spectrumResult.port2) {
- p.spectrumResult.port2 = port2Measurement;
- }
- break;
- case Detector::NegPeak:
- if(pointInBin == 0) {
- p.spectrumResult.port1 = std::numeric_limits::max();
- p.spectrumResult.port2 = std::numeric_limits::max();
- }
- if(port1Measurement < p.spectrumResult.port1) {
- p.spectrumResult.port1 = port1Measurement;
- }
- if(port2Measurement < p.spectrumResult.port2) {
- p.spectrumResult.port2 = port2Measurement;
- }
- break;
- case Detector::Sample:
- if(pointInBin <= binSize / 2) {
- // still in first half of bin, simply overwrite
- p.spectrumResult.port1 = port1Measurement;
- p.spectrumResult.port2 = port2Measurement;
- }
- break;
- case Detector::Average:
- if(pointInBin == 0) {
- p.spectrumResult.port1 = 0;
- p.spectrumResult.port2 = 0;
- }
- p.spectrumResult.port1 += port1Measurement;
- p.spectrumResult.port2 += port2Measurement;
if(lastPointInBin) {
- // calculate average
- p.spectrumResult.port1 /= binSize;
- p.spectrumResult.port2 /= binSize;
+ // Send result to application
+ p.type = Protocol::PacketType::SpectrumAnalyzerResult;
+ // measurements are already up to date, fill remaining fields
+ p.spectrumResult.pointNum = binIndex;
+ p.spectrumResult.frequency = s.f_start + (s.f_stop - s.f_start) * binIndex / (s.pointNum - 1);
+ Communication::Send(p);
}
- break;
- case Detector::Normal:
- // nothing to do, normal detector handled by PosPeak or NegPeak in each sample
- break;
- }
- if(lastPointInBin) {
- // Send result to application
- p.type = Protocol::PacketType::SpectrumAnalyzerResult;
- // measurements are already up to date, fill remaining fields
- p.spectrumResult.pointNum = binIndex;
- p.spectrumResult.frequency = s.f_start + (s.f_stop - s.f_start) * binIndex / (s.pointNum - 1);
- Communication::Send(p);
}
// setup for next step
signalIDstep = 0;
- if(pointCnt < points - 1) {
- pointCnt++;
+ if(pointCnt < points - DFTpoints) {
+ pointCnt += DFTpoints;
} else {
pointCnt = 0;
}
diff --git a/Software/VNA_embedded/Application/VNA.cpp b/Software/VNA_embedded/Application/VNA.cpp
index 8d74732..450c10d 100644
--- a/Software/VNA_embedded/Application/VNA.cpp
+++ b/Software/VNA_embedded/Application/VNA.cpp
@@ -187,6 +187,9 @@ bool VNA::Setup(Protocol::SweepSettings s, SweepCallback cb) {
IFTableIndexCnt = 0;
adcShifted = false;
active = true;
+ // Enable new data and sweep halt interrupt
+ FPGA::EnableInterrupt(FPGA::Interrupt::NewData);
+ FPGA::EnableInterrupt(FPGA::Interrupt::SweepHalted);
// Start the sweep
FPGA::StartSweep();
return true;