2026-01-13 10:05:02 +01:00

146 lines
5.5 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.reg32.all;
use work.task.all;
entity crc is
port (
clk : in std_logic;
reset : in std_logic;
task_start : in std_logic;
task_state : out work.task.State;
signal_read : out std_logic;
signal_readdata : in std_logic_vector( 31 downto 0 );
signal_write : out std_logic;
signal_writedata : out std_logic_vector( 31 downto 0 )
);
end entity crc;
architecture rtl of crc is
constant CRC32_POLY_REVERSED : std_logic_vector(31 downto 0) := x"EDB88320";
constant CRC32_INIT : std_logic_vector(31 downto 0) := x"FFFFFFFF";
signal current_task_state : work.task.State;
signal next_task_state : work.task.State;
signal index : integer range 0 to work.task.STREAM_LEN;
-- CRC Berechnung
signal crc_value : std_logic_vector(31 downto 0);
-- Zustandsmaschine für CRC-Berechnung
signal bit_counter : integer range 0 to 32;
signal word_buffer : std_logic_vector(31 downto 0);
type processing_state_t is (IDLE, READ_WAIT, COMPUTE);
signal proc_state : processing_state_t;
begin
task_state_transitions : process ( current_task_state, task_start, index, proc_state ) is
begin
next_task_state <= current_task_state;
case current_task_state is
when work.task.TASK_IDLE =>
if ( task_start = '1' ) then
next_task_state <= work.task.TASK_RUNNING;
end if;
when work.task.TASK_RUNNING =>
if ( index = work.task.STREAM_LEN and proc_state = IDLE ) then
next_task_state <= work.task.TASK_DONE;
end if;
when work.task.TASK_DONE =>
if ( task_start = '1' ) then
next_task_state <= work.task.TASK_RUNNING;
end if;
end case;
end process task_state_transitions;
sync : process ( clk, reset ) is
variable crc_temp : std_logic_vector(31 downto 0);
variable bit_in : std_logic;
begin
if ( reset = '1' ) then
current_task_state <= work.task.TASK_IDLE;
index <= 0;
crc_value <= CRC32_INIT;
bit_counter <= 0;
proc_state <= IDLE;
signal_read <= '0';
signal_write <= '0';
signal_writedata <= (others => '0');
word_buffer <= (others => '0');
elsif ( rising_edge( clk ) ) then
current_task_state <= next_task_state;
case next_task_state is
when work.task.TASK_IDLE =>
index <= 0;
crc_value <= CRC32_INIT;
bit_counter <= 0;
proc_state <= IDLE;
signal_read <= '0';
signal_write <= '0';
when work.task.TASK_RUNNING =>
signal_write <= '0';
case proc_state is
when IDLE =>
if index < work.task.STREAM_LEN then
-- Leseanfrage starten
signal_read <= '1';
proc_state <= READ_WAIT;
end if;
when READ_WAIT =>
-- Daten sind jetzt verfügbar (nach 1 Takt)
signal_read <= '0';
word_buffer <= signal_readdata;
bit_counter <= 0;
proc_state <= COMPUTE;
when COMPUTE =>
-- Bitweise CRC berechnen (32 Bits pro Wort, LSB first)
if bit_counter < 32 then
crc_temp := crc_value;
-- Bit aus word_buffer extrahieren (LSB first)
bit_in := word_buffer(bit_counter);
-- CRC Update für ein Bit
if (crc_temp(0) xor bit_in) = '1' then
crc_temp := ('0' & crc_temp(31 downto 1)) xor CRC32_POLY_REVERSED;
else
crc_temp := '0' & crc_temp(31 downto 1);
end if;
crc_value <= crc_temp;
bit_counter <= bit_counter + 1;
else
-- Wort fertig verarbeitet, nächstes Wort
index <= index + 1;
proc_state <= IDLE;
end if;
end case;
when work.task.TASK_DONE =>
-- Finales CRC schreiben (invertiert)
if proc_state = IDLE then
signal_write <= '1';
signal_writedata <= not crc_value;
signal_read <= '0';
else
signal_write <= '0';
proc_state <= IDLE;
end if;
end case;
end if;
end process sync;
task_state <= current_task_state;
end architecture rtl;