Commit 6f177d4a authored by Wesley W. Terpstra's avatar Wesley W. Terpstra

eca2: include TLU event stream

parent 52076aaa
......@@ -2,10 +2,12 @@ files = [
"eca_internals_pkg.vhd",
"eca_auto_pkg.vhd",
"eca_queue_auto_pkg.vhd",
"eca_tlu_auto_pkg.vhd",
"eca_ac_wbm_auto_pkg.vhd",
"eca_pkg.vhd",
"eca_auto.vhd",
"eca_queue_auto.vhd",
"eca_tlu_auto.vhd",
"eca_ac_wbm_auto.vhd",
"eca_sdp.vhd",
"eca_tdp.vhd",
......@@ -27,4 +29,6 @@ files = [
"wr_eca.vhd",
"eca_ac_wbm.vhd",
"eca_scubus_channel.vhd",
"eca_queue.vhd"]
"eca_queue.vhd",
"eca_tlu_fsm.vhd",
"eca_tlu.vhd"]
......@@ -101,6 +101,7 @@ package eca_internals_pkg is
function f_eca_add(x : std_logic_vector; y : integer) return std_logic_vector;
function f_eca_add(x : std_logic_vector; y : std_logic) return std_logic_vector;
function f_eca_add(x, y : std_logic_vector) return std_logic_vector;
function f_eca_sub(x, y : std_logic_vector) return std_logic_vector;
function f_eca_delta(x, previous, current : std_logic_vector) return std_logic_vector;
function f_eca_1hot_decode(x : std_logic_vector) return std_logic_vector;
......@@ -648,6 +649,24 @@ package eca_internals_pkg is
i_master_o : out t_wishbone_master_out);
end component;
component eca_tlu_fsm is
generic(
g_history: natural := 10000; -- how many ticks in the past can events come?
g_stable : natural := 10;
g_serdes : natural := 8);
port(
clk_i : in std_logic;
rst_n_i : in std_logic;
enable_i : in std_logic;
stable_i : in std_logic_vector(g_stable-1 downto 0);
time_i : in t_time;
gpio_i : in std_logic_vector(g_serdes-1 downto 0);
ack_i : in std_logic;
stb_o : out std_logic;
edge_o : out std_logic;
time_o : out t_time);
end component;
end eca_internals_pkg;
package body eca_internals_pkg is
......@@ -786,6 +805,11 @@ package body eca_internals_pkg is
return std_logic_vector(unsigned(x) + unsigned(y));
end function;
function f_eca_sub(x, y : std_logic_vector) return std_logic_vector is
begin
return std_logic_vector(unsigned(x) - unsigned(y));
end function;
function f_eca_delta(x, previous, current : std_logic_vector) return std_logic_vector is
begin
return std_logic_vector(unsigned(x) + (unsigned(current) - unsigned(previous)));
......
......@@ -29,6 +29,7 @@ library work;
use work.wishbone_pkg.all;
use work.eca_auto_pkg.all;
use work.eca_queue_auto_pkg.all;
use work.eca_tlu_auto_pkg.all;
use work.eca_ac_wbm_auto_pkg.all;
use work.eca_internals_pkg.all;
......@@ -36,6 +37,7 @@ package eca_pkg is
constant c_eca_slave_sdb : t_sdb_device := work.eca_auto_pkg.c_eca_slave_sdb;
constant c_eca_queue_slave_sdb : t_sdb_device := work.eca_queue_auto_pkg.c_eca_queue_slave_sdb;
constant c_eca_tlu_slave_sdb : t_sdb_device := work.eca_tlu_auto_pkg.c_eca_tlu_slave_sdb;
constant c_eca_ac_wbm_slave_sdb : t_sdb_device := work.eca_ac_wbm_auto_pkg.c_eca_ac_wbm_slave_sdb;
constant c_eca_event_sdb : t_sdb_device := (
......@@ -59,6 +61,7 @@ package eca_pkg is
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;
subtype t_time is work.eca_internals_pkg.t_time;
type t_gpio_array is array(natural range <>) of std_logic_vector(7 downto 0);
constant c_linux : natural := 1;
......@@ -114,6 +117,25 @@ package eca_pkg is
e_stall_i : in std_logic);
end component;
-- Convert input edges into inbound ECA event stream
component eca_tlu is
generic(
g_inputs : natural;
g_history : natural := 10000; -- 10us
g_stable : natural := 10);
port(
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;
a_clk_i : in std_logic;
a_rst_n_i : in std_logic;
a_time_i : in t_time;
a_gpio_i : in t_gpio_array(g_inputs-1 downto 0);
a_stream_o : out t_stream;
a_stall_i : in std_logic);
end component;
-- FIFO-style interface to access the output of an ECA channel
component eca_queue is
generic(
......
--! @file eca_tlu.vhd
--! @brief ECA TLU
--! @author Wesley W. Terpstra <w.terpstra@gsi.de>
--!
--! Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH
--!
--! This component recovers clock
--!
--------------------------------------------------------------------------------
--! This library is free software; you can redistribute it and/or
--! modify it under the terms of the GNU Lesser General Public
--! License as published by the Free Software Foundation; either
--! version 3 of the License, or (at your option) any later version.
--!
--! This library is distributed in the hope that it will be useful,
--! but WITHOUT ANY WARRANTY; without even the implied warranty of
--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
--! Lesser General Public License for more details.
--!
--! You should have received a copy of the GNU Lesser General Public
--! License along with this library. If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.eca_pkg.t_gpio_array;
use work.eca_internals_pkg.all;
use work.eca_tlu_auto_pkg.all;
entity eca_tlu is
generic(
g_inputs : natural;
g_history : natural := 10000; -- 10us
g_stable : natural := 10);
port(
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;
a_clk_i : in std_logic;
a_rst_n_i : in std_logic;
a_time_i : in t_time;
a_gpio_i : in t_gpio_array(g_inputs-1 downto 0);
a_stream_o : out t_stream;
a_stall_i : in std_logic);
end eca_tlu;
architecture rtl of eca_tlu is
constant c_serdes : natural := 8;
constant c_input_bits : natural := f_eca_log2(g_inputs);
signal sc_select : std_logic_vector(7 downto 0);
signal sc_enable : std_logic;
signal sc_event : t_event;
signal sc_stable : std_logic_vector(31 downto 0);
signal sc_write : std_logic;
signal rc_xor_o : std_logic := '0';
signal rc_xor_i : std_logic_vector(4 downto 0) := (others => '0');
signal rc_stall : std_logic := '0';
signal ra_xor : std_logic_vector(4 downto 0) := (others => '0');
signal ra_enables : std_logic_vector(g_inputs-1 downto 0) := (others => '0');
signal raw_select : std_logic_vector(7 downto 0);
signal raw_enable : std_logic;
signal raw_event : t_event;
signal raw_stable : std_logic_vector(31 downto 0);
type t_stable_array is array(g_inputs-1 downto 0) of std_logic_vector(g_stable-1 downto 0);
signal ra_stables : t_stable_array;
type t_time_array is array(g_inputs-1 downto 0) of t_time;
signal sa_times : t_time_array;
signal sa_edges : std_logic_vector(g_inputs-1 downto 0);
signal sa_stbs : std_logic_vector(g_inputs-1 downto 0);
signal sa_acks : std_logic_vector(g_inputs-1 downto 0);
signal sa_event : t_event;
type t_state is (S_IDLE, S_OUTPUT, S_WAIT);
signal ra_state : t_state := S_IDLE;
signal ra_stb : std_logic := '0';
signal sa_stb : std_logic;
signal sa_mux : std_logic_vector(c_input_bits-1 downto 0);
signal ra_mux : std_logic_vector(c_input_bits-1 downto 0);
signal ra_event : t_event;
signal ra_time : t_time;
begin
auto : eca_tlu_auto
generic map(
g_num_inputs => g_inputs)
port map(
clk_sys_i => c_clk_i,
rst_sys_n_i => c_rst_n_i,
slave_i => c_slave_i,
slave_o => c_slave_o,
error_i => "0",
stall_i(0) => rc_stall,
input_select_o => sc_select,
enable_o(0) => sc_enable,
event_hi_o => sc_event(63 downto 32),
event_lo_o => sc_event(31 downto 0),
stable_o => sc_stable,
write_o(0) => sc_write);
main_c : process(c_clk_i, c_rst_n_i) is
begin
if c_rst_n_i = '0' then
rc_xor_o <= '0';
rc_xor_i <= (others => '0');
elsif rising_edge(c_clk_i) then
rc_xor_o <= rc_xor_o xor (sc_write and not rc_stall);
rc_xor_i <= ra_xor(0) & rc_xor_i(rc_xor_i'high downto 1);
if sc_write = '1' then
rc_stall <= '1';
end if;
if rc_xor_i(0) /= rc_xor_i(1) then
rc_stall <= '0';
end if;
end if;
end process;
main_a : process(a_clk_i, a_rst_n_i) is
begin
if a_rst_n_i = '0' then
ra_xor <= (others => '0');
ra_enables <= (others => '0');
elsif rising_edge(a_clk_i) then
ra_xor <= rc_xor_o & ra_xor(ra_xor'high downto 1);
ra_enables(to_integer(unsigned(raw_select))) <= raw_enable;
end if;
end process;
bulk_a : process(a_clk_i) is
begin
if rising_edge(a_clk_i) then
if ra_xor(1) /= ra_xor(0) then
raw_select <= sc_select;
raw_enable <= sc_enable;
raw_event <= sc_event;
raw_stable <= sc_stable;
end if;
ra_stables(to_integer(unsigned(raw_select))) <= raw_stable(g_stable-1 downto 0);
end if;
end process;
fsms : for i in 0 to g_inputs-1 generate
fsm : eca_tlu_fsm
generic map(
g_history => g_history,
g_stable => g_stable,
g_serdes => c_serdes)
port map(
clk_i => a_clk_i,
rst_n_i => a_rst_n_i,
enable_i => ra_enables(i),
stable_i => ra_stables(i),
time_i => a_time_i,
gpio_i => a_gpio_i(i),
ack_i => sa_acks(i),
stb_o => sa_stbs(i),
edge_o => sa_edges(i),
time_o => sa_times(i));
-- Send ack to the correct core once edge_o and time_o latched
sa_acks(i) <= f_eca_eq(ra_mux, std_logic_vector(to_unsigned(i, c_input_bits)))
when ra_state = S_OUTPUT else '0';
end generate;
events : eca_sdp
generic map(
g_addr_bits => c_input_bits,
g_data_bits => 64,
g_bypass => false, -- new or old ... don't care
g_dual_clock => false)
port map(
r_clk_i => a_clk_i,
r_addr_i => sa_mux,
r_data_o => sa_event,
w_clk_i => a_clk_i,
w_en_i => '1',
w_addr_i => raw_select(c_input_bits-1 downto 0),
w_data_i => raw_event);
-- Select one of the strobes for service
sa_mux <= f_eca_1hot_decode(sa_stbs and f_eca_add(not sa_stbs, '1'));
sa_stb <= f_eca_or(sa_stbs);
push_fsm : process(a_clk_i, a_rst_n_i) is
begin
if a_rst_n_i = '0' then
ra_state <= S_IDLE;
ra_stb <= '0';
elsif rising_edge(a_clk_i) then
case ra_state is
when S_IDLE =>
if sa_stb = '1' then
ra_state <= S_OUTPUT;
end if;
when S_OUTPUT =>
ra_stb <= '1';
ra_state <= S_WAIT;
when S_WAIT =>
if a_stall_i = '0' then
ra_stb <= '0';
if sa_stb = '1' then
ra_state <= S_OUTPUT;
else
ra_state <= S_IDLE;
end if;
end if;
end case;
end if;
end process;
output : process(a_clk_i) is
begin
if rising_edge(a_clk_i) then
ra_mux <= sa_mux;
if ra_state = S_OUTPUT then
ra_event <= sa_event;
ra_event(0) <= sa_edges(to_integer(unsigned(ra_mux)));
ra_time <= sa_times(to_integer(unsigned(ra_mux)));
end if;
end if;
end process;
a_stream_o.stb <= ra_stb;
a_stream_o.event <= ra_event;
a_stream_o.param <= (others => '0');
a_stream_o.tef <= (others => '0');
a_stream_o.time <= ra_time;
end rtl;
<wbdevice author="Wesley W. Terpstra" email="w.terpstra@gsi.de" version="2.0">
<generic name="num_inputs" type="natural" default="0" comment="Total number of inputs attached to the TLU"/>
<slaveinterface name="slave" data="32" type="pipelined">
<sdb vendorID="GSI" productID="0x7c82afbc" version="2" date="auto" name="ECA_UNIT:TLU" />
<registers>
<reg name="num_inputs" read="yes" reset="num_inputs" bits="8" comment="Total number of inputs attached to the TLU"/>
<reg name="input_select" read="yes" write="yes" bits="8" comment="Write the configuration of this input"/>
<reg name="enable" read="yes" write="yes" bits="1" comment="Will this input generate timing events on an edge"/>
<reg name="stable" read="yes" write="yes" bits="32" comment="Signal must be high/low for stable cycles to be counted as a valid transition"/>
<reg name="event_hi" read="yes" write="yes" bits="32" comment="Timing Event to generate (high word)"/>
<reg name="event_lo" read="yes" write="yes" bits="32" comment="Timing Event to generate (low word), lowest bit is replaced with the edge of the transition"/>
<reg name="write" pulse="yes" write="yes" bits="1" comment="Write register contents to TLU configuration"/>
</registers>
</slaveinterface>
</wbdevice>
--! @file eca_tlu_auto.vhd
-- DesignUnit eca_tlu_auto
--! @author Wesley W. Terpstra <w.terpstra@gsi.de>
--! @date 15/04/2016
--! @version 2.0
--! @copyright 2016 GSI Helmholtz Centre for Heavy Ion Research GmbH
--!
--! @brief AUTOGENERATED WISHBONE-SLAVE CORE FOR eca_tlu.vhd
--!
--------------------------------------------------------------------------------
--! This library is free software; you can redistribute it and/or
--! modify it under the terms of the GNU Lesser General Public
--! License as published by the Free Software Foundation; either
--! version 3 of the License, or (at your option) any later version.
--!
--! This library is distributed in the hope that it will be useful,
--! but WITHOUT ANY WARRANTY; without even the implied warranty of
--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
--! Lesser General Public License for more details.
--!
--! You should have received a copy of the GNU Lesser General Public
--! License along with this library. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------
-- ***********************************************************
-- ** WARNING - THIS IS AUTO-GENERATED CODE! DO NOT MODIFY! **
-- ***********************************************************
--
-- If you want to change the interface,
-- modify eca_tlu.xml and re-run 'python wbgenplus.py eca_tlu.xml' !
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.wbgenplus_pkg.all;
use work.genram_pkg.all;
use work.eca_tlu_auto_pkg.all;
entity eca_tlu_auto is
generic(
g_num_inputs : natural := 0 --Total number of inputs attached to the TLU
);
Port(
clk_sys_i : std_logic; -- Clock input for sys domain
rst_sys_n_i : std_logic; -- Reset input (active low) for sys domain
error_i : in std_logic_vector(1-1 downto 0); -- Error control
stall_i : in std_logic_vector(1-1 downto 0); -- flow control
enable_o : out std_logic_vector(1-1 downto 0); -- Will this input generate timing events on an edge
event_hi_o : out std_logic_vector(32-1 downto 0); -- Timing Event to generate (high word)
event_lo_o : out std_logic_vector(32-1 downto 0); -- Timing Event to generate (low word), lowest bit is replaced with the edge of the transition
input_select_o : out std_logic_vector(8-1 downto 0); -- Write the configuration of this input
stable_o : out std_logic_vector(32-1 downto 0); -- Signal must be high/low for stable cycles to be counted as a valid transition
write_o : out std_logic_vector(1-1 downto 0); -- Write register contents to TLU configuration
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out
);
end eca_tlu_auto;
architecture rtl of eca_tlu_auto is
signal s_pop, s_push : std_logic;
signal s_empty, s_full : std_logic;
signal r_e_wait : std_logic;
signal s_stall : std_logic;
signal s_valid : std_logic;
signal r_ack : std_logic;
signal r_err : std_logic;
signal s_e, s_w : std_logic;
signal s_d : std_logic_vector(32-1 downto 0);
signal s_s : std_logic_vector(4-1 downto 0);
signal s_a : std_logic_vector(3-1 downto 0);
signal s_a_ext, r_a_ext : std_logic_vector(5-1 downto 0);
signal r_error : std_logic_vector(1-1 downto 0) := std_logic_vector(to_unsigned(0, 1)); -- Error
signal s_error_i : std_logic_vector(1-1 downto 0) := (others => '0'); -- Error control
signal s_stall_i : std_logic_vector(1-1 downto 0) := (others => '0'); -- flow control
signal r_num_inputs : std_logic_vector(8-1 downto 0) := std_logic_vector(to_unsigned(g_num_inputs, 8)); -- Total number of inputs attached to the TLU
signal r_input_select : std_logic_vector(8-1 downto 0) := (others => '0'); -- Write the configuration of this input
signal r_enable : std_logic_vector(1-1 downto 0) := (others => '0'); -- Will this input generate timing events on an edge
signal r_stable : std_logic_vector(32-1 downto 0) := (others => '0'); -- Signal must be high/low for stable cycles to be counted as a valid transition
signal r_event_hi : std_logic_vector(32-1 downto 0) := (others => '0'); -- Timing Event to generate (high word)
signal r_event_lo : std_logic_vector(32-1 downto 0) := (others => '0'); -- Timing Event to generate (low word), lowest bit is replaced with the edge of the transition
signal r_write : std_logic_vector(1-1 downto 0) := (others => '0'); -- Write register contents to TLU configuration
begin
sp : wb_skidpad
generic map(
g_adrbits => 3
)
Port map(
clk_i => clk_sys_i,
rst_n_i => rst_sys_n_i,
push_i => s_push,
pop_i => s_pop,
full_o => s_full,
empty_o => s_empty,
adr_i => slave_i.adr(4 downto 2),
dat_i => slave_i.dat,
sel_i => slave_i.sel,
we_i => slave_i.we,
adr_o => s_a,
dat_o => s_d,
sel_o => s_s,
we_o => s_w
);
validmux: with to_integer(unsigned(s_a_ext)) select
s_valid <=
'1' when others;
s_a_ext <= s_a & "00";
s_stall <= s_full;
s_push <= slave_i.cyc and slave_i.stb and not s_stall;
-- push if wb op not stalled
s_e <= not (s_empty or r_e_wait or stall_i(0)) ;-- op enable when skidpad not empty and not waiting for completion
s_pop <= (s_e or r_e_wait) and s_valid; -- if op enabled or waiting for completion, pop on valid from entity
slave_o.stall <= s_stall;
s_error_i <= error_i;
s_stall_i <= stall_i;
input_select_o <= r_input_select;
enable_o <= r_enable;
stable_o <= r_stable;
event_hi_o <= r_event_hi;
event_lo_o <= r_event_lo;
write_o <= r_write;
slave : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(rst_sys_n_i = '0') then
r_e_wait <= '0';
r_a_ext <= (others => '0');
r_error <= std_logic_vector(to_unsigned(0, 1));
r_num_inputs <= std_logic_vector(to_unsigned(g_num_inputs, 8));
r_write <= (others => '0');
else
r_a_ext <= s_a_ext;
r_e_wait <= (r_e_wait or s_e) and not s_valid;
r_ack <= s_pop and not (error_i(0) or r_error(0));
r_err <= s_pop and (error_i(0) or r_error(0));
slave_o.ack <= r_ack;
slave_o.err <= r_err;
r_error <= (others => '0');
r_write <= (others => '0');
if(s_e = '1') then
if(s_w = '1') then
-- WISHBONE WRITE ACTIONS
case to_integer(unsigned(s_a_ext)) is
when c_input_select_RW => r_input_select <= f_wb_wr(r_input_select, s_d, s_s, "owr"); --
when c_enable_RW => r_enable <= f_wb_wr(r_enable, s_d, s_s, "owr"); --
when c_stable_RW => r_stable <= f_wb_wr(r_stable, s_d, s_s, "owr"); --
when c_event_hi_RW => r_event_hi <= f_wb_wr(r_event_hi, s_d, s_s, "owr"); --
when c_event_lo_RW => r_event_lo <= f_wb_wr(r_event_lo, s_d, s_s, "owr"); --
when c_write_OWR => r_write <= f_wb_wr(r_write, s_d, s_s, "owr"); --
when others => r_error <= "1";
end case;
else
-- WISHBONE READ ACTIONS
case to_integer(unsigned(s_a_ext)) is
when c_num_inputs_GET => null;
when c_input_select_RW => null;
when c_enable_RW => null;
when c_stable_RW => null;
when c_event_hi_RW => null;
when c_event_lo_RW => null;
when others => r_error <= "1";
end case;
end if; -- s_w
end if; -- s_e
case to_integer(unsigned(r_a_ext)) is
when c_num_inputs_GET => slave_o.dat <= std_logic_vector(resize(unsigned(r_num_inputs), slave_o.dat'length)); --
when c_input_select_RW => slave_o.dat <= std_logic_vector(resize(unsigned(r_input_select), slave_o.dat'length)); --
when c_enable_RW => slave_o.dat <= std_logic_vector(resize(unsigned(r_enable), slave_o.dat'length)); --
when c_stable_RW => slave_o.dat <= std_logic_vector(resize(unsigned(r_stable), slave_o.dat'length)); --
when c_event_hi_RW => slave_o.dat <= std_logic_vector(resize(unsigned(r_event_hi), slave_o.dat'length)); --
when c_event_lo_RW => slave_o.dat <= std_logic_vector(resize(unsigned(r_event_lo), slave_o.dat'length)); --
when others => slave_o.dat <= (others => 'X');
end case;
end if; -- rst
end if; -- clk edge
end process;
end rtl;
--! @file eca_tlu_auto_pkg.vhd
-- DesignUnit eca_tlu_auto
--! @author Wesley W. Terpstra <w.terpstra@gsi.de>
--! @date 15/04/2016
--! @version 2.0
--! @copyright 2016 GSI Helmholtz Centre for Heavy Ion Research GmbH
--!
--! @brief AUTOGENERATED WISHBONE-SLAVE PACKAGE FOR eca_tlu.vhd
--!
--------------------------------------------------------------------------------
--! This library is free software; you can redistribute it and/or
--! modify it under the terms of the GNU Lesser General Public
--! License as published by the Free Software Foundation; either
--! version 3 of the License, or (at your option) any later version.
--!
--! This library is distributed in the hope that it will be useful,
--! but WITHOUT ANY WARRANTY; without even the implied warranty of
--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
--! Lesser General Public License for more details.
--!
--! You should have received a copy of the GNU Lesser General Public
--! License along with this library. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------
-- ***********************************************************
-- ** WARNING - THIS IS AUTO-GENERATED CODE! DO NOT MODIFY! **
-- ***********************************************************
--
-- If you want to change the interface,
-- modify eca_tlu.xml and re-run 'python wbgenplus.py eca_tlu.xml' !
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.wbgenplus_pkg.all;
use work.genram_pkg.all;
package eca_tlu_auto_pkg is
constant c_num_inputs_GET : natural := 16#00#; -- ro, 8 b, Total number of inputs attached to the TLU
constant c_input_select_RW : natural := 16#04#; -- rw, 8 b, Write the configuration of this input
constant c_enable_RW : natural := 16#08#; -- rw, 1 b, Will this input generate timing events on an edge
constant c_stable_RW : natural := 16#0c#; -- rw, 32 b, Signal must be high/low for stable cycles to be counted as a valid transition
constant c_event_hi_RW : natural := 16#10#; -- rw, 32 b, Timing Event to generate (high word)
constant c_event_lo_RW : natural := 16#14#; -- rw, 32 b, Timing Event to generate (low word), lowest bit is replaced with the edge of the transition
constant c_write_OWR : natural := 16#18#; -- wo, 1 b, Write register contents to TLU configuration
--| Component ----------------------- eca_tlu_auto ------------------------------------------|
component eca_tlu_auto is
generic(
g_num_inputs : natural := 0 --Total number of inputs attached to the TLU
);
Port(
clk_sys_i : std_logic; -- Clock input for sys domain
rst_sys_n_i : std_logic; -- Reset input (active low) for sys domain
error_i : in std_logic_vector(1-1 downto 0); -- Error control
stall_i : in std_logic_vector(1-1 downto 0); -- flow control
enable_o : out std_logic_vector(1-1 downto 0); -- Will this input generate timing events on an edge
event_hi_o : out std_logic_vector(32-1 downto 0); -- Timing Event to generate (high word)
event_lo_o : out std_logic_vector(32-1 downto 0); -- Timing Event to generate (low word), lowest bit is replaced with the edge of the transition
input_select_o : out std_logic_vector(8-1 downto 0); -- Write the configuration of this input
stable_o : out std_logic_vector(32-1 downto 0); -- Signal must be high/low for stable cycles to be counted as a valid transition
write_o : out std_logic_vector(1-1 downto 0); -- Write register contents to TLU configuration
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out
);
end component;
constant c_eca_tlu_slave_sdb : t_sdb_device := (
abi_class => x"0000", -- undocumented device
abi_ver_major => x"01",
abi_ver_minor => x"00",
wbd_endian => c_sdb_endian_big,
wbd_width => x"7", -- 8/16/32-bit port granularity
sdb_component => (
addr_first => x"0000000000000000",
addr_last => x"000000000000001f",
product => (
vendor_id => x"0000000000000651",
device_id => x"7c82afbc",
version => x"00000020",
date => x"20160415",
name => "ECA_UNIT:TLU ")));
end eca_tlu_auto_pkg;
package body eca_tlu_auto_pkg is
end eca_tlu_auto_pkg;
--! @file eca_tlu_fsm.vhd
--! @brief ECA TLU FSM
--! @author Wesley W. Terpstra <w.terpstra@gsi.de>
--!
--! Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH
--!
--! This component detects when a signal toggles
--!
--------------------------------------------------------------------------------
--! This library is free software; you can redistribute it and/or
--! modify it under the terms of the GNU Lesser General Public
--! License as published by the Free Software Foundation; either
--! version 3 of the License, or (at your option) any later version.
--!
--! This library is distributed in the hope that it will be useful,
--! but WITHOUT ANY WARRANTY; without even the implied warranty of
--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
--! Lesser General Public License for more details.
--!
--! You should have received a copy of the GNU Lesser General Public
--! License along with this library. If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.eca_internals_pkg.all;
entity eca_tlu_fsm is
generic(
g_history: natural := 10000; -- how many ticks in the past can events come?
g_stable : natural := 10;
g_serdes : natural := 8);
port(
clk_i : in std_logic;
rst_n_i : in std_logic;
enable_i : in std_logic;
stable_i : in std_logic_vector(g_stable-1 downto 0);
time_i : in t_time;
gpio_i : in std_logic_vector(g_serdes-1 downto 0);
ack_i : in std_logic;
stb_o : out std_logic;
edge_o : out std_logic;
time_o : out t_time);
end eca_tlu_fsm;
architecture rtl of eca_tlu_fsm is
constant c_increment_bits : natural := f_eca_log2(g_serdes+1);
constant c_history_bits : natural := f_eca_log2(g_history);
constant c_delay_adjust : natural := g_serdes * 4;
constant c_opposed_init : std_logic_vector(c_history_bits-1 downto 0) := std_logic_vector(to_unsigned(c_delay_adjust, c_history_bits));
signal r_prior : std_logic := '0';
signal r_gpio : std_logic_vector(g_serdes -1 downto 0) := (others => '0');
signal r_flat : std_logic_vector(g_stable -1 downto 0) := (others => '0');
signal r_increment : std_logic_vector(c_increment_bits-1 downto 0) := (others => '0');
signal r_opposed : std_logic_vector(c_history_bits -1 downto 0) := c_opposed_init;
signal r_state : std_logic := '0';
signal r_stb : std_logic := '0';
signal r_edge : std_logic := '-';
signal r_time : t_time := (others => '-');
signal s_state : std_logic_vector(g_serdes -1 downto 0);
signal s_prior : std_logic_vector(g_serdes -1 downto 0);
signal s_flat_eq : std_logic;
-- Hopefully logic minimization does a good job on this
function f_count(x : std_logic_vector)
return std_logic_vector is
variable result : std_logic_vector(c_increment_bits-1 downto 0) := (others => '0');
begin
for i in x'range loop
result := f_eca_add(result, x(i));
end loop;
return result;
end f_count;
begin
s_state <= (others => r_state);
s_prior <= (others => r_prior);
s_flat_eq <= f_eca_eq(r_flat, stable_i);
main : process(clk_i, rst_n_i) is
begin
if rst_n_i = '0' then
r_prior <= '0';
r_gpio <= (others => '0');
r_flat <= (others => '0');
r_increment <= (others => '0');
r_opposed <= c_opposed_init;
r_state <= '0';
r_stb <= '0';
r_edge <= '-';
r_time <= (others => '-');
elsif rising_edge(clk_i) then
r_prior <= r_gpio(r_gpio'high);
r_gpio <= gpio_i;
-- Spread the counting over a few cycles for timing closure.
-- Since we only clear these when the input signal has been stable, the
-- information lost is relating to the constant past => safe to ignore
r_increment <= f_count(r_gpio xor s_state);
r_opposed <= f_eca_add(r_opposed, r_increment);
if ack_i = '1' then
r_stb <= '0';
end if;
if s_prior /= r_gpio then
r_flat <= (others => '0');
else
r_flat <= f_eca_add(r_flat, not s_flat_eq);
if s_flat_eq = '1' then
r_state <= r_prior;
r_increment <= (others => '0');
r_opposed <= c_opposed_init;
if r_state /= r_prior then
r_stb <= enable_i;
r_edge <= r_prior;
r_time <= f_eca_sub(time_i, r_opposed);
end if;
end if;
end if;
end if;
end process;
stb_o <= r_stb;
edge_o <= r_edge;
time_o <= r_time;
end rtl;
/** @file eca_tlu_regs.h
* DesignUnit eca_tlu
* @author Wesley W. Terpstra <w.terpstra@gsi.de>
* @date 15/04/2016
* @version 2.0
* @copyright 2016 GSI Helmholtz Centre for Heavy Ion Research GmbH
*
* @brief Register map for Wishbone interface of VHDL entity <eca_tlu_auto>
*/
#ifndef _ECA_TLU_H_
#define _ECA_TLU_H_
#define ECA_TLU_SDB_VENDOR_ID 0x00000651
#define ECA_TLU_SDB_DEVICE_ID 0x7c82afbc
#define ECA_TLU_NUM_INPUTS_GET 0x00 //ro, 8 b, Total number of inputs attached to the TLU
#define ECA_TLU_INPUT_SELECT_RW 0x04 //rw, 8 b, Write the configuration of this input
#define ECA_TLU_ENABLE_RW 0x08 //rw, 1 b, Will this input generate timing events on an edge
#define ECA_TLU_STABLE_RW 0x0c //rw, 32 b, Signal must be high/low for stable cycles to be counted as a valid transition
#define ECA_TLU_EVENT_HI_RW 0x10 //rw, 32 b, Timing Event to generate (high word)
#define ECA_TLU_EVENT_LO_RW 0x14 //rw, 32 b, Timing Event to generate (low word), lowest bit is replaced with the edge of the transition
#define ECA_TLU_WRITE_OWR 0x18 //wo, 1 b, Write register contents to TLU configuration
#endif
......@@ -9,9 +9,11 @@ for i in \
eca_internals_pkg.vhd \
eca_auto_pkg.vhd \
eca_queue_auto_pkg.vhd \
eca_tlu_auto_pkg.vhd \
eca_ac_wbm_auto_pkg.vhd \
eca_auto.vhd \
eca_queue_auto.vhd \
eca_tlu_auto.vhd \
eca_ac_wbm_auto.vhd \
eca_pkg.vhd \
eca_compact.vhd \
......@@ -49,6 +51,8 @@ for i in \
wr_eca.vhd \
eca_ac_wbm.vhd \
eca_scubus_channel.vhd \
eca_tlu_fsm.vhd \
eca_tlu.vhd \
eca_tb.vhd; \
do echo $i; ghdl -a --std=93 --ieee=standard --syn-binding $i
done
......
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