Commit 52076aaa authored by Wesley W. Terpstra's avatar Wesley W. Terpstra

eca: make event stream interface public, for use by TLU

parent 23b49fd8
......@@ -10,6 +10,7 @@ entity eca is
generic(
g_channel_types : t_nat_array;
g_channel_nums : t_nat_array; -- Anything not explicitly set is 1
g_num_streams : natural := 1; -- Number of input streams
g_num_ios : natural := 8; -- Number of gpios
g_log_table_size : natural := 8; -- 2**g_log_table_size = maximum number of conditions
g_log_queue_size : natural := 8; -- 2**g_log_size = maximum number of pending actions
......@@ -18,22 +19,19 @@ entity eca is
g_log_latency : natural := 12; -- 2**g_log_latency = ticks of calendar delay
g_log_counter : natural := 20);-- number of bits in the counters reported
port(
-- Push events to the ECA unit (a_clk_i domain)
e_stb_i : in std_logic;
e_stall_o : out std_logic;
e_event_i : in t_event;
e_param_i : in t_param;
e_tef_i : in t_tef;
e_time_i : in t_time;
-- ECA control registers
c_clk_i : in std_logic;
c_rst_n_i : in std_logic;
c_slave_i : in t_wishbone_slave_in;
c_slave_o : out t_wishbone_slave_out;
-- Actions output according to time
-- Action clock domain
a_clk_i : in std_logic;
a_rst_n_i : in std_logic;
a_time_i : in t_time;
-- Input streams (lower index has priority)
a_stream_i : in t_stream_array(g_num_streams-1 downto 0);
a_stall_o : out std_logic_vector(g_num_streams-1 downto 0);
-- Output actions
a_stall_i : in std_logic_vector(g_channel_types'range);
a_channel_o : out t_channel_array(g_channel_types'range);
a_io_o : out t_eca_matrix(g_num_ios-1 downto 0, 2**g_log_multiplier-1 downto 0);
......@@ -144,6 +142,9 @@ architecture rtl of eca is
signal s_slave_channel_executed_hi_RD_o : std_logic_vector(1-1 downto 0); -- Read enable flag
signal s_slave_channel_executed_lo_RD_o : std_logic_vector(1-1 downto 0); -- Read enable flag
signal sa_streams : t_stream_array(g_num_streams downto 0);
signal sa_stalls : std_logic_vector(g_num_streams downto 0);
signal rc_page : std_logic := '0';
signal ra_page : std_logic_vector(3 downto 0);
signal r_bad_ack : std_logic := '0';
......@@ -324,19 +325,35 @@ begin
when f_eca_safe(s_slave_channel_select_o) = '1' else
(others => 'X');
-- Arbitrate inputs, priority access goes to #0
sa_streams(g_num_streams).stb <= '0';
sa_streams(g_num_streams).event <= (others => '-');
sa_streams(g_num_streams).param <= (others => '-');
sa_streams(g_num_streams).tef <= (others => '-');
sa_streams(g_num_streams).time <= (others => '-');
Sx : for s in 0 to g_num_streams-1 generate
sa_stalls(s+1) <= a_stream_i(s).stb or sa_stalls(s);
sa_streams(s).stb <= a_stream_i(s).stb or sa_streams(s+1).stb;
sa_streams(s).event <= a_stream_i(s).event when a_stream_i(s).stb='1' else sa_streams(s+1).event;
sa_streams(s).param <= a_stream_i(s).param when a_stream_i(s).stb='1' else sa_streams(s+1).param;
sa_streams(s).tef <= a_stream_i(s).tef when a_stream_i(s).stb='1' else sa_streams(s+1).tef;
sa_streams(s).time <= a_stream_i(s).time when a_stream_i(s).stb='1' else sa_streams(s+1).time;
end generate;
a_stall_o <= sa_stalls(a_stall_o'range);
search : eca_search
generic map(
g_log_table_size => g_log_table_size)
port map(
clk_i => a_clk_i,
rst_n_i => a_rst_n_i,
e_stb_i => e_stb_i,
e_stall_o => e_stall_o,
e_stb_i => sa_streams(0).stb,
e_stall_o => sa_stalls(0),
e_page_i => "not"(ra_page(0)),
e_event_i => e_event_i,
e_param_i => e_param_i,
e_tef_i => e_tef_i,
e_time_i => e_time_i,
e_event_i => sa_streams(0).event,
e_param_i => sa_streams(0).param,
e_tef_i => sa_streams(0).tef,
e_time_i => sa_streams(0).time,
w_stb_o => s_sw_stb,
w_stall_i => s_ws_stall,
w_page_o => s_sw_page,
......
......@@ -44,6 +44,14 @@ package eca_internals_pkg is
subtype t_num is std_logic_vector(c_num_bits-1 downto 0);
subtype t_code is std_logic_vector(c_code_bits-1 downto 0);
type t_stream is record
stb : std_logic;
event : t_event;
param : t_param;
tef : t_tef;
time : t_time;
end record t_stream;
type t_channel is record
valid : std_logic;
delayed : std_logic;
......@@ -70,12 +78,8 @@ package eca_internals_pkg is
(others => '0'));
type t_nat_array is array(natural range <>) of natural;
type t_stream_array is array(natural range <>) of t_stream;
type t_channel_array is array(natural range <>) of t_channel;
type t_event_array is array(natural range <>) of t_event;
type t_param_array is array(natural range <>) of t_param;
type t_tag_array is array(natural range <>) of t_tag;
type t_tef_array is array(natural range <>) of t_tef;
type t_time_array is array(natural range <>) of t_time;
type t_num_array is array(natural range <>) of t_num;
type t_code_array is array(natural range <>) of t_code;
......@@ -612,6 +616,7 @@ package eca_internals_pkg is
generic(
g_channel_types : t_nat_array;
g_channel_nums : t_nat_array; -- Anything not explicitly set is 1
g_num_streams : natural := 1; -- Number of streams
g_num_ios : natural := 8; -- Number of gpios
g_log_table_size : natural := 8; -- 2**g_log_table_size = maximum number of conditions
g_log_queue_size : natural := 8; -- 2**g_log_size = maximum number of pending actions
......@@ -620,22 +625,19 @@ package eca_internals_pkg is
g_log_latency : natural := 12; -- 2**g_log_latency = ticks of calendar delay
g_log_counter : natural := 20);-- number of bits in the counters reported
port(
-- Push events to the ECA unit (a_clk_i domain)
e_stb_i : in std_logic;
e_stall_o : out std_logic;
e_event_i : in t_event;
e_param_i : in t_param;
e_tef_i : in t_tef;
e_time_i : in t_time;
-- ECA control registers
c_clk_i : in std_logic;
c_rst_n_i : in std_logic;
c_slave_i : in t_wishbone_slave_in;
c_slave_o : out t_wishbone_slave_out;
-- Actions output according to time
-- Action clock domain
a_clk_i : in std_logic;
a_rst_n_i : in std_logic;
a_time_i : in t_time;
-- Input streams (lower index has priority)
a_stream_i : in t_stream_array(g_num_streams-1 downto 0);
a_stall_o : out std_logic_vector(g_num_streams-1 downto 0);
-- Output actions
a_stall_i : in std_logic_vector(g_channel_types'range);
a_channel_o : out t_channel_array(g_channel_types'range);
a_io_o : out t_eca_matrix(g_num_ios-1 downto 0, 2**g_log_multiplier-1 downto 0);
......@@ -646,23 +648,6 @@ package eca_internals_pkg is
i_master_o : out t_wishbone_master_out);
end component;
-- Convert WB writes into inbound ECA events
component eca_wb_event is
port(
w_clk_i : in std_logic;
w_rst_n_i : in std_logic;
w_slave_i : in t_wishbone_slave_in;
w_slave_o : out t_wishbone_slave_out;
e_clk_i : in std_logic;
e_rst_n_i : in std_logic;
e_stb_o : out std_logic;
e_stall_i : in std_logic;
e_event_o : out t_event;
e_param_o : out t_param;
e_tef_o : out t_tef;
e_time_o : out t_time);
end component;
end eca_internals_pkg;
package body eca_internals_pkg is
......
......@@ -55,6 +55,8 @@ package eca_pkg is
name => "ECA_UNIT:EVENTS_IN ")));
subtype t_nat_array is work.eca_internals_pkg.t_nat_array;
subtype t_stream is work.eca_internals_pkg.t_stream;
subtype t_stream_array is work.eca_internals_pkg.t_stream_array;
subtype t_channel is work.eca_internals_pkg.t_channel;
subtype t_channel_array is work.eca_internals_pkg.t_channel_array;
type t_gpio_array is array(natural range <>) of std_logic_vector(7 downto 0);
......@@ -68,27 +70,27 @@ package eca_pkg is
generic(
g_channel_types : t_nat_array := (0 => c_linux);
g_channel_nums : t_nat_array := (0 => 32); -- Anything not explicitly set is 1
g_num_streams : natural := 1; -- Number of streams
g_num_ios : natural := 8; -- Number of gpios
g_num_streams : natural := 1; -- Number of streams (must be >= 1)
g_log_table_size : natural := 8; -- 2**g_log_table_size = maximum number of conditions
g_log_queue_size : natural := 8; -- 2**g_log_size = maximum number of pending actions
g_log_max_delay : natural := 32);-- 2**g_log_max_delay = maximum delay before executed as early
port(
-- Stream events to the ECA unit (lower index has priority)
e_clk_i : in std_logic_vector (g_num_streams-1 downto 0);
e_rst_n_i : in std_logic_vector (g_num_streams-1 downto 0);
e_slave_i : in t_wishbone_slave_in_array (g_num_streams-1 downto 0);
e_slave_o : out t_wishbone_slave_out_array(g_num_streams-1 downto 0);
-- ECA control registers
c_clk_i : in std_logic;
c_rst_n_i : in std_logic;
c_slave_i : in t_wishbone_slave_in;
c_slave_o : out t_wishbone_slave_out;
-- Actions output according to time
-- Action clock domain
a_clk_i : in std_logic;
a_rst_n_i : in std_logic; -- Hold for at least 10 cycles
a_tai_i : in std_logic_vector(39 downto 0);
a_cycles_i : in std_logic_vector(27 downto 0);
a_time_o : out t_time;
-- Input streams (lower index has priority)
a_stream_i : in t_stream_array(g_num_streams-1 downto 0);
a_stall_o : out std_logic_vector(g_num_streams-1 downto 0);
-- Output actions
a_stall_i : in std_logic_vector(g_channel_types'range);
a_channel_o : out t_channel_array(g_channel_types'range);
a_io_o : out t_gpio_array(g_num_ios-1 downto 0);
......@@ -99,6 +101,19 @@ package eca_pkg is
i_master_o : out t_wishbone_master_out);
end component;
-- Convert WB writes into inbound ECA event stream
component eca_wb_event is
port(
w_clk_i : in std_logic;
w_rst_n_i : in std_logic;
w_slave_i : in t_wishbone_slave_in;
w_slave_o : out t_wishbone_slave_out;
e_clk_i : in std_logic;
e_rst_n_i : in std_logic;
e_stream_o : out t_stream;
e_stall_i : in std_logic);
end component;
-- FIFO-style interface to access the output of an ECA channel
component eca_queue is
generic(
......
......@@ -31,19 +31,15 @@ use work.wishbone_pkg.all;
use work.eca_internals_pkg.all;
entity eca_wb_event is
port(
w_clk_i : in std_logic;
w_rst_n_i : in std_logic;
w_slave_i : in t_wishbone_slave_in;
w_slave_o : out t_wishbone_slave_out;
e_clk_i : in std_logic;
e_rst_n_i : in std_logic;
e_stb_o : out std_logic;
e_stall_i : in std_logic;
e_event_o : out t_event;
e_param_o : out t_param;
e_tef_o : out t_tef;
e_time_o : out t_time);
port(
w_clk_i : in std_logic;
w_rst_n_i : in std_logic;
w_slave_i : in t_wishbone_slave_in;
w_slave_o : out t_wishbone_slave_out;
e_clk_i : in std_logic;
e_rst_n_i : in std_logic;
e_stream_o : out t_stream;
e_stall_i : in std_logic);
end eca_wb_event;
architecture rtl of eca_wb_event is
......@@ -91,11 +87,16 @@ architecture rtl of eca_wb_event is
signal re_state : t_state := S0;
signal re_stb : std_logic := '0';
signal re_addr : t_addr1 := (others => '0');
signal re_event : t_event := (others => '0');
signal re_param : t_param := (others => '0');
signal re_tef : t_tef := (others => '0');
signal re_time : t_time := (others => '0');
-- Signals in clock domain e_clk_i
signal se_exit_s0 : boolean;
signal se_addr : t_addr1;
signal se_data : t_wishbone_data;
begin
w_slave_o.DAT <= (others => '0');
......@@ -209,7 +210,11 @@ begin
end if; -- clock
end process;
e_stb_o <= re_stb;
e_stream_o.stb <= re_stb;
e_stream_o.event <= re_event;
e_stream_o.param <= re_param;
e_stream_o.tef <= re_tef;
e_stream_o.time <= re_time;
-- This cannot be inside the process because both re_addr and Q.r_addr_i latch se_addr
se_exit_s0 <= (re_sent /= re_ready) and (re_stb = '0' or e_stall_i = '0');
......@@ -227,10 +232,10 @@ begin
re_ready <= unsigned(f_eca_gray_decode(std_logic_vector(re0_ready_gray), 1));
if e_rst_n_i = '0' then
e_event_o <= (others => '0');
e_param_o <= (others => '0');
e_tef_o <= (others => '0');
e_time_o <= (others => '0');
re_event <= (others => '0');
re_param <= (others => '0');
re_tef <= (others => '0');
re_time <= (others => '0');
re_sent <= (others => '0');
re_state <= S0;
......@@ -246,7 +251,7 @@ begin
end if;
if re_stb = '0' or e_stall_i = '0' then
e_event_o(63 downto 32) <= se_data;
re_event(63 downto 32) <= se_data;
end if;
if se_exit_s0 then
......@@ -254,15 +259,15 @@ begin
end if;
when S1 =>
e_event_o(31 downto 0) <= se_data;
re_event(31 downto 0) <= se_data;
re_state <= S2;
when S2 =>
e_param_o(63 downto 32) <= se_data;
re_param(63 downto 32) <= se_data;
re_state <= S3;
when S3 =>
e_param_o(31 downto 0) <= se_data;
re_param(31 downto 0) <= se_data;
re_state <= S4;
when S4 =>
......@@ -270,15 +275,15 @@ begin
re_state <= S5;
when S5 =>
e_tef_o(31 downto 0) <= se_data;
re_tef(31 downto 0) <= se_data;
re_state <= S6;
when S6 =>
e_time_o(63 downto 32) <= se_data;
re_time(63 downto 32) <= se_data;
re_state <= S7;
when S7 =>
e_time_o(31 downto 0) <= se_data;
re_time(31 downto 0) <= se_data;
re_state <= S0;
re_stb <= '1';
......
......@@ -34,27 +34,27 @@ entity wr_eca is
generic(
g_channel_types : t_nat_array;
g_channel_nums : t_nat_array;
g_num_ios : natural := 8; -- Number of gpios
g_num_streams : natural := 1; -- Number of streams (must be >= 1)
g_num_ios : natural := 8; -- Number of gpios
g_log_table_size : natural := 8; -- 2**g_log_table_size = maximum number of conditions
g_log_queue_size : natural := 8; -- 2**g_log_size = maximum number of pending actions
g_log_max_delay : natural := 32);-- 2**g_log_max_delay = maximum delay before executed as early
port(
-- Stream events to the ECA unit (lower index has priority)
e_clk_i : in std_logic_vector (g_num_streams-1 downto 0);
e_rst_n_i : in std_logic_vector (g_num_streams-1 downto 0);
e_slave_i : in t_wishbone_slave_in_array (g_num_streams-1 downto 0);
e_slave_o : out t_wishbone_slave_out_array(g_num_streams-1 downto 0);
-- ECA control registers
c_clk_i : in std_logic;
c_rst_n_i : in std_logic;
c_slave_i : in t_wishbone_slave_in;
c_slave_o : out t_wishbone_slave_out;
-- Actions output according to time
-- Action clock domain
a_clk_i : in std_logic;
a_rst_n_i : in std_logic; -- Hold for at least 10 cycles
a_tai_i : in std_logic_vector(39 downto 0);
a_cycles_i : in std_logic_vector(27 downto 0);
a_time_o : out t_time;
-- Input streams (lower index has priority)
a_stream_i : in t_stream_array(g_num_streams-1 downto 0);
a_stall_o : out std_logic_vector(g_num_streams-1 downto 0);
-- Output actions
a_stall_i : in std_logic_vector(g_channel_types'range);
a_channel_o : out t_channel_array(g_channel_types'range);
a_io_o : out t_gpio_array(g_num_ios-1 downto 0);
......@@ -66,26 +66,9 @@ entity wr_eca is
end wr_eca;
architecture rtl of wr_eca is
-- Out of principle, tell quartus to leave my design alone.
attribute altera_attribute : string;
attribute altera_attribute of rtl : architecture is "-name AUTO_SHIFT_REGISTER_RECOGNITION OFF";
signal sa_time0 : t_time;
signal sa_stb : std_logic_vector(g_num_streams-1 downto 0);
signal sa_event : t_event_array (g_num_streams-1 downto 0);
signal sa_param : t_param_array (g_num_streams-1 downto 0);
signal sa_tef : t_tef_array (g_num_streams-1 downto 0);
signal sa_time : t_time_array (g_num_streams-1 downto 0);
signal sa_full_stb : std_logic_vector(g_num_streams downto 0);
signal sa_full_stall : std_logic_vector(g_num_streams downto 0);
signal sa_full_event : t_event_array (g_num_streams downto 0);
signal sa_full_param : t_param_array (g_num_streams downto 0);
signal sa_full_tef : t_tef_array (g_num_streams downto 0);
signal sa_full_time : t_time_array (g_num_streams downto 0);
signal sa_io : t_eca_matrix(g_num_ios-1 downto 0, 7 downto 0);
signal sa_time : t_time;
signal sa_io : t_eca_matrix(g_num_ios-1 downto 0, 7 downto 0);
begin
......@@ -94,6 +77,7 @@ begin
g_channel_types => g_channel_types,
g_channel_nums => g_channel_nums,
g_num_ios => g_num_ios,
g_num_streams => g_num_streams,
g_log_table_size => g_log_table_size,
g_log_queue_size => g_log_queue_size,
g_log_multiplier => 3, -- 125*2**3 = 1GHz
......@@ -101,19 +85,15 @@ begin
g_log_latency => 12, -- 2**12 = 4096ns < 5us as required
g_log_counter => 20) -- saftd can easily poll at 2**20ns = 1s = 1Hz
port map(
e_stb_i => sa_full_stb (0),
e_stall_o => sa_full_stall(0),
e_event_i => sa_full_event(0),
e_param_i => sa_full_param(0),
e_tef_i => sa_full_tef (0),
e_time_i => sa_full_time (0),
c_clk_i => c_clk_i,
c_rst_n_i => c_rst_n_i,
c_slave_i => c_slave_i,
c_slave_o => c_slave_o,
a_clk_i => a_clk_i,
a_rst_n_i => a_rst_n_i,
a_time_i => sa_time0,
a_time_i => sa_time,
a_stream_i => a_stream_i,
a_stall_o => a_stall_o,
a_stall_i => a_stall_i,
a_channel_o => a_channel_o,
a_io_o => sa_io,
......@@ -134,38 +114,8 @@ begin
rst_n_i => a_rst_n_i,
tai_i => a_tai_i,
cycles_i => a_cycles_i,
time_o => sa_time0);
sa_full_stb (g_num_streams) <= '0';
sa_full_event(g_num_streams) <= (others => '-');
sa_full_param(g_num_streams) <= (others => '-');
sa_full_tef (g_num_streams) <= (others => '-');
sa_full_time (g_num_streams) <= (others => '-');
-- Priority access goes to #0
Sx : for stream in 0 to g_num_streams-1 generate
S : eca_wb_event
port map(
w_clk_i => e_clk_i (stream),
w_rst_n_i => e_rst_n_i(stream),
w_slave_i => e_slave_i(stream),
w_slave_o => e_slave_o(stream),
e_clk_i => a_clk_i,
e_rst_n_i => a_rst_n_i,
e_stb_o => sa_stb (stream),
e_stall_i => sa_full_stall(stream),
e_event_o => sa_event(stream),
e_param_o => sa_param(stream),
e_tef_o => sa_tef (stream),
e_time_o => sa_time (stream));
sa_full_stall(stream+1) <= sa_stb (stream) or sa_full_stall(stream);
sa_full_stb (stream) <= sa_stb (stream) or sa_full_stb (stream+1);
sa_full_event(stream) <= sa_event(stream) when sa_stb(stream)='1' else sa_full_event(stream+1);
sa_full_param(stream) <= sa_param(stream) when sa_stb(stream)='1' else sa_full_param(stream+1);
sa_full_tef (stream) <= sa_tef (stream) when sa_stb(stream)='1' else sa_full_tef (stream+1);
sa_full_time (stream) <= sa_time (stream) when sa_stb(stream)='1' else sa_full_time (stream+1);
end generate;
time_o => sa_time);
a_time_o <= sa_time;
end rtl;
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