183 lines
6.8 KiB
VHDL
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; |