Files
es-abschlussprojekt/Hardware/axis_crc.vhd
T

169 lines
6.1 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
initial_value : 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 MSB : std_logic;
variable data : std_logic_vector(31 downto 0);
variable lowerByte : std_logic_vector(7 downto 0);
variable upperByte : std_logic_vector(7 downto 0);
variable firstWord : boolean := false; -- is True if first word of current packet receiving
variable last : std_logic;
begin
wait until rising_edge(CLK);
if RESETN = '0' then
state <= IDLE;
S_AXIS_TREADY <= '1';
M_AXIS_TVALID <= '0';
M_AXIS_TLAST <= '0';
CRC := (others=>'0');
firstWord := true;
else
case state is
when IDLE =>
if S_AXIS_TVALID = '1' then
data := S_AXIS_TDATA;
last := S_AXIS_TLAST;
S_AXIS_TREADY <= '0';
-- load initial value
if firstWord = true then
CRC := initial_value;
firstWord := false;
end if;
-- Board speichert Daten mit LITTLE ENDIAN
-- -> Die Daten aus dem Speicher sollen aufsteigend
-- in die CRC-Summe reingerechnet werden
upperByte := data(7 downto 0);
lowerByte := data(15 downto 8);
-- Reflect Input
if inOutReflected(0) = '1' then
upperByte := reflect(upperByte);
lowerByte := reflect(lowerByte);
end if;
-- Erstes und zweites byte reinrechnen
CRC := CRC xor (upperByte & lowerByte & (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;
state <= SECOND_HALF;
end if;
when SECOND_HALF =>
-- Dann obere 16 Bit in die CRC Summe reinrechnen
upperByte := data(23 downto 16);
lowerByte := data(31 downto 24);
-- Reflect Input
if inOutReflected(0) = '1' then
upperByte := reflect(upperByte);
lowerByte := reflect(lowerByte);
end if;
-- Drittes byte reinrechnen
CRC := CRC xor (upperByte & lowerByte & (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
if last = '1' then
M_AXIS_TLAST <= '1';
-- Reflect Output
if inOutReflected(1) = '1' then
CRC := reflect(CRC);
end if;
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;