From 5f3392ec282cac3748cbab41bc86299c49694a97 Mon Sep 17 00:00:00 2001 From: Dimitris Lampridis <dimitris.lampridis@cern.ch> Date: Wed, 21 Nov 2018 16:12:57 +0100 Subject: [PATCH] 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. --- .../wb_slave_adapter/wb_slave_adapter.vhd | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd b/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd index 47ffd5e1..dcf9207d 100644 --- a/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd +++ b/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd @@ -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; -- GitLab