Files
es-abschlussprojekt/Hardware/axis_dma.vhd
T

508 lines
22 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity axis_dma is
generic (
DWIDTH : positive := 32;
IDWIDTH : positive := 1;
MAX_BURSTLEN : positive := 16;
FIFO_AWIDTH : positive := 8;
polynomial_default : std_logic_vector(31 downto 0) := x"04C11DB7";
initial_value_default : std_logic_vector(31 downto 0) := x"00000000"
);
port (
CLK : in std_logic;
RESETN : in std_logic;
INTERRUPT : out std_logic := '0';
-- for crc calulaction
initial_value : out std_logic_vector(31 downto 0);
polynomial : out std_logic_vector(31 downto 0);
finalXOR : out std_logic_vector(31 downto 0);
inOutReflected : out std_logic_vector( 1 downto 0);
-- FIFOs
FIFO_NUM_FREE : in std_logic_vector(7 downto 0);
FIFO_NUM_AVAIL : in std_logic_vector(7 downto 0);
-- AXIL Slave Interface
S_AXIL_AWADDR : in std_logic_vector(7 downto 0);
S_AXIL_AWVALID : in std_logic;
S_AXIL_AWREADY : out std_logic;
S_AXIL_WDATA : in std_logic_vector(31 downto 0);
S_AXIL_WVALID : in std_logic;
S_AXIL_WREADY : out std_logic;
S_AXIL_WSTRB : in std_logic_vector((32/8)-1 downto 0);
S_AXIL_BVALID : out std_logic;
S_AXIL_BREADY : in std_logic;
S_AXIL_BRESP : out std_logic_vector(1 downto 0);
S_AXIL_ARADDR : in std_logic_vector(7 downto 0);
S_AXIL_ARVALID : in std_logic;
S_AXIL_ARREADY : out std_logic;
S_AXIL_RDATA : out std_logic_vector(31 downto 0);
S_AXIL_RVALID : out std_logic;
S_AXIL_RREADY : in std_logic;
S_AXIL_RRESP : out std_logic_vector(1 downto 0);
-- AXI Master Interface (Memory)
M_AXI_ARREADY : in std_logic;
M_AXI_ARVALID : out std_logic := '0';
M_AXI_ARADDR : out std_logic_vector(31 downto 0);
M_AXI_ARID : out std_logic_vector(IDWIDTH-1 downto 0);
M_AXI_ARLEN : out std_logic_vector( 3 downto 0);
M_AXI_ARSIZE : out std_logic_vector( 2 downto 0);
M_AXI_ARBURST : out std_logic_vector( 1 downto 0);
M_AXI_ARPROT : out std_logic_vector( 2 downto 0);
M_AXI_ARCACHE : out std_logic_vector( 3 downto 0);
M_AXI_RREADY : out std_logic;
M_AXI_RVALID : in std_logic;
M_AXI_RDATA : in std_logic_vector(DWIDTH-1 downto 0);
M_AXI_RRESP : in std_logic_vector( 1 downto 0);
M_AXI_RID : in std_logic_vector(IDWIDTH-1 downto 0);
M_AXI_RLAST : in std_logic;
M_AXI_AWREADY : in std_logic := '0';
M_AXI_AWVALID : out std_logic := '0';
M_AXI_AWADDR : out std_logic_vector(31 downto 0);
M_AXI_AWLEN : out std_logic_vector( 3 downto 0);
M_AXI_AWSIZE : out std_logic_vector( 2 downto 0);
M_AXI_AWID : out std_logic_vector(IDWIDTH-1 downto 0);
M_AXI_AWBURST : out std_logic_vector( 1 downto 0);
M_AXI_AWPROT : out std_logic_vector( 2 downto 0);
M_AXI_AWCACHE : out std_logic_vector( 3 downto 0);
M_AXI_WREADY : in std_logic := '0';
M_AXI_WVALID : out std_logic := '0';
M_AXI_WDATA : out std_logic_vector(DWIDTH-1 downto 0);
M_AXI_WSTRB : out std_logic_vector(DWIDTH/8-1 downto 0);
M_AXI_WLAST : out std_logic := '0';
M_AXI_WID : out std_logic_vector(DWIDTH-1 downto 0);
M_AXI_BREADY : out std_logic;
M_AXI_BVALID : in std_logic := '0';
M_AXI_BID : in std_logic_vector( DWIDTH-1 downto 0);
M_AXI_BRESP : in std_logic_vector( 1 downto 0);
-- AXI Streaming Target Port
S_AXIS_TVALID : in std_logic;
S_AXIS_TDATA : in std_logic_vector(31 downto 0);
S_AXIS_TLAST : in std_logic := '0';
S_AXIS_TREADY : out std_logic;
-- AXI Streaming Initiator Port
M_AXIS_TVALID : out std_logic;
M_AXIS_TDATA : out std_logic_vector(31 downto 0);
M_AXIS_TLAST : out std_logic;
M_AXIS_TREADY : in std_logic
);
end entity;
architecture rtl of axis_dma is
-- AXIL Registers
signal run_reg : std_logic := '0';
signal interrupt_enable_reg : std_logic;
signal read_address_reg : std_logic_vector(31 downto 0);
signal write_address_reg : std_logic_vector(31 downto 0);
signal packet_size_reg : std_logic_vector(15 downto 0);
signal packet_number_reg : std_logic_vector(15 downto 0);
signal polynomial_reg : std_logic_vector(31 downto 0);
signal initial_value_reg : std_logic_vector(31 downto 0);
signal finalXOR_reg : std_logic_vector(31 downto 0);
signal inOut_reflected_reg : std_logic_vector( 1 downto 0);
-- Helper Signals
signal run_reg_set : std_logic;
signal run_reg_clear : std_logic;
-- M_AXI Read Data state machine
type read_state_t is (IDLE, REQ, WAIT_REQ_ACCEPT, READ_DATA, FINISHED);
signal read_state : read_state_t := IDLE;
-- M_AXI Write Data state machine
type write_state_t is (IDLE, REQ, WAIT_REQ_ACCEPT, WRITE_DATA, FINISHED);
signal write_state : write_state_t := IDLE;
-- control signals
signal packets_cnt : unsigned(15 downto 0);
signal data_cnt : unsigned(31 downto 0);
signal read_addr_cnt : unsigned(31 downto 0);
signal write_addr_cnt : unsigned(31 downto 0);
signal interrupt_reset : std_logic;
signal packet_last_word : std_logic := '0';
signal interrupt_sig : std_logic := '0';
begin
-------------------------------------------
-- Interrupt
-------------------------------------------
interrupt_sig <= '1' when read_state=FINISHED and write_state=FINISHED and interrupt_enable_reg='1' else '0';
INTERRUPT <= interrupt_sig;
-------------------------------------------
-- S_AXIL Schnittstelle
-------------------------------------------
S_AXIL_BRESP <= (others=>'0'); -- No write errors
S_AXIL_RRESP <= (others=>'0'); -- No read errors
S_AXIL_ARREADY <= '1'; -- IP is always ready
S_AXIL_AWREADY <= S_AXIL_AWVALID and S_AXIL_WVALID;
S_AXIL_WREADY <= S_AXIL_AWVALID and S_AXIL_WVALID;
-- AXIL Register nach aussen fuehren
polynomial <= polynomial_reg;
initial_value <= initial_value_reg;
inOutReflected <= inOut_reflected_reg;
process
begin
wait until rising_edge(CLK);
if RESETN = '0' then
S_AXIL_BVALID <= '0';
S_AXIL_RVALID <= '0';
-- AXIL-Register zuruecksetzen
run_reg <= '0';
interrupt_enable_reg <= '0';
read_address_reg <= (others => '0');
write_address_reg <= (others => '0');
packet_number_reg <= (others => '0');
packet_size_reg <= (others => '0');
polynomial_reg <= polynomial_default;
initial_value_reg <= initial_value_default;
finalXOR_reg <= (others=>'0');
inOut_reflected_reg <= (others=>'0');
else
-- FLip Flop-Register fuer sauberes Setzen und Loeschen des Run-Signals
if interrupt_sig = '1' then
run_reg <= '0';
elsif run_reg_set = '1' then
run_reg <= '1';
elsif run_reg_clear = '1' then
run_reg <= '0';
end if;
-- Lesezugriff
if S_AXIL_RREADY = '1' then
S_AXIL_RVALID <= '0';
end if;
if S_AXIL_ARVALID = '1' then
S_AXIL_RDATA <= (others=>'0');
if S_AXIL_ARADDR(7 downto 0) = x"00" then
S_AXIL_RDATA(0) <= run_reg;
S_AXIL_RDATA(1) <= interrupt_enable_reg;
elsif S_AXIL_ARADDR(7 downto 0) = x"04" then
S_AXIL_RDATA(0) <= interrupt_sig;
elsif S_AXIL_ARADDR(7 downto 0) = x"08" then
S_AXIL_RDATA <= read_address_reg;
elsif S_AXIL_ARADDR(7 downto 0) = x"0C" then
S_AXIL_RDATA <= write_address_reg;
elsif S_AXIL_ARADDR(7 downto 0) = x"10" then
S_AXIL_RDATA(15 downto 0) <= packet_size_reg;
elsif S_AXIL_ARADDR(7 downto 0) = x"14" then
S_AXIL_RDATA(15 downto 0) <= packet_number_reg;
elsif S_AXIL_ARADDR(7 downto 0) = x"18" then
S_AXIL_RDATA <= polynomial_reg;
elsif S_AXIL_ARADDR(7 downto 0) = x"1C" then
S_AXIL_RDATA <= initial_value_reg;
elsif S_AXIL_ARADDR(7 downto 0) = x"20" then
S_AXIL_RDATA <= finalXOR_reg;
elsif S_AXIL_ARADDR(7 downto 0) = x"24" then
S_AXIL_RDATA(1 downto 0) <= inOut_reflected_reg;
end if;
S_AXIL_RVALID <= '1';
end if;
if S_AXIL_BREADY = '1' then
S_AXIL_BVALID <= '0';
end if;
interrupt_reset <= '0';
run_reg_set <= '0';
if S_AXIL_AWVALID = '1' and S_AXIL_WVALID = '1' then
S_AXIL_BVALID <= '1';
-- Register schreiben
if S_AXIL_AWADDR = x"00" then
if S_AXIL_WSTRB(0) = '1' then
run_reg_set <= S_AXIL_WDATA(0);
interrupt_enable_reg <= S_AXIL_WDATA(1);
end if;
elsif S_AXIL_AWADDR = x"04" then
if S_AXIL_WSTRB(0) = '1' then
interrupt_reset <= not S_AXIL_WDATA(0);
end if;
elsif S_AXIL_AWADDR = x"08" then
if S_AXIL_WSTRB = "1111" then
read_address_reg <= S_AXIL_WDATA;
end if;
elsif S_AXIL_AWADDR = x"0C" then
if S_AXIL_WSTRB = "1111" then
write_address_reg <= S_AXIL_WDATA;
end if;
elsif S_AXIL_AWADDR = x"10" then
if S_AXIL_WSTRB(1 downto 0) = "11" then
packet_size_reg <= S_AXIL_WDATA(15 downto 0);
end if;
elsif S_AXIL_AWADDR = x"14" then
if S_AXIL_WSTRB(1 downto 0) = "11" then
packet_number_reg <= S_AXIL_WDATA(15 downto 0);
end if;
elsif S_AXIL_AWADDR = x"18" then
if S_AXIL_WSTRB = "1111" then
polynomial_reg <= S_AXIL_WDATA;
end if;
elsif S_AXIL_AWADDR = x"1C" then
if S_AXIL_WSTRB = "1111" then
initial_value_reg <= S_AXIL_WDATA;
end if;
elsif S_AXIL_AWADDR = x"20" then
if S_AXIL_WSTRB = "1111" then
finalXOR_reg <= S_AXIL_WDATA;
end if;
elsif S_AXIL_AWADDR = x"24" then
if S_AXIL_WSTRB(0) = '1' then
inOut_reflected_reg <= S_AXIL_WDATA(1 downto 0);
end if;
end if;
end if;
end if;
end process;
-------------------------------------------
-- M_AXI Read data from DRAM state machine
-------------------------------------------
M_AXI_ARSIZE <= "010" when DWIDTH=32 else "011"; -- Data width 32/64
M_AXI_ARBURST <= "01";
M_AXI_ARPROT <= "000";
M_AXI_ARCACHE <= "0000";
M_AXI_ARID <= (others=>'0');
M_AXI_RREADY <= '1';
process
variable packets_cnt : unsigned(15 downto 0); -- Anzahl der verbleibenden Pakete Minus 1
variable packet_data_cnt : unsigned(15 downto 0); -- Anzahl der verbleibenden Worte Minus 1 beim aktuellen Packet
variable data_cnt : unsigned(31 downto 0); -- Anzahl der insgesamt verbleibenden Worte Minus 1
variable read_addr_cnt : unsigned(31 downto 0);
begin
wait until rising_edge(CLK);
if RESETN = '0' then
packets_cnt := (others=>'0');
packet_data_cnt := (others=>'0');
data_cnt := (others=>'0');
read_addr_cnt := (others=>'0');
M_AXI_ARVALID <= '0';
M_AXI_ARADDR <= (others=>'0');
M_AXI_ARLEN <= (others=>'0');
read_state <= IDLE;
else
case read_state is
when IDLE =>
if run_reg_set = '1' then
packets_cnt := unsigned(packet_number_reg);
packet_data_cnt := unsigned(packet_size_reg);
data_cnt := (unsigned(packet_size_reg)+1) * (unsigned(packet_number_reg)+1) - 1;
read_addr_cnt := unsigned(read_address_reg);
read_state <= REQ;
end if;
when REQ =>
if (unsigned(FIFO_NUM_FREE) >= MAX_BURSTLEN) then
M_AXI_ARADDR <= std_logic_vector(read_addr_cnt);
M_AXI_ARVALID <= '1';
-- Burstlaenge setzen
if (data_cnt+1) >= MAX_BURSTLEN then
M_AXI_ARLEN <= std_logic_vector(to_unsigned(MAX_BURSTLEN-1, 4));
read_addr_cnt := read_addr_cnt + to_unsigned(MAX_BURSTLEN, 32); -- increment address
else
M_AXI_ARLEN <= std_logic_vector(data_cnt(3 downto 0));
end if;
read_state <= WAIT_REQ_ACCEPT;
end if;
when WAIT_REQ_ACCEPT =>
if M_AXI_ARREADY = '1' then
M_AXI_ARVALID <= '0';
-- setzen des LAST Signals bei packet_size = 0
if packet_data_cnt = 0 then
packet_last_word <= '1';
end if;
read_state <= READ_DATA;
end if;
when READ_DATA =>
if M_AXI_RVALID = '1' then
-- Markieren des letzten Wortes
if packet_data_cnt = 1 then
packet_last_word <= '1';
end if;
-- Zaehler runterzaehlen
if packet_data_cnt = 0 then
packet_last_word <= '0';
if packets_cnt = 0 then
else
packets_cnt := packets_cnt - 1;
packet_data_cnt := unsigned(packet_size_reg);
end if;
else
packet_data_cnt := packet_data_cnt - 1;
end if;
if M_AXI_RLAST = '1' then
packet_last_word <= '0';
if data_cnt = 0 then -- Alle Datenpakete gelesen?
if interrupt_enable_reg = '1' then
read_state <= FINISHED;
else
read_state <= IDLE;
end if;
else
read_state <= REQ;
end if;
end if;
data_cnt := data_cnt - 1;
end if;
when FINISHED =>
-- Interrupt zuruecksetzen
if interrupt_reset = '1' then
read_state <= IDLE;
end if;
when others => null;
end case;
end if;
end process;
-------------------------------------------
-- M_AXIS und S_AXIS Interface connections
-------------------------------------------
M_AXIS_TVALID <= M_AXI_RVALID;
M_AXIS_TDATA <= M_AXI_RDATA;
M_AXIS_TLAST <= M_AXI_RVALID and packet_last_word;
S_AXIS_TREADY <= '1' when (write_state=WRITE_DATA) and M_AXI_WREADY = '1' else '0';
M_AXI_WVALID <= '1' when (write_state=WRITE_DATA) and S_AXIS_TVALID = '1' else '0';
M_AXI_WDATA <= S_AXIS_TDATA;
-------------------------------------------
-- M_AXI Write data to DRAM state machine
-------------------------------------------
M_AXI_AWSIZE <= "010" when DWIDTH=32 else "011"; -- Data width 32/64
M_AXI_AWBURST <= "01";
M_AXI_AWPROT <= "000";
M_AXI_AWCACHE <= "0000";
M_AXI_BREADY <= '1';
M_AXI_WSTRB <= (others=>'1');
M_AXI_AWID <= (others=>'0');
M_AXI_WID <= (others=>'0');
process
variable burst_data_cnt : integer range 0 to MAX_BURSTLEN;
variable data_cnt : unsigned(31 downto 0);
variable write_addr : unsigned(31 downto 0);
begin
wait until rising_edge(CLK);
if RESETN = '0' then
M_AXI_AWVALID <= '0';
M_AXI_AWADDR <= (others=>'0');
M_AXI_AWLEN <= (others=>'0');
M_AXI_WLAST <= '0';
burst_data_cnt := 0;
data_cnt := (others=>'0');
write_addr := (others=>'0');
write_state <= IDLE;
else
case write_state is
when IDLE =>
if run_reg = '1' then
data_cnt := (unsigned(packet_size_reg)+1) * (unsigned(packet_number_reg)+1) - 1 + unsigned(packet_number_reg) + 1;
write_addr := unsigned(write_address_reg);
write_state <= REQ;
end if;
when REQ =>
-- Senden wenn mindestens eine ganze Burstlaenge zu Verfuegung steht
-- oder wenn nur noch restliche Daten, die weniger als eine Burstlaenge sind zur Verfuegung stehen
if unsigned(FIFO_NUM_AVAIL) >= MAX_BURSTLEN or ((data_cnt+1) < MAX_BURSTLEN and unsigned(FIFO_NUM_AVAIL) = (data_cnt+1)) then
M_AXI_AWADDR <= std_logic_vector(write_addr);
M_AXI_AWVALID <= '1';
-- Burstlaenge setzen
if unsigned(FIFO_NUM_AVAIL) >= MAX_BURSTLEN then
burst_data_cnt := MAX_BURSTLEN - 1;
M_AXI_AWLEN <= std_logic_vector(to_unsigned(MAX_BURSTLEN-1, 4));
write_addr := write_addr + to_unsigned(MAX_BURSTLEN, 32); -- increment address
else
M_AXI_AWLEN <= std_logic_vector(data_cnt(3 downto 0));
burst_data_cnt := to_integer(data_cnt);
end if;
write_state <= WAIT_REQ_ACCEPT;
end if;
when WAIT_REQ_ACCEPT =>
if M_AXI_AWREADY = '1' then
M_AXI_AWVALID <= '0';
if burst_data_cnt = 1 then
M_AXI_WLAST <= '1';
end if;
write_state <= WRITE_DATA;
end if;
when WRITE_DATA =>
if M_AXI_WREADY = '1' then
if burst_data_cnt = 1 then
M_AXI_WLAST <= '1';
end if;
if burst_data_cnt = 0 then
M_AXI_WLAST <= '0';
if data_cnt = 0 then
write_state <= FINISHED;
-- clear run register
run_reg_clear <= '1';
else
write_state <= REQ;
end if;
end if;
burst_data_cnt := burst_data_cnt - 1;
data_cnt := data_cnt - 1;
end if;
when FINISHED =>
run_reg_clear <= '0';
-- Interrupt zuruecksetzen, fall Interrupt aktiviert
if interrupt_enable_reg = '0' then
write_state <= IDLE;
elsif interrupt_reset = '1' then
write_state <= IDLE;
end if;
when others => null;
end case;
end if;
end process;
end architecture;