-------------------------------------------------------------------------------
-- Title      :  CRC generator
-- Project    :  Bluetooth baseband core
-------------------------------------------------------------------------------
-- File        : crc_gen.vhd
-- Author      : Jamil Khatib  (khatib@ieee.org)
-- Organization: OpenIPCore Project
-- Created     : 2000/11/18
-- Last update : 2000/12/09
-- Platform    : 
-- Simulators  : Modelsim 5.3XE/Windows98
-- Synthesizers: Leonardo/WindowsNT
-- Target      : 
-- Dependency  : ieee.std_logic_1164
-------------------------------------------------------------------------------
-- Description: CRC generator core
-------------------------------------------------------------------------------
-- Copyright (c) 2000 Jamil Khatib
-- 
-- This VHDL design file is an open design; you can redistribute it and/or
-- modify it and/or implement it after contacting the author
-- You can check the draft license at
-- http://www.opencores.org/OIPC/license.shtml

-------------------------------------------------------------------------------
-- Revisions  :
-- Revision Number :   1
-- Version         :   0.1
-- Date            :   18 Nov 2000
-- Modifier        :   Jamil Khatib (khatib@ieee.org)
-- Desccription    :   Created
-- Known bugs      :   
-- To Optimze      :   
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

entity crc_gen_ent is

  port (
    clk : in std_logic;                 -- system clock
    rst : in std_logic;                 -- system reset
    en  : in std_logic;                 -- System enable and load new Init value

    DataIn  : in  std_logic;                       -- Input data stream
    DataOut : out std_logic;                       -- Output Data stream
    Init    : in  std_logic_vector(15 downto 0));  -- LFSR LSB init values

end crc_gen_ent;

architecture crc_gen_beh of crc_gen_ent is

  type CRCstates_typ is (IDLE_st, NORMAL_st);  -- CRC state machine
--  constant IDLE_st : std_logic := '0';
--  constant NORMAL_st : std_logic := 1';

  signal lfsr  : std_logic_vector(15 downto 0);  -- lfsr register
  signal state : CRCstates_typ;

begin  -- crc_gen_beh

  -- purpose: CRC core
  -- type   : sequential
  -- inputs : clk, rst
  -- outputs: 
  crccore_proc          : process (clk, rst)
                                        -- CRC machine state diagram
    variable out_var    : std_logic;    -- Output temporary variable
    variable cell12_var : std_logic;    -- Cell 12 variable
    variable cell5_var  : std_logic;    -- Cell 5 variable

  begin  -- process crccore_proc
    if rst = '0' then                   -- asynchronous reset (active low)

      lfsr <= (others => '1');

      state <= IDLE_st;

      out_var    := '0';
      cell12_var := '0';
      cell5_var  := '0';

      DataOut <= '0';

    elsif clk'event and clk = '1' then  -- rising clock edge

      case state is

        when IDLE_st =>                 -- Idle state
          if en = '1' then
            state <= Normal_st;         -- go to Normal state

            lfsr    <= (Init);          -- load lfsr
            out_var := lfsr(15) xor '0';

            cell5_var  := '0';
            cell12_var := '0';

          else
            state <= IDLE_st;           -- stay in Idle state

            out_var    := lfsr(15) xor '0';
            cell5_var  := out_var xor lfsr(4);
            cell12_var := out_var xor lfsr(11);

            lfsr <= lfsr(14 downto 12) & cell12_var & lfsr(10 downto 5) & cell5_var & lfsr(3 downto 0) & out_var;

          end if;

        when NORMAL_st =>               -- Normal state
          if en = '1' then
            state <= NORMAL_st;         -- Stay in Normal state

          else

            state <= IDLE_st;           -- go to Idle state 

          end if;

          out_var := lfsr(15) xor DataIn;

          cell5_var  := out_var xor lfsr(4);
          cell12_var := out_var xor lfsr(11);

          lfsr <= lfsr(14 downto 12) & cell12_var & lfsr(10 downto 5) & cell5_var & lfsr(3 downto 0) & out_var;


        when others => null;
      end case;

      DataOut <= out_var;

    end if;
  end process crccore_proc;

end crc_gen_beh;