Commit 7f67f492 authored by Pascal Bos's avatar Pascal Bos

Initial commit

parent f8681465
......@@ -102,6 +102,24 @@ package axi4_pkg is
RDATA : std_logic_vector (31 downto 0);
end record;
-- AXI4-Stream interface, 32 bits
type t_axis_32 is record
data : std_logic_vector(31 DOWNTO 0);
last : std_logic;
valid : std_logic;
ready : std_logic;
keep : std_logic_vector(3 DOWNTO 0);
end record t_axis_32;
-- AXI4-Stream interface, 64 bits
type t_axis_64 is record
data : std_logic_vector(63 DOWNTO 0);
last : std_logic;
valid : std_logic;
ready : std_logic;
keep : std_logic_vector(7 DOWNTO 0);
end record t_axis_64;
constant c_axi4_lite_default_master_in_32 : t_axi4_lite_master_in_32 :=
(
AWREADY => '0',
......
files = [
"xaxi4lite_wb_bridge.vhd",
"wb_axi4lite_bridge.vhd",
];
-------------------------------------------------------------------------------
-- Title : WB-to-AXI4Lite bridge
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : wb_axi4lite_bridge.vhd
-- Author : Pascal Bos
-- Company : Nikhef
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Description:
--
-- This module is a WB Slave Classic to AXI4-Lite Master bridge.
-------------------------------------------------------------------------------
-- Copyright (c) 2020 CERN
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
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 entity xwb_axi4lite_bridge;
architecture rtl of xwb_axi4lite_bridge is
type state_type is (IDLE, SR_SEND_ADDR, SR_GET_DATA, SR_SEND_DATA, SW_GET_DATA, SW_GET_ADDR, SW_SEND, SW_RESP);
signal prs, nxt : state_type;
begin
--state register for the Moore state machine, also has a timeout counter.
state_register : process(clk_sys_i,rst_n_i) is
variable count : unsigned(10 downto 0);
begin
if rst_n_i = '0' then
prs <= IDLE;
count := (others => '0');
elsif rising_edge(clk_sys_i) then
if prs /= IDLE then
count := count + 1;
else
count := (others => '0');
end if;
if count > 100 then
prs <= IDLE;
else
prs <= nxt;
end if;
end if;
end process state_register;
--next state decoder for the Moore state machine.
next_state_decoder : process(prs, wb_master_i, axi4_slave_i) is
begin
case prs is
when IDLE =>
if axi4_slave_i.awvalid = '1' and axi4_slave_i.wvalid = '1'then
nxt <= SW_SEND;
elsif axi4_slave_i.awvalid = '0' and axi4_slave_i.wvalid = '1' then
nxt <= SW_GET_ADDR;
elsif axi4_slave_i.awvalid = '1' and axi4_slave_i.wvalid = '0' then
nxt <= SW_GET_DATA;
elsif axi4_slave_i.arvalid = '1' then
nxt <= SR_SEND_ADDR;
else
nxt <= IDLE;
end if;
when SW_GET_ADDR =>
if axi4_slave_i.awvalid = '1' then
nxt <= SW_SEND;
else
nxt <= SW_GET_ADDR;
end if;
when SW_GET_DATA =>
if axi4_slave_i.wvalid = '1' then
nxt <= SW_SEND;
else
nxt <= SW_GET_DATA;
end if;
when SW_SEND =>
if wb_master_i.ack = '1' or wb_master_i.stall = '0' then
nxt <= SW_RESP;
else
nxt <= SW_SEND;
end if;
when SR_SEND_ADDR =>
if wb_master_i.stall = '0' then
nxt <= SR_GET_DATA;
else
nxt <= SR_SEND_ADDR;
end if;
when SR_GET_DATA =>
if wb_master_i.ack = '1' then
nxt <= SR_SEND_DATA;
else
nxt <= SR_GET_DATA;
end if;
when SR_SEND_DATA =>
if axi4_slave_i.rready = '1' then
nxt <= IDLE;
else
nxt <= SR_SEND_DATA;
end if;
when SW_RESP =>
if axi4_slave_i.bready = '1' then
nxt <= IDLE;
else
nxt <= SW_RESP;
end if;
end case;
end process next_state_decoder;
--manages the Wishbone addres signal, sources it from the axi-read or write channel depending on the command.
addr_register : process(clk_sys_i, rst_n_i) is
begin
if rst_n_i = '0' then
wb_master_o.adr <= (others => '0');
elsif rising_edge(clk_sys_i) then
if axi4_slave_i.awvalid = '1' then
wb_master_o.adr <= axi4_slave_i.awaddr;
elsif prs = SW_RESP then
wb_master_o.adr <= (others => '0');
elsif axi4_slave_i.arvalid = '1' then
wb_master_o.adr <= axi4_slave_i.araddr;
elsif prs = SR_SEND_DATA then
wb_master_o.adr <= (others => '0');
end if;
end if;
end process addr_register;
--manages the two data registers, one for reading (and byte-validation) the other for writing.
data_register : process(clk_sys_i, rst_n_i) is
begin
if rst_n_i = '0' then
wb_master_o.dat <= (others => '0');
wb_master_o.sel <= (others => '0');
axi4_slave_o.rdata <= (others => '0');
elsif rising_edge(clk_sys_i) then
if axi4_slave_i.wvalid = '1' then
wb_master_o.dat <= axi4_slave_i.wdata;
wb_master_o.sel <= axi4_slave_i.wstrb;
elsif prs = SW_RESP then
wb_master_o.dat <= (others => '0');
wb_master_o.sel <= (others => '0');
end if;
if prs = SR_GET_DATA and wb_master_i.ack = '1' then
axi4_slave_o.rdata <= wb_master_i.dat;
elsif prs = IDLE then
axi4_slave_o.rdata <= (others => '0');
end if;
end if;
end process data_register;
--roughly convers wishbone error messages to axi-error mesages.
error_register : process(clk_sys_i, rst_n_i) is
begin
if rst_n_i = '0' then
axi4_slave_o.bresp <= "10";
axi4_slave_o.rresp <= "10";
elsif rising_edge(clk_sys_i) then
if prs = SW_SEND and wb_master_i.ack = '1' then
axi4_slave_o.bresp <= wb_master_i.err & '0';
axi4_slave_o.rresp <= "00";
elsif prs = SW_SEND and wb_master_i.ack = '1' then
axi4_slave_o.bresp <= "00";
axi4_slave_o.rresp <= wb_master_i.err & '0';
elsif prs = IDLE then
axi4_slave_o.bresp <= "00";
axi4_slave_o.rresp <= "00";
end if;
end if;
end process error_register;
--AXI READ RELATED SIGNALS
axi4_slave_o.arready <= '1' when rst_n_i = '1' and prs = IDLE else '0';
axi4_slave_o.rvalid <= '1' when prs = SR_SEND_DATA else '0';
axi4_slave_o.rlast <= '1' when prs = SR_SEND_DATA else '0';
--AXI WRITE RELATED SIGNALS
axi4_slave_o.awready <= '1' when rst_n_i = '1' and (prs = IDLE or prs = SW_GET_ADDR) else '0';
axi4_slave_o.wready <= '1' when rst_n_i = '1' and (prs = IDLE or prs = SW_GET_DATA) else '0';
axi4_slave_o.bvalid <= '1' when prs = SW_RESP else '0';
--WISHBONE RELATED SIGNALS
wb_master_o.we <= '1' when prs = SW_SEND else '0';
wb_master_o.cyc <= '1' when prs = SR_SEND_ADDR or prs = SR_GET_DATA or prs = SW_SEND else '0';
wb_master_o.stb <= '1' when prs = SR_SEND_ADDR or prs = SW_SEND else '0';
end architecture rtl;
-------------------------------------------------------------------------------
-- Title : WB-to-AXI4Lite bridge
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : xaxi4lite_wb_bridge.vhd
-- Author : Grzegorz Daniluk
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Description:
--
-- This module is a WB Slave Classic to AXI4-Lite Master bridge.
-------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.axi4_pkg.all;
use work.wishbone_pkg.all;
entity xaxi4lite_wb_bridge is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
wb_slave_i : in t_wishbone_slave_in;
wb_slave_o : out t_wishbone_slave_out;
axi4_master_o : out t_axi4_lite_master_out_32;
axi4_master_i : in t_axi4_lite_master_in_32);
end xaxi4lite_wb_bridge;
architecture behav of xaxi4lite_wb_bridge is
type t_state is (IDLE, READ, WRITE, WB_END);
signal state : t_state;
begin
wb_slave_o.stall <= '0';
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_slave_o.ack <= '0';
wb_slave_o.err <= '0';
axi4_master_o <= c_axi4_lite_default_master_out_32;
state <= IDLE;
else
case state is
-------------------------------------------
when IDLE =>
wb_slave_o.ack <= '0';
wb_slave_o.err <= '0';
axi4_master_o.ARVALID <= '0';
axi4_master_o.ARADDR <= (others=>'X');
axi4_master_o.RREADY <= '0';
axi4_master_o.AWVALID <= '0';
axi4_master_o.AWADDR <= (others=>'X');
axi4_master_o.WVALID <= '0';
axi4_master_o.WDATA <= (others=>'X');
axi4_master_o.WSTRB <= "0000";
axi4_master_o.BREADY <= '0';
if wb_slave_i.stb = '1' and wb_slave_i.we = '0' then
-- AXI: set address for read cycle
axi4_master_o.ARVALID <= '1';
axi4_master_o.ARADDR <= wb_slave_i.adr;
-- AXI: ready to accept data from slave
axi4_master_o.RREADY <= '1';
state <= READ;
elsif (wb_slave_i.stb = '1' and wb_slave_i.we = '1') then
-- AXI: set address for write cycle
axi4_master_o.AWVALID <= '1';
axi4_master_o.AWADDR <= wb_slave_i.adr;
-- AXI: set data for write cycle
axi4_master_o.WVALID <= '1';
axi4_master_o.WDATA <= wb_slave_i.dat;
axi4_master_o.WSTRB <= wb_slave_i.sel;
state <= WRITE;
end if;
-------------------------------------------
-- READ CYCLE --
-------------------------------------------
when READ =>
wb_slave_o.ack <= '0';
wb_slave_o.err <= '0';
axi4_master_o.RREADY <= '1';
if (axi4_master_i.ARREADY = '1') then
-- AXI: address received by slave
axi4_master_o.ARVALID <= '0';
end if;
if (axi4_master_i.RVALID = '1' and axi4_master_i.RRESP = c_AXI4_RESP_OKAY) then
-- received valid data, pass it to wishbone
wb_slave_o.dat <= axi4_master_i.RDATA;
wb_slave_o.ack <= '1';
wb_slave_o.err <= '0';
elsif (axi4_master_i.RVALID = '1') then
wb_slave_o.ack <= '0';
wb_slave_o.err <= '1';
else
wb_slave_o.ack <= '0';
wb_slave_o.err <= '0';
end if;
if (axi4_master_i.RVALID = '1') then
axi4_master_o.RREADY <= '0';
state <= WB_END;
end if;
-------------------------------------------
-- WRITE CYCLE --
-------------------------------------------
when WRITE =>
wb_slave_o.ack <= '0';
wb_slave_o.err <= '0';
axi4_master_o.BREADY <= '1';
if (axi4_master_i.AWREADY = '1') then
axi4_master_o.AWVALID <= '0';
end if;
if (axi4_master_i.WREADY = '1') then
axi4_master_o.WVALID <= '0';
end if;
if (axi4_master_i.BVALID = '1' and axi4_master_i.BRESP = c_AXI4_RESP_OKAY) then
wb_slave_o.ack <= '1';
wb_slave_o.err <= '0';
elsif (axi4_master_i.BVALID = '1') then
wb_slave_o.ack <= '0';
wb_slave_o.err <= '1';
else
wb_slave_o.ack <= '0';
wb_slave_o.err <= '0';
end if;
if (axi4_master_i.BVALID = '1') then
axi4_master_o.BREADY <= '0';
state <= WB_END;
end if;
-------------------------------------------
when WB_END =>
wb_slave_o.ack <= '0';
wb_slave_o.err <= '0';
-- WB: wait for the cycle to end
if (wb_slave_i.stb = '0') then
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
end behav;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment