diff --git a/modules/wishbone/Manifest.py b/modules/wishbone/Manifest.py index 6ebc4aeb0dc26c76703c4ca61debd7bcd98be96d..9b320aae4479c3bddecd1327789d6a6f7876c9ea 100644 --- a/modules/wishbone/Manifest.py +++ b/modules/wishbone/Manifest.py @@ -1,6 +1,7 @@ modules = { "local" : [ "wb_async_bridge", + "wb_axi4lite_bridge", "wb_onewire_master", "wb_i2c_master", "wb_bus_fanout", @@ -18,7 +19,7 @@ modules = { "local" : [ "wb_dma", "wb_serial_lcd", "wb_spi_flash", - "wb_simple_pwm", + "wb_simple_pwm", "wb_i2c_bridge", "wbgen2", "wbgenplus", diff --git a/modules/wishbone/wb_axi4lite_bridge/Manifest.py b/modules/wishbone/wb_axi4lite_bridge/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..26ff090d697808e783c2ee22bfb574b10995a9d4 --- /dev/null +++ b/modules/wishbone/wb_axi4lite_bridge/Manifest.py @@ -0,0 +1,5 @@ +files = [ + "axi4_pkg.vhd", + "wb_axi4lite_bridge.vhd", + "xwb_axi4lite_bridge.vhd" +] diff --git a/modules/wishbone/wb_axi4lite_bridge/axi4_pkg.vhd b/modules/wishbone/wb_axi4lite_bridge/axi4_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..366e6c8a5fce0aa5b9e08ea7e43aced0358e63bb --- /dev/null +++ b/modules/wishbone/wb_axi4lite_bridge/axi4_pkg.vhd @@ -0,0 +1,224 @@ +library ieee; +use ieee.std_logic_1164.all; + +use work.wishbone_pkg.all; + +package axi4_pkg is + + -- AXI4-Full interface, master output ports, 32 bits + type t_axi4_full_master_out_32 is record + ARVALID : std_logic; + AWVALID : std_logic; + BREADY : std_logic; + RREADY : std_logic; + WLAST : std_logic; + WVALID : std_logic; + ARID : std_logic_vector (11 downto 0); + AWID : std_logic_vector (11 downto 0); + WID : std_logic_vector (11 downto 0); + ARBURST : std_logic_vector (1 downto 0); + ARLOCK : std_logic_vector (1 downto 0); + ARSIZE : std_logic_vector (2 downto 0); + AWBURST : std_logic_vector (1 downto 0); + AWLOCK : std_logic_vector (1 downto 0); + AWSIZE : std_logic_vector (2 downto 0); + ARPROT : std_logic_vector (2 downto 0); + AWPROT : std_logic_vector (2 downto 0); + ARADDR : std_logic_vector (31 downto 0); + AWADDR : std_logic_vector (31 downto 0); + WDATA : std_logic_vector (31 downto 0); + ARCACHE : std_logic_vector (3 downto 0); + ARLEN : std_logic_vector (3 downto 0); + ARQOS : std_logic_vector (3 downto 0); + AWCACHE : std_logic_vector (3 downto 0); + AWLEN : std_logic_vector (3 downto 0); + AWQOS : std_logic_vector (3 downto 0); + WSTRB : std_logic_vector (3 downto 0); + end record; + + -- AXI4-Full interface, master input ports, 32 bits + type t_axi4_full_master_in_32 is record + ARREADY : std_logic; + AWREADY : std_logic; + BVALID : std_logic; + RLAST : std_logic; + RVALID : std_logic; + WREADY : std_logic; + BID : std_logic_vector (11 downto 0); + RID : std_logic_vector (11 downto 0); + BRESP : std_logic_vector (1 downto 0); + RRESP : std_logic_vector (1 downto 0); + RDATA : std_logic_vector (31 downto 0); + end record; + + -- AXI4-Lite interface, master output ports, 32 bits + type t_axi4_lite_master_out_32 is record + ARVALID : std_logic; + AWVALID : std_logic; + BREADY : std_logic; + RREADY : std_logic; + WLAST : std_logic; + WVALID : std_logic; + ARADDR : std_logic_vector (31 downto 0); + AWADDR : std_logic_vector (31 downto 0); + WDATA : std_logic_vector (31 downto 0); + WSTRB : std_logic_vector (3 downto 0); + end record; + + -- AXI4-Lite interface, master input ports, 32 bits + type t_axi4_lite_master_in_32 is record + ARREADY : std_logic; + AWREADY : std_logic; + BVALID : std_logic; + RLAST : std_logic; + RVALID : std_logic; + WREADY : std_logic; + BRESP : std_logic_vector (1 downto 0); + RRESP : std_logic_vector (1 downto 0); + RDATA : std_logic_vector (31 downto 0); + end record; + + constant c_axi4_lite_default_master_in_32 : t_axi4_lite_master_in_32 := + ( + AWREADY => '0', + ARREADY => '0', + BVALID => '0', + RLAST => '0', + RVALID => '0', + WREADY => '0', + BRESP => "00", + RRESP => "00", + RDATA => (others => '0') + ); + + + constant c_axi4_lite_default_master_out_32 : t_axi4_lite_master_out_32 := + ( + ARVALID => '0', + AWVALID => '0', + BREADY => '0', + RREADY => '0', + WLAST => '0', + WVALID => '0', + ARADDR => (others => '0'), + AWADDR => (others => '0'), + WDATA => (others => '0'), + WSTRB => (others => '0') + ); + + + + subtype t_axi4_lite_slave_in_32 is t_axi4_lite_master_out_32; + subtype t_axi4_lite_slave_out_32 is t_axi4_lite_master_in_32; + + constant c_AXI4_RESP_OKAY : std_logic_vector(1 downto 0) := "00"; + constant c_AXI4_RESP_EXOKAY : std_logic_vector(1 downto 0) := "01"; + constant c_AXI4_RESP_SLVERR : std_logic_vector(1 downto 0) := "10"; + constant c_AXI4_RESP_DECERR : std_logic_vector(1 downto 0) := "11"; + + function f_axi4_full_to_lite ( + f : t_axi4_full_master_out_32 + ) return t_axi4_lite_master_out_32; + + function f_axi4_lite_to_full ( + l : t_axi4_lite_master_in_32 + ) return t_axi4_full_master_in_32; + + component xwb_axi4lite_bridge is + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + axi4_slave_i : in t_axi4_lite_slave_in_32; + axi4_slave_o : out t_axi4_lite_slave_out_32; + wb_master_o : out t_wishbone_master_out; + wb_master_i : in t_wishbone_master_in); + end component xwb_axi4lite_bridge; + + component wb_axi4lite_bridge is + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + ARVALID : in std_logic; + AWVALID : in std_logic; + BREADY : in std_logic; + RREADY : in std_logic; + WLAST : in std_logic; + WVALID : in std_logic; + ARADDR : in std_logic_vector (31 downto 0); + AWADDR : in std_logic_vector (31 downto 0); + WDATA : in std_logic_vector (31 downto 0); + WSTRB : in std_logic_vector (3 downto 0); + ARREADY : out std_logic; + AWREADY : out std_logic; + BVALID : out std_logic; + RLAST : out std_logic; + RVALID : out std_logic; + WREADY : out std_logic; + BRESP : out std_logic_vector (1 downto 0); + RRESP : out std_logic_vector (1 downto 0); + RDATA : out std_logic_vector (31 downto 0); + + wb_adr : out std_logic_vector(c_wishbone_address_width-1 downto 0); + wb_dat_m2s : out std_logic_vector(c_wishbone_data_width-1 downto 0); + wb_sel : out std_logic_vector(c_wishbone_data_width/8-1 downto 0); + wb_cyc : out std_logic; + wb_stb : out std_logic; + wb_we : out std_logic; + + wb_dat_s2m : in std_logic_vector(c_wishbone_data_width-1 downto 0); + wb_err : in std_logic := '0'; + wb_rty : in std_logic := '0'; + wb_ack : in std_logic; + wb_stall : in std_logic + ); + end component; + +end package; + +package body axi4_pkg is + + function f_axi4_full_to_lite ( + f : t_axi4_full_master_out_32 + ) return t_axi4_lite_master_out_32 is + variable l : t_axi4_lite_master_out_32; + begin + + l.ARVALID := f.ARVALID; + l.AWVALID := f.AWVALID; + l.BREADY := f.BREADY; + l.RREADY := f.RREADY; + l.WLAST := f.WLAST; + l.WVALID := f.WVALID; + l.ARADDR := f.ARADDR; + l.AWADDR := f.AWADDR; + l.WDATA := f.WDATA; + l.WSTRB := f.WSTRB; + + return l; + + end f_axi4_full_to_lite; + + function f_axi4_lite_to_full ( + l : t_axi4_lite_master_in_32 + ) return t_axi4_full_master_in_32 is + variable f : t_axi4_full_master_in_32; + begin + f.ARREADY := l.ARREADY; + f.AWREADY := l.AWREADY; + f.BVALID := l.BVALID; + f.RLAST := l.RLAST; + f.RVALID := l.RVALID; + f.WREADY := l.WREADY; + f.BID := (others => '0'); + f.RID := (others => '0'); + f.BRESP := l.BRESP; + f.RRESP := l.RRESP; + f.RDATA := l.RDATA; + + return f; + + end f_axi4_lite_to_full; + + +end package body; diff --git a/modules/wishbone/wb_axi4lite_bridge/wb_axi4lite_bridge.vhd b/modules/wishbone/wb_axi4lite_bridge/wb_axi4lite_bridge.vhd new file mode 100644 index 0000000000000000000000000000000000000000..302fca2a8dc7e6ddfc4940a4bb9fc44dcddbec86 --- /dev/null +++ b/modules/wishbone/wb_axi4lite_bridge/wb_axi4lite_bridge.vhd @@ -0,0 +1,102 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.axi4_pkg.all; +use work.wishbone_pkg.all; + +entity wb_axi4lite_bridge is + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + ARVALID : in std_logic; + AWVALID : in std_logic; + BREADY : in std_logic; + RREADY : in std_logic; + WLAST : in std_logic; + WVALID : in std_logic; + ARADDR : in std_logic_vector (31 downto 0); + AWADDR : in std_logic_vector (31 downto 0); + WDATA : in std_logic_vector (31 downto 0); + WSTRB : in std_logic_vector (3 downto 0); + ARREADY : out std_logic; + AWREADY : out std_logic; + BVALID : out std_logic; + RLAST : out std_logic; + RVALID : out std_logic; + WREADY : out std_logic; + BRESP : out std_logic_vector (1 downto 0); + RRESP : out std_logic_vector (1 downto 0); + RDATA : out std_logic_vector (31 downto 0); + + wb_adr : out std_logic_vector(c_wishbone_address_width-1 downto 0); + wb_dat_m2s : out std_logic_vector(c_wishbone_data_width-1 downto 0); + wb_sel : out std_logic_vector(c_wishbone_data_width/8-1 downto 0); + wb_cyc : out std_logic; + wb_stb : out std_logic; + wb_we : out std_logic; + + wb_dat_s2m : in std_logic_vector(c_wishbone_data_width-1 downto 0); + wb_err : in std_logic := '0'; + wb_rty : in std_logic := '0'; + wb_ack : in std_logic; + wb_stall : in std_logic + ); + +end wb_axi4lite_bridge; + +architecture rtl of wb_axi4lite_bridge is + + signal axi_in : t_axi4_lite_master_out_32; + signal axi_out : t_axi4_lite_master_in_32; + signal wb_in : t_wishbone_master_in; + signal wb_out : t_wishbone_master_out; + +begin + + axi_in.ARVALID <= ARVALID; + axi_in.AWVALID <= AWVALID; + axi_in.BREADY <= BREADY; + axi_in.RREADY <= RREADY; + axi_in.WLAST <= WLAST; + axi_in.WVALID <= WVALID; + axi_in.ARADDR <= ARADDR; + axi_in.AWADDR <= AWADDR; + axi_in.WDATA <= WDATA; + axi_in.WSTRB <= WSTRB; + ARREADY <= axi_out.ARREADY; + AWREADY <= axi_out.AWREADY; + BVALID <= axi_out.BVALID; + RLAST <= axi_out.RLAST; + RVALID <= axi_out.RVALID; + WREADY <= axi_out.WREADY; + BRESP <= axi_out.BRESP; + RRESP <= axi_out.RRESP; + RDATA <= axi_out.RDATA; + + wb_adr <= wb_out.adr; + wb_dat_m2s <= wb_out.dat; + wb_stb <= wb_out.stb; + wb_sel <= wb_out.sel; + wb_cyc <= wb_out.cyc; + wb_we <= wb_out.we; + + wb_in.err <= wb_err; + wb_in.rty <= wb_rty; + wb_in.ack <= wb_ack; + wb_in.int <= '0'; + wb_in.stall <= wb_stall; + wb_in.dat <= wb_dat_s2m; + + U_Wrapped_Bridge : xwb_axi4lite_bridge + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + axi4_slave_i => axi_in, + axi4_slave_o => axi_out, + wb_master_o => wb_out, + wb_master_i => wb_in); + +end rtl; + diff --git a/modules/wishbone/wb_axi4lite_bridge/xwb_axi4lite_bridge.vhd b/modules/wishbone/wb_axi4lite_bridge/xwb_axi4lite_bridge.vhd new file mode 100644 index 0000000000000000000000000000000000000000..2b733f7b468affee15276500d7f2f1bb0b038d16 --- /dev/null +++ b/modules/wishbone/wb_axi4lite_bridge/xwb_axi4lite_bridge.vhd @@ -0,0 +1,167 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.axi4_pkg.all; +use work.wishbone_pkg.all; + +entity xwb_axi4lite_bridge is + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + axi4_slave_i : in t_axi4_lite_slave_in_32; + axi4_slave_o : out t_axi4_lite_slave_out_32; + + wb_master_o : out t_wishbone_master_out; + wb_master_i : in t_wishbone_master_in + + ); + +end xwb_axi4lite_bridge; + +architecture rtl of xwb_axi4lite_bridge is + + constant c_timeout : integer := 256; + + type t_state is + (IDLE, ISSUE_WRITE, ISSUE_READ, COMPLETE_WRITE, COMPLETE_READ, WAIT_ACK_READ, WAIT_ACK_WRITE, RESPONSE_READ, RESPONSE_WRITE); + + signal state : t_state; + + signal count : unsigned(10 downto 0); + +begin + + process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + axi4_slave_o <= c_axi4_lite_default_master_in_32; + wb_master_o.cyc <= '0'; + state <= IDLE; + else + case state is + when IDLE => + wb_master_o.cyc <= '0'; + axi4_slave_o.ARREADY <= '1'; + axi4_slave_o.AWREADY <= '1'; + axi4_slave_o.WREADY <= '0'; + axi4_slave_o.BVALID <= '0'; + axi4_slave_o.BRESP <= (others => 'X'); + axi4_slave_o.RDATA <= (others => 'X'); + axi4_slave_o.RRESP <= (others => 'X'); + axi4_slave_o.RVALID <= '0'; + axi4_slave_o.RLAST <= '0'; + + if(axi4_slave_i.AWVALID = '1') then + state <= ISSUE_WRITE; + wb_master_o.adr <= axi4_slave_i.AWADDR; + elsif (axi4_slave_i.ARVALID = '1') then + state <= ISSUE_READ; + wb_master_o.adr <= axi4_slave_i.ARADDR; + end if; + + when ISSUE_WRITE => + axi4_slave_o.WREADY <= '1'; + + wb_master_o.cyc <= '1'; + wb_master_o.we <= '1'; + + if(axi4_slave_i.WVALID = '1') then + wb_master_o.stb <= '1'; + wb_master_o.sel <= axi4_slave_i.WSTRB; + wb_master_o.dat <= axi4_slave_i.WDATA; + state <= COMPLETE_WRITE; + end if; + + when ISSUE_READ => + + wb_master_o.cyc <= '1'; + wb_master_o.stb <= '1'; + wb_master_o.we <= '0'; + axi4_slave_o.RVALID <= '0'; + axi4_slave_o.RLAST <= '0'; + state <= COMPLETE_READ; + + when COMPLETE_READ => + if(wb_master_i.stall = '0') then + wb_master_o.stb <= '0'; + if(wb_master_i.ack = '1') then + state <= IDLE; + axi4_slave_o.RRESP <= c_AXI4_RESP_EXOKAY; + axi4_slave_o.RDATA <= wb_master_i.dat; + axi4_slave_o.RVALID <= '1'; + axi4_slave_o.RLAST <= '1'; + wb_master_o.cyc <= '0'; + else + state <= WAIT_ACK_READ; + count <= (others => '0'); + end if; + end if; + + + when COMPLETE_WRITE => + if(wb_master_i.stall = '0') then + wb_master_o.stb <= '0'; + if(wb_master_i.ack = '1') then + state <= RESPONSE_WRITE; + axi4_slave_o.BRESP <= c_AXI4_RESP_EXOKAY; + wb_master_o.cyc <= '0'; + else + state <= WAIT_ACK_WRITE; + count <= (others => '0'); + end if; + end if; + + + when WAIT_ACK_WRITE => + if(wb_master_i.ack = '1') then + state <= RESPONSE_WRITE; + axi4_slave_o.BRESP <= c_AXI4_RESP_EXOKAY; + wb_master_o.cyc <= '0'; + elsif count = c_timeout then + state <= RESPONSE_WRITE; + axi4_slave_o.BRESP <= c_AXI4_RESP_SLVERR; + wb_master_o.cyc <= '0'; + end if; + count <= count + 1; + + when WAIT_ACK_READ => + if(wb_master_i.ack = '1') then + state <= IDLE; + axi4_slave_o.RRESP <= c_AXI4_RESP_EXOKAY; + axi4_slave_o.RVALID <= '1'; + axi4_slave_o.RLAST <= '1'; + axi4_slave_o.RDATA <= wb_master_i.dat; + wb_master_o.cyc <= '0'; + elsif count = c_timeout then + state <= IDLE; + axi4_slave_o.RRESP <= c_AXI4_RESP_SLVERR; + axi4_slave_o.RVALID <= '1'; + axi4_slave_o.RLAST <= '1'; + axi4_slave_o.RDATA <= (others => 'X'); + wb_master_o.cyc <= '0'; + end if; + count <= count + 1; + + + when RESPONSE_WRITE => + if (axi4_slave_i.BREADY = '1') then + axi4_slave_o.BVALID <= '1'; + state <= IDLE; + end if; + + when RESPONSE_READ => null; + + + end case; + + + + end if; + end if; + end process; + +end rtl; +