OpenCores
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;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2026 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.