Commit 14eb481d authored by David Cussans's avatar David Cussans

Checking in changes needed to get firmware to simulate under QuestSim

Also, tidying up code and hopefully reducing potential timing-race and meta-stability
issues.

eventFormatter_rtl.vhd
parent eb9752c5
......@@ -175,14 +175,24 @@ BEGIN
end process examine_lut;
--! Coarse time stamp. Phase w.r.t. strobe
c_coarse_ts : entity work.CounterUp
-- c_coarse_ts : entity work.CounterUp
-- PORT MAP (
-- clk => clk_4x_logic_i,
-- ce => '1',
-- sinit => strobe_4x_logic_i, --'0',
-- q(31 downto 2) => open,
-- q(1 downto 0) => s_coarse_bits
-- );
--
c_coarse_ts : entity work.CounterWithReset
GENERIC MAP (
g_COUNTER_WIDTH => 2 )
PORT MAP (
clk => clk_4x_logic_i,
ce => '1',
sinit => strobe_4x_logic_i, --'0',
q(31 downto 2) => open,
q(1 downto 0) => s_coarse_bits
clock_i => clk_4x_logic_i,
enable_i => '1',
reset_i => strobe_4x_logic_i, --'0',
result_o => s_coarse_bits
);
END ARCHITECTURE rtl;
......@@ -36,12 +36,12 @@ architecture rtl of clocks_s6_extphy is
signal s_clk_logic_xtal : std_logic;
-- signal clk_400: std_logic;
component clock_divider_s6 port(
clk: in std_logic;
d25: out std_logic;
d28: out std_logic
);
end component;
-- component clock_divider_s6 port(
-- clk: in std_logic;
-- d25: out std_logic;
-- d28: out std_logic
-- );
-- end component;
begin
......@@ -90,8 +90,10 @@ begin
rst => '0'
);
clkdiv: clock_divider_s6 port map(
clkdiv: entity work.clock_divider_s6 port map(
-- clkdiv: entity work.clock_div port map(
clk => sysclk,
-- D17 => open,
d25 => d25,
d28 => onehz
);
......
--=============================================================================
--! @file counterWithReset_rtl.vhd
--=============================================================================
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- unit name: counterWithReset (counterWithReset / rtl)
--
--! @brief Simple counter with synchronous reset
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date Feb\2012
--
--! @version v0.1
--
--! @details
--!
--! <b>Dependencies:</b>\n
--! None
--!
--! <b>References:</b>\n
--! referenced by ipBusMarocTriggerGenerator \n
--!
--! <b>Modified by:</b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--! 5/Mar/12 DGC Changed to use numeric_std\n
--! 26/Feb/14 DGC Added registers to output to aid timing closure.
--!
-------------------------------------------------------------------------------
--! @todo <next thing to do> \n
--! <another thing to do> \n
---------------------------------------------------------------------------------
--============================================================================
--! Entity declaration for counterWithReset
--============================================================================
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
ENTITY counterWithReset IS
GENERIC (g_COUNTER_WIDTH : integer := 32; --! Number of bits
g_OUTPUT_REGISTERS : integer := 4 --! Number of output registers. Minumum =1. Aids timing closure.
);
PORT
(
clock_i: IN STD_LOGIC; --! rising edge active clock
reset_i: IN STD_LOGIC; --! Active high. syncronous with rising clk
enable_i: IN STD_LOGIC; --! counts when enable=1
result_o: OUT STD_LOGIC_VECTOR ( g_COUNTER_WIDTH-1 downto 0) --! Unsigned integer output
);
END counterWithReset;
ARCHITECTURE rtl OF counterWithReset IS
type t_register_array is array(natural range <>) of UNSIGNED ( g_COUNTER_WIDTH-1 downto 0) ; -- --! Array of arrays for output register...
signal s_output_registers : t_register_array(g_OUTPUT_REGISTERS downto 0); -- --! Output registers.
BEGIN
--! Process to count up from zero when enable_i is high.
p_counter: PROCESS (clock_i)
BEGIN
IF rising_edge(clock_i) THEN
IF (reset_i = '1') THEN
s_output_registers(0) <= (others => '0');
ELSIF (enable_i='1') THEN
s_output_registers(0) <= s_output_registers(0) + 1;
END IF;
END IF;
END PROCESS p_counter;
--! Generate some output registers. Number controlled by g_OUTPUT_REGISTERS
generate_registers: for v_register in 1 to g_OUTPUT_REGISTERS generate
--! An individual register
p_outputRegister: process (clock_i)
begin -- process p_outputRegister
if rising_edge(clock_i) then
s_output_registers( v_register) <=
s_output_registers( v_register-1);
end if;
end process p_outputRegister;
end generate generate_registers; -- v_register
--! Copy the (registered) result to the output
result_o <= STD_LOGIC_VECTOR(s_output_registers(g_OUTPUT_REGISTERS));
END rtl;
......@@ -29,6 +29,7 @@
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--! Separated FSM for calibration control into a separate entity. DGC, 22/Feb/14
-------------------------------------------------------------------------------
--! @todo Implement a periodic calibration sequence\n
--! <another thing to do> \n
......@@ -73,105 +74,52 @@ ARCHITECTURE rtl OF dualSERDES_1to4 IS
signal s_data_o : std_logic_vector(7 downto 0); --! Deserialized data
signal s_rst : std_logic := '0'; -- IODELAY and ISERDES reset
signal s_cal_FSM : std_logic := '0'; --! Take high to calibrate the IDELAY components
signal s_rst_FSM : std_logic := '0'; -- IODELAY reset
signal s_initial_cal : std_logic := '1'; -- Start up calibration flag
signal s_calibration : std_logic := '0'; -- Start calibration
--! Calibration FSM state values
type state_values is (st0, st1, st2, st3, st4);
signal pres_state, next_state: state_values := st0;
BEGIN
--! Calibration start condition
s_calibration <= serdes_reset_i or s_initial_cal;
s_rst <= s_rst_FSM; -- or serdes_reset_i;
--! Calibration FSM register
statereg: process(fabricClk_i, serdes_reset_i)
begin
if rising_edge(fabricClk_i) then
pres_state <= next_state; -- Move to next state
end if;
end process statereg;
--! Calibration FSM combinational block
fsm: process(pres_state, s_calibration, s_busy_idelay_m)
begin
next_state <= pres_state;
-- Default values
s_Rst_FSM <= '0';
s_cal_FSM <= '0';
case pres_state is
-- st0 - IDLE
when st0=>
if ( s_calibration = '1') then
next_state <= st1; -- Next state is "st1 - SEND CALIBRATION SIGNAL"
end if;
-- st1 - SEND CALIBRATION SIGNAL
when st1=>
s_cal_FSM <= '1';
s_initial_cal <= '0';
if s_busy_idelay_m = '1' then
next_state <= st2; -- Next state is "st2 - WAIT BUSY = '0'"
end if;
-- st2 - WAIT BUSY = '0'
when st2=>
if s_busy_idelay_m = '0' then
next_state <= st3; -- Next state is "st3 - RESET STATE"
end if;
-- st3 - RESET STATE
when st3=>
s_Rst_FSM <= '1';
if s_busy_idelay_m = '1' then
next_state <= st4; -- Next state is "st4 - WAIT BUSY = '0'"
end if;
-- st4 - WAIT BUSY = '0'
when st4=>
if s_busy_idelay_m = '0' then
next_state <= st0; -- Next state is "st0 - IDLE"
end if;
end case;
end process fsm;
IODELAY2_Prompt : IODELAY2
generic map (
COUNTER_WRAPAROUND => "STAY_AT_LIMIT", -- "STAY_AT_LIMIT" or "WRAPAROUND"
DATA_RATE => "SDR", -- "SDR" or "DDR"
DELAY_SRC => "IDATAIN", -- "IO", "ODATAIN" or "IDATAIN"
IDELAY_MODE => "NORMAL", -- "NORMAL" or "PCI"
--SERDES_MODE => "MASTER", -- <NONE>, MASTER, SLAVE
IDELAY_TYPE => "VARIABLE_FROM_HALF_MAX", -- "FIXED", "DEFAULT", "VARIABLE_FROM_ZERO", "VARIABLE_FROM_HALF_MAX"
BEGIN
calibration_fsm: entity work.serdesCalibrateFSM
port map (
fsm_clk_i => fabricClk_i,
serdes_reset_i => serdes_reset_i,
busy_idelay_m_i => s_busy_idelay_m,
calibrate_o => s_cal_FSM,
reset_o => s_rst);
IODELAY2_Prompt : IODELAY2
generic map (
COUNTER_WRAPAROUND => "STAY_AT_LIMIT", -- "STAY_AT_LIMIT" or "WRAPAROUND"
DATA_RATE => "SDR", -- "SDR" or "DDR"
DELAY_SRC => "IDATAIN", -- "IO", "ODATAIN" or "IDATAIN"
IDELAY_MODE => "NORMAL", -- "NORMAL" or "PCI"
SERDES_MODE => "NONE", -- <NONE>, MASTER, SLAVE
IDELAY_TYPE => "VARIABLE_FROM_HALF_MAX", -- "FIXED", "DEFAULT", "VARIABLE_FROM_ZERO", "VARIABLE_FROM_HALF_MAX"
-- or "DIFF_PHASE_DETECTOR"
IDELAY_VALUE => 0, -- Amount of taps for fixed input delay (0-255)
IDELAY2_VALUE => 0, -- Delay value when IDELAY_MODE="PCI" (0-255)
ODELAY_VALUE => 0 -- Amount of taps fixed output delay (0-255)
--SIM_TAPDELAY_VALUE=> 50 -- Per tap delay used for simulation in ps
)
port map (
BUSY => s_busy_idelay_m, -- 1-bit output: Busy output after CAL
DATAOUT => s_Data_i_d_p, -- 1-bit output: Delayed data output to ISERDES/input register
DATAOUT2 => open, -- 1-bit output: Delayed data output to general FPGA fabric
DOUT => open, -- 1-bit output: Delayed data output
TOUT => open, -- 1-bit output: Delayed 3-state output
CAL => s_cal_FSM, -- 1-bit input: Initiate calibration input
CE => '0', -- 1-bit input: Enable INC input
CLK => fabricClk_i, -- 1-bit input: Clock input
IDATAIN => data_i, -- 1-bit input: Data input (connect to top-level port or I/O buffer)
INC => '0', -- 1-bit input: Increment / decrement input
IOCLK0 => fastClk_i, -- 1-bit input: Input from the I/O clock network
IOCLK1 => '0', -- 1-bit input: Input from the I/O clock network
ODATAIN => '0', -- 1-bit input: Output data input from output register or OSERDES2.
RST => s_rst, -- 1-bit input: reset_i to zero or 1/2 of total delay period
T => '0' -- 1-bit input: 3-state input signal
);
IDELAY_VALUE => 0, -- Amount of taps for fixed input delay (0-255)
IDELAY2_VALUE => 0, -- Delay value when IDELAY_MODE="PCI" (0-255)
ODELAY_VALUE => 0 -- Amount of taps fixed output delay (0-255)
--SIM_TAPDELAY_VALUE=> 50 -- Per tap delay used for simulation in ps
)
port map (
BUSY => s_busy_idelay_m, -- 1-bit output: Busy output after CAL
DATAOUT => s_Data_i_d_p, -- 1-bit output: Delayed data output to ISERDES/input register
DATAOUT2 => open, -- 1-bit output: Delayed data output to general FPGA fabric
DOUT => open, -- 1-bit output: Delayed data output
TOUT => open, -- 1-bit output: Delayed 3-state output
CAL => s_cal_FSM, -- 1-bit input: Initiate calibration input
CE => '0', -- 1-bit input: Enable INC input
CLK => fabricClk_i, -- 1-bit input: Clock input
IDATAIN => data_i, -- 1-bit input: Data input (connect to top-level port or I/O buffer)
INC => '0', -- 1-bit input: Increment / decrement input
IOCLK0 => fastClk_i, -- 1-bit input: Input from the I/O clock network
IOCLK1 => '0', -- 1-bit input: Input from the I/O clock network
ODATAIN => '0', -- 1-bit input: Output data input from output register or OSERDES2.
RST => s_rst, -- 1-bit input: reset_i to zero or 1/2 of total delay period
T => '0' -- 1-bit input: 3-state input signal
);
IODELAY2_Delayed : IODELAY2
......@@ -180,8 +128,8 @@ BEGIN
DATA_RATE => "SDR", -- "SDR" or "DDR"
DELAY_SRC => "IDATAIN", -- "IO", "ODATAIN" or "IDATAIN"
IDELAY_MODE => "NORMAL", -- "NORMAL" or "PCI"
--SERDES_MODE => "SLAVE", -- <NONE>, MASTER, SLAVE
IDELAY_TYPE => "FIXED", -- "FIXED", "DEFAULT", "VARIABLE_FROM_ZERO", "VARIABLE_FROM_HALF_MAX"
SERDES_MODE => "NONE", -- <NONE>, MASTER, SLAVE
IDELAY_TYPE => "VARIABLE_FROM_ZERO", -- "FIXED", "DEFAULT", "VARIABLE_FROM_ZERO", "VARIABLE_FROM_HALF_MAX"
-- or "DIFF_PHASE_DETECTOR"
IDELAY_VALUE => 0, -- Amount of taps for fixed input delay (0-255) 10->0.75nS, 11->0.825nS
IDELAY2_VALUE => 0, -- Delay value when IDELAY_MODE="PCI" (0-255)
......@@ -194,12 +142,12 @@ BEGIN
DATAOUT2 => open, -- 1-bit output: Delayed data output to general FPGA fabric
DOUT => open, -- 1-bit output: Delayed data output
TOUT => open, -- 1-bit output: Delayed 3-state output
CAL => '0', -- 1-bit input: Initiate calibration input
CAL => s_cal_FSM, -- 1-bit input: Initiate calibration input
CE => '0', -- 1-bit input: Enable INC input
CLK => '0', -- 1-bit input: Clock input
IDATAIN => Data_i, -- 1-bit input: Data input (connect to top-level port or I/O buffer)
CLK => fabricClk_i, -- 1-bit input: Clock input
IDATAIN => data_i, -- 1-bit input: Data input (connect to top-level port or I/O buffer)
INC => '0', -- 1-bit input: Increment / decrement input
IOCLK0 => '0', -- 1-bit input: Input from the I/O clock network
IOCLK0 => fastClk_i, -- 1-bit input: Input from the I/O clock network
IOCLK1 => '0', -- 1-bit input: Input from the I/O clock network
ODATAIN => '0', -- 1-bit input: Output data input from output register or OSERDES2.
RST => s_rst, -- 1-bit input: reset_i to zero or 1/2 of total delay period
......
......@@ -30,6 +30,8 @@
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--! 27/Feb/14 DGC Change "If" when setting s_word2 to a case ... generate. Questasim
--! doesn't like having an if that can take an array out of bounds.
-------------------------------------------------------------------------------
--! @todo Add more input data: \n
--! a) shutter signals. One per DUT. ?? \n
......@@ -114,7 +116,7 @@ ARCHITECTURE rtl OF eventFormatter IS
-- 3 - Spill
--! delayed strobes
signal s_event_strobe , s_event_strobe_d1 ,s_event_strobe_d2 ,s_event_strobe_d3 : std_logic := '0';
signal s_event_strobe , s_event_strobe_d1 ,s_event_strobe_d2 ,s_event_strobe_d3 , s_event_strobe_d3_opt : std_logic := '0';
signal shutter_i_d1, shutter_i_d2, edge_i_d1, edge_i_d2, spill_i_d1, spill_i_d2 : std_logic := '0';
signal s_evttype : t_evttype(3+g_NUM_EDGE_INPUTS-1 downto 0) := (others=>(others=>'0')); -- Event type
......@@ -212,22 +214,26 @@ BEGIN
if rising_edge(clk_4x_logic_i) then
s_event_strobe_d1 <= trigger_i and s_enable_trigger;
s_event_strobe_d2 <= s_event_strobe_d1;
if to_unsigned(g_NUM_TRIG_INPUTS,4) > 4 then
s_event_strobe_d3 <= s_event_strobe_d2;
end if;
s_event_strobe_d3 <= s_event_strobe_d2;
s_FIFO_rd_d <= s_FIFO_rd;
s_FIFO_rd_d <= s_FIFO_rd;
shutter_i_d1 <= shutter_i and s_enable_shutter;
shutter_i_d2 <= shutter_i_d1;
shutter_i_d1 <= shutter_i and s_enable_shutter;
shutter_i_d2 <= shutter_i_d1;
spill_i_d1 <= spill_i and s_enable_spill;
spill_i_d2 <= spill_i_d1;
spill_i_d1 <= spill_i and s_enable_spill;
spill_i_d2 <= spill_i_d1;
end if;
end process p_reg;
-- If there are more than 4 trigger inputs we need to fill a second word.
-- .. do this by having an optional strobe.
-- If 4 or fewer trigger inputs, just leave s_event_strobe_d3_opt at zero..
gen_strobe_d3: if (g_NUM_TRIG_INPUTS > 4) generate
s_event_strobe_d3_opt <= s_event_strobe_d3;
end generate;
-------------------------------------------------------------------------------
-- Trigger event formater
-------------------------------------------------------------------------------
......@@ -240,40 +246,66 @@ BEGIN
s_word1 <= "000" & trigger_times_i(0) & "000" & trigger_times_i(1) &
"000" & trigger_times_i(2) & "000" & trigger_times_i(3) &
trigger_cnt_i;
s_word2 <= "000" & trigger_times_i(4) & X"00000000000000" when (g_NUM_TRIG_INPUTS = 5) else
"000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
X"000000000000" when (g_NUM_TRIG_INPUTS = 6) else
"000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
"000" & trigger_times_i(6) & X"0000000000" when (g_NUM_TRIG_INPUTS = 7) else
"000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
"000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
X"00000000" when (g_NUM_TRIG_INPUTS = 8) else
"000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
"000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
"000" & trigger_times_i(8) & X"000000" when (g_NUM_TRIG_INPUTS = 9) else
"000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
"000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
"000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
X"0000" when (g_NUM_TRIG_INPUTS = 10) else
"000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
"000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
"000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
"000" & trigger_times_i(10)& X"00" when (g_NUM_TRIG_INPUTS = 11) else
"000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
"000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
"000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
"000" & trigger_times_i(10)& "000" & trigger_times_i(11) when (g_NUM_TRIG_INPUTS = 12) else
(others=>'0');
-- Different number of trigger inputs require packing into s_word2 in
-- different ways.
-- Do this in a generate since g_NUM_TRIG_INPUTS is static and
-- Questasim doesn't like refering to indices outside declared range.
s_word2 <= (others=>'0'); -- Set all bits to zero
-- then override with the following assignments....
gen_word2: for v_trigInput in 4 to g_NUM_TRIG_INPUTS-1 generate
s_word2( (((11-v_trigInput)*8)+c_NUM_TIME_BITS-1) downto ((11-v_trigInput)*8) ) <= trigger_times_i(v_trigInput);
end generate;
-- N.B. This is VHDL-2008 syntax.
-- Would be easier to do this with a for ... generate loop, but I
-- didn't think of this in time....
-- gen_word2: case g_NUM_TRIG_INPUTS generate
-- when 5 =>
-- s_word2 <= "000" & trigger_times_i(4) & X"00000000000000";
-- when 6 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- X"000000000000";
-- when 7 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & X"0000000000";
-- when 8 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- X"00000000";
-- when 9 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- "000" & trigger_times_i(8) & X"000000" ;
-- when 10 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- "000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
-- X"0000" ;
-- when 11 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- "000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
-- "000" & trigger_times_i(10)& X"00" ;
-- when 12 =>
-- s_word2 <= "000" & trigger_times_i(4) & "000" & trigger_times_i(5) &
-- "000" & trigger_times_i(6) & "000" & trigger_times_i(7) &
-- "000" & trigger_times_i(8) & "000" & trigger_times_i(9) &
-- "000" & trigger_times_i(10)& "000" & trigger_times_i(11) ;
-- when others =>
-- s_word2 <= (others=>'0');
-- end generate;
--! Could also output data on trigger_i , but let's use the delayed signals. \n
--! The counters are one cicle delayed from the signal generation
--! The counters are one cycle delayed from the signal generation
s_FIFO_i(0) <= s_word0 when (s_event_strobe_d1 = '1') else
s_word1 when (s_event_strobe_d2 = '1') else
s_word2 when (s_event_strobe_d3 = '1') else
s_word2 when (s_event_strobe_d3_opt = '1') else
(others => '0');
--! If there is data in the FIFO output we put the strobe signal at high level.
s_FIFO_wr(0) <= s_event_strobe_d1 or s_event_strobe_d2 or s_event_strobe_d3;
s_FIFO_wr(0) <= s_event_strobe_d1 or s_event_strobe_d2 or s_event_strobe_d3_opt;
s_FIFO_wr(1) <= shutter_i_d1 xor shutter_i_d2;
s_evttype(1) <= "0011" when shutter_i_d1 = '1' and shutter_i_d2 = '0' else
......
......@@ -91,6 +91,7 @@ BEGIN
ipbus_o.ipb_rdata(31 downto 8) <= ( others => '0');
ipbus_o.ipb_err <= '1'; -- never return an error.
END ARCHITECTURE rtl;
......@@ -20,7 +20,7 @@ architecture rtl of ipbus_ver is
begin
ipbus_out.ipb_rdata <= X"a5e3" & X"1008"; -- Lower 16b are ipbus firmware build ID (temporary arrangement).
ipbus_out.ipb_rdata <= X"a5e4" & X"1008"; -- Lower 16b are ipbus firmware build ID (temporary arrangement).
ipbus_out.ipb_ack <= ipbus_in.ipb_strobe;
ipbus_out.ipb_err <= '0';
......
......@@ -114,12 +114,14 @@ ARCHITECTURE rtl OF logic_clocks IS
signal s_logic_clk_generator : std_logic_vector(3 downto 0) := "1100"; --! Stores state of 40MHz "clock"
signal s_strobe_fb : std_logic := '0';
signal s_logic_reset_ipb : std_logic := '0';
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 : std_logic := '0';
-- ! reset signal clocked onto logic-clock domain.
signal s_ipbus_ack : std_logic := '0';
signal s_reset_pll : std_logic := '0';
--signal s_Reset : std_logic := '0';
-- ! Global Reset signal
......@@ -149,7 +151,10 @@ BEGIN
end if;
s_ipbus_ack <= ipbus_i.ipb_strobe and not s_ipbus_ack;
-- 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;
end if;
end process ipbus_write;
......@@ -173,7 +178,7 @@ BEGIN
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;
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 <= s_logic_reset_d2 and ( not s_logic_reset_d3);
......@@ -297,11 +302,12 @@ BEGIN
-- Status and control signals
LOCKED => s_locked_pll,
-- RST => s_logic_clk_rst,
RST => Reset_i or s_logic_reset, --'0',
RST => s_reset_pll,
-- Input clock control
CLKFBIN => s_clkfbout_buf,
CLKIN => s_clk);
s_reset_pll <= Reset_i or s_logic_reset;
-- Buffer the 16x clock and generate the ISERDES strobe signal
BUFPLL_inst : BUFPLL
......
......@@ -37,7 +37,8 @@
--! <b>References:</b>\n
--!
--! <b>Modified by:</b>\n
--! Author:
--! Author:
--! David Cussans, 26/2/14 - Added registers to output to aid timing closure.
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
-------------------------------------------------------------------------------
......
--=============================================================================
--! @file serdesCalibrateFSM_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- UoB , USC
-- --
------------------------------------------------------------------------------- --
--
--! @brief Finite-state machine to control calibration and reset signals to
--! Iserdes, IDelay
--! based on code by Alvaro Dosil\n
--
--! @author Alvaro Dosil (David Cussans , David.Cussans@bristol.ac.uk)
--
--! @date 22/Feb/2014
--
--! @version v0.1
--
--! @details
--
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
-------------------------------------------------------------------------------
--! @todo Implement a periodic calibration sequence\n
--! <another thing to do> \n
-
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity serdesCalibrateFSM is
port (
serdes_reset_i : in std_logic; --! Take high to start calibration
fsm_clock_i : in std_logic;
busy_idelay_m_i , busy_idelay_m_i : in std_logic; --! Status of IDELAY elements.
calibrate_o , reset_o : out std_logic --! Output from FSM to calibrate and reset lines
);
end entity serdesCalibrateFSM;
architecture rtl of serdesCalibrateFSM is
signal s_calibration : std_logic := '0'; -- Start calibration
--! Calibration FSM state values
type state_values is (st0, st1, st2, st3, st4);
signal pres_state, next_state: state_values := st0;
signal s_initial_cal : std_logic := '1'; -- Start up calibration flag
signal s_rst_FSM : std_logic := '0'; -- IODELAY reset
begin -- rtl
--! Calibration start condition
s_calibration <= serdes_reset_i or s_initial_cal;
--! Calibration FSM register
statereg: process(fabricClk_i, serdes_reset_i)
begin
if rising_edge(fabricClk_i) then
pres_state <= next_state; -- Move to next state
end if;
end process statereg;
--! Calibration FSM combinational block
fsm: process(pres_state, s_calibration, s_busy_idelay_m)
begin
next_state <= pres_state;
-- Default values
s_Rst_FSM <= '0';
s_cal_FSM <= '0';
case pres_state is
-- st0 - IDLE
when st0=>
if ( s_calibration = '1') then
next_state <= st1; -- Next state is "st1 - SEND CALIBRATION SIGNAL"
end if;
-- st1 - SEND CALIBRATION SIGNAL
when st1=>
s_cal_FSM <= '1';
s_initial_cal <= '0';
if s_busy_idelay_m = '1' then
next_state <= st2; -- Next state is "st2 - WAIT BUSY = '0'"
end if;
-- st2 - WAIT BUSY = '0'
when st2=>
if s_busy_idelay_m = '0' then
next_state <= st3; -- Next state is "st3 - RESET STATE"
end if;
-- st3 - RESET STATE
when st3=>
s_Rst_FSM <= '1';
if s_busy_idelay_m = '1' then
next_state <= st4; -- Next state is "st4 - WAIT BUSY = '0'"
end if;
-- st4 - WAIT BUSY = '0'
when st4=>
if s_busy_idelay_m = '0' then
next_state <= st0; -- Next state is "st0 - IDLE"
end if;
end case;
end process fsm;
calibrate_o <= s_cal_FSM;
reset_o <= s_Rst_FSM;
end rtl;
--=============================================================================
--! @file synchronizeRegisters_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- VHDL Architecture worklib.synchronizeRegisters.rtl
--
--! @brief Regularly transfers the input to the output.\n
--! One clock for input , one clock for output\n
--! Can't just put entire bus through a couple of register stages,\n
--! Since this will just swap meta-stability issues for race issues.
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 24/Nov/12
--
--! @version v0.1
--
--! @details A six stage "ring oscillator" is used to generate two strobes.
--! One reads data into a register. The other registers the data to the output
--! Three stages are clocked on clk_write_i , three stages are clocked on clk_read_i
--! The time taken for an edge to travel round the complete loop is
--! 2 cycles of clk_read_i and 2 cycles of clk_write_i plus two intervals
--! that depend on the relative phase of clk_read_i and clk_write_i
--!
--! Based on registerCounters