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;