-------------------------------------------------------------------------------
-- Title      : WR Node Core Example Design (SPEC)
-- Project    : WR Node Core
-------------------------------------------------------------------------------
-- File       : spec_masterfip_mt.vhd
-- Author     : Tomasz Włostowski
-- Company    : CERN BE-CO-HT
-- Created    : 2014-04-01
-- Last update: 2015-08-14
-- Platform   : FPGA-generic
-- Standard   : VHDL'93
-------------------------------------------------------------------------------
-- Description: 
--
-- A simple WR Node core design for experimenting or using as a template for
-- your projects. Use in conjunction with the WR Node "Hello, world" example
-- from the WR Node Core Software project (ohwr.org/projects/wr-node-core-sw).
--
-- This design contains:
-- - WR Node with 2 CPU Cores (each with 32 kB of RAM)
-- - 2 GPIO controllers connected to the Dedicated Peripheral ports of each of
--   the CPU cores. The GPIO outputs are connected together.
-- - The GPIO controls the 4 LEDs on the SPEC front panel
-------------------------------------------------------------------------------
--
-- Copyright (c) 2014-2015 CERN
--
-- This source file is free software; you can redistribute it   
-- and/or modify it under the terms of the GNU Lesser General   
-- Public License as published by the Free Software Foundation; 
-- either version 2.1 of the License, or (at your option) any   
-- later version.                                               
--
-- This source is distributed in the hope that it will be       
-- useful, but WITHOUT ANY WARRANTY; without even the implied   
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      
-- PURPOSE.  See the GNU Lesser General Public License for more 
-- details.                                                     
--
-- You should have received a copy of the GNU Lesser General    
-- Public License along with this source; if not, download it   
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.all;

library work;
use work.wishbone_pkg.all;
use work.spec_node_pkg.all;
use work.wrn_mqueue_pkg.all;
use work.wr_node_pkg.all;
use work.masterFIP_pkg.all;
use work.gencores_pkg.all;

library unisim;
use unisim.vcomponents.all;

entity spec_masterfip_mt is
  generic (g_simulation : boolean := false);

  port
    (-- Clocks
     clk_20m_vcxo_i      : in    std_logic;                    -- 20MHz VCXO
     clk_125m_pllref_p_i : in    std_logic;                    -- 125 MHz PLL reference 
     clk_125m_pllref_n_i : in    std_logic;
     clk_125m_gtp_n_i    : in    std_logic;                    -- 125 MHz GTP reference
     clk_125m_gtp_p_i    : in    std_logic;
     
     -- GENNUM interface
     L_RST_N             : in    std_logic;                    -- local bus reset
     gpio                : inout std_logic_vector(1 downto 0); -- general purpose interface
     p2l_rdy             : out   std_logic;                    -- pcie to local [inbound data] - rx
     p2l_clkn            : in    std_logic;
     p2l_clkp            : in    std_logic;
     p2l_data            : in    std_logic_vector(15 downto 0);
     p2l_dframe          : in    std_logic;
     p2l_valid           : in    std_logic;
     p_wr_req            : in    std_logic_vector(1 downto 0); -- inbound buffer request/status
     p_wr_rdy            : out   std_logic_vector(1 downto 0);
     rx_error            : out   std_logic;
     l2p_data            : out   std_logic_vector(15 downto 0);-- local to parallel [outbound data] - tx
     l2p_dframe          : out   std_logic;
     l2p_valid           : out   std_logic;
     l2p_clkn            : out   std_logic;
     l2p_clkp            : out   std_logic;
     l2p_edb             : out   std_logic;
     l2p_rdy             : in    std_logic;                    -- outbound buffer status
     l_wr_rdy            : in    std_logic_vector(1 downto 0);
     p_rd_d_rdy          : in    std_logic_vector(1 downto 0);
     tx_error            : in    std_logic;
     vc_rdy              : in    std_logic_vector(1 downto 0);

     -- SPEC LEDs 
     led_red             : out   std_logic;
     led_green           : out   std_logic;

     -- SPEC EEPROM 
     fmc_scl_b           : inout std_logic;
     fmc_sda_b           : inout std_logic;
     
     -- SPEC 1-wire 
     carrier_onewire_b   : inout std_logic;
     fmc_prsnt_m2c_l_i   : in    std_logic;
    
     -- WorldFIP bus speed
     speed_b0_i          : in    std_logic;
     speed_b1_i          : in    std_logic;
    
     -- WorldFIP bus termination
     bus_term_en_n_o     : out   std_logic;     -- 150 Ohms termination of the bus -- check again
     
     -- WorldFIP external synchronisation pulse transceiver 
     ext_sync_term_en_o  : out   std_logic;     -- enable 50 Ohms termination of the pulse
     ext_sync_dir_o      : out   std_logic;     -- transceiver direction 
     ext_sync_oe_o       : out   std_logic;     -- transceiver output enable
     ext_sync_tst_n_o    : out   std_logic;     -- emulation of the LEMO input
     ext_sync_i          : in    std_logic;     -- sync pulse
     
     -- WorldFIP FielDrive
     fd_rxcdn_i          : in    std_logic;
     fd_rxd_i            : in    std_logic;
     fd_txer_i           : in    std_logic;
     fd_wdgn_i           : in    std_logic;
     fd_rstn_o           : out   std_logic;
     fd_txck_o           : out   std_logic;
     fd_txd_o            : out   std_logic;
     fd_txena_o          : out   std_logic;
     
     -- WorldFIP diagnostics ADC power supplies
     adc_1v8_shdn_n_o    : out   std_logic;
     adc_m5v_shdn_n_o    : out   std_logic;
     adc_5v_en_n_o       : out   std_logic;
     adc_prim_conn_n_o   : out   std_logic;
     adc_sec_conn_n_o    : out   std_logic;     

     -- WorldFIP LEDs
     led_tx_err_n_o      : out   std_logic;
     led_tx_act_n_o      : out   std_logic;
     led_rx_err_n_o      : out   std_logic;
     led_rx_act_n_o      : out   std_logic;
     led_out_of_sync_n_o : out   std_logic;
     led_sync_n_o        : out   std_logic);
end spec_masterfip_mt;

architecture rtl of spec_masterfip_mt is

  -- TODO: check comments on the WRNC..
  
  -- Host Message Queue configuration
  -- Each CPU has three queues assigned:
  -- 1) a small incoming queue (8 entries x 32 words) for sending host to CPU commands
  -- 2) a large outgoing queue (128 entries x 16 words) for optional event
  -- logging (asynchronous)
  -- 3) a small outgoing queue (8 entries x 128 words) for receiving command replies
  --    (CPU to host)
  
constant c_hmq_config : t_wrn_mqueue_config :=
    (
      out_slot_count  => 4,
      out_slot_config => (
        0             => (width => 128, entries => 4),  -- control CPU 0 (to host)
        1             => (width => 128, entries => 4),  -- control CPU 1 (to host)
        2             => (width => 128, entries => 4),  -- log CPU 0
        3             => (width => 128, entries => 4),  -- log CPU 1
        others        => (0, 0)),

      in_slot_count  => 2,
      in_slot_config => (
        0            => (width => 128, entries => 4),  -- control CPU 0 (from host)
        1            => (width => 128, entries => 4),  -- control CPU 1 (from host)
        others       => (0, 0)
        )
      );

  -- Remote Message Queue, for playing with White Rabbit/Etherbone
  -- 1) outgoing path (CPU -> WR Network): 16 entries x 128 words
  -- 2) incoming path (WR Network -> CPU): 16 entries x 128 words.
  -- Use at your convenience.
  
  constant c_rmq_config : t_wrn_mqueue_config :=
    (
      out_slot_count  => 1,
      out_slot_config => (
        0             => (width => 128, entries => 4),  -- TDC remote out
        others        => (0, 0)),

      in_slot_count  => 1,
      in_slot_config => (
        0            => (width => 128, entries => 4),  -- FD remote in

        others => (0, 0)
        )
      );

  constant c_node_config : t_wr_node_config :=
    (
      app_id          => x"0f1dc03e",
      cpu_count       => 2,
      cpu_memsizes    => (65536, 65536, 0, 0, 0, 0, 0, 0),
      hmq_config      => c_hmq_config,
      rmq_config      => c_rmq_config,
      shared_mem_size => 65536
      );

  signal clk_sys   : std_logic;
  signal rst_n_sys : std_logic;

  signal fmc_dp_wb_out : t_wishbone_master_out;
  signal fmc_dp_wb_in  : t_wishbone_master_in;

  signal cpu0_gpio_oen : std_logic_vector(31 downto 0);
  signal cpu0_gpio_out : std_logic_vector(31 downto 0);
  signal cpu0_gpio_in  : std_logic_vector(31 downto 0);

  -- keep VHDL happy... :-(
  signal dummy  : std_logic_vector(31 downto 0);
  signal dummy2 : std_logic_vector(31 downto 0);

  signal rx_err, rx_act, fd_txena : std_logic;
  signal aux                      : std_logic_vector(7 downto 0);
  
    -- LEDs
  signal led_clk_40m_divider      : unsigned(22 downto 0);
  signal led_clk_40m_aux          : std_logic_vector(7 downto 0);
  
begin

  U_Node_Template : spec_node_template
    generic map (
      g_simulation               => g_simulation,
      g_with_wr_phy              => false,
      g_with_white_rabbit        => false,
      g_double_wrnode_core_clock => false,
      g_system_clock_freq        => 100000000,  -------***-------
      g_wr_node_config           => c_node_config)
    port map (
      rst_n_sys_o => rst_n_sys,
      clk_sys_o   => clk_sys,

      clk_20m_vcxo_i      => clk_20m_vcxo_i,
      clk_125m_pllref_p_i => clk_125m_pllref_p_i,
      clk_125m_pllref_n_i => clk_125m_pllref_n_i,
      clk_125m_gtp_n_i    => clk_125m_gtp_n_i,
      clk_125m_gtp_p_i    => clk_125m_gtp_p_i,

      l_rst_n    => l_rst_n,
      gpio       => gpio,
      p2l_rdy    => p2l_rdy,
      p2l_clkn   => p2l_clkn,
      p2l_clkp   => p2l_clkp,
      p2l_data   => p2l_data,
      p2l_dframe => p2l_dframe,
      p2l_valid  => p2l_valid,
      p_wr_req   => p_wr_req,
      p_wr_rdy   => p_wr_rdy,
      rx_error   => rx_error,
      l2p_data   => l2p_data,
      l2p_dframe => l2p_dframe,
      l2p_valid  => l2p_valid,
      l2p_clkn   => l2p_clkn,
      l2p_clkp   => l2p_clkp,
      l2p_edb    => l2p_edb,
      l2p_rdy    => l2p_rdy,
      l_wr_rdy   => l_wr_rdy,
      p_rd_d_rdy => p_rd_d_rdy,
      tx_error   => tx_error,
      vc_rdy     => vc_rdy,
      led_red    => led_red,
      led_green  => led_green,

      sfp_mod_def0_b => dummy2(0),      -- sigh

      fmc_scl_b => fmc_scl_b,
      fmc_sda_b => fmc_sda_b,

      carrier_onewire_b => carrier_onewire_b,
      fmc_prsnt_m2c_l_i => fmc_prsnt_m2c_l_i,

      fmc0_dp_wb_o => fmc_dp_wb_out,
      fmc0_dp_wb_i => fmc_dp_wb_in,

      fmc0_clk_aux_i  => '0',
      fmc0_host_irq_i => '0'
      );

  cmp_masterFIP_core : fmc_masterFIP_core
    generic map
    (g_span             => 32,
     g_width            => 32,
     values_for_simul   => g_simulation)
    port map
    (clk_i              => clk_sys,
     rst_i              => not(rst_n_sys),
     fd_rxcdn_i         => fd_rxcdn_i,
     fd_rxd_i           => fd_rxd_i,
     fd_txer_i          => fd_txer_i,
     fd_wdgn_i          => fd_wdgn_i,
     fd_rstn_o          => fd_rstn_o,
     fd_txck_o          => fd_txck_o,
     fd_txd_o           => fd_txd_o,
     fd_txena_o         => fd_txena,
     speed_b0_i         => speed_b0_i,
     speed_b1_i         => speed_b1_i,
     bus_term_en_n_o    => bus_term_en_n_o,
     ext_sync_term_en_o => ext_sync_term_en_o,
     ext_sync_dir_o     => ext_sync_dir_o,
     ext_sync_oe_o      => ext_sync_oe_o,
     ext_sync_tst_n_o   => ext_sync_tst_n_o,  
     ext_sync_i         => ext_sync_i,    
     adc_1v8_shdn_n_o   => adc_1v8_shdn_n_o, 
     adc_m5v_shdn_n_o   => adc_m5v_shdn_n_o,
     adc_5v_en_n_o      => adc_5v_en_n_o,
     adc_prim_conn_n_o  => adc_prim_conn_n_o,
     adc_sec_conn_n_o   => adc_sec_conn_n_o,
     -- WISHBONE interface with
     wb_adr_i           => fmc_dp_wb_out.adr,
     wb_dat_i           => fmc_dp_wb_out.dat,
     wb_stb_i           => fmc_dp_wb_out.stb,
     wb_we_i            => fmc_dp_wb_out.we,
     wb_cyc_i           => fmc_dp_wb_out.cyc,
     wb_sel_i           => fmc_dp_wb_out.sel,
     wb_dat_o           => fmc_dp_wb_in.dat,
     wb_ack_o           => fmc_dp_wb_in.ack,
     wb_stall_o         => fmc_dp_wb_in.stall,
     -- Aux
     aux_o              => aux);


  fmc_dp_wb_in.err <= '0';
  fmc_dp_wb_in.rty <= '0';
  fmc_dp_wb_in.int <= '0';
    
  fd_txena_o <= fd_txena;

  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  
  -- LEDs front panel
  --led_tx_err_n_o <= fd_txer_i;
  -- led_tx_act_n_o <= fd_txena;
  -- led_rx_err_n_o <= rx_err;
  -- led_rx_act_n_o <= rx_act;

  cmp_rx_err_extend_p : gc_extend_pulse
    generic map (
      g_width => 50000)
    port map (
      clk_i      => clk_sys,
      rst_n_i    => rst_n_sys,
      pulse_i    => aux(2),
      extended_o => rx_err);

  cmp_rx_act_extend_p : gc_extend_pulse
    generic map (
      g_width => 50000)
    port map (
      clk_i      => clk_sys,
      rst_n_i    => rst_n_sys,
      pulse_i    => aux(1),
      extended_o => rx_act);
      
   clk_40m_sys_drive_led: process (clk_sys)
   begin
     if rising_edge(clk_sys) then

       if(rst_n_sys = '0') then
         led_clk_40m_aux     <= "01111111";
         led_clk_40m_divider <= (others => '0');
       else
         led_clk_40m_divider <= led_clk_40m_divider+ 1;
         if(led_clk_40m_divider = 0) then
           led_clk_40m_aux   <= led_clk_40m_aux(6 downto 0) & led_clk_40m_aux(7);
         end if;
       end if;
     end if;
   end process;
  -- --  --  --  --  --
  -- led_tx_err_n_o <= led_clk_40m_aux(0);

  led_tx_act_n_o      <= aux(0); -- R5
  led_tx_err_n_o      <= aux(1); -- R8
  led_rx_act_n_o      <= aux(2); -- R6
  led_rx_err_n_o      <= aux(3); -- R9
  led_out_of_sync_n_o <= aux(4); -- R7
  led_sync_n_o        <= aux(5); -- R2
      
      

end rtl;



