Commit 5f3392ec authored by Dimitris Lampridis's avatar Dimitris Lampridis

wb_slave_adapter: in the P2C scenario, only strobe ACK/ERR/RTY for 1 cycle.

Although not mentioned in section 5.2 of Wishbone B4 specification, when interfacing a pipelined
master to a standard slave, it is also necessary to make sure that if the slave asserts ACK/ERR/RTY
for more than one clock cycle (which a standard slave could do since, according to Rule 3.50 of
Wishbone B4, "the slave deasserts ACK/ERR/RTY in response to the negation of STB"), the master will
still only see a one cycle wide pulse.
parent 8052c7b1
......@@ -105,15 +105,10 @@ architecture rtl of wb_slave_adapter is
return std_logic_vector(to_unsigned(0, size));
end f_zeros;
type t_fsm_state is (IDLE, WAIT4ACK);
signal fsm_state : t_fsm_state := IDLE;
signal master_in : t_wishbone_master_in;
signal master_out : t_wishbone_master_out;
signal slave_in : t_wishbone_slave_in;
signal slave_out : t_wishbone_slave_out;
signal stored_we : std_logic;
begin -- rtl
......@@ -170,17 +165,41 @@ begin -- rtl
master_out.adr <= f_zeros(f_num_byte_address_bits)
& slave_in.adr(c_wishbone_address_width-1 downto f_num_byte_address_bits);
end if;
end process;
end process p_gen_address;
P2C : if (g_slave_mode = PIPELINED and g_master_mode = CLASSIC) generate
signal master_in_ack_d1 : std_logic := '0';
signal master_in_err_d1 : std_logic := '0';
signal master_in_rty_d1 : std_logic := '0';
begin
-- we need delayed versions of of ack/err/rty to detect rising edges and
-- send a one clock cycle wide ack/err/rty to the pipelined side.
p_wb_term_d1: process (clk_sys_i) is
begin
if rising_edge(clk_sys_i) then
master_in_ack_d1 <= master_in.ack;
master_in_err_d1 <= master_in.err;
master_in_rty_d1 <= master_in.rty;
end if;
end process p_wb_term_d1;
master_out.stb <= slave_in.stb;
slave_out.stall <= not master_in.ack;
end generate;
slave_out.stall <= '0' when slave_in.cyc = '0' else not master_in.ack;
slave_out.ack <= master_in.ack and not master_in_ack_d1;
slave_out.err <= master_in.err and not master_in_err_d1;
slave_out.rty <= master_in.rty and not master_in_rty_d1;
end generate P2C;
C2P : if (g_slave_mode = CLASSIC and g_master_mode = PIPELINED) generate
type t_fsm_state is (IDLE, WAIT4ACK);
signal fsm_state : t_fsm_state := IDLE;
begin
master_out.stb <= slave_in.stb when fsm_state=IDLE else '0';
slave_out.ack <= master_in.ack;
slave_out.err <= master_in.err;
slave_out.rty <= master_in.rty;
slave_out.stall <= '0'; -- classic will ignore this anyway
state_machine : process(clk_sys_i) is
begin
if rising_edge(clk_sys_i) then
......@@ -188,32 +207,34 @@ begin -- rtl
fsm_state <= IDLE;
else
case fsm_state is
when IDLE =>
if slave_in.stb ='1' and slave_in.cyc = '1' and master_in.stall='0' and master_in.ack='0' then
when IDLE =>
if (slave_in.stb = '1' and slave_in.cyc = '1') and
(master_in.stall = '0' and master_in.ack = '0' and master_in.rty = '0') then
fsm_state <= WAIT4ACK;
end if;
when WAIT4ACK =>
if (slave_in.stb = '0' and slave_in.cyc = '0') or master_in.ack='1' or master_in.err='1' then
when WAIT4ACK =>
if (slave_in.stb = '0' and slave_in.cyc = '0') or
(master_in.ack = '1' or master_in.err = '1' or master_in.rty = '1') then
fsm_state <= IDLE;
end if;
end case;
end if;
end if;
end process;
end generate;
end process state_machine;
end generate C2P;
X2X : if (g_slave_mode = g_master_mode) generate
master_out.stb <= slave_in.stb;
slave_out.stall <= master_in.stall;
end generate;
slave_out.ack <= master_in.ack;
slave_out.err <= master_in.err;
slave_out.rty <= master_in.rty;
end generate X2X;
master_out.dat <= slave_in.dat;
master_out.cyc <= slave_in.cyc;
master_out.sel <= slave_in.sel;
master_out.we <= slave_in.we;
slave_out.ack <= master_in.ack;
slave_out.err <= master_in.err;
slave_out.rty <= master_in.rty;
slave_out.dat <= master_in.dat;
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