Commit 2f068985 authored by Michael Reese's avatar Michael Reese Committed by Michael Reese

ebs: add MSI-slave interface. MSIs can be polled from additional cfg-space registers.

parent f95568c4
......@@ -6,17 +6,28 @@
-- Author : Wesley W. Terpstra
-- Company : GSI
-- Created : 2013-04-08
-- Last update: 2013-04-08
-- Last update: 2020-04-09
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Buffers Config space requests
--
-- Can be used as MSI slave and provides three registers that
-- can be polled in the following order:
-- 1) 0x40: address field of the MSI
-- 2) 0x44: data field of the MSI
-- 3) 0x48: MSI counter and valid flags
-- bits 31 downto 17 : number of accepted MSI by the slave interface
-- bits 16 downto 2 : sequence number of the last polled MSI
-- bit 1 : more MSI are waiting to be polled
-- bit 0 : the current MSI is valid.
-------------------------------------------------------------------------------
-- Copyright (c) 2013 GSI
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2013-04-08 1.0 terpstra Created
-- 2020-04-09 1.1 reese Add MSI slave and a polling interface
-------------------------------------------------------------------------------
library ieee;
......@@ -26,6 +37,7 @@ use ieee.numeric_std.all;
library work;
use work.wishbone_pkg.all;
use work.eb_internals_pkg.all;
use work.etherbone_pkg.all;
entity eb_cfg_fifo is
generic(
......@@ -39,6 +51,10 @@ entity eb_cfg_fifo is
cfg_i : in t_wishbone_slave_in;
cfg_o : out t_wishbone_slave_out;
-- MSI interface
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out;
fsm_stb_i : in std_logic;
fsm_adr_i : in t_wishbone_address;
fsm_full_o : out std_logic;
......@@ -50,6 +66,7 @@ entity eb_cfg_fifo is
my_mac_o : out std_logic_vector(47 downto 0);
my_ip_o : out std_logic_vector(31 downto 0);
my_port_o : out std_logic_vector(15 downto 0));
end eb_cfg_fifo;
architecture rtl of eb_cfg_fifo is
......@@ -59,13 +76,29 @@ architecture rtl of eb_cfg_fifo is
signal r_mac : std_logic_vector(6*8-1 downto 0);
signal r_ip : std_logic_vector(4*8-1 downto 0);
signal r_port : std_logic_vector(2*8-1 downto 0);
signal s_fsm_adr : std_logic_vector(2 downto 0);
signal s_fifo_adr : std_logic_vector(2 downto 0);
signal s_fsm_adr : std_logic_vector(4 downto 0);
signal s_fifo_adr : std_logic_vector(4 downto 0);
signal s_fifo_empty : std_logic;
signal s_fifo_pop : std_logic;
signal r_cache_empty : std_logic;
signal r_cache_adr : std_logic_vector(2 downto 0);
signal r_cache_adr : std_logic_vector(4 downto 0);
-- msi registers and constants
signal msi_full : std_logic;
signal msi_push : std_logic := '0';
signal msi_dat_adr_push : std_logic_vector(63 downto 0):=(others => '0');
signal msi_dat_adr_pop : std_logic_vector(63 downto 0):=(others => '0');
signal msi_empty : std_logic;
signal msi_pop : std_logic := '0';
signal msi_dat : std_logic_vector(31 downto 0):=(others => '0');
signal msi_adr : std_logic_vector(31 downto 0):=(others => '0');
signal msi_cnt : std_logic_vector(31 downto 0):=(others => '0');
signal msi_counter : unsigned(14 downto 0);
signal msi_counter_in : unsigned(14 downto 0);
signal msi_lock : std_logic := '0';
type msi_state_t is (MSI_S_WAIT_NOT_EMPTY, MSI_S_READ_FIFO, MSI_S_PROVIDE_DATA);
signal msi_state : msi_state_t := MSI_S_WAIT_NOT_EMPTY;
impure function update(x : std_logic_vector) return std_logic_vector is
alias y : std_logic_vector(x'length-1 downto 0) is x;
......@@ -99,7 +132,7 @@ begin
cfg_o.dat <= (others => '0');
elsif rising_edge(clk_i) then
if cfg_i.cyc = '1' and cfg_i.stb = '1' and cfg_i.we = '1' then
case to_integer(unsigned(cfg_i.adr(4 downto 2))) is
case to_integer(unsigned(cfg_i.adr(5 downto 2))) is
when 4 => r_mac(47 downto 32) <= update(r_mac(47 downto 32));
when 5 => r_mac(31 downto 0) <= update(r_mac(31 downto 0));
when 6 => r_ip <= update(r_ip);
......@@ -109,8 +142,8 @@ begin
end if;
cfg_o.ack <= cfg_i.cyc and cfg_i.stb;
case to_integer(unsigned(cfg_i.adr(4 downto 2))) is
case to_integer(unsigned(cfg_i.adr(6 downto 2))) is
when 0 => cfg_o.dat <= errreg_i(63 downto 32);
when 1 => cfg_o.dat <= errreg_i(31 downto 0);
when 2 => cfg_o.dat <= (others => '0');
......@@ -118,18 +151,19 @@ begin
when 4 => cfg_o.dat <= c_pad & r_mac(47 downto 32);
when 5 => cfg_o.dat <= r_mac(31 downto 0);
when 6 => cfg_o.dat <= r_ip;
when others => cfg_o.dat <= c_pad & r_port;
when 7 => cfg_o.dat <= c_pad & r_port;
when others => cfg_o.dat <= x"00000000";
end case;
end if;
end process;
-- Discard writes.
s_fsm_adr <= fsm_adr_i(4 downto 2);
s_fsm_adr <= fsm_adr_i(6 downto 2);
fifo : eb_fifo
generic map(
g_width => 3,
g_width => 5,
g_size => c_queue_depth)
port map(
clk_i => clk_i,
......@@ -157,20 +191,103 @@ begin
end process;
mux_empty_o <= r_cache_empty;
with r_cache_adr select
mux_dat_o <=
errreg_i(63 downto 32) when "000",
errreg_i(31 downto 0) when "001",
x"00000000" when "010",
g_sdb_address when "011",
c_pad & r_mac(47 downto 32) when "100",
r_mac(31 downto 0) when "101",
r_ip when "110",
c_pad & r_port when others;
with r_cache_adr select
mux_dat_o <=
errreg_i(63 downto 32) when "00000",
errreg_i(31 downto 0) when "00001",
x"00000000" when "00010",
g_sdb_address when "00011",
c_pad & r_mac(47 downto 32) when "00100",
r_mac(31 downto 0) when "00101",
r_ip when "00110",
c_pad & r_port when "00111",
-- what follows is for MSI
x"00000000" when "01000",
x"00000000" when "01001",
x"00000000" when "01010",
x"00000001" when "01011",
x"00000000" when "01100",
c_ebs_msi.sdb_component.addr_first(31 downto 0) when "01101",
x"00000000" when "01110",
c_ebs_msi.sdb_component.addr_last(31 downto 0) when "01111",
msi_adr when "10000",
msi_dat when "10001",
msi_cnt when "10010",
x"00000000" when others;
my_mac_o <= r_mac;
my_ip_o <= r_ip;
my_port_o <= r_port;
-- MSI polling
msi_slave_o.stall <= msi_full;
msi_push <= msi_slave_i.stb and msi_slave_i.cyc and not msi_full;
msi_slave_o.ack <= msi_slave_i.stb and msi_slave_i.cyc and not msi_full;
msi_dat_adr_push <= msi_slave_i.dat & msi_slave_i.adr;
msi_slave_o.dat <= (others => '-');
msi_slave_o.rty <= '0';
msi_slave_o.err <= '0';
msi : eb_fifo
generic map(
g_width => 64,
g_size => c_queue_depth)
port map(
clk_i => clk_i,
rstn_i => rstn_i,
w_full_o => msi_full,
w_push_i => msi_push,
w_dat_i => msi_dat_adr_push,
r_empty_o => msi_empty,
r_pop_i => msi_pop,
r_dat_o => msi_dat_adr_pop);
msi_output : process(rstn_i, clk_i) is
begin
if rstn_i = '0' then
msi_counter <= (others => '0');
msi_counter_in <= (others => '0');
msi_state <= MSI_S_WAIT_NOT_EMPTY;
elsif rising_edge(clk_i) then
if msi_push = '1' then
msi_counter_in <= msi_counter_in + 1;
end if;
msi_pop <= '0';
case msi_state is
when MSI_S_WAIT_NOT_EMPTY =>
if msi_empty = '0' and mux_pop_i = '0' and msi_lock = '0' then
msi_state <= MSI_S_READ_FIFO;
msi_dat <= msi_dat_adr_pop(63 downto 32);
msi_adr <= msi_dat_adr_pop(31 downto 0);
msi_cnt <= std_logic_vector(msi_counter_in) & std_logic_vector(msi_counter + 1) & not msi_empty & '1';
msi_counter <= msi_counter + 1;
end if;
when MSI_S_READ_FIFO =>
msi_pop <= '1';
msi_state <= MSI_S_PROVIDE_DATA;
when MSI_S_PROVIDE_DATA =>
if msi_empty = '0' then
msi_cnt(1) <= '1';
end if;
if mux_pop_i = '1' and r_cache_empty = '0' and r_cache_adr = "10010" then
msi_state <= MSI_S_WAIT_NOT_EMPTY;
msi_cnt <= (others => '0');
end if;
end case;
-- msi_lock prevents a pop from the fifo while MSI registers are polled by the host.
-- access to msi_adr at config address 0x40 sets the lock
-- access to msi_cnt at config address 0x48 releases the lock
if mux_pop_i = '1' and r_cache_empty = '0' and r_cache_adr = "10000" then
msi_lock <= '1';
end if;
if mux_pop_i = '1' and r_cache_empty = '0' and r_cache_adr = "10010" then
msi_lock <= '0';
end if;
end if;
end process;
end rtl;
......@@ -117,6 +117,8 @@ begin
EB_RX_o => s_fsm2widen,
EB_TX_i => s_narrow2fsm,
EB_TX_o => s_fsm2narrow,
msi_slave_o => open,
msi_slave_i => cc_dummy_slave_in,
skip_stb_o => s_skip_stb,
skip_stall_i => s_skip_stall,
WB_config_i => cfg_slave_i,
......
......@@ -55,11 +55,17 @@ architecture rtl of eb_fifo is
signal r_idx1 : unsigned(c_depth downto 0);
signal w_idx1 : unsigned(c_depth downto 0);
signal aa : std_logic_vector(c_depth-1 downto 0);
signal ab : std_logic_vector(c_depth-1 downto 0);
constant c_low : unsigned(c_depth-1 downto 0) := (others => '0');
constant c_high : unsigned(c_depth downto 0) := '1' & c_low;
begin
aa <= std_logic_vector(w_idx(c_depth-1 downto 0));
ab <= std_logic_vector(r_idx1(c_depth-1 downto 0));
ram : generic_simple_dpram
generic map(
g_data_width => g_width,
......@@ -71,11 +77,11 @@ begin
clka_i => clk_i,
bwea_i => (others => '1'),
wea_i => w_push_i,
aa_i => std_logic_vector(w_idx(c_depth-1 downto 0)),
aa_i => aa,
da_i => w_dat_i,
clkb_i => clk_i,
ab_i => std_logic_vector(r_idx1(c_depth-1 downto 0)),
ab_i => ab,
qb_o => r_dat_o);
r_idx1 <= (r_idx+1) when r_pop_i ='1' else r_idx;
......
......@@ -47,7 +47,10 @@ package eb_internals_pkg is
my_mac_o : out std_logic_vector(47 downto 0);
my_ip_o : out std_logic_vector(31 downto 0);
my_port_o : out std_logic_vector(15 downto 0));
my_port_o : out std_logic_vector(15 downto 0);
-- MSI interface
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out);
end component;
component eb_slave_fsm is
......@@ -181,6 +184,10 @@ package eb_internals_pkg is
cfg_i : in t_wishbone_slave_in;
cfg_o : out t_wishbone_slave_out;
-- MSI interface
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out;
fsm_stb_i : in std_logic;
fsm_adr_i : in t_wishbone_address;
......
......@@ -52,7 +52,11 @@ entity eb_raw_slave is
cfg_slave_o : out t_wishbone_slave_out;
cfg_slave_i : in t_wishbone_slave_in;
master_o : out t_wishbone_master_out;
master_i : in t_wishbone_master_in);
master_i : in t_wishbone_master_in;
-- MSI interface
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out
);
end eb_raw_slave;
architecture rtl of eb_raw_slave is
......@@ -105,6 +109,9 @@ begin
WB_master_o => master_o,
my_mac_o => open,
my_ip_o => open,
my_port_o => open);
my_port_o => open,
msi_slave_i => msi_slave_i,
msi_slave_o => msi_slave_o
);
end rtl;
......@@ -50,7 +50,10 @@ entity eb_slave_top is
my_mac_o : out std_logic_vector(47 downto 0);
my_ip_o : out std_logic_vector(31 downto 0);
my_port_o : out std_logic_vector(15 downto 0));
my_port_o : out std_logic_vector(15 downto 0);
-- MSI interface
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out);
end eb_slave_top;
architecture rtl of eb_slave_top is
......@@ -176,6 +179,8 @@ begin
errreg_i => errreg,
cfg_i => WB_config_i,
cfg_o => WB_config_o,
msi_slave_i => msi_slave_i,
msi_slave_o => msi_slave_o,
fsm_stb_i => fsm_cfg_stb,
fsm_adr_i => fsm_cfg_adr,
fsm_full_o => cfg_fsm_full,
......
......@@ -70,7 +70,10 @@ package etherbone_pkg is
cfg_slave_o : out t_wishbone_slave_out;
cfg_slave_i : in t_wishbone_slave_in;
master_o : out t_wishbone_master_out;
master_i : in t_wishbone_master_in);
master_i : in t_wishbone_master_in;
-- MSI interface
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out);
end component;
component eb_master_slave_wrapper is
......
......@@ -44,6 +44,10 @@ entity ez_usb is
master_i : in t_wishbone_master_in;
master_o : out t_wishbone_master_out;
-- MSI interface
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out;
-- USB Console
uart_o : out std_logic;
uart_i : in std_logic;
......@@ -302,6 +306,9 @@ begin
cfg_slave_o => open,
cfg_slave_i => cc_dummy_slave_in,
master_o => master_o,
master_i => master_i);
master_i => master_i,
msi_slave_i => msi_slave_i,
msi_slave_o => msi_slave_o
);
end rtl;
......@@ -35,6 +35,10 @@ package ez_usb_pkg is
-- Wishbone interface
master_i : in t_wishbone_master_in;
master_o : out t_wishbone_master_out;
-- MSI interface
msi_slave_i : in t_wishbone_slave_in;
msi_slave_o : out t_wishbone_slave_out;
-- USB Console
uart_o : out std_logic;
......
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