419 lines
16 KiB
VHDL
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;
|
|
|