Skip to content

Commit

Permalink
Merge pull request #14 from ianmalcolm/high_resolution_adc
Browse files Browse the repository at this point in the history
High resolution adc
  • Loading branch information
jack-h committed Aug 7, 2017
2 parents e48018f + 0663cbd commit f2f6bd0
Show file tree
Hide file tree
Showing 6 changed files with 407 additions and 244 deletions.
144 changes: 116 additions & 28 deletions jasper_library/hdl_sources/adc16_interface/ADC_ISERDES_7series.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@ use IEEE.numeric_std.all;

-- entity declaraction
entity ADC_ISERDES_7series is

generic (
ADC_RESOLUTION : integer := 8
);
port (
-- System
reset : in std_logic;
bitslip : in std_logic;

-- Clock inputs
clkin : in std_logic; -- line
clkdiv : in std_logic; -- frame
clkin : in std_logic; -- line clock or bit clock
clkdiv : in std_logic; -- fabric_clk or frame_clk_2x
frame_clk : in std_logic; -- frame_clk

-- Data (serial in, parallel out)
s_data : in std_logic;
p_data : out std_logic_vector(7 downto 0)
p_data : out std_logic_vector(ADC_RESOLUTION-1 downto 0)
);

end ADC_ISERDES_7series;
Expand Down Expand Up @@ -83,6 +86,16 @@ architecture ADC_ISERDES_arc of ADC_ISERDES_7series is
signal iserdes_bitslip_d2 : std_logic;
signal iserdes_bitslip_d3 : std_logic;

signal bitslip_swap : std_logic_vector( 1 downto 0);
-- signal bitslip_swap : std_logic;
signal bitslip_count : std_logic_vector( 3 downto 0);
signal bitslip_delay : std_logic_vector( 3 downto 0);
-- signal q_d0 : std_logic_vector( 7 downto 0);
signal q_d0 : std_logic_vector(15 downto 0);
signal q_d1 : std_logic_vector(15 downto 0);

attribute mark_debug : string;

begin

