CRC_Hardware
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity CRC is
|
||||
generic (
|
||||
crcLength : positive;
|
||||
inDataLength : positive;
|
||||
polynomial : std_logic_vector;
|
||||
initialValue : std_logic_vector
|
||||
);
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
-- Kontrollsignale
|
||||
reset : in std_logic;
|
||||
enable : in std_logic;
|
||||
-- Datensignale
|
||||
inData : in std_logic_vector(inDataLength-1 downto 0);
|
||||
checksum : out std_logic_vector(crcLength-1 downto 0)
|
||||
);
|
||||
end CRC;
|
||||
|
||||
architecture rtl of CRC is
|
||||
|
||||
-- Interne Signale fuer CRC Pruefsumme
|
||||
signal checksum_i : std_logic_vector(crcLength-1 downto 0);
|
||||
signal nextChecksum : std_logic_vector(crcLength-1 downto 0);
|
||||
|
||||
begin
|
||||
-- Kombinatorik fuer CRC-Berechnung
|
||||
ProcNextCRC: process (inData, checksum_i)
|
||||
variable mix: std_logic_vector(crcLength-1 downto 0);
|
||||
variable MSB : std_logic;
|
||||
begin
|
||||
mix := checksum_i;
|
||||
for i in inData'range loop
|
||||
-- Pruefen ob MSB gesetzt ist
|
||||
MSB := mix(mix'length-1);
|
||||
-- neues Bit reinschieben
|
||||
mix := mix(mix'length-2 downto 0) & inData(i);
|
||||
-- XOR Verknuepfung
|
||||
if MSB = '1' then
|
||||
mix := mix XOR polynomial;
|
||||
end if;
|
||||
end loop;
|
||||
nextChecksum <= mix;
|
||||
end process;
|
||||
|
||||
-- Register zum Speichern der CRC-Pruefsumme
|
||||
Reg: process (CLK)
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if reset = '1' then
|
||||
checksum_i <= initialValue;
|
||||
elsif enable = '1' then
|
||||
checksum_i <= nextChecksum;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
checksum <= checksum_i;
|
||||
|
||||
end architecture;
|
||||
@@ -0,0 +1,258 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
entity Mem_to_CRC is
|
||||
generic (
|
||||
logLength : integer
|
||||
);
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
RST : in std_logic;
|
||||
-- Control IO
|
||||
ready : out std_logic := '0';
|
||||
start : in std_logic;
|
||||
startAddress : in std_logic_vector(31 downto 0);
|
||||
lengthM1 : in std_logic_vector(logLength-1 downto 0);
|
||||
-- Wishbone Master
|
||||
D_DAT_O : out std_logic_vector(31 downto 0) := (others => '0') ;
|
||||
D_DAT_I : in std_logic_vector(31 downto 0);
|
||||
D_STB_O : out std_logic := '0';
|
||||
D_ADR_O : out unsigned(31 downto 0) := (others => '0') ;
|
||||
D_SEL_O : out std_logic_vector( 3 downto 0);
|
||||
D_WE_O : out std_logic;
|
||||
D_ACK_I : in std_logic;
|
||||
-- CRC output
|
||||
checksum : out std_logic_vector(31 downto 0) := (others => '0')
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture arch of Mem_to_CRC is
|
||||
|
||||
--Signale zwischen Steuerwerk und Rechenwerk
|
||||
signal lengthEN : std_logic := '0';
|
||||
signal lengthLD : std_logic := '0';
|
||||
signal lengthTC : std_logic := '0';
|
||||
signal dataEN : std_logic := '0';
|
||||
signal CRCEN : std_logic := '0';
|
||||
signal CRCRST : std_logic := '0';
|
||||
signal startAddressEN : std_logic := '0';
|
||||
signal startAddressLD : std_logic := '0';
|
||||
signal startBytesEN : std_logic := '0';
|
||||
signal startBytesLD : std_logic := '0';
|
||||
signal startBytesTC : std_logic := '0';
|
||||
|
||||
|
||||
begin
|
||||
Rechenwerk: block
|
||||
|
||||
-- Register
|
||||
signal dataByte3 : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal dataByte2 : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal dataByte1 : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal dataByte0 : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal toCRC : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal byteSelect : std_logic_vector(1 downto 0) := (others => '0');
|
||||
|
||||
begin
|
||||
--Zaehler der Anzahl der Datenbytes
|
||||
CounterLength: process(CLK)
|
||||
variable counterValue: unsigned(logLength - 1 downto 0) := (others => '0');
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if lengthLD = '1' then --Laden
|
||||
counterValue := unsigned(lengthM1);
|
||||
elsif lengthEN = '1' then --runterzaehlen
|
||||
counterValue := counterValue - 1;
|
||||
end if;
|
||||
if counterValue = 0 then --TC setzen
|
||||
lengthTC <= '1';
|
||||
else
|
||||
lengthTC <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--Zaehler fuer Adressen
|
||||
CounterAddress: process(CLK)
|
||||
variable counterValue : unsigned(31 downto 2) := (others => '0');
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if startAddressLD = '1' then
|
||||
counterValue := unsigned(startAddress(31 downto 2)); --Speicher laden
|
||||
elsif startAddressEN = '1' then
|
||||
counterValue := counterValue + 1; --hochzaehlen
|
||||
end if;
|
||||
--Variabel ausgeben und auf 32 Bit erweitern
|
||||
D_ADR_O <= counterValue & "00";
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--Modulozaehler fuer die einzelnen Bytes
|
||||
CounterBytes: process(CLK)
|
||||
variable counterValue : unsigned(1 downto 0) := (others => '0');
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if startBytesLD = '1' then
|
||||
counterValue := unsigned(startAddress(1 downto 0)); --Speicher laden
|
||||
elsif startBytesEN = '1' and counterValue < 3 then --hochzaehlen
|
||||
counterValue := counterValue + 1;
|
||||
elsif startBytesEN = '1' and counterValue = 3 then
|
||||
counterValue := (others => '0'); --zuruecksetzen
|
||||
end if;
|
||||
if counterValue = 3 then --TC setzen
|
||||
startBytesTC <= '1';
|
||||
else
|
||||
startBytesTC <= '0';
|
||||
end if;
|
||||
--Variabel ausgeben und zum Multiplexer fuehren
|
||||
byteSelect <= std_logic_vector(counterValue);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--vier Pufferregister fuer das Datenwort -> vier Datenbytes
|
||||
SeparateDataWords: process(CLK)
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
if DataEN = '1' then
|
||||
dataByte3 <= D_DAT_I(31 downto 24);
|
||||
dataByte2 <= D_DAT_I(23 downto 16);
|
||||
dataByte1 <= D_DAT_I(15 downto 8);
|
||||
dataByte0 <= D_DAT_I(7 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--Multiplexer für das Ansteuern des ersten Datenbytes
|
||||
ByteSelectMUX: process(byteSelect, dataByte0, dataByte1, dataByte2, dataByte3)
|
||||
begin
|
||||
toCRC <= (others => '0');
|
||||
case byteSelect is
|
||||
when "11" => toCRC <= dataByte3;
|
||||
when "10" => toCRC <= dataByte2;
|
||||
when "01" => toCRC <= dataByte1;
|
||||
when "00" => toCRC <= dataByte0;
|
||||
when others => toCRC <= (others => '-');
|
||||
end case;
|
||||
end process;
|
||||
|
||||
--Feste Ausgaenge
|
||||
D_SEL_O <= "1111";
|
||||
D_WE_O <= '0';
|
||||
|
||||
------------------------------------------------------------
|
||||
-- CRC Berechnung
|
||||
------------------------------------------------------------
|
||||
CRC_Inst: entity work.CRC
|
||||
generic map (
|
||||
crcLength => 32,
|
||||
inDataLength => 8,
|
||||
polynomial => x"04C11DB7",
|
||||
initialValue => x"00000000"
|
||||
)
|
||||
port map (
|
||||
CLK => CLK,
|
||||
reset => CRCRST,
|
||||
enable => CRCEN,
|
||||
inData => toCRC(7 downto 0),
|
||||
checksum => checksum(31 downto 0)
|
||||
);
|
||||
|
||||
end block;
|
||||
|
||||
Steuerwerk : block
|
||||
-- Typ fuer die Zustandswerte
|
||||
type state_t is (S_IDLE, S_READ_WORD, S_CALCULATE_CRC, S_ERROR);
|
||||
-- Interne Signale des Rechenwerks
|
||||
signal state : state_t := S_IDLE;
|
||||
signal state_next : state_t;
|
||||
begin
|
||||
-- Prozess zur Berechnung des Folgezustandes und der Mealy-Ausgaenge
|
||||
Transition: process(RST, state, start, D_ACK_I, startBytesTC, lengthTC)
|
||||
begin
|
||||
-- Default-Werte fuer Folgezustand und Mealy-Ausgaenge
|
||||
state_next <= S_ERROR;
|
||||
lengthEN <= '0';
|
||||
lengthLD <= '0';
|
||||
dataEN <= '0';
|
||||
CRCRST <= '0';
|
||||
startAddressEN <= '0';
|
||||
startAddressLD <= '0';
|
||||
startBytesEN <= '0';
|
||||
startBytesLD <= '0';
|
||||
-- Berechnung des Folgezustandes und der Mealy-Ausgaenge
|
||||
case state is
|
||||
when S_IDLE =>
|
||||
if RST = '1' then
|
||||
state_next <= S_IDLE;
|
||||
elsif start = '1' then
|
||||
state_next <= S_READ_WORD;
|
||||
lengthLD <= '1';
|
||||
CRCRST <= '1';
|
||||
startAddressLD <= '1';
|
||||
startBytesLD <= '1';
|
||||
elsif start = '0' then
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when S_READ_WORD =>
|
||||
if RST = '1' then
|
||||
state_next <= S_IDLE;
|
||||
elsif D_ACK_I = '0' then
|
||||
state_next <= S_READ_WORD;
|
||||
elsif D_ACK_I = '1' then
|
||||
state_next <= S_CALCULATE_CRC;
|
||||
dataEN <= '1';
|
||||
end if;
|
||||
when S_CALCULATE_CRC =>
|
||||
if RST = '1' then
|
||||
state_next <= S_IDLE;
|
||||
elsif startBytesTC = '0' and lengthTC = '0' then
|
||||
state_next <= S_CALCULATE_CRC;
|
||||
lengthEN <= '1';
|
||||
startBytesEN <= '1';
|
||||
elsif startBytesTC = '1' and lengthTC = '0' then
|
||||
state_next <= S_READ_WORD;
|
||||
lengthEN <= '1';
|
||||
startBytesEN <= '1';
|
||||
startAddressEN <= '1';
|
||||
elsif lengthTC = '1' then
|
||||
state_next <= S_IDLE;
|
||||
end if;
|
||||
when others =>
|
||||
lengthEN <= 'X';
|
||||
lengthLD <= 'X';
|
||||
dataEN <= 'X';
|
||||
CRCRST <= 'X';
|
||||
startAddressEN <= 'X';
|
||||
startAddressLD <= 'X';
|
||||
startBytesEN <= 'X';
|
||||
startBytesLD <= 'X';
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- Register fuer Zustand und Moore-Ausgaenge
|
||||
Reg: process (CLK)
|
||||
begin
|
||||
if rising_edge(CLK) then
|
||||
-- Zustandsregister
|
||||
state <= state_next;
|
||||
-- Berechnung der Moore-Ausgaenge
|
||||
--Default-Werte
|
||||
ready <= '0';
|
||||
CRCEN <= '0';
|
||||
D_STB_O <= '0';
|
||||
case state_next is
|
||||
when S_IDLE =>
|
||||
ready <= '1';
|
||||
when S_READ_WORD =>
|
||||
D_STB_O <= '1';
|
||||
when S_CALCULATE_CRC =>
|
||||
CRCEN <= '1';
|
||||
when others =>
|
||||
ready <= 'X';
|
||||
CRCEN <= 'X';
|
||||
D_STB_O <= 'X';
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
end block;
|
||||
end architecture;
|
||||
Reference in New Issue
Block a user