259 lines
7.6 KiB
VHDL
259 lines
7.6 KiB
VHDL
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;
|