--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+
+
+entity test_wb_bridge is
+end test_wb_bridge;
+
+
+architecture behavior of test_wb_bridge is
+
+ constant CLK_PERIOD: time := 10 ns;
+
+ signal rst: std_logic;
+ signal clk: std_logic;
+
+ signal a_cyc: std_logic;
+ signal a_stb: std_logic;
+ signal a_we: std_logic;
+ signal a_ack: std_logic;
+ signal a_adr: std_logic_vector(7 downto 0);
+ signal a_mosi: std_logic_vector(7 downto 0);
+ signal a_miso: std_logic_vector(7 downto 0);
+
+ signal b_cyc: std_logic;
+ signal b_stb: std_logic;
+ signal b_we: std_logic;
+ signal b_ack: std_logic;
+ signal b_adr: std_logic_vector(7 downto 0);
+ signal b_mosi: std_logic_vector(7 downto 0);
+ signal b_miso: std_logic_vector(7 downto 0);
+
+begin
+
+ p_test: process
+ begin
+ -- Initial values
+ a_cyc <= '0';
+ a_stb <= '0';
+ a_we <= '0';
+ a_adr <= (others => '0');
+ a_mosi <= (others => '0');
+
+ -- Reset
+ rst <= '1';
+ wait for CLK_PERIOD*2;
+ rst <= '0';
+ wait for CLK_PERIOD*2;
+
+ -- Make a request
+ a_cyc <= '1';
+ a_stb <= '1';
+ wait until a_ack = '1';
+ a_cyc <= '0';
+ a_stb <= '0';
+
+ wait;
+ end process;
+
+
+ e_uut: entity work.wb_bridge
+ generic map (A_WIDTH => 8, D_WIDTH => 8)
+ port map (
+ rst_i => rst,
+ clk_i => clk,
+
+ a_cyc_i => a_cyc,
+ a_stb_i => a_stb,
+ a_we_i => a_we,
+ a_ack_o => a_ack,
+ a_adr_i => a_adr,
+ a_dat_i => a_mosi,
+ a_dat_o => a_miso,
+
+ b_cyc_o => b_cyc,
+ b_stb_o => b_stb,
+ b_we_o => b_we,
+ b_ack_i => b_ack,
+ b_adr_o => b_adr,
+ b_dat_o => b_mosi,
+ b_dat_i => b_miso
+ );
+
+
+ p_device: process (rst, clk, b_cyc, b_stb, b_we, b_adr, b_mosi)
+ begin
+ b_ack <= not rst;
+ b_miso <= x"a5";
+ end process;
+
+
+ p_clk: process
+ begin
+ clk <= '0';
+ wait for CLK_PERIOD/2;
+ clk <= '1';
+ wait for CLK_PERIOD/2;
+ end process;
+
+end;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+
+
+entity wb_bridge is
+ generic (
+ A_WIDTH: natural := 32;
+ D_WIDTH: natural := 8
+ );
+ port (
+ rst_i: in std_logic;
+ clk_i: in std_logic;
+
+ a_cyc_i: in std_logic;
+ a_stb_i: in std_logic;
+ a_we_i: in std_logic;
+ a_ack_o: out std_logic;
+ a_adr_i: in std_logic_vector(A_WIDTH-1 downto 0);
+ a_dat_i: in std_logic_vector(D_WIDTH-1 downto 0);
+ a_dat_o: out std_logic_vector(D_WIDTH-1 downto 0);
+
+ b_cyc_o: out std_logic;
+ b_stb_o: out std_logic;
+ b_we_o: out std_logic;
+ b_ack_i: in std_logic;
+ b_adr_o: out std_logic_vector(A_WIDTH-1 downto 0);
+ b_dat_o: out std_logic_vector(D_WIDTH-1 downto 0);
+ b_dat_i: in std_logic_vector(D_WIDTH-1 downto 0)
+ );
+end wb_bridge;
+
+architecture behavioral of wb_bridge is
+
+ signal cyc_reg: std_logic;
+ signal stb_reg: std_logic;
+ 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)
+ 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;
+
+end behavioral;