URL
https://opencores.org/ocsvn/ax4lbr/ax4lbr/trunk
Subversion Repositories ax4lbr
[/] [ax4lbr/] [trunk/] [rtl/] [axil2wb.vhd] - Rev 10
Compare with Previous | Blame | View Log
------------------------------------------------------------------------------- -- File : axil2ipb.vhd -- Author : Wojciech M. Zabolotny <wojciech.zabolotny@pw.edu.pl> -- (with significant support of ChatGPT) -- : some corrections by Marek Guminski -- Company : Institute of Electronic Systems, Warsaw University of Technology -- Created : 2026-01-10 -- Last update: 2026-02-27 -- License : This work is released into the public domain under -- Creative Commons CC0 1.0 Universal (CC0 1.0) License. -- https://creativecommons.org/publicdomain/zero/1.0/ -- Platform : -- Standard : VHDL'93/02 ------------------------------------------------------------------------------- -- Description: AXI Lite -> WB bridge -- This is an improved and cleaned-up version of the simple AXI-Lite to Wishbone -- bridge originally published on OpenCores -- The modification was significantly supported by ChatGPT. -- Therefore the solution is released to public domain. ------------------------------------------------------------------------------- -- Copyright (c) 2026 ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2026-01-10 1.0 WZab+ChatGPT Created library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity axil2wb is generic ( ADRWIDTH : integer := 32; DATAWIDTH : integer := 32; WB_TIMEOUT_CYCLES : integer := 256; SYNC_RESET : boolean := true; MASK_ERRORS : boolean := true ); port ( -- AXI4-Lite S_AXI_ACLK : in std_logic; S_AXI_ARESETN : in std_logic; S_AXI_AWADDR : in std_logic_vector(ADRWIDTH-1 downto 0); S_AXI_AWVALID : in std_logic; S_AXI_AWREADY : out std_logic; S_AXI_WDATA : in std_logic_vector(31 downto 0); S_AXI_WSTRB : in std_logic_vector(3 downto 0); S_AXI_WVALID : in std_logic; S_AXI_WREADY : out std_logic; S_AXI_BRESP : out std_logic_vector(1 downto 0); S_AXI_BVALID : out std_logic; S_AXI_BREADY : in std_logic; S_AXI_ARADDR : in std_logic_vector(ADRWIDTH-1 downto 0); S_AXI_ARVALID : in std_logic; S_AXI_ARREADY : out std_logic; S_AXI_RDATA : out std_logic_vector(31 downto 0); S_AXI_RRESP : out std_logic_vector(1 downto 0); S_AXI_RVALID : out std_logic; S_AXI_RREADY : in std_logic; -- Wishbone master wb_clk_o : out std_logic; wb_rst_o : out std_logic; wb_addr_o : out std_logic_vector(31 downto 0); wb_dat_o : out std_logic_vector(31 downto 0); wb_dat_i : in std_logic_vector(31 downto 0); wb_we_o : out std_logic; wb_sel_o : out std_logic_vector(3 downto 0); wb_stb_o : out std_logic; wb_cyc_o : out std_logic; wb_ack_i : in std_logic; wb_err_i : in std_logic ); end entity; architecture rtl of axil2wb is type state_t is (RST, IDLE, WB_READ, WB_WRITE, AXI_RSP); signal state : state_t := IDLE; signal S_AXI_AWREADY_s : std_logic := '0'; signal S_AXI_ARREADY_s : std_logic := '0'; signal S_AXI_WREADY_s : std_logic := '0'; signal aw_addr_r : std_logic_vector(ADRWIDTH-1 downto 0); signal ar_addr_r : std_logic_vector(ADRWIDTH-1 downto 0); signal w_data_r : std_logic_vector(31 downto 0); signal aw_seen, w_seen, ar_seen : std_logic := '0'; signal write_ongoing : std_logic := '0'; signal s_rst_n, s_rst_n_0, s_rst_n_1 : std_logic := '0'; signal timeout_cnt : integer range 0 to WB_TIMEOUT_CYCLES; begin wb_clk_o <= S_AXI_ACLK; wb_rst_o <= not s_rst_n; wb_sel_o <= (others => '1'); is_sync_reset : if SYNC_RESET generate -- Synchronize the reset signal process(S_AXI_ACLK,S_AXI_ARESETN) begin if S_AXI_ARESETN = '0' then s_rst_n_0 <= '0'; s_rst_n_1 <= '0'; s_rst_n <= '0'; elsif rising_edge(S_AXI_ACLK) then s_rst_n_0 <= S_AXI_ARESETN; s_rst_n_1 <= s_rst_n_0; s_rst_n <= s_rst_n_1; end if; end process; end generate is_sync_reset; not_sync_reset : if not SYNC_RESET generate s_rst_n <= S_AXI_ARESETN; end generate not_sync_reset; -- AXI READY (deterministic!) S_AXI_AWREADY_s <= '1' when (state = IDLE and aw_seen = '0' and ar_seen = '0') else '0'; S_AXI_WREADY_s <= '1' when (state = IDLE and w_seen = '0' and ar_seen = '0') else '0'; S_AXI_ARREADY_s <= '1' when (state = IDLE and ar_seen = '0' and w_seen = '0' and aw_seen = '0') else '0'; S_AXI_AWREADY <= S_AXI_AWREADY_s; S_AXI_WREADY <= S_AXI_WREADY_s; S_AXI_ARREADY <= S_AXI_ARREADY_s; process (S_AXI_ACLK) begin if rising_edge(S_AXI_ACLK) then if s_rst_n = '0' then state <= RST; aw_seen <= '0'; w_seen <= '0'; ar_seen <= '0'; wb_cyc_o <= '0'; wb_stb_o <= '0'; wb_we_o <= '0'; S_AXI_BVALID <= '0'; S_AXI_RVALID <= '0'; S_AXI_RDATA <= (others => '0'); S_AXI_BRESP <= "00"; S_AXI_RRESP <= "00"; timeout_cnt <= 0; write_ongoing <= '0'; else -- defaults S_AXI_BVALID <= '0'; S_AXI_RVALID <= '0'; case state is when RST => state <= IDLE; when IDLE => timeout_cnt <= 0; wb_cyc_o <= '0'; wb_stb_o <= '0'; wb_we_o <= '0'; if S_AXI_AWVALID = '1' and S_AXI_AWREADY_s = '1' then aw_addr_r <= S_AXI_AWADDR; aw_seen <= '1'; end if; if S_AXI_WVALID = '1' and S_AXI_WREADY_s = '1' then w_data_r <= S_AXI_WDATA; w_seen <= '1'; end if; if S_AXI_ARVALID = '1' and S_AXI_ARREADY_s = '1' then ar_seen <= '1'; -- Divide the address by 4 (in WB we use word not byte addressing) ar_addr_r <= S_AXI_ARADDR; end if; if aw_seen = '1' and w_seen = '1' then -- Divide the address by 4 (in WB we use word not byte addressing) wb_addr_o <= (others => '0'); wb_addr_o(ADRWIDTH-3 downto 0) <= aw_addr_r(ADRWIDTH-1 downto 2); wb_dat_o <= w_data_r; wb_we_o <= '1'; wb_cyc_o <= '1'; wb_stb_o <= '1'; write_ongoing <= '1'; state <= WB_WRITE; elsif ar_seen = '1' then wb_addr_o <= (others => '0'); wb_addr_o(ADRWIDTH-3 downto 0) <= ar_addr_r(ADRWIDTH-1 downto 2); wb_we_o <= '0'; wb_cyc_o <= '1'; wb_stb_o <= '1'; write_ongoing <= '0'; state <= WB_READ; end if; when WB_WRITE => if timeout_cnt < WB_TIMEOUT_CYCLES then timeout_cnt <= timeout_cnt + 1; end if; if wb_ack_i = '1' or wb_err_i = '1' then wb_cyc_o <= '0'; wb_stb_o <= '0'; wb_we_o <= '0'; if wb_err_i = '1' then if MASK_ERRORS then S_AXI_BRESP <= "00"; else S_AXI_BRESP <= "10"; end if; else S_AXI_BRESP <= "00"; end if; S_AXI_BVALID <= '1'; state <= AXI_RSP; elsif timeout_cnt = WB_TIMEOUT_CYCLES then wb_cyc_o <= '0'; wb_stb_o <= '0'; wb_we_o <= '0'; if MASK_ERRORS then S_AXI_BRESP <= "00"; else S_AXI_BRESP <= "11"; -- timeout signalled as DECERR end if; S_AXI_BVALID <= '1'; state <= AXI_RSP; end if; when WB_READ => if timeout_cnt < WB_TIMEOUT_CYCLES then timeout_cnt <= timeout_cnt + 1; end if; if wb_ack_i = '1' or wb_err_i = '1' then wb_cyc_o <= '0'; wb_stb_o <= '0'; wb_we_o <= '0'; S_AXI_RDATA <= wb_dat_i; if wb_err_i = '1' then if MASK_ERRORS then S_AXI_RDATA <= x"deadbeaf"; S_AXI_RRESP <= "00"; else S_AXI_RRESP <= "10"; end if; S_AXI_RVALID <= '1'; else S_AXI_RRESP <= "00"; S_AXI_RVALID <= '1'; end if; state <= AXI_RSP; elsif timeout_cnt = WB_TIMEOUT_CYCLES then wb_cyc_o <= '0'; wb_stb_o <= '0'; wb_we_o <= '0'; if MASK_ERRORS then S_AXI_RDATA <= x"deadbeaf"; S_AXI_RRESP <= "00"; else S_AXI_RRESP <= "11"; -- timeout signalled as DECERR end if; S_AXI_RVALID <= '1'; state <= AXI_RSP; end if; when AXI_RSP => if write_ongoing = '1' then S_AXI_BVALID <= '1'; if S_AXI_BREADY = '1' then S_AXI_BVALID <= '0'; aw_seen <= '0'; w_seen <= '0'; write_ongoing <= '0'; state <= IDLE; end if; else S_AXI_RVALID <= '1'; if S_AXI_RREADY = '1' then S_AXI_RVALID <= '0'; ar_seen <= '0'; state <= IDLE; end if; end if; end case; end if; end if; end process; end architecture;
