---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2004
--
-- Filename: CrcTB.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card Dsp FPGA
--
-- Design Description:
-- Tesbench for module to generate a 32bit CRC
---------------------------------------------------------------------------

library IEEE;
use IEEE.Std_Logic_1164.all;

use work.PCK_CRC32_D16.all;

entity CrcTB is
end entity CrcTB;


architecture Test of CrcTB is

  component TriggerPulseGen is
    port (-- Local bus signals
          pnReset            : in  std_ulogic;
          pSample2xClk       : in  std_ulogic;
          pTriggerLen        : in  std_logic_vector(11 downto 0);
          pPulseCount        : in  std_logic_vector(3 downto 0);
          pTriggerIn         : in  std_ulogic;
          pTxDone            : out std_ulogic;
          pTriggerOut        : out std_ulogic);
  end component TriggerPulseGen;

  signal nReset      : std_ulogic;
  signal Clk         : std_ulogic := '0';

  signal SramData:       std_logic_vector(31 downto 0);
  signal ACrc:           std_logic_vector(31 downto 0);
  signal nACrc:          std_logic_vector(31 downto 0);
  signal CrcH:           std_logic_vector(15 downto 0);
  signal ACrcRst:        std_ulogic;
  signal ACrcEn:         std_ulogic;
  signal ACrcHEn:        std_ulogic;

  type DataArray is array (0 to 47) of std_logic_vector(7 downto 0);
  -- 40 Octets filled with "0"
  -- CPCS-UU = 0, CPI = 0, Length = 40, CRC-32 = 864d7f99
  constant TestData1: DataArray := (x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
                                   x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
                                   x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
                                   x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
                                   x"00",x"00",x"00",x"28",x"86",x"4d",x"7f",x"99");
  -- 40 Octets filled with "1"
  -- CPCS-UU = 0, CPI = 0, Length = 40, CRC-32 = c55e457a
  constant TestData2: DataArray := (x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",
                                    x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",
                                    x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",
                                    x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",x"ff",
                                    x"00",x"00",x"00",x"28",x"c5",x"5e",x"45",x"7a");

  -- 40 Octets counting: 1 to 40
  -- CPCS-UU = 0", CPI = 0", Length = 40, CRC-32 = bf671ed0
  constant TestData3: DataArray := (x"01",x"02",x"03",x"04",x"05",x"06",x"07",x"08",x"09",x"0a",
                                    x"0b",x"0c",x"0d",x"0e",x"0f",x"10",x"11",x"12",x"13",x"14",
                                    x"15",x"16",x"17",x"18",x"19",x"1a",x"1b",x"1c",x"1d",x"1e",
                                    x"1f",x"20",x"21",x"22",x"23",x"24",x"25",x"26",x"27",x"28",
                                    x"00",x"00",x"00",x"28",x"bf",x"67",x"1e",x"d0");

  -- 40 Octets counting: 1 to 40
  -- CPCS-UU = 11, CPI = 22, CRC-32 = acba602a
  constant TestData4: DataArray := (x"01",x"02",x"03",x"04",x"05",x"06",x"07",x"08",x"09",x"0a",
                                    x"0b",x"0c",x"0d",x"0e",x"0f",x"10",x"11",x"12",x"13",x"14",
                                    x"15",x"16",x"17",x"18",x"19",x"1a",x"1b",x"1c",x"1d",x"1e",
                                    x"1f",x"20",x"21",x"22",x"23",x"24",x"25",x"26",x"27",x"28",
                                    x"11",x"22",x"00",x"28",x"ac",x"ba",x"60",x"2a");