-- Signal routing
Expand All @@ -91,35 +104,110 @@ architecture ADC_ISERDES_arc of ADC_ISERDES_7series is
iserdes_clkdiv <= clkdiv;
iserdes_rst <= reset;
iserdes_d <= s_data;
-- iserdes_q is inverted, has MSb in bit 0 (due to differential-pair
-- routing on ADC16 board, and is in straight offset binary. Leave MSb
-- inverted to convert to 2's complement, but invert/restore polarity of
-- remaining bits and bit-reverse since ADC sends LSb first.
-- SNAP: reverse the bit inversion described above, since the snap doesn't flip differential pairs
p_data <= not iserdes_q(0) &
iserdes_q(1) &
iserdes_q(2) &
iserdes_q(3) &
iserdes_q(4) &
iserdes_q(5) &
iserdes_q(6) &
iserdes_q(7);

process (clkdiv)
begin
if rising_edge(clkdiv) then
iserdes_bitslip_d1 <= bitslip;
iserdes_bitslip_d2 <= iserdes_bitslip_d1;
iserdes_bitslip_d3 <= iserdes_bitslip_d2;
iserdes_bitslip <= (not iserdes_bitslip_d3 and iserdes_bitslip_d2);
end if;
end process;

ISERDES_BITSLIP_PROCESS: process ( clkdiv, reset, bitslip_delay )
begin
if reset = '1' then
bitslip_delay <= "0000";
elsif rising_edge(clkdiv) then
bitslip_delay(3 downto 1) <= bitslip_delay(2 downto 0);
bitslip_delay(0) <= bitslip;
end if;

-- Reference Xilinx UG471, the last paragraph of page 159:
-- Bitslip cannot be asserted for two consecutive CLKDIV cycles.
-- Bitslip must be deasserted for at least one CLKDIV cycle
-- between two bitslip assertions.
if bitslip_delay = "0001" then
iserdes_bitslip <= '1';
else
iserdes_bitslip <= '0';
end if;

-- Swap the two halves of the output of this module when ADC_RESOLUTON/2 bitslips
-- happen
if reset = '1' then
bitslip_count <= (others => '0');
bitslip_swap <= (others => '0');
elsif rising_edge(clkdiv) then
if bitslip_count < ADC_RESOLUTION/2 then
bitslip_count <= bitslip_count + iserdes_bitslip;
else
bitslip_count <= (others => '0');
bitslip_swap <= bitslip_swap + 1;
end if;
end if;
end process;

ISERDES_OUTPUT_PROCESS: process ( clkdiv, reset, bitslip_swap, q_d1 )
-- ISERDES_OUTPUT_PROCESS: process ( clkdiv, reset )
begin
if reset = '1' then
q_d0 <= (others => '0');
q_d1 <= (others => '0');
elsif rising_edge(clkdiv) then
-- Example 1 of receiving 0x5e, 0x5f and 0x60
-- frame_clk 0>1 1>0 0>1 1>0 0>1 1>0
-- q_d0 e f 0
-- q_d1 5 5 6
-- p_data 5e 5f 60

-- Example 2 of receiving 0x5e, 0x5f and 0x60
-- frame_clk 0>1 1>0 0>1 1>0 0>1 1>0
-- q_d0 5 5 6
-- q_d1 e f 0
-- p_data 5e 5f 60

if frame_clk = '0' then
q_d0( 7 downto 0) <= iserdes_q(0) &
iserdes_q(1) &
iserdes_q(2) &
iserdes_q(3) &
iserdes_q(4) &
iserdes_q(5) &
iserdes_q(6) &
iserdes_q(7);
else
q_d0(15 downto 8) <= iserdes_q(0) &
iserdes_q(1) &
iserdes_q(2) &
iserdes_q(3) &
iserdes_q(4) &
iserdes_q(5) &
iserdes_q(6) &
iserdes_q(7);
end if;

if frame_clk='0' and bitslip_swap(1)='0' then
q_d1( 7 downto 0) <= q_d0( 7 downto 0);
q_d1(15 downto 8) <= q_d0(15 downto 8);
elsif frame_clk='1' and bitslip_swap(1)='1' then
q_d1( 7 downto 0) <= q_d0(15 downto 8);
q_d1(15 downto 8) <= q_d0( 7 downto 0);
else
q_d1 <= q_d1;
end if;
end if;

if bitslip_swap(0) = '0' then
p_data <= q_d1(15 downto 16-ADC_RESOLUTION/2) &
q_d1( 7 downto 8-ADC_RESOLUTION/2);
else
p_data <= q_d1( 7 downto 8-ADC_RESOLUTION/2) &
q_d1(15 downto 16-ADC_RESOLUTION/2);

end if;

end process;



-- ISERDESE1 Master
iserdes_m_inst : ISERDESE2
GENERIC MAP (
DATA_RATE => "DDR",
DATA_WIDTH => 8,
-- DATA_WIDTH => 8,
DATA_WIDTH => ADC_RESOLUTION/2,
DYN_CLKDIV_INV_EN => false,
DYN_CLK_INV_EN => false,
INTERFACE_TYPE => "NETWORKING",
Expand Down
24 changes: 16 additions & 8 deletions jasper_library/hdl_sources/adc16_interface/ADC_MMCM.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use IEEE.numeric_std.all;

-- entity declaraction
entity ADC_MMCM is

generic (
ADC_RESOLUTION : integer := 8
);
port (
-- System
reset : in std_logic;
Expand Down Expand Up @@ -66,7 +68,7 @@ architecture ADC_MMCM_arc of ADC_MMCM is
CLKOUT3_PHASE : real;
CLKOUT3_DUTY_CYCLE : real;
CLKOUT3_USE_FINE_PS : boolean;
CLKIN1_PERIOD : real;
--CLKIN1_PERIOD : real;
REF_JITTER1 : real
);
port (
Expand Down Expand Up @@ -126,6 +128,12 @@ architecture ADC_MMCM_arc of ADC_MMCM is
signal mmcm_locked : std_logic;
signal mmcm_reset : std_logic;

constant CLK_MUL : REAL := 5.0;
constant CLK_DIV : Integer := 2;
constant CLK0_DIV : Real := CLK_MUL/Real(CLK_DIV);
constant CLK1_DIV : Integer := Integer(CLK0_DIV*(Real(ADC_RESOLUTION)/4.0)*2.0);
constant CLK2_DIV : Integer := Integer(CLK0_DIV*(Real(ADC_RESOLUTION)/4.0));

begin

-- Signal routing
Expand Down Expand Up @@ -153,27 +161,27 @@ architecture ADC_MMCM_arc of ADC_MMCM is
CLOCK_HOLD => false,
COMPENSATION => "ZHOLD",
STARTUP_WAIT => false,
DIVCLK_DIVIDE => 2, -- D = 2
CLKFBOUT_MULT_F => 5.000, -- M = 5.000
DIVCLK_DIVIDE => CLK_DIV, -- D = 2
CLKFBOUT_MULT_F => CLK_MUL, -- M = 5.000
CLKFBOUT_PHASE => 0.000,
CLKFBOUT_USE_FINE_PS => false,
CLKOUT0_DIVIDE_F => 2.500, -- Fout = (M * Fin) / (D * 2.500) = Fin (when D=2, M=5)
CLKOUT0_DIVIDE_F => CLK0_DIV, -- Fout = (M * Fin) / (D * 2.500) = Fin (when D=2, M=5)
CLKOUT0_PHASE => 0.000,
CLKOUT0_DUTY_CYCLE => 0.500,
CLKOUT0_USE_FINE_PS => false,
CLKOUT1_DIVIDE => 10, -- Fout = (M * Fin) / (D * 10) = Fin / 4 (when D=2, M=5)
CLKOUT1_DIVIDE => CLK1_DIV, -- Fout = (M * Fin) / (D * 10) = Fin / 4 (when D=2, M=5)
CLKOUT1_PHASE => 0.000,
CLKOUT1_DUTY_CYCLE => 0.500,
CLKOUT1_USE_FINE_PS => false,
CLKOUT2_DIVIDE => 5, -- Fout = (M * Fin) / (D * 4) = Fin / 2 (when D=2, M=5)
CLKOUT2_DIVIDE => CLK2_DIV, -- Fout = (M * Fin) / (D * 4) = Fin / 2 (when D=2, M=5)
CLKOUT2_PHASE => 0.000,
CLKOUT2_DUTY_CYCLE => 0.500,
CLKOUT2_USE_FINE_PS => false,
CLKOUT3_DIVIDE => 5, -- Fout = (M * Fin) / (D * 4) = Fin / 2 (when D=2, M=5)
CLKOUT3_PHASE => 90.000,
CLKOUT3_DUTY_CYCLE => 0.500,
CLKOUT3_USE_FINE_PS => false,
CLKIN1_PERIOD => 2.500, -- 400 MHz (should be calculated from user input)
-- CLKIN1_PERIOD => 2.500, -- 400 MHz (should be calculated from user input)
REF_JITTER1 => 0.010

--BANDWIDTH => "OPTIMIZED",
Expand Down
Loading

0 comments on commit f2f6bd0

Please sign in to comment.