]> git.the-white-hart.net Git - vhdl/commitdiff
Add Wisbhone register bridge
authorRyan <>
Tue, 23 Sep 2025 16:17:12 +0000 (11:17 -0500)
committerRyan <>
Tue, 23 Sep 2025 16:17:12 +0000 (11:17 -0500)
libraries/utility/tests/test_wb_bridge.vhd [new file with mode: 0644]
libraries/utility/wb_bridge.vhd [new file with mode: 0644]

diff --git a/libraries/utility/tests/test_wb_bridge.vhd b/libraries/utility/tests/test_wb_bridge.vhd
new file mode 100644 (file)
index 0000000..6c9afde
--- /dev/null
@@ -0,0 +1,102 @@
+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;
diff --git a/libraries/utility/wb_bridge.vhd b/libraries/utility/wb_bridge.vhd
new file mode 100644 (file)
index 0000000..c96e14b
--- /dev/null
@@ -0,0 +1,94 @@
+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;