begin
  Clk <= not Clk after 5 ns;

  nACrc <= not ACrc;

  -- CRC-32 calculation
  GenCrc: process(nReset, Clk)
    variable vData : std_logic_vector(15 downto 0);
  begin
    if nReset = '0' then
      ACrc <= (others => '1');
      CrcH <= (others => '0');
      ACrcHEn <= '0';
    elsif rising_edge(Clk) then
      CrcH <= SramData(31 downto 16);
      if ACrcEn = '1' then
        vData := SramData(7 downto 0) & SramData(15 downto 8);
      else
        vData := CrcH(7 downto 0) & CrcH(15 downto 8);
      end if;

      ACrcHEn <= ACrcEn;
      if ACrcRst = '1' then
        ACrc <= (others => '1');
      elsif (ACrcEn = '1' or ACrcHEn = '1') then
        ACrc <= nextCRC32_D16(vData, ACrc);
      end if;
    end if;
  end process GenCrc;

  process
    variable i: integer;
  begin
    nReset <= '0';
    ACrcEn <= '0';
    ACrcRst <= '0';
    wait until rising_edge(Clk);
    wait until rising_edge(Clk);
    nReset <= '1';

    -- Test Case 0
    ACrcRst <= '1';
    wait until rising_edge(Clk);
    ACrcRst <= '0';
    wait until rising_edge(Clk);

    i := 0;
    while (i < 32) loop
      ACrcEn <= '1';
      SramData <= (others => '0');
      wait until rising_edge(Clk);
      ACrcEn <= '0';

      wait until rising_edge(Clk);
      i := i + 4;
    end loop;

    wait until rising_edge(Clk);
    assert ACrc = x"4a55af67" report "CRC simulation failed" severity failure;
    ---------------------------------------------------------------------------


    -- Test Case 1
    ACrcRst <= '1';
    wait until rising_edge(Clk);
    ACrcRst <= '0';
    wait until rising_edge(Clk);

    i := 0;
    while (i < 48) loop
      ACrcEn <= '1';
      SramData <= TestData1(i+3) & TestData1(i+2) & TestData1(i+1) & TestData1(i); -- little endian
      wait until rising_edge(Clk);
      ACrcEn <= '0';
      -- check CRC 1's compliment value
      if i = 44 then
        assert nACrc = x"864d7f99" report "CRC simulation failed" severity failure;
      end if;

      wait until rising_edge(Clk);
      i := i + 4;
    end loop;

    wait until rising_edge(Clk);
    -- Check value including CRC
    assert ACrc = x"C704DD7B" report "CRC simulation failed" severity failure;
    ---------------------------------------------------------------------------

    -- Test Case 2
    ACrcRst <= '1';
    wait until rising_edge(Clk);
    ACrcRst <= '0';
    wait until rising_edge(Clk);

    i := 0;
    while (i < 48) loop
      ACrcEn <= '1';
      SramData <= TestData2(i+3) & TestData2(i+2) & TestData2(i+1) & TestData2(i); -- little endian
      wait until rising_edge(Clk);
      ACrcEn <= '0';
      -- check CRC 1's compliment value
      if i = 44 then
        assert nACrc = x"c55e457a" report "CRC simulation failed" severity failure;
      end if;

      wait until rising_edge(Clk);
      i := i + 4;
    end loop;

    wait until rising_edge(Clk);
    -- Check value including CRC
    assert ACrc = x"C704DD7B" report "CRC simulation failed" severity failure;
    ---------------------------------------------------------------------------

    -- Test Case 3
    ACrcRst <= '1';
    wait until rising_edge(Clk);
    ACrcRst <= '0';
    wait until rising_edge(Clk);

    i := 0;
    while (i < 48) loop
      ACrcEn <= '1';
      SramData <= TestData3(i+3) & TestData3(i+2) & TestData3(i+1) & TestData3(i); -- little endian
      wait until rising_edge(Clk);
      ACrcEn <= '0';
      -- check CRC 1's compliment value
      if i = 44 then
        assert nACrc = x"bf671ed0" report "CRC simulation failed" severity failure;
      end if;

      wait until rising_edge(Clk);
      i := i + 4;
    end loop;

    wait until rising_edge(Clk);
    -- Check value including CRC
    assert ACrc = x"C704DD7B" report "CRC simulation failed" severity failure;
    ---------------------------------------------------------------------------

    -- Test Case 4
    ACrcRst <= '1';
    wait until rising_edge(Clk);
    ACrcRst <= '0';
    wait until rising_edge(Clk);

    i := 0;
    while (i < 48) loop
      ACrcEn <= '1';
      SramData <= TestData4(i+3) & TestData4(i+2) & TestData4(i+1) & TestData4(i); -- little endian
      wait until rising_edge(Clk);
      ACrcEn <= '0';
      -- check CRC 1's compliment value
      if i = 44 then
        assert nACrc = x"acba602a" report "CRC simulation failed" severity failure;
      end if;

      wait until rising_edge(Clk);
      i := i + 4;
    end loop;

    wait until rising_edge(Clk);
    -- Check value including CRC
    if ACrc = x"C704DD7B" then
      assert false report "CRC simulation passed" severity failure;
    else
      assert false report "CRC simulation failed" severity failure;
    end if;

    wait;
  end process;
     
end Test;