----------------------------------------------------------------------------------
-- Company:        www.mlab.cz
-- Based on code written by MIHO.
-- 
-- HW Design Name: S3AN01A
-- Project Name:   gtime
-- Target Devices: XC3S50AN-4
-- Tool versions:  ISE 13.3
-- Description:    Time and frequency synchronisation for RDMS01A.
--
-- Dependencies:   CLKGEN01B, GPS01A
--
-- Version:  $Id: PulseGen.vhd 2534 2012-09-02 13:40:37Z kakl $
--
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

library UNISIM;
use UNISIM.vcomponents.all;

entity gtime is
        generic (
                --      Top Value for 100MHz Clock Counter
--!!!KAKL               MAXCOUNT:       integer :=      30_000_000;
                MAXCOUNT:       integer :=      3_000_000;
                MUXCOUNT:       integer :=      100_000                         --      LED Display Multiplex Clock Divider
        );
        port (
                -- Main Clock
                CLK100MHz:      in              std_logic;

                -- Mode Signals (usualy not used)
                M:                              in              std_logic_vector(2 downto 0);
                VS:                     in              std_logic_vector(2 downto 0);

                -- Dipswitch Inputs
                DIPSW:          in              std_logic_vector(7 downto 0);

                -- Push Buttons
                PB:                     in              std_logic_vector(3 downto 0);

                -- LED Bar Outputs
                LED:                    out     std_logic_vector(7 downto 0);

                --      LED Display (8 digit with 7 segments and ddecimal point)
                LD_A_n:         out     std_logic;
                LD_B_n:         out     std_logic;
                LD_C_n:         out     std_logic;
                LD_D_n:         out     std_logic;
                LD_E_n:         out     std_logic;
                LD_F_n:         out     std_logic;
                LD_G_n:         out     std_logic;
                LD_DP_n:                out     std_logic;
                LD_0_n:         out     std_logic;
                LD_1_n:         out     std_logic;
                LD_2_n:         out     std_logic;
                LD_3_n:         out     std_logic;
                LD_4_n:         out     std_logic;
                LD_5_n:         out     std_logic;
                LD_6_n:         out     std_logic;
                LD_7_n:         out     std_logic;

                --      VGA Video Out Port
                VGA_R:          out     std_logic_vector(1 downto 0);
                VGA_G:          out     std_logic_vector(1 downto 0);
                VGA_B:          out     std_logic_vector(1 downto 0);
                VGA_VS:         out     std_logic;
                VGA_HS:         out     std_logic;

                -- Bank 1 Pins - Inputs for this Test
                B:                              inout           std_logic_vector(24 downto 0);
                
                -- PS/2 Bidirectional Port (open collector, J31 and J32)
--              PS2_CLK1:       inout   std_logic;
--              PS2_DATA1:      inout   std_logic;
                PS2_CLK2:       inout   std_logic;
                PS2_DATA2:      inout   std_logic;

                --      Diferencial Signals on 4 pin header (J7)
                DIF1P:          inout   std_logic;
                DIF1N:          inout   std_logic;
                DIF2P:          inout   std_logic;
                DIF2N:          inout   std_logic;
                

                --      I2C Signals (on connector J30)
                I2C_SCL:                inout   std_logic;
                I2C_SDA:                inout   std_logic;

                --      Diferencial Signals on SATA like connectors (not SATA capable, J28 and J29)
                SD1AP:          inout   std_logic;
                SD1AN:          inout   std_logic;
                SD1BP:          inout   std_logic;
                SD1BN:          inout   std_logic;
                SD2AP:          inout   std_logic;
                SD2AN:          inout   std_logic;
                SD2BP:          inout   std_logic;
                SD2BN:          inout   std_logic;

                --      Analog In Out
           ANA_OUTD:    out     std_logic;
                ANA_REFD:       out     std_logic;
                ANA_IND:                in              std_logic;

                --      SPI Memory Interface
                SPI_CS_n:       inout   std_logic;
                SPI_DO:         inout   std_logic;
                SPI_DI:         inout   std_logic;
                SPI_CLK:                inout   std_logic;
                SPI_WP_n:       inout   std_logic
        );
end entity gtime;


architecture gtime_a of gtime is

function to_bcd ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector is
variable i : integer:=0;
variable mybcd : std_logic_vector(11 downto 0) := (others => '0');
variable bint : std_logic_vector(7 downto 0) := bin;
begin
        for i in 0 to 7 loop  -- repeating 8 times.
                mybcd(11 downto 1) := mybcd(10 downto 0);  --shifting the bits.
                mybcd(0) := bint(7);
                bint(7 downto 1) := bint(6 downto 0);
                bint(0) :='0';


                if(i < 7 and mybcd(3 downto 0) > "0100") then --add 3 if BCD digit is greater than 4.
                mybcd(3 downto 0) := std_logic_vector(unsigned(mybcd(3 downto 0)) + 3);
                end if;

                if(i < 7 and mybcd(7 downto 4) > "0100") then --add 3 if BCD digit is greater than 4.
                mybcd(7 downto 4) := std_logic_vector(unsigned(mybcd(7 downto 4)) + 3);
                end if;

                if(i < 7 and mybcd(11 downto 8) > "0100") then  --add 3 if BCD digit is greater than 4.
                mybcd(11 downto 8) := std_logic_vector(unsigned(mybcd(11 downto 8)) + 3);
                end if;
        end loop;
        
        return mybcd;
end to_bcd;


        -- LED Demo Signals
        --      ----------------

        signal Counter:         unsigned(31 downto 0)   := X"00000000"; --      Main Counter (binary)
        signal Bar:                             unsigned(7 downto 0)            :=      X"00";                  --      Counter for Bar output (binary)

        signal FastBlink:               std_logic;                                                                                      --      Signal mask for half intensity LED output (several kHz)

        --      LED Display
        --      -----------

        signal Number:                  std_logic_vector(32 downto 0);                          --      LED Display Input
        signal MuxCounter:      unsigned(31 downto 0)   :=      (others => '0'); --      LED Multiplex - Multiplex Clock Divider
        signal Enable:                  std_logic;
        signal Digits:                  std_logic_vector(7 downto 0)    :=      X"01";  --      LED Multiplex - Digit Counter - LED Digit Output
        signal Segments:                std_logic_vector(0 to 7);                                               --      LED Segment Output
        signal Code:                    std_logic_vector(3 downto 0);                                   --      BCD to 7 Segment Decoder Output

        
        signal LO_CLOCK:        std_logic;

        signal Decko:   std_logic;
        signal Disp:    std_logic := '0';
        
begin

        --      Basic LED Blinking Test
        --      =======================

        -- LED Bar Counter
        process (LO_CLOCK)
        begin
                if rising_edge(LO_CLOCK) then
                        if Counter < MAXCOUNT-1 then
                                Counter <= Counter + 1;
                        else
                                Counter <= (others => '0');
                                Bar <= Bar + 1;
                        end if;
                end if;
        end process;

        process (LO_CLOCK)
        begin
                if rising_edge(LO_CLOCK) then
                        Decko <= DIPSW(0);
                end if;
        end process;
                        

        process (LO_CLOCK)
        begin
                if rising_edge(LO_CLOCK) then
                        if Decko = '1'  then
                                if Disp = '0' then
                                        Number(3  downto 0)  <= std_logic_vector(Bar(3 downto 0));
                                        Number(7  downto 4)  <= std_logic_vector(Bar(7 downto 4));
                                        Number(15 downto 8)  <= (others=>'0'); 
                                        Number(19 downto 16) <= (others=>'0');
                                        Number(31 downto 20) <= (others=>'0'); --to_bcd(std_logic_vector(T1));
                                        Disp <= '1';
                                end if;
                        else
                                Disp <= '0';
                        end if;
                end if;
        end process;
                        
   LED <= std_logic_vector(Bar); --     LED Bar Connected to Counter

