Commit b61af01c authored by David Cussans's avatar David Cussans

Changed triggerInput test bench to use logic_clocks entity.

This led to some minor changes to logic_clocks. Hopefully making it more robust...
parent def38894
......@@ -27,11 +27,11 @@
------------------------------------------------------------------------------
-- __primary__________40.000____________0.010
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
USE work.ipbus.all;
use work.ipbus.all;
library unisim;
use unisim.vcomponents.all;
......@@ -54,200 +54,260 @@ use unisim.vcomponents.all;
--! \li 0x00000001 - reset logic. Write to bit-zero to send reset.
--!
--!
ENTITY logic_clocks IS
GENERIC(
g_USE_EXTERNAL_CLK : integer := 1
entity logic_clocks is
generic(
g_USE_EXTERNAL_CLK : integer := 1
);
PORT(
ipbus_clk_i : IN std_logic;
ipbus_i : IN ipb_wbus;
ipbus_reset_i : IN std_logic;
Reset_i : IN std_logic;
clk_logic_xtal_i : IN std_logic; --! 40MHz clock derived from onboard xtal
clk_8x_logic_o : OUT std_logic; --! 640MHz clock
clk_4x_logic_o : OUT std_logic; --! 160MHz clock
ipbus_o : OUT ipb_rbus;
strobe_8x_logic_o : OUT std_logic; --! strobes once every 4 cycles of clk_16x
strobe_4x_logic_o : OUT std_logic; --! one pulse every 4 cycles of clk_4x
DUT_clk_o : OUT std_logic; --! 40MHz to DUTs
logic_clocks_locked_o : OUT std_logic; --! Goes high if clocks locked.
logic_reset_o : OUT std_logic --! Goes high to reset counters etc. Sync with clk_4x_logic
port(
ipbus_clk_i : in std_logic;
ipbus_i : in ipb_wbus;
ipbus_reset_i : in std_logic;
Reset_i : in std_logic;
clk_logic_xtal_i : in std_logic; --! 40MHz clock derived from onboard xtal
clk_8x_logic_o : out std_logic; --! 640MHz clock
clk_4x_logic_o : out std_logic; --! 160MHz clock
ipbus_o : out ipb_rbus;
strobe_8x_logic_o : out std_logic; --! strobes once every 4 cycles of clk_16x
strobe_4x_logic_o : out std_logic; --! one pulse every 4 cycles of clk_4x
DUT_clk_o : out std_logic; --! 40MHz to DUTs
logic_clocks_locked_o : out std_logic; --! Goes high if clocks locked.
logic_reset_o : out std_logic --! Goes high to reset counters etc. Sync with clk_4x_logic
);
-- Declarations
END ENTITY logic_clocks ;
end entity logic_clocks;
--
ARCHITECTURE rtl OF logic_clocks IS
signal s_clk40 : std_logic;
constant C_NUM_STROBE_TAPS : positive := 2; --! Adjust to shift strobes relative to 40MHz clock edge
signal s_clk40_delayed_160 : std_logic_vector(C_NUM_STROBE_TAPS downto 0); --! Shift register used to generate clock_4x strobe. Adjust length for correct alignment with incoming clock
signal s_clk40_delayed_320 : std_logic_vector((2*C_NUM_STROBE_TAPS)+1 downto 0); --! Shift register used to generate clock_8x strobe. Adjust length for correct alignment with incoming clock
signal s_clk160 ,s_clk160_internal : std_logic;
signal s_clk320 , s_clk320_internal : std_logic;
signal s_locked_pll : std_logic;
signal s_clk : std_logic;
signal s_DUT_Clk : std_logic;
signal s_clkfbout : std_logic;
signal s_logic_reset_ipb, s_logic_reset_ipb_d1 : std_logic := '0'; --! Reset signal in IPBus clock domain
signal s_logic_reset , s_logic_reset_d1 , s_logic_reset_d2 , s_logic_reset_d3 , s_logic_reset_d4 : std_logic := '0'; --! reset signal clocked onto logic-clock domain.
attribute SHREG_EXTRACT: string;
attribute SHREG_EXTRACT of s_logic_reset_d1: signal is "no"; -- Synchroniser not to be optimised into shreg
attribute SHREG_EXTRACT of s_logic_reset_d2: signal is "no"; -- Synchroniser not to be optimised into shreg
attribute SHREG_EXTRACT of s_logic_reset_d3: signal is "no"; -- Synchroniser not to be optimised into shreg
attribute SHREG_EXTRACT of s_logic_reset_d4: signal is "no"; -- Synchroniser not to be optimised into shreg
attribute SHREG_EXTRACT of s_clk40_delayed_160: signal is "no"; -- delay to help timing not to be optimised into shreg
attribute SHREG_EXTRACT of s_clk40_delayed_320: signal is "no"; -- delay to help timing not to be optimised into shreg
signal s_ipbus_ack : std_logic := '0';
signal s_reset_pll : std_logic := '0'; -- ! PLL Reset signal
signal s_clock_status_ipb : std_logic_vector( ipbus_o.ipb_rdata'range ); --! contains status of clocks
BEGIN
-----------------------------------------------------------------------------
-- IPBus write
-----------------------------------------------------------------------------
ipbus_write: process (ipbus_clk_i)
begin -- process ipb_clk_i
architecture rtl of logic_clocks is
signal s_clk40 : std_logic;
constant C_NUM_STROBE_TAPS : positive := 2; --! Adjust to shift strobes relative to 40MHz clock edge
signal s_clk40_delayed_160 : std_logic_vector(C_NUM_STROBE_TAPS downto 0); --! Shift register used to generate clock_4x strobe. Adjust length for correct alignment with incoming clock
signal s_clk40_delayed_320 : std_logic_vector((2*C_NUM_STROBE_TAPS)+1 downto 0); --! Shift register used to generate clock_8x strobe. Adjust length for correct alignment with incoming clock
signal s_clk160, s_clk160_internal : std_logic;
signal s_clk320, s_clk320_internal : std_logic;
signal s_locked_pll : std_logic;
signal s_clk : std_logic;
signal s_DUT_Clk : std_logic;
signal s_clkfbout : std_logic;
signal s_logic_reset_ipb, s_logic_reset_ipb_d1 : std_logic := '0'; --! Reset signal in IPBus clock domain
signal s_logic_reset, s_logic_reset_d1, s_logic_reset_d2, s_logic_reset_d3, s_logic_reset_d4 : std_logic := '0'; --! reset signal clocked onto logic-clock domain.
attribute SHREG_EXTRACT : string;
attribute SHREG_EXTRACT of s_logic_reset_d1 : signal is "no"; -- Synchroniser not to be optimised into shreg
attribute SHREG_EXTRACT of s_logic_reset_d2 : signal is "no"; -- Synchroniser not to be optimised into shreg
attribute SHREG_EXTRACT of s_logic_reset_d3 : signal is "no"; -- Synchroniser not to be optimised into shreg
attribute SHREG_EXTRACT of s_logic_reset_d4 : signal is "no"; -- Synchroniser not to be optimised into shreg
attribute SHREG_EXTRACT of s_clk40_delayed_160 : signal is "no"; -- delay to help timing not to be optimised into shreg
attribute SHREG_EXTRACT of s_clk40_delayed_320 : signal is "no"; -- delay to help timing not to be optimised into shreg
signal s_ipbus_ack : std_logic := '0';
signal s_reset_pll : std_logic := '0'; -- ! PLL Reset signal
signal s_clock_status_ipb : std_logic_vector(ipbus_o.ipb_rdata'range); --! contains status of clocks
signal s_enable_strobes : std_logic; -- take high to start strobes running.
begin
-----------------------------------------------------------------------------
-- IPBus write
-----------------------------------------------------------------------------
ipbus_write : process (ipbus_clk_i)
begin -- process ipb_clk_i
if rising_edge(ipbus_clk_i) then
s_logic_reset_ipb <= '0';
if (ipbus_i.ipb_strobe = '1' and ipbus_i.ipb_write = '1') then
case ipbus_i.ipb_addr(1 downto 0) is
when "01" =>
s_logic_reset_ipb <= ipbus_i.ipb_wdata(0) ; -- write to reset
when others => null;
end case;
end if;
-- register reset signal to aid timing.
s_logic_reset_ipb_d1 <= s_logic_reset_ipb;
s_ipbus_ack <= ipbus_i.ipb_strobe and not s_ipbus_ack;
-- register the clock status signals onto IPBus domain.
s_clock_status_ipb <= x"0000000" & '0' & '0' & '0' & s_locked_pll; -- The only useful bit is now the PLL lock status.
s_logic_reset_ipb <= '0';
if (ipbus_i.ipb_strobe = '1' and ipbus_i.ipb_write = '1') then
case ipbus_i.ipb_addr(1 downto 0) is
when "01" =>
s_logic_reset_ipb <= ipbus_i.ipb_wdata(0); -- write to reset
when others => null;
end case;
end if;
-- register reset signal to aid timing.
s_logic_reset_ipb_d1 <= s_logic_reset_ipb;
s_ipbus_ack <= ipbus_i.ipb_strobe and not s_ipbus_ack;
-- register the clock status signals onto IPBus domain.
s_clock_status_ipb <= x"0000000" & '0' & '0' & '0' & s_locked_pll; -- The only useful bit is now the PLL lock status.
end if;
end process ipbus_write;
end process ipbus_write;
ipbus_o.ipb_ack <= s_ipbus_ack;
ipbus_o.ipb_err <= '0';
ipbus_o.ipb_ack <= s_ipbus_ack;
ipbus_o.ipb_err <= '0';
-----------------------------------------------------------------------------
-- IPBUS read
-----------------------------------------------------------------------------
with ipbus_i.ipb_addr(1 downto 0) select
-----------------------------------------------------------------------------
-- IPBUS read
-----------------------------------------------------------------------------
with ipbus_i.ipb_addr(1 downto 0) select
ipbus_o.ipb_rdata <=
s_clock_status_ipb when "00",
(others => '1') when others;
s_clock_status_ipb when "00",
(others => '1') when others;
-----------------------------------------------------------------------------
-- Generate reset signal on logic-clock domain
-- This relies on the IPBus clock being much slower than the 4x logic clock.
-----------------------------------------------------------------------------
p_reset: process (s_clk160_internal)
begin -- process p_reset
-----------------------------------------------------------------------------
-- Generate reset signal on logic-clock domain
-- This relies on the IPBus clock being much slower than the 4x logic clock.
-----------------------------------------------------------------------------
p_reset : process (s_clk160_internal)
begin -- process p_reset
if rising_edge(s_clk160_internal) then
s_logic_reset_d1 <= s_logic_reset_ipb_d1;
s_logic_reset_d2 <= s_logic_reset_d1;
s_logic_reset_d3 <= s_logic_reset_d2;
s_logic_reset_d4 <= s_logic_reset_d2 and ( not s_logic_reset_d3);
s_logic_reset <= s_logic_reset_d4;
s_logic_reset_d1 <= s_logic_reset_ipb_d1;
s_logic_reset_d2 <= s_logic_reset_d1;
s_logic_reset_d3 <= s_logic_reset_d2;
s_logic_reset_d4 <= s_logic_reset_d2 and (not s_logic_reset_d3);
s_logic_reset <= s_logic_reset_d4;
end if;
end process p_reset;
logic_reset_o <= s_logic_reset;
logic_clocks_locked_o <= s_locked_pll;
s_DUT_Clk <= clk_logic_xtal_i;
--! Clocking primitive
-------------------------------------
--! Instantiation of the PLL primitive
pll_base_inst : PLL_BASE
end process p_reset;
logic_reset_o <= s_logic_reset or (not s_locked_pll);
logic_clocks_locked_o <= s_locked_pll;
s_DUT_Clk <= clk_logic_xtal_i;
--! Clocking primitive
-------------------------------------
--! Instantiation of the PLL primitive
pll_base_inst : PLL_BASE
generic map
(BANDWIDTH => "OPTIMIZED",
CLK_FEEDBACK => "CLKFBOUT",
COMPENSATION => "SYSTEM_SYNCHRONOUS",
DIVCLK_DIVIDE => 1,
CLKFBOUT_MULT => 16, -- Run PLL at 640MHz
CLKFBOUT_PHASE => 0.000,
CLKOUT0_DIVIDE => 2, -- CLK0 = 320MHz
CLKOUT0_PHASE => 0.000,
CLKOUT0_DUTY_CYCLE => 0.500,
CLKOUT1_DIVIDE => 4, -- CLK1 = 160MHz
CLKOUT1_PHASE => 0.000,
CLKOUT1_DUTY_CYCLE => 0.500,
CLKOUT2_DIVIDE => 16, -- CLK2 = 40MHz
CLKOUT2_PHASE => +16.900, -- Shift 40MHz clock later to avoid negative hold time in strobe generator
CLKOUT2_DUTY_CYCLE => 0.500,
CLKIN_PERIOD => 25.000,
REF_JITTER => 0.010)
(BANDWIDTH => "OPTIMIZED",
CLK_FEEDBACK => "CLKFBOUT",
COMPENSATION => "SYSTEM_SYNCHRONOUS",
DIVCLK_DIVIDE => 1,
CLKFBOUT_MULT => 16, -- Run PLL at 640MHz
CLKFBOUT_PHASE => 0.000,
CLKOUT0_DIVIDE => 2, -- CLK0 = 320MHz
CLKOUT0_PHASE => 0.000,
CLKOUT0_DUTY_CYCLE => 0.500,
CLKOUT1_DIVIDE => 4, -- CLK1 = 160MHz
CLKOUT1_PHASE => 0.000,
CLKOUT1_DUTY_CYCLE => 0.500,
CLKOUT2_DIVIDE => 16, -- CLK2 = 40MHz
CLKOUT2_PHASE => +16.875, -- Shift 40MHz clock later to avoid negative hold time in strobe generator
CLKOUT2_DUTY_CYCLE => 0.500,
CLKIN_PERIOD => 25.000,
REF_JITTER => 0.010)
port map(
-- Output clocks
CLKFBOUT => s_clkfbout,
CLKOUT0 => s_clk320,
CLKOUT1 => s_clk160,
CLKOUT2 => s_clk40,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
-- Status and control signals
LOCKED => s_locked_pll,
RST => s_reset_pll,
-- Input clock control
CLKFBIN => s_clkfbout,
CLKIN => s_DUT_clk);
-- Output clocks
CLKFBOUT => s_clkfbout,
CLKOUT0 => s_clk320,
CLKOUT1 => s_clk160,
CLKOUT2 => s_clk40,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
-- Status and control signals
LOCKED => s_locked_pll,
RST => s_reset_pll,
-- Input clock control
CLKFBIN => s_clkfbout,
CLKIN => s_DUT_clk);
-- TODO: Replace PLL_BASE ( Spartan6 etc. with PLLE2_ADV - synthesis tools
-- seem to cope but ........
-- plle2_adv_instL PLLE2_ADV
-- generic map
-- (BANDWIDTH => "OPTIMIZED",
-- COMPENSATION => "ZHOLD",
-- STARTUP_WAIT => "FALSE",
-- DIVCLK_DIVIDE => 1,
-- CLKFBOUT_MULT => 24,
-- CLKFBOUT_PHASE => 0.000,
-- CLKOUT0_DIVIDE => 3,
-- CLKOUT0_PHASE => 0.000,
-- CLKOUT0_DUTY_CYCLE => 0.500,
-- CLKOUT1_DIVIDE => 6,
-- CLKOUT1_PHASE => 0.000,
-- CLKOUT1_DUTY_CYCLE => 0.500,
-- CLKOUT2_DIVIDE => 24,
-- CLKOUT2_PHASE => 16.875,
-- CLKOUT2_DUTY_CYCLE => 0.500,
-- CLKIN1_PERIOD => 25.000)
-- port map (
-- .CLKFBOUT => s_clkfbout ,
-- .CLKOUT0 => s_clk320,
-- .CLKOUT1 => s_clk160,
-- .CLKOUT2 => s_clk40,
-- .CLKOUT3 => open,
-- .CLKOUT4 => open,
-- .CLKOUT5 => open,
-- // Input clock control
-- .CLKFBIN => s_clkfbout ,
-- .CLKIN1 => s_DUT_clk,
-- .CLKIN2 => '0',
-- -- Tied to always select the primary input clock
-- .CLKINSEL => '1',
-- -- Ports for dynamic reconfiguration
-- .DADDR => (others => '0') ,
-- .DCLK => '0',
-- .DEN => '0',
-- .DI => (others => '0') ,
-- .DO => open ,
-- .DRDY => open,
-- .DWE => '0',
-- -- Other control and status signals
-- .LOCKED => s_locked_pll,
-- .PWRDWN => '0',
-- .RST => s_clkfbout );
s_reset_pll <= Reset_i or s_logic_reset;
s_reset_pll <= Reset_i or s_logic_reset;
DUT_clk_o <= s_DUT_clk;
DUT_clk_o <= s_DUT_clk;
s_enable_strobes <= s_locked_pll when rising_edge(s_clk40);
-- Generate a strobe signal for 160MHz clock
generate_4x_strobe: process (s_clk160_internal, s_clk40)
begin -- process generate_4x_strobe
if rising_edge(s_clk160_internal) then
generate_4x_strobe : process (s_clk160_internal, s_clk40)
begin -- process generate_4x_strobe
if rising_edge(s_clk160_internal) then
if (s_enable_strobes = '0') then
s_clk40_delayed_160 <= (others => '0');
strobe_4x_logic_o <= '0';
else
s_clk40_delayed_160 <= s_clk40_delayed_160(s_clk40_delayed_160'left-1 downto 0) & s_clk40;
strobe_4x_logic_o <= s_clk40_delayed_160(s_clk40_delayed_160'left-1) and not s_clk40_delayed_160(s_clk40_delayed_160'left);
strobe_4x_logic_o <= s_clk40_delayed_160(s_clk40_delayed_160'left-1) and not s_clk40_delayed_160(s_clk40_delayed_160'left);
end if;
end process generate_4x_strobe;
end if;
end process generate_4x_strobe;
-- Generate a strobe signal for 320MHz clock
generate_8x_strobe: process (s_clk320_internal, s_clk40)
begin -- process generate_8x_strobe
if rising_edge(s_clk320_internal) then
generate_8x_strobe : process (s_clk320_internal, s_clk40)
begin -- process generate_8x_strobe
if rising_edge(s_clk320_internal) then
if (s_enable_strobes = '0') then
s_clk40_delayed_320 <= (others => '0');
strobe_8x_logic_o <= '0';
else
s_clk40_delayed_320 <= s_clk40_delayed_320(s_clk40_delayed_320'left-1 downto 0) & s_clk40;
strobe_8x_logic_o <= s_clk40_delayed_320(s_clk40_delayed_320'left-1) and not s_clk40_delayed_320(s_clk40_delayed_320'left);
strobe_8x_logic_o <= s_clk40_delayed_320(s_clk40_delayed_320'left-1) and not s_clk40_delayed_320(s_clk40_delayed_320'left);
end if;
end process generate_8x_strobe;
end if;
end process generate_8x_strobe;
-- buffer 160MHz (4x) clock
--------------------------------------
clk160_o_buf : BUFG
clk160_o_buf : BUFG
port map(
O => s_clk160_internal,
I => s_clk160);
clk_4x_logic_o <= s_clk160_internal;
O => s_clk160_internal,
I => s_clk160);
clk_4x_logic_o <= s_clk160_internal;
-- buffer 320MHz (8x) clock
--------------------------------------
clk320_o_buf: BUFG
clk320_o_buf : BUFG
port map (
I => s_clk320,
O => s_clk320_internal
);
clk_8x_logic_o <= s_clk320_internal;
END ARCHITECTURE rtl;
I => s_clk320,
O => s_clk320_internal
);
clk_8x_logic_o <= s_clk320_internal;
end architecture rtl;
......@@ -64,10 +64,14 @@ architecture bench of triggerInputs_newTLU_tb is
signal s_clk40_delayed_160 : std_logic_vector(C_NUM_STROBE_TAPS downto 0); --! Shift register used to generate clock_4x strobe. Adjust length for correct alignment with incoming clock
signal s_clk40_delayed_320 : std_logic_vector((2*C_NUM_STROBE_TAPS)+1 downto 0); --! Shift register used to generate clock_8x strobe. Adjust length for correct alignment with incoming clock
constant clock320_period: time := 3.125 ns; -- 320 MHz clock
constant clock200_period: time := 5 ns; -- 200 MHz clock
signal s_dut_clk, s_clocks_locked , s_logic_reset : std_logic;
constant delta : time := 0.02 ns; -- make sure IPBus clock drifts w.r.t.
-- logic clocks
constant clockLogic_period : time := 25 ns; -- 40MHz clock
--constant clock320_period: time := 3.125 ns; -- 320 MHz clock
constant clock200_period: time := 5 ns + delta; -- 200 MHz clock
constant clockipbus_period: time := 31.25 ns + delta; -- 320 MHz clock
signal stop_the_clock: boolean;
......@@ -82,7 +86,7 @@ begin
strobe_4x_logic_i => strobe_4x_logic_i,
threshold_discr_p_i => threshold_discr_p_i,
threshold_discr_n_i => threshold_discr_n_i,
reset_i => reset_i,
reset_i => s_logic_reset,
trigger_times_o => trigger_times_o,
trigger_o => trigger_o,
edge_rising_times_o => edge_rising_times_o,
......@@ -101,59 +105,47 @@ begin
stop_the_clock <= false;
-- Put initialisation code here
reset_i <= '1';
wait for clock320_period * 16;
ipbus_reset_i <= '1';
wait for clockLogic_period * 16;
reset_i <= '0';
wait for clock320_period * 200;
ipbus_reset_i <= '0';
wait for clockLogic_period * 500;
-- Put test bench stimulus code here
stop_the_clock <= true;
wait;
stop_the_clock <= true;
reset_i <= '1';
wait;
end process;
clock320: process
clockGenerator: ENTITY work.logic_clocks
port map (
ipbus_clk_i => ipbus_clk_i,
ipbus_i => ipbus_i,
ipbus_reset_i => ipbus_reset_i,
Reset_i => reset_i,
clk_logic_xtal_i => clk_logic,
clk_8x_logic_o => clk_8x_logic_i,
clk_4x_logic_o => clk_4x_logic,
ipbus_o => ipbus_o,
strobe_8x_logic_o => strobe_8x_logic_i,
strobe_4x_logic_o => strobe_4x_logic_i,
DUT_clk_o => s_dut_clk,
logic_clocks_locked_o => s_clocks_locked,
logic_reset_o => s_logic_reset
);
clockLogic: process
begin
while not stop_the_clock loop
clk_8x_logic_i <= '0', '1' after clock320_period / 2;
wait for clock320_period;
clk_logic <= '0', '1' after clockLogic_period / 2;
wait for clockLogic_period;
end loop;
wait;
end process;
clock4x_1x: process( clk_8x_logic_i )
variable ctr : unsigned(2 downto 0):= (others => '0');
begin
if rising_edge( clk_8x_logic_i ) then
clk_4x_logic <= not clk_4x_logic;
ctr := ctr + 1;
clk_logic <= ctr(2);
end if;
end process;
-- Generate a strobe signal for 160MHz clock
generate_4x_strobe: process (clk_4x_logic, clk_logic)
begin -- process generate_4x_strobe
if rising_edge(clk_4x_logic) then
s_clk40_delayed_160 <= s_clk40_delayed_160(s_clk40_delayed_160'left-1 downto 0) & clk_logic;
strobe_4x_logic_i <= s_clk40_delayed_160(s_clk40_delayed_160'left-1) and not s_clk40_delayed_160(s_clk40_delayed_160'left);
end if;
end process generate_4x_strobe;
-- Generate a strobe signal for 320MHz clock
generate_8x_strobe: process (clk_8x_logic_i, clk_logic)
begin -- process generate_4x_strobe
if rising_edge(clk_8x_logic_i) then
s_clk40_delayed_320 <= s_clk40_delayed_320(s_clk40_delayed_320'left-1 downto 0) & clk_logic;
strobe_8x_logic_i <= s_clk40_delayed_320(s_clk40_delayed_320'left-1) and not s_clk40_delayed_320(s_clk40_delayed_320'left);
end if;
end process generate_8x_strobe;
clockIpbus: process
begin
while not stop_the_clock loop
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment