Skip to content
Snippets Groups Projects
Commit 0bcf6830 authored by Wesley W. Terpstra's avatar Wesley W. Terpstra
Browse files

eb2: appease modelsim and fine-tune flow control logic

parent 8516e717
No related merge requests found
...@@ -6,5 +6,6 @@ files = [ ...@@ -6,5 +6,6 @@ files = [
"eb_tag_fifo.vhd", "eb_tag_fifo.vhd",
"eb_wbm_fifo.vhd", "eb_wbm_fifo.vhd",
"eb_internals_pkg.vhd", "eb_internals_pkg.vhd",
"eb_hdr_pkg.vhd",
"eb_slave.vhd" "eb_slave.vhd"
] ]
...@@ -7,12 +7,12 @@ use IEEE.numeric_std.all; ...@@ -7,12 +7,12 @@ use IEEE.numeric_std.all;
library work; library work;
--! Additional packages --! Additional packages
use work.eb_internals_pkg.all; use work.eb_internals_pkg.all;
use work.eb_hdr_pkg.all;
use work.wishbone_pkg.all; use work.wishbone_pkg.all;
entity eb_rx_fsm is entity eb_rx_fsm is
port ( port(
clk_i : in std_logic; clk_i : in std_logic;
rstn_i : in std_logic; rstn_i : in std_logic;
rx_cyc_i : in std_logic; rx_cyc_i : in std_logic;
...@@ -40,35 +40,28 @@ end entity; ...@@ -40,35 +40,28 @@ end entity;
architecture behavioral of eb_rx_fsm is architecture behavioral of eb_rx_fsm is
signal rx_dat_i : std_logic_vector(31 downto 0); type t_state_RX is (S_EB_HDR, S_PROBE_ID, s_CYC_HDR, S_WR_ADR, S_WRITE, S_RD_ADR, S_READ, S_ERRORS);
signal r_rx_stall_o : std_logic; signal r_tx_cyc_o : std_logic;
signal r_tag_stb_o : std_logic; signal r_tag_stb_o : std_logic;
signal r_tag_dat_o : t_tag; signal r_tag_dat_o : t_tag;
signal r_pass_stb_o : std_logic; signal r_pass_stb_o : std_logic;
signal r_pass_dat_o : std_logic; signal r_pass_dat_o : t_wishbone_data;
signal r_cfg_o : t_wishbone_master_out; signal r_cfg_stb_o : std_logic;
signal r_wb_o : t_wishbone_master_out; signal r_wbm_stb_o : std_logic;
signal r_adr_o : t_wishbone_address;
signal s_state : t_state_RX; signal r_we_o : std_logic;
signal r_wr_adr : unsigned(31 downto 0);
impure function f_reset is signal r_wait_mux : std_logic;
begin signal r_rx_cyc_hdr : EB_CYC;
r_rx_stall_o <= '0'; signal r_tx_cyc_hdr : EB_CYC;
r_tag_stb_o <= '0'; signal r_state : t_state_RX;
r_tag_dat_o <= (others => '0'); signal s_stall : std_logic;
r_pass_stb_o <= '0';
r_pass_dat_o <= (others => '0'); function reply(rx_cyc_hdr : EB_CYC)
r_cfg_o <= cc_dummy_master_out; return EB_CYC is
r_wb_o <= cc_dummy_master_out; variable tx_cyc_hdr : EB_CYC;
r_state <= EB_HDR; begin
r_wait_mux <= '0';
end f_reset;
function reply(rx_cyc_hdr : EB_CYC)
return EB_CYC is
variable tx_cyc_hdr : EB_CYC;
begin
tx_cyc_hdr := INIT_EB_CYC; tx_cyc_hdr := INIT_EB_CYC;
tx_cyc_hdr.WCA_CFG := rx_cyc_hdr.BCA_CFG; tx_cyc_hdr.WCA_CFG := rx_cyc_hdr.BCA_CFG;
tx_cyc_hdr.RD_FIFO := '0'; tx_cyc_hdr.RD_FIFO := '0';
...@@ -76,211 +69,226 @@ begin ...@@ -76,211 +69,226 @@ begin
tx_cyc_hdr.WR_FIFO := rx_cyc_hdr.RD_FIFO; tx_cyc_hdr.WR_FIFO := rx_cyc_hdr.RD_FIFO;
tx_cyc_hdr.WR_CNT := rx_cyc_hdr.RD_CNT; tx_cyc_hdr.WR_CNT := rx_cyc_hdr.RD_CNT;
tx_cyc_hdr.SEL := rx_cyc_hdr.SEL; tx_cyc_hdr.SEL := rx_cyc_hdr.SEL;
tx_cyc_hdr.DROP_CYC := rx_cyc_hdr.DROP_CYC; tx_cyc_hdr.DROP_CYC := rx_cyc_hdr.DROP_CYC;
return tx_cyc_hdr; return tx_cyc_hdr;
end function reply; end function;
impure function pass_on(data : std_logic_vector) is
return boolean is
variable result : boolean := false;
begin begin
s_pass_dat_o <= data;
s_tag_dat_o <= c_tag_pass_on; rx_stall_o <= s_stall;
tx_cyc_o <= r_tx_cyc_o;
if(pass_full_i = '0' AND tag_full_i = '0') then tag_stb_o <= r_tag_stb_o;
s_tag_stb_o <= '1'; tag_dat_o <= r_tag_dat_o;
s_pass_stb_o <= '1'; pass_stb_o <= r_pass_stb_o;
s_rx_stall_o <= '0'; pass_dat_o <= r_pass_dat_o;
result := true;
else cfg_wb_o.cyc <= '1';
s_tag_stb_o <= '0'; cfg_wb_o.stb <= r_cfg_stb_o;
s_pass_stb_o <= '0'; cfg_wb_o.adr <= r_adr_o;
s_rx_stall_o <= '1'; cfg_wb_o.we <= r_we_o;
result := false; cfg_wb_o.sel <= r_rx_cyc_hdr.sel;
end if; cfg_wb_o.dat <= rx_dat_i;
return result;
end pass_on;
impure function wb_write(adr : std_logic_vector; data : std_logic_vector) is
begin
s_pass_dat_o <= data;
s_tag_dat_o <= c_tag_pass_on;
if(pass_full_i = '0' AND tag_full_i = '0') then
s_tag_stb_o <= '1';
s_pass_stb_o <= '1';
s_rx_stall_o <= '0';
result := true;
else
s_tag_stb_o <= '0';
s_pass_stb_o <= '0';
s_rx_stall_o <= '1';
result := false;
end if;
end pass_on;
impure function wb_read((adr : std_logic_vector) is
begin
s_pass_dat_o <= data;
s_tag_dat_o <= c_tag_pass_on;
if(pass_full_i = '0' AND tag_full_i = '0') then wbm_wb_o.cyc <= not r_wait_mux or not mux_empty_i; -- Lower when mux is drained
s_tag_stb_o <= '1'; wbm_wb_o.stb <= r_wbm_stb_o;
s_pass_stb_o <= '1'; wbm_wb_o.adr <= r_adr_o;
s_rx_stall_o <= '0'; wbm_wb_o.we <= r_we_o;
result := true; wbm_wb_o.sel <= r_rx_cyc_hdr.sel;
else wbm_wb_o.dat <= rx_dat_i;
s_tag_stb_o <= '0';
s_pass_stb_o <= '0';
s_rx_stall_o <= '1';
result := false;
end if;
end pass_on;
type t_state_RX is (EB_HDR, PROBE_ID, CYC_HDR, WR_ADR, WRITE, RD_ADR, READ, CYC_DONE, EB_DONE, ERRORS); -- Stall if FIFOs full or we are trying to quiet the bus
s_stall <= pass_full_i OR tag_full_i OR wbm_full_i OR (r_wait_mux and not mux_empty_i);
signal stall : std_logic;
signal r_rx_cyc_hdr : EB_CYC;
signal r_tx_cyc_hdr : EB_CYC;
begin
stall <= pass_full_i OR tag_full_i OR wbm_full_i OR (r_wait_mux and not mux_empty_i);
fsm : process(clk_i, rstn_i)
variable rx_frame_hdr : EB_HDR; fsm : process(clk_i, rstn_i) is
variable tx_frame_hdr : EB_HDR; variable rx_frame_hdr : EB_HDR;
variable tx_frame_hdr : EB_HDR;
variable rx_cyc_hdr : EB_CYC; variable rx_cyc_hdr : EB_CYC;
variable tx_cyc_hdr : EB_CYC; variable tx_cyc_hdr : EB_CYC;
begin begin
if (rstn_i = '0') then if (rstn_i = '0') then
f_reset; r_tx_cyc_o <= '0';
r_tag_stb_o <= '0';
r_tag_dat_o <= (others => '0');
r_pass_stb_o <= '0';
r_pass_dat_o <= (others => '0');
r_cfg_stb_o <= '0';
r_wbm_stb_o <= '0';
r_adr_o <= (others => '0');
r_we_o <= '0';
r_wr_adr <= (others => '0');
r_wait_mux <= '0';
r_rx_cyc_hdr <= INIT_EB_CYC;
r_tx_cyc_hdr <= INIT_EB_CYC;
r_state <= S_EB_HDR;
elsif rising_edge(clk_i) then elsif rising_edge(clk_i) then
if(rx_cyc_i = '1') then
if(rx_stb_i '1' and stall = '0') then -- By default, write nowhere in particular
r_tag_stb_o <= '0';
r_pass_stb_o <= '0';
r_cfg_stb_o <= '0';
r_wbm_stb_o <= '0';
if(rx_cyc_i = '0') then
r_wait_mux <= '1'; -- stop next request until mux has drained
r_state <= S_EB_HDR;
r_tx_cyc_o <= not mux_empty_i; -- !!! might combine packets
elsif(rx_stb_i = '1' and s_stall = '0') then
-- Every non-error state must write something
case r_state is
when s_EB_HDR =>
rx_frame_hdr := TO_EB_HDR(rx_dat_i);
if( (rx_frame_hdr.EB_MAGIC = c_EB_MAGIC_WORD) and
((rx_frame_hdr.ADDR_SIZE and c_MY_EB_ADDR_SIZE) /= x"0") and
((rx_frame_hdr.PORT_SIZE and c_MY_EB_PORT_SIZE) /= x"0") and
(rx_frame_hdr.VER = c_EB_VER)
) then --header valid ?
-- Raise TX cycle line if this needs to be sent
r_tx_cyc_o <= NOT rx_frame_hdr.NO_RESPONSE;
-- Create output header
tx_frame_hdr := init_EB_hdr;
tx_frame_hdr.PROBE_RES := rx_frame_hdr.PROBE;
-- Write the header using pass fifo
r_tag_stb_o <= '1';
r_tag_dat_o <= c_tag_pass_on;
r_pass_stb_o <= '1';
r_pass_dat_o <= to_std_logic_vector(tx_frame_hdr);
if(tx_frame_hdr.PROBE_RES = '1') then
r_state <= S_PROBE_ID;
else
r_state <= S_CYC_HDR;
end if;
else --bad eb header. drop all til cycle line is lowered again
r_state <= S_ERRORS;
end if;
r_pass_stb_o <= '0'; when S_PROBE_ID =>
r_wb_o.stb <= '0'; -- Write the probe-id using pass fifo
r_cfg_o.stb <= '0'; r_tag_stb_o <= '1';
r_tag_dat_o <= c_tag_pass_on;
r_pass_stb_o <= '1';
r_pass_dat_o <= rx_dat_i;
r_state <= s_CYC_HDR;
case s_state is when S_CYC_HDR =>
when EB_HDR => rx_frame_hdr := TO_EB_HDR(rx_dat_i); rx_cyc_hdr := TO_EB_CYC(rx_dat_i);
if( (rx_frame_hdr.EB_MAGIC = c_EB_MAGIC_WORD) tx_cyc_hdr := reply(rx_cyc_hdr);
((rx_frame_hdr.ADDR_SIZE and c_MY_EB_ADDR_SIZE) /= x"0") r_tx_cyc_hdr <= tx_cyc_hdr;
((rx_frame_hdr.PORT_SIZE and c_MY_EB_PORT_SIZE) /= x"0") r_rx_cyc_hdr <= rx_cyc_hdr;
(rx_frame_hdr.VER = c_EB_VER)
) then --header valid ?
tx_cyc_o <= NOT rx_frame_hdr.NO_RESPONSE;
tx_frame_hdr := init_EB_hdr;
tx_frame_hdr.PROBE_RES := rx_frame_hdr.PROBE;
pass_on(tx_frame_hdr);
--if pass on succesful, go to...
if(tx_frame_hdr.PROBE_RES = '1') then
--...get probe id
s_state <= PROBE_ID;
else
--...get record header
s_state <= CYC_HDR;
end if;
else
--bad eb header. drop all til cycle line is lowered again
s_state <= ERRORS;
end if;
when PROBE_ID => pass_on(rx_dat_i); r_wait_mux <= '0'; -- Re-enable pipelining
s_state <= CYC_HDR;
-- Write padding/header using pass fifo
when CYC_HDR => rx_cyc_hdr := TO_EB_HDR(rx_dat_i); r_tag_stb_o <= '1';
--check if record hdr is valid r_tag_dat_o <= c_tag_pass_on;
tx_cyc_hdr := reply(rx_cyc_hdr); r_pass_stb_o <= '1';
r_wait_mux <= '0';
if (rx_cyc_hdr.WR_CNT > 0) then if (rx_cyc_hdr.WR_CNT /= 0) then
--padding logic 1. insert padding instead of the header --padding logic 1. insert padding instead of the header
pass_on(x"00000000"); r_pass_dat_o <= x"00000000";
s_state <= WR_ADR; r_state <= S_WR_ADR;
elsif (rx_cyc_hdr.RD_CNT > 0) then elsif (rx_cyc_hdr.RD_CNT /= 0) then
--no writes, no padding. insert the header --no writes, no padding. insert the header
pass_on(tx_cyc_hdr); r_pass_dat_o <= to_std_logic_vector(tx_cyc_hdr);
s_state <= RD_ADR; r_state <= S_RD_ADR;
else else
--no writes, no padding. insert the header --no writes, no padding. insert the header
pass_on(tx_cyc_hdr); r_pass_dat_o <= to_std_logic_vector(tx_cyc_hdr);
r_wait_mux <= rx_cyc_hdr.DROP_CYC;
s_state <= CYC_HDR; r_wait_mux <= rx_cyc_hdr.DROP_CYC;
end if; r_state <= S_CYC_HDR;
end if;
r_tx_cyc_hdr <= tx_cyc_hdr;
r_rx_cyc_hdr <= rx_cyc_hdr;
when WR_ADR => wb_adr <= rx_dat_i;
pass_on(x"00000000");
s_state <= WRITE;
when WRITE => if(r_rx_cyc_hdr.WR_CNT > 0) then
r_rx_cyc_hdr.WR_CNT <= std_logic_vector(unsigned(r_rx_cyc_hdr.WR_CNT) -1);
if(r_rx_cyc_hdr.WR_FIFO = '0') then
wb_adr <= wb_adr +4;
end if;
wb_write(wr_adr, rx_dat_i);
--padding logic 2. insert the header as the last write padding
if(r_rx_cyc_hdr.WR_CNT > 1) then
pass_on(x"00000000");
else
pass_on(tx_cyc_hdr);
end if;
else
if (r_cyc_hdr.RD_CNT > 0) then
s_state <= RD_ADR;
else
r_wait_mux <= r_rx_cyc_hdr.DROP_CYC;
s_state <= CYC_HDR;
end if;
end if;
when RD_ADR => pass_on(rx_dat_i); --pass the rx readback address as base write address to tx when S_WR_ADR =>
s_state <= READ; r_wr_adr <= unsigned(rx_dat_i);
when READ => if(r_rx_cyc_hdr.RD_CNT > 0) then -- Write padding using pass fifo
r_rx_cyc_hdr.RD_CNT <= std_logic_vector(unsigned(r_rx_cyc_hdr.RD_CNT) -1); r_tag_stb_o <= '1';
wb_read(rx_dat_i); r_tag_dat_o <= c_tag_pass_on;
else r_pass_stb_o <= '1';
r_wait_mux <= r_rx_cyc_hdr.DROP_CYC; r_pass_dat_o <= x"00000000";
s_state <= CYC_HDR;
end if; r_state <= S_WRITE;
when ERRORS => null; when S_WRITE =>
-- Writes set to eb_wbm_fifo do not generate output
if r_rx_cyc_hdr.BCA_CFG = '1' then
r_cfg_stb_o <= '1';
else
r_wbm_stb_o <= '1';
end if;
r_adr_o <= std_logic_vector(r_wr_adr);
r_we_o <= '1';
if(r_rx_cyc_hdr.WR_FIFO = '0') then
r_wr_adr <= r_wr_adr + 4;
end if;
-- Write padding/header using pass fifo
r_tag_stb_o <= '1';
r_tag_dat_o <= c_tag_pass_on;
r_pass_stb_o <= '1';
if (r_rx_cyc_hdr.WR_CNT /= 1) then
r_pass_dat_o <= x"00000000";
else
r_pass_dat_o <= to_std_logic_vector(r_tx_cyc_hdr);
if (r_rx_cyc_hdr.RD_CNT /= 0) then
r_state <= S_RD_ADR;
else
r_wait_mux <= r_rx_cyc_hdr.DROP_CYC;
r_state <= S_CYC_HDR;
end if;
end if;
r_rx_cyc_hdr.WR_CNT <= r_rx_cyc_hdr.WR_CNT - 1;
when S_RD_ADR =>
-- Copy address using pass fifo
r_tag_stb_o <= '1';
r_tag_dat_o <= c_tag_pass_on;
r_pass_stb_o <= '1';
r_pass_dat_o <= rx_dat_i; --pass the rx readback address as base write address to tx
r_state <= S_READ;
when S_READ =>
-- Get data from either cfg or wbm fifos
r_tag_stb_o <= '1';
if r_rx_cyc_hdr.BCA_CFG = '1' then
r_cfg_stb_o <= '1';
r_tag_dat_o <= c_tag_cfg_req;
else
r_wbm_stb_o <= '1';
r_tag_dat_o <= c_tag_wbm_req;
end if;
r_adr_o <= rx_dat_i;
r_we_o <= '0';
if(r_rx_cyc_hdr.RD_CNT = 1) then
r_wait_mux <= r_rx_cyc_hdr.DROP_CYC;
r_state <= S_CYC_HDR;
end if;
r_rx_cyc_hdr.RD_CNT <= r_rx_cyc_hdr.RD_CNT - 1;
when S_ERRORS =>
null;
when others => s_state <= ERRORS; when others =>
end case; r_state <= S_ERRORS;
end if; --rx_stb_i end case;
else end if; --rx_stb_i
r_wait_mux <= '1';
s_state <= EB_HDR;
end if; --rx_cyc_i
end if; --clk edge end if; --clk edge
end process; end process;
end architecture; end architecture;
...@@ -192,9 +192,9 @@ begin ...@@ -192,9 +192,9 @@ begin
mux_empty <= mux_empty <=
not wbm_busy and not wbm_busy and
wbm_mux_empty and -- wbm_mux_empty and -- redundant
cfg_mux_empty and -- cfg_mux_empty and
pass_mux_empty and -- pass_mux_empty and
tag_mux_empty; tag_mux_empty;
end rtl; end rtl;
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