--      FastBlink <= Counter(13) and Counter(14) and Counter(15) and Counter(16);       --      1/16 intensity

        --      LED Display (multiplexed)
        --      =========================

        --      Connect LED Display Output Ports (negative outputs)
        LD_A_n  <=      not (Segments(0) and Enable);
        LD_B_n  <=      not (Segments(1) and Enable);
        LD_C_n  <=      not (Segments(2) and Enable);
        LD_D_n  <=      not (Segments(3) and Enable);
        LD_E_n  <=      not (Segments(4) and Enable);
        LD_F_n  <=      not (Segments(5) and Enable);
        LD_G_n  <=      not (Segments(6) and Enable);
        LD_DP_n <=      not (Segments(7) and Enable);

        LD_0_n  <=      not Digits(0);
        LD_1_n  <=      not Digits(1);
        LD_2_n  <=      not Digits(2);
        LD_3_n  <=      not Digits(3);
        LD_4_n  <=      not Digits(4);
        LD_5_n  <=      not Digits(5);
        LD_6_n  <=      not Digits(6);
        LD_7_n  <=      not Digits(7);

        --      Time Multiplex
        process (CLK100MHz)
        begin
                if rising_edge(CLK100MHz) then
                        if MuxCounter < MUXCOUNT-1 then
                                MuxCounter <= MuxCounter + 1;
                        else
                                MuxCounter <= (others => '0');
                                Digits(7 downto 0) <= Digits(6 downto 0) & Digits(7);   --      Rotate Left
                                Enable <= '0';
                        end if;
                        if MuxCounter > (MUXCOUNT-4) then
                                Enable <= '1';
                        end if;
                end if;
        end process;

        --      HEX to 7 Segmet Decoder
        --       --     A
        --      |  |  F   B
        --       --     G
        --      |  |  E   C
        --       --     D   H
        --              ABCDEFGH
        Segments                <=      "11111100"      when    Code="0000"     else    --      Digit 0
                                                "01100000"      when    Code="0001"     else    --      Digit 1
                                                "11011010"      when    Code="0010"     else    --      Digit 2
                                                "11110010"      when    Code="0011"     else    --      Digit 3
                                                "01100110"      when    Code="0100"     else    --      Digit 4
                                                "10110110"      when    Code="0101"     else    --      Digit 5
                                                "10111110"      when    Code="0110"     else    --      Digit 6
                                                "11100000"      when    Code="0111"     else    --      Digit 7
                                                "11111110"      when    Code="1000"     else    --      Digit 8
                                                "11110110"      when    Code="1001"     else    --      Digit 9
                                                "11101110"      when    Code="1010"     else    --      Digit A
                                                "00111110"      when    Code="1011"     else    --      Digit b
                                                "10011100"      when    Code="1100"     else    --      Digit C
                                                "01111010"      when    Code="1101"     else    --      Digit d
                                                "10011110"      when    Code="1110"     else    --      Digit E
                                                "10001110"      when    Code="1111"     else    --      Digit F
                                                "00000000";

        Code                    <=      Number( 3 downto  0)    when    Digits="00000001"       else
                                                Number( 7 downto  4)    when    Digits="00000010"       else
                                                Number(11 downto  8)    when    Digits="00000100"       else
                                                Number(15 downto 12)    when    Digits="00001000"       else
                                                Number(19 downto 16)    when    Digits="00010000"       else
                                                Number(23 downto 20)    when    Digits="00100000"       else
                                                Number(27 downto 24)    when    Digits="01000000"       else
                                                Number(31 downto 28)    when    Digits="10000000"       else
                                                "0000";


        --      Display on 7seg.
--      Number(3  downto 0)  <= (others=>'0');
--      Number(15 downto 4)  <= (others=>'1'); --to_bcd(std_logic_vector(T2));
--      Number(19 downto 16) <= (others=>'0');
--      Number(31 downto 20) <= (others=>'1'); --to_bcd(std_logic_vector(T1));
        

        -- Diferencial In/Outs
        -- ========================
   DIFbuffer1 : IBUFGDS
   generic map (
      DIFF_TERM => TRUE, -- Differential Termination 
      IBUF_DELAY_VALUE => "0", -- Specify the amount of added input delay for buffer, 
                               -- "0"-"16" 
      IOSTANDARD => "DEFAULT")
   port map (
      I => SD1AP,  -- Diff_p buffer input (connect directly to top-level port)
      IB => SD1AN, -- Diff_n buffer input (connect directly to top-level port)
      O => LO_CLOCK  -- Buffer output
   );

        
        --      Output Signal on SATA Connector
--      SD1AP                   <=      'Z';
--      SD1AN                   <=      'Z';
        SD1BP                   <=      'Z';
        SD1BN                   <=      'Z';

        --      Input Here via SATA Cable
        SD2AP                   <=      'Z';
        SD2AN                   <=      'Z';
        SD2BP                   <=      'Z';
        SD2BN                   <=      'Z';


        --      Unused Signals
        --      ==============

        --      I2C Signals (on connector J30)
        I2C_SCL         <=      'Z';
        I2C_SDA         <=      'Z';

        --      SPI Memory Interface
        SPI_CS_n                <=      'Z';
        SPI_DO          <=      'Z';
        SPI_DI          <=      'Z';
        SPI_CLK         <=      'Z';
        SPI_WP_n                <=      'Z';

   ANA_OUTD     <= 'Z';
        ANA_REFD <= 'Z';

        VGA_R   <= "ZZ";
        VGA_G   <= "ZZ";
        VGA_B   <= "ZZ";
        VGA_VS  <= 'Z';
        VGA_HS  <= 'Z';

end architecture gtime_a;