Files
2025-02-19 14:42:38 +01:00

183 lines
6.8 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity axis_crc is
port (
CLK : in std_logic;
RESETN : in std_logic;
-- for crc calculation
initialValue : in std_logic_vector(31 downto 0);
polynomial : in std_logic_vector(31 downto 0);
finalXOR : in std_logic_vector(31 downto 0);
inOutReflected : 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_crc is
function reflect(input : std_logic_vector) return std_logic_vector is
variable result : std_logic_vector(input'range);
begin
for i in input'range loop
result(i) := input(input'low + input'length - 1 - i);
end loop;
return result;
end function;
type state_t is (IDLE, FIRST_HALF, SECOND_HALF, PROVIDE_DATA, CHECKSUM);
signal state : state_t := IDLE;
begin
process
-- fuer CRC-Berechnung
variable CRC : std_logic_vector(31 downto 0);
variable data : std_logic_vector(31 downto 0);
variable byte_0 : std_logic_vector( 7 downto 0);
variable byte_1 : std_logic_vector( 7 downto 0);
variable byte_2 : std_logic_vector( 7 downto 0);
variable byte_3 : std_logic_vector( 7 downto 0);
variable firstWord : boolean := false; -- is True if first word of current packet receiving
variable last : std_logic; -- is True if last word of packets is receivied
begin
wait until rising_edge(CLK);
if RESETN = '0' then
S_AXIS_TREADY <= '1';
M_AXIS_TVALID <= '0';
M_AXIS_TLAST <= '0';
CRC := (others=>'0');
byte_0 := (others=>'0');
byte_1 := (others=>'0');
byte_2 := (others=>'0');
byte_3 := (others=>'0');
firstWord := true;
last := '0';
state <= IDLE;
else
case state is
when IDLE =>
if S_AXIS_TVALID = '1' then
-- Daten von AXIS-Schnittstelle annehmen
data := S_AXIS_TDATA;
byte_0 := S_AXIS_TDATA( 7 downto 0);
byte_1 := S_AXIS_TDATA(15 downto 8);
byte_2 := S_AXIS_TDATA(23 downto 16);
byte_3 := S_AXIS_TDATA(31 downto 24);
last := S_AXIS_TLAST;
S_AXIS_TREADY <= '0';
-- Initialwert laden
if firstWord = true then
CRC := initialValue;
firstWord := false;
end if;
-- Reflect Input
if inOutReflected(0) = '1' then
byte_0 := reflect(byte_0);
byte_1 := reflect(byte_1);
byte_2 := reflect(byte_2);
byte_3 := reflect(byte_3);
end if;
-- Board speichert Daten mit LITTLE ENDIAN
-- -> Die Daten aus dem Speicher sollen aufsteigend
-- in die CRC-Summe reingerechnet werden
-- Erstes Byte reinrechnen
CRC := CRC xor (byte_0 & (23 downto 0 =>'0'));
for i in 0 to 7 loop
if CRC(31) = '1' then
CRC := (CRC(30 downto 0) & '0') xor polynomial;
else
CRC := CRC(30 downto 0) & '0';
end if;
end loop;
state <= SECOND_HALF;
end if;
when SECOND_HALF =>
-- Zweites und Drittes Byte reinrechnen
CRC := CRC xor (byte_1 & byte_2 & (15 downto 0 =>'0'));
for i in 0 to 15 loop
if CRC(31) = '1' then
CRC := (CRC(30 downto 0) & '0') xor polynomial;
else
CRC := CRC(30 downto 0) & '0';
end if;
end loop;
-- Daten an M_AXIS ausgeben
M_AXIS_TVALID <= '1';
M_AXIS_TDATA <= data;
state <= PROVIDE_DATA;
when PROVIDE_DATA =>
if M_AXIS_TREADY = '1' then
-- letztes Byte reinrechnen
CRC := CRC xor (byte_3 & (23 downto 0 =>'0'));
for i in 0 to 7 loop
if CRC(31) = '1' then
CRC := (CRC(30 downto 0) & '0') xor polynomial;
else
CRC := CRC(30 downto 0) & '0';
end if;
end loop;
if last = '1' then
M_AXIS_TLAST <= '1';
-- Reflect Output
if inOutReflected(1) = '1' then
CRC := reflect(CRC);
end if;
-- CRC Pruefsumme ausgeben
CRC := CRC xor finalXOR;
M_AXIS_TDATA <= CRC;
state <= CHECKSUM;
else
S_AXIS_TREADY <= '1';
M_AXIS_TVALID <= '0';
state <= IDLE;
end if;
end if;
when CHECKSUM =>
if M_AXIS_TREADY = '1' then
S_AXIS_TREADY <= '1';
M_AXIS_TVALID <= '0';
M_AXIS_TLAST <= '0';
firstWord := true;
state <= IDLE;
end if;
when others => null;
end case;
end if;
end process;
end architecture;