146 lines
5.5 KiB
VHDL
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;
|