From: Ryan <> Date: Tue, 30 Sep 2025 07:39:18 +0000 (-0500) Subject: Drive Wishbone bridge with state machine X-Git-Url: https://git.the-white-hart.net/?a=commitdiff_plain;h=6638def55cd9ad6f39037b789f418675b8a9800e;p=vhdl Drive Wishbone bridge with state machine --- diff --git a/libraries/utility/wb_bridge.vhd b/libraries/utility/wb_bridge.vhd index c96e14b..fb0560e 100644 --- a/libraries/utility/wb_bridge.vhd +++ b/libraries/utility/wb_bridge.vhd @@ -31,62 +31,71 @@ end wb_bridge; architecture behavioral of wb_bridge is - signal cyc_reg: std_logic; - signal stb_reg: std_logic; + type state_t is (S_IDLE, S_STB, S_ACK); + signal state_cur_reg: state_t; + signal state_next: state_t; + signal we_reg: std_logic; - signal ack_reg: std_logic; signal adr_reg: std_logic_vector(A_WIDTH-1 downto 0); signal mosi_reg: std_logic_vector(D_WIDTH-1 downto 0); signal miso_reg: std_logic_vector(D_WIDTH-1 downto 0); begin - process (rst_i, clk_i, stb_reg, - a_cyc_i, a_stb_i, a_we_i, a_adr_i, a_dat_i, - b_dat_i) + process (rst_i, clk_i) + begin + if rising_edge(clk_i) then + if rst_i = '1' then + state_cur_reg <= S_IDLE; + else + state_cur_reg <= state_next; + end if; + end if; + end process; + + process (state_cur_reg, a_cyc_i, a_stb_i, b_ack_i) + begin + state_next <= state_cur_reg; + b_cyc_o <= '0'; + b_stb_o <= '0'; + a_ack_o <= '0'; + + case state_cur_reg is + when S_IDLE => + if a_cyc_i = '1' and a_stb_i = '1' then + state_next <= S_STB; + end if; + + when S_STB => + b_cyc_o <= '1'; + b_stb_o <= '1'; + if b_ack_i = '1' then + state_next <= S_ACK; + end if; + + when S_ACK => + a_ack_o <= '1'; + state_next <= S_IDLE; + + when others => + state_next <= S_IDLE; + end case; + end process; + + process (rst_i, clk_i, a_we_i, a_adr_i, a_dat_i, b_dat_i) begin if rising_edge(clk_i) then -- Most signals just get registered - cyc_reg <= a_cyc_i; we_reg <= a_we_i; adr_reg <= a_adr_i; mosi_reg <= a_dat_i; miso_reg <= b_dat_i; - - -- The strobe input from side A will still be asserted when side B - -- acknowledges because it will take another clock cycle for side A - -- to get the adknowledgement, so we need to lower the strobe signal - -- ourselves once side B acknowledges to prevent a second - -- transaction from starting - if stb_reg = '1' and b_ack_i = '1' then - stb_reg <= '0'; - else - stb_reg <= a_stb_i; - end if; - - -- Some devices always assert ACK because they respond within a - -- single clock cycle. These should not be passed back to side A - -- until after the strobe has been sent to side B - if stb_reg = '0' then - ack_reg <= '0'; - else - ack_reg <= b_ack_i; - end if; - - -- The CYC signal determines validity of all others, so only it - -- needs to be reset to zero - if rst_i = '1' then - cyc_reg <= '0'; - end if; end if; end process; -- Outputs come from registers only - a_ack_o <= ack_reg; a_dat_o <= miso_reg; - b_cyc_o <= cyc_reg; - b_stb_o <= stb_reg; b_we_o <= we_reg; b_adr_o <= adr_reg; b_dat_o <= mosi_reg;