Files
zcu102_ad9081/source/dds_pulse_2x_top.vhd

419 lines
16 KiB
VHDL

-------------------------------------------------------------------------------
-- Company:
-- Engineer: Jason M. Blevins
--
-- Create Date: 19:38:12 11/10/2016
-- Design Name:
-- Module Name: dds_pulse_2x_top - behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- * All information is proprietary/confidential *
--
-- Supports single channel mode or dual channel (summed) mode.
-- When using dual channel mode, the module hangs after the shortest of the
-- two pulse streams completes. Ideally, both streams will be equal length.
--
-- For each channel:
-- A 256-bit control word (32x8 right shifted in) is read from an external FIFO.
-- The control word contains all information needed to create a pulse
--
-- RESERVED = fifo_data_r(255 downto 241) -- 15-bits
-- SWAP IQ CHANELS = fifo_data_r(240) -- 1-bit set to '1' for negative frequencies
-- SCALE FACTOR TO SCALE OUTPUT AMPLITUDE = fifo_data_r(239 downto 224) -- 16-bits, (0,1], full-scale = 1.000000000000000
-- DDS PHASE OFFSET = fifo_data_r(223 downto 192) -- 32-bits, reserved, set to 0x0000_0000
-- DDS PHASE INCREMENT = fifo_data_r(191 downto 160) -- 32-bits
-- # DDS SAMPLES = fifo_data_r(159 downto 128) -- 32-bits
-- # MIDPOINT SAMPLES PRIOR TO PULSE = fifo_data_r(127 downto 96) -- 32-bits
-- RESERVED = fifo_data_r(95 downto 88) -- 8-bit
-- DDS PHASE INCREMENT STEP = fifo_data_r(87 downto 64) -- 24-bits (2's complement SIGNED !!)
-- RESERVED = fifo_data_r(63 downto 48) -- 16-bits
-- DDS PHASE INCREMENT DWELL = fifo_data_r(47 downto 32) -- 16-bits
--
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--Library UNIMACRO;
--use UNIMACRO.vcomponents.all;
USE IEEE.NUMERIC_STD.ALL;
entity dds_pulse_2x_top is
port(
clk_in : in std_logic;
rst_in : in std_logic;
mode_in : in std_logic; -- 0=single, 1=dual
scale_in : in std_logic_vector(15 downto 0);
fifo1_data_in : in std_logic_vector(31 downto 0);
fifo1_dval_in : in std_logic;
fifo1_empty_in : in std_logic;
fifo1_rden_out : out std_logic;
fifo2_data_in : in std_logic_vector(31 downto 0);
fifo2_dval_in : in std_logic;
fifo2_empty_in : in std_logic;
fifo2_rden_out : out std_logic;
holdoff_in : in std_logic;
overflow_out : out std_logic_vector(1 downto 0);
underflow_out : out std_logic_vector(1 downto 0);
i_max_abs_out : out std_logic_vector(15 downto 0);
q_max_abs_out : out std_logic_vector(15 downto 0);
data_out : out std_logic_vector(31 downto 0);
dval_out : out std_logic
);
end entity;
architecture mixed of dds_pulse_2x_top is
component mult_16signed_x_16unsigned_latency3
port(
clk : in std_logic;
a : in std_logic_vector(15 downto 0);
b : in std_logic_vector(15 downto 0);
ce : in std_logic;
sclr : in std_logic;
p : out std_logic_vector(15 downto 0)
);
end component;
component dds_pulse_gen is
port(
clk_in : in std_logic;
rst_in : in std_logic;
fifo_data_in : in std_logic_vector(31 downto 0);
fifo_dval_in : in std_logic;
fifo_empty_in : in std_logic;
fifo_rden_out : out std_logic;
holdoff_in : in std_logic;
data_out : out std_logic_vector(31 downto 0);
dval_out : out std_logic
);
end component;
component sfifo_32b_1024_pf992_latency1
port(
clk : in std_logic;
srst : in std_logic;
din : in std_logic_vector(31 downto 0);
wr_en : in std_logic;
rd_en : in std_logic;
dout : out std_logic_vector(31 downto 0);
full : out std_logic;
overflow : out std_logic;
empty : out std_logic;
underflow : out std_logic;
prog_full : out std_logic
);
end component;
component adder_16signed_16signed_latency2
port(
a : in std_logic_vector(15 downto 0);
b : in std_logic_vector(15 downto 0);
clk : in std_logic;
ce : in std_logic;
bypass : in std_logic;
s : out std_logic_vector(16 downto 0)
);
end component;
signal rst_r : std_logic := '1';
signal mode_n_r : std_logic := '1'; -- 1=single, 0=dual
signal scale_r : std_logic_vector(15 downto 0) := x"8000";
signal pulse_fifo_dval_r : std_logic_vector(1 downto 0) := "00";
signal pulse_adder_dval_r : std_logic := '0';
signal pulse_adder_ce : std_logic;
signal pulse_data_r : std_logic_vector(31 downto 0) := (others => '0');
signal pulse_dval_r : std_logic := '0';
signal adder_dval_r : std_logic := '0';
signal holdoff_r : std_logic;
signal pulse1_mult_dval_r : std_logic := '0';
signal pulse1_mult_ce_pipe_r : std_logic_vector(1 downto 0) := "00";
signal pulse1_mult_ce : std_logic;
signal pulse1_data : std_logic_vector(31 downto 0);
signal pulse1_dval : std_logic;
signal pulse1_data_scaled : std_logic_vector(31 downto 0);
signal pulse1_fifo_overflow : std_logic;
signal pulse1_fifo_empty : std_logic;
signal pulse1_fifo_underflow : std_logic;
signal pulse1_fifo_progfull : std_logic;
signal pulse1_fifo_rden : std_logic;
signal pulse1_fifo_rden_r : std_logic := '0';
signal pulse1_fifo_dout : std_logic_vector(31 downto 0);
signal pulse1_fifo_dout_r : std_logic_vector(31 downto 0) := (others => '0');
signal adder1_s : std_logic_vector(16 downto 0);
signal adder1_s_r : std_logic_vector(16 downto 0);
signal adder1_s_r1 : std_logic_vector(15 downto 0);
signal i_abs_max_r : unsigned(15 downto 0);
signal fifo1_underflow_r : std_logic := '0';
signal fifo1_overflow_r : std_logic := '0';
signal pulse2_mult_dval_r : std_logic := '0';
signal pulse2_mult_ce_pipe_r : std_logic_vector(1 downto 0) := "00";
signal pulse2_mult_ce : std_logic;
signal pulse2_data : std_logic_vector(31 downto 0);
signal pulse2_dval : std_logic;
signal pulse2_data_scaled : std_logic_vector(31 downto 0);
signal pulse2_fifo_overflow : std_logic;
signal pulse2_fifo_empty : std_logic;
signal pulse2_fifo_underflow : std_logic;
signal pulse2_fifo_progfull : std_logic;
signal pulse2_fifo_rden : std_logic;
signal pulse2_fifo_dout : std_logic_vector(31 downto 0);
signal pulse2_fifo_dout_r : std_logic_vector(31 downto 0);
signal adder2_s : std_logic_vector(16 downto 0);
signal adder2_s_r : std_logic_vector(16 downto 0);
signal adder2_s_r1 : std_logic_vector(15 downto 0);
signal q_abs_max_r : unsigned(15 downto 0);
signal fifo2_underflow_r : std_logic := '0';
signal fifo2_overflow_r : std_logic := '0';
begin
data_out <= pulse_data_r;
dval_out <= pulse_dval_r;
i_max_abs_out <= std_logic_vector(i_abs_max_r);
q_max_abs_out <= std_logic_vector(q_abs_max_r);
overflow_out <= fifo2_overflow_r & fifo1_overflow_r;
underflow_out <= fifo2_underflow_r & fifo1_underflow_r;
process(clk_in)
begin
if(rising_edge(clk_in))then
rst_r <= rst_in;
scale_r <= scale_in;
mode_n_r <= not(mode_in);
holdoff_r <= holdoff_in;
end if;
end process;
process(clk_in)
begin
if(rising_edge(clk_in))then
pulse1_mult_dval_r <= pulse1_mult_ce_pipe_r(1);
pulse1_mult_ce_pipe_r(1 downto 0) <= pulse1_mult_ce_pipe_r(0) & pulse1_dval;
pulse2_mult_dval_r <= pulse2_mult_ce_pipe_r(1);
pulse2_mult_ce_pipe_r(1 downto 0) <= pulse2_mult_ce_pipe_r(0) & pulse2_dval;
pulse_fifo_dval_r(1 downto 0) <= pulse_fifo_dval_r(0) & pulse1_fifo_rden_r;
pulse_adder_dval_r <= pulse_fifo_dval_r(1);
pulse1_fifo_rden_r <= pulse1_fifo_rden;
pulse1_fifo_dout_r <= pulse1_fifo_dout;
pulse2_fifo_dout_r <= pulse2_fifo_dout;
end if;
end process;
pulse1_mult_ce <= pulse1_mult_ce_pipe_r(1) or pulse1_mult_ce_pipe_r(0) or pulse1_dval;
pulse2_mult_ce <= pulse2_mult_ce_pipe_r(1) or pulse2_mult_ce_pipe_r(0) or pulse2_dval;
pulse1_fifo_rden <= not(pulse1_fifo_empty) and not(pulse2_fifo_empty) and not(holdoff_r) when mode_n_r = '0' else
not(pulse1_fifo_empty) and not(holdoff_r);
pulse2_fifo_rden <= not(pulse1_fifo_empty) and not(pulse2_fifo_empty) and not(holdoff_r) when mode_n_r = '0' else
'0';
pulse_adder_ce <= pulse_fifo_dval_r(1) or pulse_fifo_dval_r(0);
i_dds_pulse1_gen : dds_pulse_gen
port map(
clk_in => clk_in,
rst_in => rst_r,
fifo_data_in => fifo1_data_in,
fifo_dval_in => fifo1_dval_in,
fifo_empty_in => fifo1_empty_in,
fifo_rden_out => fifo1_rden_out,
holdoff_in => pulse1_fifo_progfull,
data_out => pulse1_data,
dval_out => pulse1_dval
);
i_pulse1_mult1 : mult_16signed_x_16unsigned_latency3
port map(
clk => clk_in,
a => pulse1_data(15 downto 0),
b => scale_r,
ce => pulse1_mult_ce,
sclr => '0',
p => pulse1_data_scaled(15 downto 0)
);
i_pulse1_mult2 : mult_16signed_x_16unsigned_latency3
port map(
clk => clk_in,
a => pulse1_data(31 downto 16),
b => scale_r,
ce => pulse1_mult_ce,
sclr => '0',
p => pulse1_data_scaled(31 downto 16)
);
i_pulse1_fifo : sfifo_32b_1024_pf992_latency1
port map(
clk => clk_in,
srst => rst_r,
din => pulse1_data_scaled,
wr_en => pulse1_mult_dval_r,
rd_en => pulse1_fifo_rden,
dout => pulse1_fifo_dout,
full => open,
overflow => pulse1_fifo_overflow,
empty => pulse1_fifo_empty,
underflow => pulse1_fifo_underflow,
prog_full => pulse1_fifo_progfull
);
i_dds_pulse2_gen : dds_pulse_gen
port map(
clk_in => clk_in,
rst_in => rst_r,
fifo_data_in => fifo2_data_in,
fifo_dval_in => fifo2_dval_in,
fifo_empty_in => fifo2_empty_in,
fifo_rden_out => fifo2_rden_out,
holdoff_in => pulse2_fifo_progfull,
data_out => pulse2_data,
dval_out => pulse2_dval
);
i_pulse2_mult1 : mult_16signed_x_16unsigned_latency3
port map(
clk => clk_in,
a => pulse2_data(15 downto 0),
b => scale_r,
ce => pulse2_mult_ce,
sclr => '0',
p => pulse2_data_scaled(15 downto 0)
);
i_pulse2_mult2 : mult_16signed_x_16unsigned_latency3
port map(
clk => clk_in,
a => pulse2_data(31 downto 16),
b => scale_r,
ce => pulse2_mult_ce,
sclr => '0',
p => pulse2_data_scaled(31 downto 16)
);
i_pulse2_fifo : sfifo_32b_1024_pf992_latency1
port map(
clk => clk_in,
srst => rst_r,
din => pulse2_data_scaled,
wr_en => pulse2_mult_dval_r,
rd_en => pulse2_fifo_rden,
dout => pulse2_fifo_dout,
full => open,
overflow => pulse2_fifo_overflow,
empty => pulse2_fifo_empty,
underflow => pulse2_fifo_underflow,
prog_full => pulse2_fifo_progfull
);
i_pulse_adder1 : adder_16signed_16signed_latency2
port map(
a => pulse2_fifo_dout_r(15 downto 0),
b => pulse1_fifo_dout_r(15 downto 0),
clk => clk_in,
ce => pulse_adder_ce,
bypass => mode_n_r, -- when set to '1', b input proceeds to s output
s => adder1_s
);
i_pulse_adder2 : adder_16signed_16signed_latency2
port map(
a => pulse2_fifo_dout_r(31 downto 16),
b => pulse1_fifo_dout_r(31 downto 16),
clk => clk_in,
ce => pulse_adder_ce,
bypass => mode_n_r, -- when set to '1', b input proceeds to s output
s => adder2_s
);
process(clk_in)
begin
if(rising_edge(clk_in))then
adder1_s_r <= adder1_s;
adder2_s_r <= adder2_s;
adder_dval_r <= pulse_adder_dval_r;
pulse_dval_r <= adder_dval_r;
if(adder_dval_r = '1')then
case adder1_s_r(16 downto 15) is
when "01" => --positive overflow
pulse_data_r(15 downto 0) <= x"7FFF";
when "10" => --negative overflow
pulse_data_r(15 downto 0) <= x"8000";
when others =>
pulse_data_r(15 downto 0) <= adder1_s_r(16) & adder1_s_r(14 downto 0);
end case;
case adder2_s_r(16 downto 15) is
when "01" => --positive overflow
pulse_data_r(31 downto 16) <= x"7FFF";
when "10" => --negative overflow
pulse_data_r(31 downto 16) <= x"8000";
when others =>
pulse_data_r(31 downto 16) <= adder2_s_r(16) & adder2_s_r(14 downto 0);
end case;
end if;
if(rst_r = '1')then
--adder_dval_r <= '0';
--pulse_dval_r <= '0';
i_abs_max_r <= (others => '0');
q_abs_max_r <= (others => '0');
fifo1_overflow_r <= '0';
fifo1_underflow_r <= '0';
fifo2_overflow_r <= '0';
fifo2_underflow_r <= '0';
else
--adder_dval_r <= pulse_adder_dval_r;
--pulse_dval_r <= adder_dval_r;
if(pulse1_fifo_overflow = '1')then
fifo1_overflow_r <= '1';
end if;
if(pulse1_fifo_underflow = '1')then
fifo1_underflow_r <= '1';
end if;
if(pulse2_fifo_overflow = '1')then
fifo2_overflow_r <= '1';
end if;
if(pulse2_fifo_underflow = '1')then
fifo2_underflow_r <= '1';
end if;
if(adder_dval_r = '1')then
-- if(abs(signed(adder1_s_r)) > i_abs_max_r)then
-- i_abs_max_r <= abs(signed(adder1_s_r));
-- end if;
if(adder1_s_r(16) = '0')then
adder1_s_r1 <= adder1_s_r(15 downto 0);
else
adder1_s_r1 <= not(adder1_s_r(15 downto 0));
end if;
-- if(abs(signed(adder2_s_r)) > q_abs_max_r)then
-- q_abs_max_r <= abs(signed(adder2_s_r));
-- end if;
if(adder2_s_r(16) = '0')then
adder2_s_r1 <= adder2_s_r(15 downto 0);
else
adder2_s_r1 <= not(adder2_s_r(15 downto 0));
end if;
end if;
if(pulse_dval_r = '1')then
if(unsigned(adder1_s_r1) > i_abs_max_r)then
i_abs_max_r <= unsigned(adder1_s_r1);
end if;
if(unsigned(adder2_s_r1) > q_abs_max_r)then
q_abs_max_r <= unsigned(adder2_s_r1);
end if;
end if;
end if;
end if;
end process;
end mixed;