Commit 704c126d authored by Michael Munch's avatar Michael Munch
Browse files

Internalize vme watchdog

parent 7512196c
Pipeline #25761 failed with stage
in 30 seconds
......@@ -58,7 +58,8 @@ entity vme_data_bus is
signal vme_ds_n_dir : out std_logic := c_PIN_IN;
signal vme_berr_n_i : in std_logic;
-- signal vme_berr_n_o : out std_logic;
signal vme_berr_n_o : out std_logic;
signal vme_berr_n_dir : out std_logic;
---------------------------------
......@@ -199,7 +200,9 @@ architecture rtl of vme_data_bus is
LATCH_DATA, -- 6
BLT_READ_WAIT, -- 7
BLT_WRITE_WAIT, -- 8
IDLE_DELAY -- 9
IDLE_DELAY, -- 9
TIMEOUT, -- 10
TIMEOUT_WAIT -- 11
);
type addr_type_t is (
......@@ -229,7 +232,10 @@ architecture rtl of vme_data_bus is
constant c_N_DS_SPACING : natural range 1 to 8 :=
(35 / CLOCK_PERIOD);
constant c_N_DATA_WAIT : natural range 1 to 8 :=
(25 / CLOCK_PERIOD);
(25 / CLOCK_PERIOD);
constant c_N_TIMEOUT_WAIT : natural range 1 to 8 :=
(30 / CLOCK_PERIOD);
-- Latched signals
signal l_addr : vme_addr_t;
......@@ -244,6 +250,13 @@ architecture rtl of vme_data_bus is
signal l_data : std_logic_vector(63 downto 0) := (others => '0');
signal first_cycle : std_logic := '1';
-- Timeout of operations, in order to never get stuck.
constant TIMEOUT_CNT_MAX : integer := 255;
signal timeout_cnt : integer range 0 to 255 := TIMEOUT_CNT_MAX;
signal last_ds : std_logic_vector(1 downto 0);
begin
-- Determine addressing mode
......@@ -293,7 +306,9 @@ begin
vme_am_dir <= c_PIN_IN;
vme_data_dir <= c_PIN_IN;
vme_as_n_dir <= c_PIN_IN;
vme_as_n_o <= '1';
vme_as_n_o <= '1';
vme_berr_n_dir <= c_PIN_IN;
vme_berr_n_o <= '1';
vme_iack_n_dir <= c_PIN_IN;
vme_dtack_n_dir <= c_PIN_IN;
vme_ds_n_dir <= c_PIN_IN;
......@@ -472,18 +487,18 @@ begin
-- [30 ns]
--
-- Munk: Thus we can only catch BERR* here.
if (vme_berr_n_i & int_timeout_n /= "11") then
vme_ds_n_o <= "11";
vme_as_n_o <= '1';
int_err_code <= (
c_ERR_BERR_I => not vme_berr_n_i,
c_ERR_TIMEOUT_I => not int_timeout_n,
others => '0'
);
busy <= '0';
state <= IDLE;
-- if (vme_berr_n_i & int_timeout_n /= "11") then
-- vme_ds_n_o <= "11";
-- vme_as_n_o <= '1';
-- int_err_code <= (
-- c_ERR_BERR_I => not vme_berr_n_i,
-- c_ERR_TIMEOUT_I => not int_timeout_n,
-- others => '0'
-- );
-- busy <= '0';
-- state <= IDLE;
elsif (vme_dtack_n_i = '0') then
if (vme_dtack_n_i = '0') then
-- RULE 2.40:
-- During all data transfer cycles, excluding A16, A24 and A32
......@@ -654,7 +669,84 @@ begin
when IDLE_DELAY =>
state <= IDLE;
busy <= '0';
end case;
-- Timeout! Something is preventing the state machine
-- from completing. Either an external error (e.g. a
-- non-responding module), or a bug in this code.
-- BERR is issued and we stop driving signals.
when TIMEOUT =>
vme_berr_n_dir <= c_PIN_OUT;
vme_berr_n_o <= '0';
vme_ds_n_dir <= c_PIN_IN;
vme_ds_n_o <= "11";
vme_as_n_dir <= c_PIN_IN;
vme_as_n_o <= '1';
-- Data present (error)
int_data_strobe <= c_DATA_PRESENT;
int_err_code <= (
c_ERR_BERR_I => not vme_berr_n_i,
c_ERR_TIMEOUT_I => '1',
others => '0'
);
busy <= '0';
-- Attempt to leave the TIMEOUT state
n_wait <= c_N_TIMEOUT_WAIT;
state <= TIMEOUT_WAIT;
-- We stay here and wait
when TIMEOUT_WAIT =>
-- Make sure that also noone else is driving
-- AS, DS or DTACK before we consider leaving
-- TIMEOUT state.
if (vme_ds_n_i /= "00" or
vme_as_n_i /= '0' or
vme_dtack_n_i /= '0') then
-- Someone is still holding a strobe.
n_wait <= c_N_TIMEOUT_WAIT;
elsif (n_wait = 0) then
vme_berr_n_o <= '1';
vme_berr_n_dir <= c_PIN_IN;
state <= IDLE;
end if;
end case;
-- This is after state machine, such that it can force
-- into TIMEOUT state, no matter what happens.
-- Also an seemingly indefinate wait in IACK_HIGH_WAIT
-- will be cut short, such that we report failure to
-- perform the access to our superiors.
-- VME spec 2.37:
-- [...]
-- The Master, upon completing the first data transfer,
-- (that is, driving the data strobes high) does not allow
-- the address strobe to go high. Instead, it repeatedly
-- drives the data strobe(s) low in response to data transfer
-- acknowledgments from the Slave
last_ds <= vme_ds_n_i;
if (last_ds /= vme_ds_n_i or --
state = IDLE or
state = IDLE_DELAY or
state = TIMEOUT or
state = TIMEOUT_WAIT) then
-- Things are good, or we have fired (no need to fire again).
timeout_cnt <= TIMEOUT_CNT_MAX;
elsif (vme_berr_n_i & int_timeout_n /= "11") then
state <= TIMEOUT;
elsif (timeout_cnt = 0) then
-- We have been operating for too long, timeout.
state <= TIMEOUT;
else
timeout_cnt <= timeout_cnt - 1;
end if;
end if;
end process;
......
Supports Markdown
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