Commit dcfde77a authored by gilsoriano's avatar gilsoriano

Clean up.

parent 3f7fd876
files = ["wr_fabric_pkg.vhd", "xwb_fabric_sink.vhd", "xwb_fabric_source.vhd"]
\ No newline at end of file
library ieee;
use ieee.std_logic_1164.all;
package wr_fabric_pkg is
constant c_WRF_DATA : std_logic_vector(1 downto 0) := "00";
constant c_WRF_OOB : std_logic_vector(1 downto 0) := "01";
constant c_WRF_STATUS : std_logic_vector(1 downto 0) := "10";
constant c_WRF_USER : std_logic_vector(1 downto 0) := "11";
constant c_WRF_OOB_TYPE_RX : std_logic_vector(3 downto 0) := "0000";
constant c_WRF_OOB_TYPE_TX : std_logic_vector(3 downto 0) := "0001";
type t_wrf_status_reg is record
is_hp : std_logic;
has_smac : std_logic;
has_crc : std_logic;
error : std_logic;
tag_me : std_logic;
match_class : std_logic_vector(7 downto 0);
end record;
type t_wrf_source_out is record
adr : std_logic_vector(1 downto 0);
dat : std_logic_vector(15 downto 0);
cyc : std_logic;
stb : std_logic;
we : std_logic;
sel : std_logic_vector(1 downto 0);
end record;
type t_wrf_source_in is record
ack : std_logic;
stall : std_logic;
err : std_logic;
rty : std_logic;
end record;
type t_wrf_oob is record
valid: std_logic;
oob_type : std_logic_vector(3 downto 0);
ts_r : std_logic_vector(27 downto 0);
ts_f : std_logic_vector(3 downto 0);
frame_id : std_logic_vector(15 downto 0);
port_id : std_logic_vector(5 downto 0);
end record;
subtype t_wrf_sink_in is t_wrf_source_out;
subtype t_wrf_sink_out is t_wrf_source_in;
type t_wrf_source_in_array is array (natural range <>) of t_wrf_source_in;
type t_wrf_source_out_array is array (natural range <>) of t_wrf_source_out;
subtype t_wrf_sink_in_array is t_wrf_source_out_array;
subtype t_wrf_sink_out_array is t_wrf_source_in_array;
function f_marshall_wrf_status (stat : t_wrf_status_reg) return std_logic_vector;
function f_unmarshall_wrf_status(stat : std_logic_vector) return t_wrf_status_reg;
constant c_dummy_src_in : t_wrf_source_in :=
('0', '0', '0', '0');
constant c_dummy_snk_in : t_wrf_sink_in :=
("XX", "XXXXXXXXXXXXXXXX", '0', '0', '0', "XX");
end wr_fabric_pkg;
package body wr_fabric_pkg is
function f_marshall_wrf_status(stat : t_wrf_status_reg)
return std_logic_vector is
variable tmp : std_logic_vector(15 downto 0);
begin
tmp(0) := stat.is_hp;
tmp(1) := stat.error;
tmp(2) := stat.has_smac;
tmp(3) := stat.has_crc;
tmp(15 downto 8) := stat.match_class;
return tmp;
end function;
function f_unmarshall_wrf_status(stat : std_logic_vector) return t_wrf_status_reg is
variable tmp : t_wrf_status_reg;
begin
tmp.is_hp := stat(0);
tmp.error := stat(1);
tmp.has_smac := stat(2);
tmp.has_crc := stat(3);
tmp.match_class := stat(15 downto 8);
return tmp;
end function;
end wr_fabric_pkg;
-------------------------------------------------------------------------------
-- Title : Wishbone Packet Fabric buffered packet sink
-- Project : WR Cores Collection
-------------------------------------------------------------------------------
-- File : xwb_fabric_sink.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-CO-HT
-- Created : 2012-01-16
-- Last update: 2012-01-22
-- Platform :
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: A simple WB packet streaming sink with builtin FIFO buffer.
-- Outputs a trivial interface (start-of-packet, end-of-packet, data-valid)
-------------------------------------------------------------------------------
--
-- Copyright (c) 2011 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
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-01-16 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.genram_pkg.all;
use work.wr_fabric_pkg.all;
entity xwb_fabric_sink is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Wishbone Fabric Interface I/O
snk_i : in t_wrf_sink_in;
snk_o : out t_wrf_sink_out;
-- Decoded & buffered fabric
addr_o : out std_logic_vector(1 downto 0);
data_o : out std_logic_vector(15 downto 0);
dvalid_o : out std_logic;
sof_o : out std_logic;
eof_o : out std_logic;
error_o : out std_logic;
bytesel_o : out std_logic;
dreq_i : in std_logic
);
end xwb_fabric_sink;
architecture rtl of xwb_fabric_sink is
constant c_fifo_width : integer := 16 + 2 + 4;
signal q_valid, full, we, rd : std_logic;
signal fin, fout, fout_reg : std_logic_vector(c_fifo_width-1 downto 0);
signal cyc_d0, rd_d0 : std_logic;
signal pre_sof, pre_eof, pre_bytesel, pre_dvalid : std_logic;
signal post_sof, post_dvalid : std_logic;
signal post_addr : std_logic_vector(1 downto 0);
signal post_data : std_logic_vector(15 downto 0);
signal snk_out : t_wrf_sink_out;
begin -- rtl
p_delay_cyc_and_rd : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
cyc_d0 <= '0';
rd_d0 <= '0';
else
if(full = '0') then
cyc_d0 <= snk_i.cyc;
end if;
rd_d0 <= rd;
end if;
end if;
end process;
pre_sof <= snk_i.cyc and not cyc_d0; -- sof
pre_eof <= not snk_i.cyc and cyc_d0; -- eof
pre_bytesel <= not snk_i.sel(0); -- bytesel
pre_dvalid <= snk_i.stb and snk_i.we and snk_i.cyc and not snk_out.stall; -- data valid
fin(15 downto 0) <= snk_i.dat;
fin(17 downto 16) <= snk_i.adr;
fin(21 downto 18) <= pre_sof & pre_eof & pre_bytesel & pre_dvalid;
snk_out.stall <= full or (snk_i.cyc and not cyc_d0);
snk_out.err <= '0';
snk_out.rty <= '0';
p_gen_ack : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
snk_out.ack <= '0';
else
snk_out.ack <= snk_i.cyc and snk_i.stb and snk_i.we and not snk_out.stall;
end if;
end if;
end process;
snk_o <= snk_out;
we <= '1' when fin(21 downto 18) /= "0000" and full = '0' else '0';
rd <= q_valid and dreq_i and not post_sof;
U_FIFO : generic_shiftreg_fifo
generic map (
g_data_width => c_fifo_width,
g_size => 16)
port map (
rst_n_i => rst_n_i,
clk_i => clk_i,
d_i => fin,
we_i => we,
q_o => fout,
rd_i => rd,
almost_full_o => full,
q_valid_o => q_valid);
p_fout_reg : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
fout_reg <= (others => '0');
elsif(rd = '1') then
fout_reg <= fout;
end if;
end if;
end process;
post_data <= fout_reg(15 downto 0);
post_addr <= fout_reg(17 downto 16);
post_sof <= fout_reg(21) and rd_d0; --and q_valid;
post_dvalid <= fout_reg(18);
sof_o <= post_sof and rd_d0;
dvalid_o <= post_dvalid and rd_d0;
error_o <= '1' when rd_d0 = '1' and (post_addr = c_WRF_STATUS) and (f_unmarshall_wrf_status(post_data).error = '1') else '0';
eof_o <= fout_reg(20) and rd_d0;
bytesel_o <= fout_reg(19);
data_o <= post_data;
addr_o <= post_addr;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use work.genram_pkg.all;
use work.wr_fabric_pkg.all;
entity wb_fabric_sink is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
snk_dat_i : in std_logic_vector(15 downto 0);
snk_adr_i : in std_logic_vector(1 downto 0);
snk_sel_i : in std_logic_vector(1 downto 0);
snk_cyc_i : in std_logic;
snk_stb_i : in std_logic;
snk_we_i : in std_logic;
snk_stall_o : out std_logic;
snk_ack_o : out std_logic;
snk_err_o : out std_logic;
snk_rty_o : out std_logic;
-- Decoded & buffered fabric
addr_o : out std_logic_vector(1 downto 0);
data_o : out std_logic_vector(15 downto 0);
dvalid_o : out std_logic;
sof_o : out std_logic;
eof_o : out std_logic;
error_o : out std_logic;
bytesel_o : out std_logic;
dreq_i : in std_logic
);
end wb_fabric_sink;
architecture wrapper of wb_fabric_sink is
component xwb_fabric_sink
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
snk_i : in t_wrf_sink_in;
snk_o : out t_wrf_sink_out;
addr_o : out std_logic_vector(1 downto 0);
data_o : out std_logic_vector(15 downto 0);
dvalid_o : out std_logic;
sof_o : out std_logic;
eof_o : out std_logic;
error_o : out std_logic;
bytesel_o : out std_logic;
dreq_i : in std_logic);
end component;
signal snk_in : t_wrf_sink_in;
signal snk_out : t_wrf_sink_out;
begin -- wrapper
U_Wrapped_Sink : xwb_fabric_sink
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
snk_i => snk_in,
snk_o => snk_out,
addr_o => addr_o,
data_o => data_o,
dvalid_o => dvalid_o,
sof_o => sof_o,
eof_o => eof_o,
error_o => error_o,
bytesel_o => bytesel_o,
dreq_i => dreq_i);
snk_in.adr <= snk_adr_i;
snk_in.dat <= snk_dat_i;
snk_in.stb <= snk_stb_i;
snk_in.we <= snk_we_i;
snk_in.cyc <= snk_cyc_i;
snk_in.sel <= snk_sel_i;
snk_stall_o <= snk_out.stall;
snk_ack_o <= snk_out.ack;
snk_err_o <= snk_out.err;
snk_rty_o <= snk_out.rty;
end wrapper;
library ieee;
use ieee.std_logic_1164.all;
use work.genram_pkg.all;
use work.wr_fabric_pkg.all;
entity xwb_fabric_source is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Wishbone Fabric Interface I/O
src_i : in t_wrf_source_in;
src_o : out t_wrf_source_out;
-- Decoded & buffered fabric
addr_i : in std_logic_vector(1 downto 0);
data_i : in std_logic_vector(15 downto 0);
dvalid_i : in std_logic;
sof_i : in std_logic;
eof_i : in std_logic;
error_i : in std_logic;
bytesel_i : in std_logic;
dreq_o : out std_logic
);
end xwb_fabric_source;
architecture rtl of xwb_fabric_source is
constant c_fifo_width : integer := 16 + 2 + 4;
signal q_valid, full, we, rd, rd_d0 : std_logic;
signal fin, fout : std_logic_vector(c_fifo_width-1 downto 0);
signal pre_dvalid : std_logic;
signal pre_eof : std_logic;
signal pre_data : std_logic_vector(15 downto 0);
signal pre_addr : std_logic_vector(1 downto 0);
signal post_dvalid, post_eof, post_bytesel, post_sof : std_logic;
signal err_status : t_wrf_status_reg;
signal cyc_int : std_logic;
begin -- rtl
err_status.error <= '1';
dreq_o <= not full;
rd <= not src_i.stall;
we <= sof_i or eof_i or error_i or dvalid_i;
pre_dvalid <= dvalid_i or error_i;
pre_data <= data_i when (error_i = '0') else f_marshall_wrf_status(err_status);
pre_addr <= addr_i when (error_i = '0') else c_WRF_STATUS;
pre_eof <= error_i or eof_i;
fin <= sof_i & pre_eof & bytesel_i & pre_dvalid & pre_addr & pre_data;
U_FIFO : generic_shiftreg_fifo
generic map (
g_data_width => c_fifo_width,
g_size => 16)
port map (
rst_n_i => rst_n_i,
clk_i => clk_i,
d_i => fin,
we_i => we,
q_o => fout,
rd_i => rd,
almost_full_o => full,
q_valid_o => q_valid);
post_sof <= fout(21);
post_eof <= fout(20);
post_dvalid <= fout(18);
p_gen_cyc : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
cyc_int <= '0';
else
if(src_i.stall = '0' and q_valid = '1') then
if(post_sof = '1')then
cyc_int <= '1';
elsif(post_eof = '1') then
cyc_int <= '0';
end if;
end if;
end if;
end if;
end process;
src_o.cyc <= cyc_int or post_sof;
src_o.we <= '1';
src_o.stb <= post_dvalid and q_valid;
src_o.sel <= '1' & not fout(19);
src_o.dat <= fout(15 downto 0);
src_o.adr <= fout(17 downto 16);
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use work.wr_fabric_pkg.all;
entity wb_fabric_source is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Wishbone Fabric Interface I/O
src_dat_o : out std_logic_vector(15 downto 0);
src_adr_o : out std_logic_vector(1 downto 0);
src_sel_o : out std_logic_vector(1 downto 0);
src_cyc_o : out std_logic;
src_stb_o : out std_logic;
src_we_o : out std_logic;
src_stall_i : in std_logic;
src_ack_i : in std_logic;
src_err_i : in std_logic;
-- Decoded & buffered fabric
addr_i : in std_logic_vector(1 downto 0);
data_i : in std_logic_vector(15 downto 0);
dvalid_i : in std_logic;
sof_i : in std_logic;
eof_i : in std_logic;
error_i : in std_logic;
bytesel_i : in std_logic;
dreq_o : out std_logic
);
end wb_fabric_source;
architecture wrapper of wb_fabric_source is
component xwb_fabric_source
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
src_i : in t_wrf_source_in;
src_o : out t_wrf_source_out;
addr_i : in std_logic_vector(1 downto 0);
data_i : in std_logic_vector(15 downto 0);
dvalid_i : in std_logic;
sof_i : in std_logic;
eof_i : in std_logic;
error_i : in std_logic;
bytesel_i : in std_logic;
dreq_o : out std_logic);
end component;
signal src_in : t_wrf_source_in;
signal src_out : t_wrf_source_out;
begin -- wrapper
U_Wrapped_Source : xwb_fabric_source
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
src_i => src_in,
src_o => src_out,
addr_i => addr_i,
data_i => data_i,
dvalid_i => dvalid_i,
sof_i => sof_i,
eof_i => eof_i,
error_i => error_i,
bytesel_i => bytesel_i,
dreq_o => dreq_o);
src_cyc_o <= src_out.cyc;
src_stb_o <= src_out.stb;
src_we_o <= src_out.we;
src_sel_o <= src_out.sel;
src_adr_o <= src_out.adr;
src_dat_o <= src_out.dat;
src_in.rty <= '0';
src_in.err <= src_err_i;
src_in.ack <= src_ack_i;
src_in.stall <= src_stall_i;
end wrapper;
files = ["mini_bone.vhd", "xmini_bone.vhd"];
library ieee;
use ieee.std_logic_1164.all;
use work.Wishbone_pkg.all;
use work.wr_fabric_pkg.all;
entity mini_bone is
generic(
g_class_mask : std_logic_vector(7 downto 0) := x"ff";
g_our_ethertype : std_logic_vector(15 downto 0) := x"a0a0");
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
snk_cyc_i : in std_logic;
snk_stb_i : in std_logic;
snk_sel_i : in std_logic_vector(1 downto 0);
snk_adr_i : in std_logic_vector(1 downto 0);
snk_dat_i : in std_logic_vector(15 downto 0);
snk_we_i : in std_logic;
snk_stall_o : out std_logic;
snk_ack_o : out std_logic;
snk_err_o : out std_logic;
src_cyc_o : out std_logic;
src_stb_o : out std_logic;
src_dat_o : out std_logic_vector(15 downto 0);
src_adr_o : out std_logic_vector(1 downto 0);
src_we_o : out std_logic;
src_ack_i : in std_logic;
src_err_i : in std_logic;
src_sel_o : out std_logic_vector(1 downto 0);
src_stall_i : in std_logic;
master_cyc_o : out std_logic;
master_we_o : out std_logic;
master_stb_o : out std_logic;
master_sel_o : out std_logic_vector(3 downto 0);
master_adr_o : out std_logic_vector(31 downto 0);
master_dat_o : out std_logic_vector(31 downto 0);
master_dat_i : in std_logic_vector(31 downto 0);
master_ack_i : in std_logic
);
end mini_bone;
architecture wrapper of mini_bone is
component xmini_bone
generic (
g_class_mask : std_logic_vector(7 downto 0);
g_our_ethertype : std_logic_vector(15 downto 0));
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
src_o : out t_wrf_source_out;
src_i : in t_wrf_source_in;
snk_o : out t_wrf_sink_out;
snk_i : in t_wrf_sink_in;
master_o : out t_wishbone_master_out;
master_i : in t_wishbone_master_in);
end component;
signal src_out : t_wrf_source_out;
signal src_in : t_wrf_source_in;
signal snk_out : t_wrf_sink_out;
signal snk_in : t_wrf_sink_in;
signal master_out : t_wishbone_master_out;
signal master_in : t_wishbone_master_in;
begin -- wrapper
U_Wrapped_MB : xmini_bone
generic map (
g_class_mask => g_class_mask,
g_our_ethertype => g_our_ethertype)
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
src_o => src_out,
src_i => src_in,
snk_o => snk_out,
snk_i => snk_in,
master_o => master_out,
master_i => master_in);
src_cyc_o <= src_out.cyc;
src_stb_o <= src_out.stb;
src_we_o <= src_out.we;
src_adr_o <= src_out.adr;
src_dat_o <= src_out.dat;
src_sel_o <= src_out.sel;
src_in.ack <= src_ack_i;
src_in.stall <= src_stall_i;
snk_in.cyc <= snk_cyc_i;
snk_in.stb <= snk_stb_i;
snk_in.we <= snk_we_i;
snk_in.sel <= snk_sel_i;
snk_in.adr <= snk_adr_i;
snk_in.dat <= snk_dat_i;
snk_ack_o <= snk_out.ack;
snk_stall_o <= snk_out.stall;
master_cyc_o <= master_out.cyc;
master_stb_o <= master_out.stb;
master_we_o <= master_out.we;
master_sel_o <= master_out.sel;
master_adr_o <= master_out.adr;
master_dat_o <= master_out.dat;
master_in.dat <= master_dat_i;
master_in.ack <= master_ack_i;
end wrapper;
This diff is collapsed.
files = ["dmtd_phase_meas.vhd",
"dmtd_with_deglitcher.vhd",
"multi_dmtd_with_deglitcher.vhd",
"hpll_period_detect.vhd",
"pulse_gen.vhd",
"pulse_stamper.vhd" ]
This diff is collapsed.
-------------------------------------------------------------------------------
-- Title : Digital DMTD Edge Tagger
-- Project : White Rabbit
-------------------------------------------------------------------------------
-- File : dmtd_with_deglitcher.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-02-25
-- Last update: 2012-04-30
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Description: Single-channel DDMTD phase tagger with integrated bit-median
-- deglitcher. Contains a DDMTD detector, which output signal is deglitched and
-- tagged with a counter running in DMTD offset clock domain. Phase tags are
-- generated for each rising edge in DDMTD output with an internal counter
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 - 2011 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
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2009-01-24 1.0 twlostow Created
-- 2011-18-04 1.1 twlostow Bit-median type deglitcher, comments
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.NUMERIC_STD.all;
library work;
use work.gencores_pkg.all;
entity dmtd_with_deglitcher is
generic (
-- Size of the phase tag counter. Must be big enough to cover at least one
-- full period of the DDMTD detector output. Given the frequencies of clk_in_i
-- and clk_dmtd_i are respectively f_in an f_dmtd, it can be calculated with
-- the following formula:
-- g_counter_bits = log2(f_in / abs(f_in - f_dmtd)) + 1
g_counter_bits : natural := 17;
g_chipscope : boolean := false;
-- Divides the inputs by 2 (effectively passing the clock through a flip flop)
-- before it gets to the DMTD, effectively removing Place&Route warnings
-- (at the cost of detector bandwidth)
g_divide_input_by_2 : boolean := false
);
port (
-- resets for different clock domains
rst_n_dmtdclk_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-- input clock
clk_in_i : in std_logic;
-- DMTD sampling clock
clk_dmtd_i : in std_logic;
-- system clock
clk_sys_i : in std_logic;
-- [clk_dmtd_i] phase shifter enable, HI level shifts the internal counter
-- forward/backward by 1 clk_dmtd_i cycle, effectively shifting the tag
-- value by +-1.
shift_en_i : in std_logic;
-- [clk_dmtd_i] phase shift direction: 1 - forward, 0 - backward
shift_dir_i : in std_logic;
-- DMTD clock enable, active high. Can be used to reduce the DMTD sampling
-- frequency - for example, two 10 MHz signals cannot be sampled directly
-- with a 125 MHz clock, but it's possible with a 5 MHz reference, obtained
-- by asserting clk_dmtd_en_i every 25 clk_dmtd_i cycles.
clk_dmtd_en_i : in std_logic := '1';
-- [clk_dmtd_i] deglitcher threshold
deglitch_threshold_i : in std_logic_vector(15 downto 0);
-- [clk_dmtd_i] raw DDMTD output (for debugging purposes)
dbg_dmtdout_o : out std_logic;
-- [clk_sys_i] deglitched edge tag value
tag_o : out std_logic_vector(g_counter_bits-1 downto 0);
-- [clk_sys_i] pulse indicates new phase tag on tag_o
tag_stb_p1_o : out std_logic
);
end dmtd_with_deglitcher;
architecture rtl of dmtd_with_deglitcher is
type t_state is (WAIT_STABLE_0, WAIT_EDGE, GOT_EDGE);
signal state : t_state;
signal stab_cntr : unsigned(15 downto 0);
signal free_cntr : unsigned(g_counter_bits-1 downto 0);
signal in_d0, in_d1 : std_logic;
signal s_one : std_logic;
--attribute keep : string;
--attribute keep of clk_i_d0: signal is “true”;
--attribute keep of clk_i_d1: signal is “true”;
--attribute keep of clk_i_d2: signal is “true”;
--attribute keep of clk_i_d3: signal is “true”;
signal clk_i_d0, clk_i_d1, clk_i_d2, clk_i_d3 : std_logic;
signal new_edge_sreg : std_logic_vector(5 downto 0);
signal new_edge_p : std_logic;
signal tag_int : unsigned(g_counter_bits-1 downto 0);
signal clk_in : std_logic;
begin -- rtl
gen_input_div2: if(g_divide_input_by_2 = true) generate
p_divide_input_clock: process(clk_in_i, rst_n_sysclk_i)
begin
if rst_n_sysclk_i = '0' then
clk_in <= '0';
elsif rising_edge(clk_in_i) then
clk_in <= not clk_in;
end if;
end process;
end generate gen_input_div2;
gen_input_straight: if(g_divide_input_by_2 = false) generate
clk_in <= clk_in_i;
end generate gen_input_straight;
p_the_dmtd_itself : process(clk_dmtd_i)
begin
if rising_edge(clk_dmtd_i) then
clk_i_d0 <= clk_in;
clk_i_d1 <= clk_i_d0;
clk_i_d2 <= clk_i_d1;
clk_i_d3 <= clk_i_d2;
end if;
end process;
-- glitchproof DMTD output edge detection
p_deglitch : process (clk_dmtd_i)
begin -- process deglitch
if rising_edge(clk_dmtd_i) then -- rising clock edge
if (rst_n_dmtdclk_i = '0') then -- synchronous reset (active low)
stab_cntr <= (others => '0');
state <= WAIT_STABLE_0;
free_cntr <= (others => '0');
new_edge_sreg <= (others => '0');
elsif(clk_dmtd_en_i = '1') then
if (shift_en_i = '0') then -- phase shifter
free_cntr <= free_cntr + 1;
elsif (shift_dir_i = '1') then
free_cntr <= free_cntr + 2;
end if;
case state is
when WAIT_STABLE_0 => -- out-of-sync
new_edge_sreg <= '0' & new_edge_sreg(new_edge_sreg'length-1 downto 1);
if clk_i_d3 /= '0' then
stab_cntr <= (others => '0');
else
stab_cntr <= stab_cntr + 1;
end if;
-- DMTD output stable counter hit the LOW level threshold?
if stab_cntr = unsigned(deglitch_threshold_i) then
state <= WAIT_EDGE;
end if;
when WAIT_EDGE =>
if (clk_i_d3 /= '0') then -- got a glitch?
state <= GOT_EDGE;
tag_int <= free_cntr;
stab_cntr <= (others => '0');
end if;
when GOT_EDGE =>
if (clk_i_d3 = '0') then
tag_int <= tag_int + 1;
end if;
if stab_cntr = unsigned(deglitch_threshold_i) then
state <= WAIT_STABLE_0;
tag_o <= std_logic_vector(tag_int);
new_edge_sreg <= (others => '1');
stab_cntr <= (others => '0');
elsif (clk_i_d3 = '0') then
stab_cntr <= (others => '0');
else
stab_cntr <= stab_cntr + 1;
end if;
end case;
end if;
end if;
end process p_deglitch;
U_sync_tag_strobe : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
data_i => new_edge_sreg(0),
synced_o => open,
npulse_o => open,
ppulse_o => new_edge_p);
tag_stb_p1_o <= new_edge_p;
gc_extend_pulse_1 : gc_extend_pulse
generic map (
g_width => 3000)
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
pulse_i => new_edge_p,
extended_o => dbg_dmtdout_o);
end rtl;
-------------------------------------------------------------------------------
-- Title : DMTD Helper PLL (HPLL) - linear frequency/period detector.
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : hpll_period_detect.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2011-10-29
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Simple linear frequency detector with programmable error
-- setpoint and gating period. The measured clocks are: clk_ref_i and clk_fbck_i.
-- The error value is outputted every 2^(hpll_fbcr_fd_gate_i + 14) cycles on a
-- freq_err_o. A pulse is produced on freq_err_stb_p_o every time freq_err_o
-- is updated with a new value. freq_err_o value is:
-- - positive when clk_fbck_i is slower than selected frequency setpoint
-- - negative when clk_fbck_i is faster than selected frequency setpoint
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tomasz Wlostowski
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-06-14 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity hpll_period_detect is
generic(
g_freq_err_frac_bits: integer);
port (
-------------------------------------------------------------------------------
-- Clocks & resets
-------------------------------------------------------------------------------
-- reference clocks
clk_ref_i : in std_logic;
-- fed-back (VCO) clock
clk_fbck_i : in std_logic;
-- system clock (wishbone and I/O)
clk_sys_i : in std_logic;
-- reset signals (the same reset synced to different clocks)
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-------------------------------------------------------------------------------
-- Outputs
-------------------------------------------------------------------------------
-- frequency error value (signed)
freq_err_o : out std_logic_vector(11 downto 0);
-- frequency error valid pulse
freq_err_stb_p_o : out std_logic;
-------------------------------------------------------------------------------
-- Wishbone regs
-------------------------------------------------------------------------------
-- gating period:
hpll_fbcr_fd_gate_i : in std_logic_vector(2 downto 0);
-- frequency error setpoint:
hpll_fbcr_ferr_set_i : in std_logic_vector(11 downto 0)
);
end hpll_period_detect;
architecture rtl of hpll_period_detect is
-- derived from the maximum gating period (2 ^ 21 + 1 "safety" bit)
constant c_COUNTER_BITS : integer := 22;
-- number of fractional bits in the frequency error output
-- constant c_FREQ_ERR_FRAC_BITS : integer := 7;
-- frequency counters: feedback clock & gating counter
signal counter_fb : unsigned(c_COUNTER_BITS-1 downto 0);
signal counter_gate : unsigned(c_COUNTER_BITS-1 downto 0);
-- clock domain synchronization stuff...
signal gate_sreg : std_logic_vector(3 downto 0);
signal pstb_sreg : std_logic_vector(3 downto 0);
signal gate_p, period_p : std_logic;
signal gate_cntr_bitsel : std_logic;
signal desired_freq : unsigned(c_COUNTER_BITS-1 downto 0);
signal cur_freq : unsigned(c_COUNTER_BITS-1 downto 0);
signal delta_f: signed(11 downto 0);
begin -- rtl
-- decoding FD gating field from FBCR register:
decode_fd_gating : process(hpll_fbcr_fd_gate_i, counter_gate)
begin
case hpll_fbcr_fd_gate_i is
when "000" => gate_cntr_bitsel <= std_logic(counter_gate(14)); -- div: 16384
desired_freq <= to_unsigned(16384, desired_freq'length);
when "001" => gate_cntr_bitsel <= std_logic(counter_gate(15)); -- ....
desired_freq <= to_unsigned(32768, desired_freq'length);
when "010" => gate_cntr_bitsel <= std_logic(counter_gate(16));
desired_freq <= to_unsigned(65536, desired_freq'length);
when "011" => gate_cntr_bitsel <= std_logic(counter_gate(17));
desired_freq <= to_unsigned(131072, desired_freq'length);
when "100" => gate_cntr_bitsel <= std_logic(counter_gate(18));
desired_freq <= to_unsigned(262144, desired_freq'length);
when "101" => gate_cntr_bitsel <= std_logic(counter_gate(19));
desired_freq <= to_unsigned(524288, desired_freq'length);
when "110" => gate_cntr_bitsel <= std_logic(counter_gate(20)); -- ....
desired_freq <= to_unsigned(1048576, desired_freq'length);
when "111" => gate_cntr_bitsel <= std_logic(counter_gate(21)); -- div: 2097152
desired_freq <= to_unsigned(2097152, desired_freq'length);
when others => null;
end case;
end process;
-------------------------------------------------------------------------------
-- Gating counter: produces a gating pulse on gate_p (clk_fbck_i domain) with
-- period configured by FD_GATE field in FBCR register
-------------------------------------------------------------------------------
gating_counter : process(clk_ref_i, rst_n_refclk_i)
begin
if rising_edge(clk_ref_i) then
if(rst_n_refclk_i = '0') then
counter_gate <= to_unsigned(1, counter_gate'length);
gate_sreg <= (others => '0');
else
if(gate_cntr_bitsel = '1') then
-- counter bit selected by hpll_fbcr_fd_gate_i changed from 0 to 1?
-- reset the counter and generate the gating signal for feedback counter
counter_gate <= to_unsigned(1, counter_gate'length);
gate_sreg <= (others => '1');
else
-- advance the counter and generate a longer pulse on gating signal
-- using a shift register so the sync chain will always work regardless of
-- the clock frequency.
counter_gate <= counter_gate + 1;
gate_sreg <= '0' & gate_sreg(gate_sreg'length-1 downto 1);
end if;
end if;
end if;
end process;
-- sync logic for the gate_p pulse (from clk_ref_i to clk_fbck_i)
sync_gating_pulse : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_fbck_i,
rst_n_i => rst_n_fbck_i,
data_i => gate_sreg(0),
synced_o => open,
npulse_o => open,
ppulse_o => gate_p);
-------------------------------------------------------------------------------
-- Main period/frequency measurement process: Takes a snapshot of the counter_fb
-- every time there's a pulse on gate_p. The capture of new frequency value
-- is indicated by pulsing period_p.
-------------------------------------------------------------------------------
period_detect : process(clk_fbck_i, rst_n_fbck_i)
begin
if rising_edge(clk_fbck_i) then
if rst_n_fbck_i = '0' then
counter_fb <= to_unsigned(1, counter_fb'length);
cur_freq <= (others => '0');
pstb_sreg <= (others => '0');
else
if(gate_p = '1') then
counter_fb <= to_unsigned(1, counter_fb'length);
cur_freq <= counter_fb;
pstb_sreg <= (others => '1');
else
counter_fb <= counter_fb + 1;
pstb_sreg <= '0' & pstb_sreg(pstb_sreg'length-1 downto 1);
end if;
end if;
end if;
end process;
-- synchronization logic for period_p (from clk_fbck_i to clk_sys_i)
sync_period_pulse : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
data_i => pstb_sreg(0),
synced_o => open,
npulse_o => open,
ppulse_o => period_p);
-- calculate the frequency difference, padded by some fractional bits
delta_f <= resize(signed(desired_freq) - signed(cur_freq), delta_f'length-g_freq_err_frac_bits) & to_signed(0, g_freq_err_frac_bits);
-------------------------------------------------------------------------------
-- Calculates the phase error by taking the difference between reference and
-- measured frequency and subtracting the error setpoint from FERR_SET field
-- in FBCR register.
-------------------------------------------------------------------------------
freq_err_output : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_sysclk_i = '0' then
freq_err_stb_p_o <= '0';
freq_err_o <= (others => '0');
else
if(period_p = '1') then
freq_err_o <= std_logic_vector(resize(delta_f - signed (hpll_fbcr_ferr_set_i), freq_err_o'length));
end if;
freq_err_stb_p_o <= period_p;
end if;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.NUMERIC_STD.all;
library work;
use work.gencores_pkg.all;
entity multi_dmtd_with_deglitcher is
generic (
g_counter_bits : natural := 17;
g_log2_replication : natural := 2
);
port (
rst_n_dmtdclk_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-- DMTD sampling clock
clk_dmtd_i : in std_logic;
-- system clock
clk_sys_i : in std_logic;
-- input clock
clk_in_i : in std_logic;
-- edge tag (clk_sys_i domain)
tag_o : out std_logic_vector(g_counter_bits-1 downto 0);
tag_stb_p_o : out std_logic;
-- phase shifter enable, HI level shifts the tag forward/backward by
-- 1 clk_dmtd_i with respect to the expected tag value.
shift_en_i : in std_logic;
-- phase shift direction: 1 - forward, 0 - backward
shift_dir_i : in std_logic;
-- deglitcher parameters (clk_dmtd_i domain)
deglitch_threshold_i: in std_logic_vector(15 downto 0);
dbg_dmtdout_o : out std_logic
);
end multi_dmtd_with_deglitcher;
architecture rtl of multi_dmtd_with_deglitcher is
constant c_num_dmtds : natural := 2**g_log2_replication;
function f_count_zeroes (x : std_logic_vector) return unsigned is
variable i : integer;
variable cnt : unsigned(g_log2_replication downto 0);
begin
cnt := (others => '0');
for i in 0 to x'left loop
if(x(i) = '0') then
cnt := cnt + 1;
end if;
end loop; -- i
return cnt;
end function f_count_zeroes;
type t_state is (WAIT_STABLE_0, WAIT_EDGE, GOT_EDGE, ROUND_TAG);
signal state : t_state;
signal stab_cntr : unsigned(deglitch_threshold_i'left downto 0);
signal free_cntr : unsigned(g_counter_bits-1 downto 0);
signal new_edge_sreg : std_logic_vector(3 downto 0);
signal new_edge_p : std_logic;
signal tag_int : unsigned(g_counter_bits + g_log2_replication -1 downto 0);
signal clk_i_d0, clk_i_d1, clk_i_d2 : std_logic_vector(c_num_dmtds-1 downto 0);
signal dmtd_in : std_logic_vector(c_num_dmtds-1 downto 0);
signal n_zeroes : unsigned(g_log2_replication downto 0);
signal in_is_0, in_is_1 : std_logic;
signal ones : std_logic_vector(31 downto 0) := x"ffffffff";
signal zeroes : std_logic_vector(31 downto 0) := x"00000000";
begin -- rtl
gen_dmtds : for i in 0 to c_num_dmtds-1 generate
the_dmtd_itself : process(clk_dmtd_i)
begin
if rising_edge(clk_dmtd_i) then
clk_i_d0(i) <= clk_in_i;
clk_i_d1(i) <= clk_i_d0(i);
clk_i_d2(i) <= clk_i_d1(i);
dmtd_in(i) <= clk_i_d2(i);
end if;
end process;
end generate gen_dmtds;
dmtd_postprocess : process(clk_dmtd_i)
begin
if rising_edge(clk_dmtd_i) then
if(dmtd_in = ones(dmtd_in'left downto 0)) then
in_is_1 <= '1';
else
in_is_1 <= '0';
end if;
if(dmtd_in = zeroes(dmtd_in'left downto 0)) then
in_is_0 <= '1';
else
in_is_0 <= '0';
end if;
n_zeroes <= f_count_zeroes(dmtd_in);
dbg_dmtdout_o <= n_zeroes(0);
end if;
end process;
deglitch : process (clk_dmtd_i) -- glitchproof DMTD output edge
-- detection
begin -- process deglitch
if rising_edge(clk_dmtd_i) then -- rising clock edge
if rst_n_dmtdclk_i = '0' then -- asynchronous reset (active low)
stab_cntr <= (others => '0');
free_cntr <= (others => '0');
state <= WAIT_STABLE_0;
new_edge_sreg <= (others => '0');
else
if(shift_en_i = '0') then
free_cntr <= free_cntr + 1;
elsif(shift_dir_i = '1') then
free_cntr <= free_cntr + 2;
end if;
case state is
when WAIT_STABLE_0 => -- out-of-sync
new_edge_sreg <= '0' & new_edge_sreg(new_edge_sreg'left downto 1);
if (in_is_0 = '0') then
stab_cntr <= (others => '0');
else
stab_cntr <= stab_cntr + 1;
end if;
-- DMTD output stable counter hit the LOW level threshold?
if stab_cntr = unsigned(deglitch_threshold_i) then
state <= WAIT_EDGE;
end if;
when WAIT_EDGE =>
if (in_is_0 = '0') then -- got a glitch?
state <= GOT_EDGE;
tag_int <= free_cntr & to_unsigned(0, g_log2_replication);
end if;
when GOT_EDGE =>
tag_int <= tag_int + n_zeroes;
if (in_is_1 = '0') then
stab_cntr <= (others => '0');
else
stab_cntr <= stab_cntr + 1;
end if;
if stab_cntr = unsigned(deglitch_threshold_i) then
state <= ROUND_TAG;
end if;
when ROUND_TAG =>
if(tag_int(g_log2_replication-1) = '1') then
tag_int <= tag_int + to_unsigned(2**g_log2_replication, g_log2_replication+1);
end if;
new_edge_sreg <= (others => '1');
state <= WAIT_STABLE_0;
end case;
end if;
end if;
end process deglitch;
--n_zeroes <= f_count_zeroes(dmtd_in);
sync_reset_refclk : gc_sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
data_i => new_edge_sreg(0),
synced_o => open,
npulse_o => open,
ppulse_o => new_edge_p);
tag_stb_p_o <= new_edge_p;
tag_o <= std_logic_vector(tag_int(tag_int'left downto g_log2_replication));
end rtl;
-------------------------------------------------------------------------------
-- Entity: pulse_gen
-- File: pulse_gen.vhd
-- Description: a pulse generator which produces a 1-tick-long pulse in its
-- output when the UTC time passed to it through a vector equals a
-- pre-programmed UTC time.
-- Author: Javier Serrano (Javier.Serrano@cern.ch)
-- Date: 24 January 2012
-- Version: 0.01
-- Todo: change gen_out process for complete coincidence (see comments above
-- that process). Substitute ready_for_trig process by a state machine.
-- Factor out synchronizer in a separate reusable block.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
-- -----------------------------------
-- 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;
entity pulse_gen is
generic (
-- reference clock frequency
g_ref_clk_rate : integer := 125000000);
port (
clk_ref_i : in std_logic; -- timing reference clock
clk_sys_i : in std_logic; -- data output reference clock
rst_n_i : in std_logic; -- system reset
pulse_o : out std_logic; -- pulse output
-------------------------------------------------------------------------------
-- Timing input (from WRPC), clk_ref_i domain
------------------------------------------------------------------------------
-- 1: time given on tm_utc_i and tm_cycles_i is valid (otherwise, don't
-- produce pulses and keep trig_ready_o line permamaently active)
tm_time_valid_i : in std_logic;
-- number of seconds
tm_utc_i : in std_logic_vector(39 downto 0);
-- number of clk_ref_i cycles
tm_cycles_i : in std_logic_vector(27 downto 0);
---------------------------------------------------------------------------
-- Time tag output (clk_sys_i domain)
---------------------------------------------------------------------------
-- 1: input is ready to accept next trigger time tag
trig_ready_o : out std_logic;
-- time at which the pulse will be produced + a single-cycle strobe to
-- latch it in
trig_utc_i : in std_logic_vector(39 downto 0);
trig_cycles_i : in std_logic_vector(27 downto 0);
trig_valid_p1_i : in std_logic
);
end pulse_gen;
architecture rtl of pulse_gen is
-- Internal registers to hold trigger time
signal trig_utc, trig_utc_ref : std_logic_vector(39 downto 0);
signal trig_cycles, trig_cycles_ref : std_logic_vector(27 downto 0);
-- Signals for the synchronizer
signal trig_valid_sys_d1, trig_valid_sys_d2 : std_logic;
signal rst_from_sync, rst_from_sync_d1 : std_logic;
signal trig_valid_ref : std_logic_vector(2 downto 0);
signal trig_valid_back : std_logic_vector(2 downto 0);
signal trig_valid_ref_p1 : std_logic;
begin -- architecture rtl
-- Get trigger time into internal registers
trig_regs: process (clk_sys_i) is
begin -- process trig_regs
if clk_sys_i'event and clk_sys_i = '1' then
if rst_n_i='0' then
trig_utc <= (others=>'0');
trig_cycles <= (others=>'0');
elsif trig_valid_p1_i='1' then
trig_utc <= trig_utc_i;
trig_cycles <= trig_cycles_i;
end if;
end if;
end process trig_regs;
-- Synchronizer to pass UTC register data to the reference clock domain
-- This synchronizer is made with the following four processes
-- First one FF with async reset, still in the clk_sys_i domain
sync_first_ff: process (clk_sys_i, rst_n_i, rst_from_sync)
begin
if rst_n_i='0' or rst_from_sync='1' then
trig_valid_sys_d1 <= '0';
elsif clk_sys_i'event and clk_sys_i='1' then
if trig_valid_p1_i='1' then
trig_valid_sys_d1 <= '1';
end if;
end if;
end process sync_first_ff;
-- OK this is just for the UTC and cycle registers to have time to settle
-- in the pathological case of a very fast ref clock and very long
-- combinational delays in the UTC and cycle registers
delay_sys: process (clk_sys_i)
begin
if clk_sys_i'event and clk_sys_i='1' then
trig_valid_sys_d2 <= trig_valid_sys_d1;
end if;
end process delay_sys;
-- Then three FFs to take the strobe safely into the clk_ref_i domain
sync_ref: process (clk_ref_i)
begin
if clk_ref_i'event and clk_ref_i='1' then
trig_valid_ref <= trig_valid_ref(1 downto 0) & trig_valid_sys_d2;
trig_valid_ref_p1 <= trig_valid_ref(1) and not trig_valid_ref(2);
end if;
end process sync_ref;
-- And then back into the clk_sys_i domain
sync_sys: process (clk_sys_i)
begin
if clk_sys_i'event and clk_sys_i='1' then
trig_valid_back <= trig_valid_back(1 downto 0) & trig_valid_ref(2);
rst_from_sync <= trig_valid_back(2);
rst_from_sync_d1 <= rst_from_sync;
end if;
end process sync_sys;
-- Now get the trig registers into the clk_ref_i domain
trig_regs_ref: process (clk_ref_i)
begin
if clk_ref_i'event and clk_ref_i='1' then
if trig_valid_ref_p1='1' then
trig_utc_ref <= trig_utc;
trig_cycles_ref <= trig_cycles;
end if;
end if;
end process trig_regs_ref;
-- Notify we're ready to receive another trigger time write
-- Having the reset set trig_ready_o to '1' is a kludge.
-- A proper state machine would be better.
ready_for_trig: process (rst_n_i, clk_sys_i)
begin
if rst_n_i='0' then
trig_ready_o <= '1';
elsif clk_sys_i'event and clk_sys_i='1' then
if trig_valid_p1_i='1' then
trig_ready_o <= '0';
elsif rst_from_sync_d1='1' and rst_from_sync='0' then
-- falling edge of reset_from_sync
trig_ready_o <= '1';
end if;
end if;
end process ready_for_trig;
-- Produce output
-- Note rst_n_i is used as an async reset because it comes from the
-- clk_sys_i domain. Not the most elegant but it ensures no glitches
-- in the output after startup.
-- This block actually creates a pulse one tick after the programmed
-- time matches the current time. Changing it for complete
-- coincidence would be trivial.
gen_out: process (rst_n_i, clk_ref_i)
begin
if rst_n_i='0' then
pulse_o <= '0';
elsif clk_ref_i'event and clk_ref_i='1' then
if tm_time_valid_i ='0' then
pulse_o <= '0';
elsif tm_utc_i=trig_utc_ref and tm_cycles_i=trig_cycles_ref then
pulse_o <= '1';
else
pulse_o <= '0';
end if;
end if;
end process gen_out;
end architecture rtl;
-------------------------------------------------------------------------------
-- Entity: pulse_stamper
-- File: pulse_stamper.vhd
-- Description: a time-tagger which associates a time-tag with an asyncrhonous
-- input pulse.
-- Author: Javier Serrano (Javier.Serrano@cern.ch)
-- Date: 24 January 2012
-- Version: 0.01
-- Todo: Factor out syncrhonizer in a separate reusable block.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
-- -----------------------------------
-- 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;
entity pulse_stamper is
generic (
-- reference clock frequency
g_ref_clk_rate : integer := 125000000);
port(
clk_ref_i : in std_logic; -- timing reference clock
clk_sys_i : in std_logic; -- data output reference clock
rst_n_i : in std_logic; -- system reset
pulse_a_i : in std_logic; -- pulses to be stamped
-------------------------------------------------------------------------------
-- Timing input (from WRPC), clk_ref_i domain
------------------------------------------------------------------------------
-- 1: time given on tm_utc_i and tm_cycles_i is valid (otherwise, don't timestamp)
tm_time_valid_i : in std_logic;
-- number of seconds
tm_utc_i : in std_logic_vector(39 downto 0);
-- number of clk_ref_i cycles
tm_cycles_i : in std_logic_vector(27 downto 0);
---------------------------------------------------------------------------
-- Time tag output (clk_sys_i domain)
---------------------------------------------------------------------------
tag_utc_o : out std_logic_vector(39 downto 0);
tag_cycles_o : out std_logic_vector(27 downto 0);
-- single-cycle pulse: strobe tag on tag_utc_o and tag_cycles_o
tag_valid_p1_o : out std_logic
);
end pulse_stamper;
architecture rtl of pulse_stamper is
-- Signals for input anti-metastability ffs
signal pulse_ref : std_logic_vector(2 downto 0);
signal pulse_ref_p1 : std_logic;
signal pulse_ref_p1_d1 : std_logic;
-- Time tagger signals
signal tag_utc_ref : std_logic_vector(39 downto 0);
signal tag_cycles_ref : std_logic_vector(27 downto 0);
-- Signals for synchronizer
signal rst_from_sync : std_logic;
signal pulse_ref_d2 : std_logic;
signal pulse_sys : std_logic_vector(2 downto 0);
signal pulse_sys_p1 : std_logic;
signal pulse_back : std_logic_vector(2 downto 0);
begin -- architecture rtl
-- Synchronization of external pulse into the clk_ref_i clock domain
sync_ext_pulse: process (clk_ref_i)
begin
if clk_ref_i'event and clk_ref_i='1' then
pulse_ref <= pulse_ref(1 downto 0) & pulse_a_i;
pulse_ref_p1 <= pulse_ref(1) and not pulse_ref(2);
pulse_ref_p1_d1 <= pulse_ref_p1 and tm_time_valid_i;
end if;
end process sync_ext_pulse;
-- Time tagging of the pulse, still in the clk_ref_i domain
tagger: process (clk_ref_i)
begin
if clk_ref_i'event and clk_ref_i='1' then
if pulse_ref_p1='1' and tm_time_valid_i='1' then
tag_utc_ref <= tm_utc_i;
tag_cycles_ref <= tm_cycles_i;
end if;
end if;
end process tagger;
-- Synchronizer to pass UTC register data to the system clock domain
-- This synchronizer is made with the following three processes
-- First one FF with async reset, still in the clk_ref_i domain
sync_first_ff: process (clk_ref_i, rst_n_i, rst_from_sync)
begin
if rst_n_i='0' or rst_from_sync='1' then
pulse_ref_d2 <= '0';
elsif clk_ref_i'event and clk_ref_i='1' then
if pulse_ref_p1_d1='1' then
pulse_ref_d2 <= '1';
end if;
end if;
end process sync_first_ff;
-- Then three FFs to take the strobe safely into the clk_sys_i domain
sync_sys: process (clk_sys_i)
begin
if clk_sys_i'event and clk_sys_i='1' then
pulse_sys <= pulse_sys(1 downto 0) & pulse_ref_d2;
pulse_sys_p1 <= pulse_sys(1) and not pulse_sys(2);
end if;
end process sync_sys;
-- And then back into the clk_ref_i domain
sync_ref: process (clk_ref_i)
begin
if clk_ref_i'event and clk_ref_i='1' then
pulse_back <= pulse_back(1 downto 0) & pulse_sys(2);
rst_from_sync <= pulse_back(2);
end if;
end process sync_ref;
-- Now we can take the time tags into the clk_sys_i domain
sys_tags: process (clk_sys_i)
begin
if clk_sys_i'event and clk_sys_i='1' then
if rst_n_i='0' then
tag_utc_o <= (others=>'0');
tag_cycles_o <= (others=>'0');
tag_valid_p1_o <= '0';
elsif pulse_sys_p1='1' then
tag_utc_o <= tag_utc_ref;
tag_cycles_o <= tag_cycles_ref;
tag_valid_p1_o <= '1';
else
tag_valid_p1_o <='0';
end if;
end if;
end process sys_tags;
end architecture rtl;
files = ["xwr_eca.vhd", "xwr_eca_pkg.vhd"]
-- Register map:
-- 0x00 = FIFO control register
-- 0x04 = current toggle value (as see at output pins)
-- 0x10 = UTChi
-- 0x14 = UTClo
-- 0x18 = cycle counter
-- 0x1C = value to XOR
-- Reading from the control register reports 0 if room in FIFO
-- Writing to the control register pushes the entry to the FIFO
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.gencores_pkg.gc_wfifo;
entity xwr_eca is
generic(
logFifoLen : integer := 4);
port(
-- Common wishbone signals
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Slave control port
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
-- Current timestamp
tm_utc_i : in std_logic_vector(39 downto 0);
tm_cycle_i : in std_logic_vector(27 downto 0);
-- Current status pins
toggle_o : out t_wishbone_data);
end xwr_eca;
architecture rtl of xwr_eca is
procedure update(signal o : out t_wishbone_address) is
begin
for i in (c_wishbone_data_width/8)-1 downto 0 loop
if slave_i.SEL(i) = '1' then
o(i*8+7 downto i*8) <= slave_i.DAT(i*8+7 downto i*8);
end if;
end loop;
end update;
function idx(v : std_logic_vector) return std_logic_vector is
alias result : std_logic_vector(v'length-1 downto 0) is v;
begin
return result;
end idx;
signal r_toggle : t_wishbone_data;
signal r_utchi : t_wishbone_data;
signal r_utclo : t_wishbone_data;
signal r_cycle : t_wishbone_data;
signal r_val : t_wishbone_data;
signal r_valid : std_logic;
signal r_tm_full : std_logic_vector(67 downto 0);
signal slave_o_ACK : std_logic;
signal slave_o_DAT : t_wishbone_data;
signal w_rdy, w_en, r_rdy, r_en : std_logic;
signal w_data, r_data : std_logic_vector(c_wishbone_data_width*4-1 downto 0);
-- Front of FIFO
signal f_tm_utc : std_logic_vector(39 downto 0);
signal f_tm_cycle : std_logic_vector(27 downto 0);
signal f_val : t_wishbone_data;
signal tm_full_i : std_logic_vector(67 downto 0);
signal f_tm_full : std_logic_vector(67 downto 0);
begin
-- Hard-wired slave pins
slave_o.ACK <= slave_o_ACK;
slave_o.ERR <= '0';
slave_o.RTY <= '0';
slave_o.STALL <= '0';
slave_o.DAT <= slave_o_DAT;
-- Output pins
toggle_o <= r_toggle;
fifo : gc_wfifo
generic map(
sync_depth => 1,
gray_code => false,
addr_width => logFifoLen,
data_width => c_wishbone_data_width*4)
port map(
rst_n_i => rst_n_i,
w_clk_i => clk_i,
w_rdy_o => w_rdy,
w_en_i => w_en,
w_data_i => w_data,
a_clk_i => '0',
a_rdy_o => open,
a_en_i => '0',
r_clk_i => clk_i,
r_rdy_o => r_rdy,
r_en_i => r_en,
r_data_o => r_data);
w_data(c_wishbone_data_width*4-1 downto c_wishbone_data_width*3) <= r_utchi;
w_data(c_wishbone_data_width*3-1 downto c_wishbone_data_width*2) <= r_utclo;
w_data(c_wishbone_data_width*2-1 downto c_wishbone_data_width*1) <= r_cycle;
w_data(c_wishbone_data_width*1-1 downto c_wishbone_data_width*0) <= r_val;
f_tm_utc <= idx(r_data(c_wishbone_data_width*4-1 downto c_wishbone_data_width*3))(7 downto 0) &
idx(r_data(c_wishbone_data_width*3-1 downto c_wishbone_data_width*2))(31 downto 0);
f_tm_cycle <= idx(r_data(c_wishbone_data_width*2-1 downto c_wishbone_data_width*1))(27 downto 0);
f_val <= idx(r_data(c_wishbone_data_width*1-1 downto c_wishbone_data_width*0));
f_tm_full <= f_tm_utc & f_tm_cycle;
tm_full_i <= tm_utc_i & tm_cycle_i;
main : process(clk_i)
variable valid : std_logic;
variable toggle : t_wishbone_data;
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
r_toggle <= (others => '0');
r_utchi <= (others => '0');
r_utclo <= (others => '0');
r_cycle <= (others => '0');
r_val <= (others => '0');
r_valid <= '0';
r_tm_full <= (others => '0');
else
-- Check for record to pop
if valid = '1' and unsigned(f_tm_full) <= unsigned(r_tm_full) then
toggle := r_toggle xor f_val;
valid := '0';
else
toggle := r_toggle;
valid := r_valid;
end if;
-- Compensate the clock by two cycles to meet the deadline exactly
r_tm_full <= std_logic_vector(unsigned(tm_full_i) + to_unsigned(2, 68));
if valid = '0' and r_rdy = '1' then
r_en <= '1';
r_valid <= '1';
else
r_en <= '0';
r_valid <= valid;
end if;
-- Output requested data
case to_integer(unsigned(slave_i.ADR(4 downto 2))) is
when 0 => slave_o_DAT <= std_logic_vector(to_unsigned(0, c_wishbone_data_width-1)) & w_rdy;
when 1 => slave_o_DAT <= r_toggle;
when 4 => slave_o_DAT <= r_utchi;
when 5 => slave_o_DAT <= r_utclo;
when 6 => slave_o_DAT <= r_cycle;
when 7 => slave_o_DAT <= r_val;
when others => slave_o_DAT <= (others => '0');
end case;
-- Process input data
w_en <= '0';
if (slave_i.CYC = '1' and slave_i.STB = '1' and slave_i.WE = '1') then
case to_integer(unsigned(slave_i.ADR(4 downto 2))) is
when 0 => w_en <= '1';
when 1 => update(r_toggle);
when 4 => update(r_utchi);
when 5 => update(r_utclo);
when 6 => update(r_cycle);
when 7 => update(r_val);
when others => r_toggle <= toggle;
end case;
else
r_toggle <= toggle;
end if;
slave_o_ACK <= slave_i.CYC and slave_i.STB;
end if;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.gencores_pkg.all;
package xwr_eca_pkg is
constant c_xwr_eca_sdwb : t_sdwb_device := (
wbd_begin => x"0000000000000000",
wbd_end => x"000000000000001f",
sdwb_child => x"0000000000000000",
wbd_flags => x"01", -- big-endian, no-child, present
wbd_width => x"04", -- 32-bit port granularity
abi_ver_major => x"01",
abi_ver_minor => x"00",
abi_class => x"00000000", -- undocumented device
dev_vendor => x"00000651", -- GSI
dev_device => x"8752bf44",
dev_version => x"00000001",
dev_date => x"20120319",
description => "GSI_ECA_UNIT ");
component xwr_eca is
generic(
logFifoLen : integer := 4);
port(
-- Common wishbone signals
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Slave control port
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
-- Current timestamp
tm_utc_i : in std_logic_vector(39 downto 0);
tm_cycle_i : in std_logic_vector(27 downto 0);
-- Current status pins
toggle_o : out t_wishbone_data);
end component;
end xwr_eca_pkg;
files = [ "endpoint_private_pkg.vhd",
"ep_rx_pcs_8bit.vhd",
"ep_tx_pcs_8bit.vhd",
"ep_tx_pcs_16bit.vhd",
"ep_rx_pcs_16bit.vhd",
"ep_autonegotiation.vhd",
"ep_pcs_tbi_mdio_wb.vhd",
"ep_1000basex_pcs.vhd",
"ep_rx_crc_size_check.vhd",
"ep_rx_bypass_queue.vhd",
"ep_rx_path.vhd",
"ep_rx_wb_master.vhd",
"ep_rx_oob_insert.vhd",
"ep_rx_early_address_match.vhd",
"ep_clock_alignment_fifo.vhd",
"ep_tx_framer.vhd",
"ep_packet_filter.vhd",
"ep_rx_vlan_unit.vhd",
"ep_ts_counter.vhd",
"ep_rx_status_reg_insert.vhd",
"ep_timestamping_unit.vhd",
"ep_leds_controller.vhd",
"ep_rtu_header_extract.vhd",
# "ep_flow_control.vhd",
# "ep_rmon_counters.vhd",
"ep_rx_buffer.vhd",
"ep_sync_detect.vhd",
"ep_sync_detect_16bit.vhd",
"ep_wishbone_controller.vhd",
"ep_registers_pkg.vhd",
"endpoint_pkg.vhd",
"wr_endpoint.vhd",
"xwr_endpoint.vhd"
];
#!/bin/bash
mkdir -p doc
~/wbgen2/wishbone-gen/wbgen2 -D ./doc/wrsw_endpoint.html -C endpoint_regs.h -p ep_registers_pkg.vhd -H record -V ep_wishbone_controller.vhd --cstyle struct --lang vhdl -K ../../sim/endpoint_regs.v ep_wishbone_controller.wb
wbgen2 -D ./doc/wrsw_endpoint_mdio.html -V ep_pcs_tbi_mdio_wb.vhd --cstyle defines --lang vhdl -K ../../sim/endpoint_mdio.v pcs_regs.wb
\ No newline at end of file
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.wr_fabric_pkg.all;
package endpoint_pkg is
component wr_endpoint
generic (
g_interface_mode : t_wishbone_interface_mode := CLASSIC;
g_address_granularity : t_wishbone_address_granularity := WORD;
g_simulation : boolean := false;
g_tx_force_gap_length : integer := 0;
g_pcs_16bit : boolean := false;
g_rx_buffer_size : integer := 1024;
g_with_rx_buffer : boolean := true;
g_with_flow_control : boolean := true;
g_with_timestamper : boolean := true;
g_with_dpi_classifier : boolean := false;
g_with_vlans : boolean := false;
g_with_rtu : boolean := false;
g_with_leds : boolean := false;
g_with_dmtd : boolean := false);
port (
clk_ref_i : in std_logic;
clk_sys_i : in std_logic;
clk_dmtd_i : in std_logic := '0';
rst_n_i : in std_logic;
pps_csync_p1_i : in std_logic := '0';
pps_valid_i : in std_logic := '1';
phy_rst_o : out std_logic;
phy_loopen_o : out std_logic;
phy_enable_o : out std_logic;
phy_syncen_o : out std_logic;
phy_ref_clk_i : in std_logic := '0';
phy_tx_data_o : out std_logic_vector(15 downto 0);
phy_tx_k_o : out std_logic_vector(1 downto 0);
phy_tx_disparity_i : in std_logic := '0';
phy_tx_enc_err_i : in std_logic := '0';
phy_rx_data_i : in std_logic_vector(15 downto 0) := x"0000";
phy_rx_clk_i : in std_logic := '0';
phy_rx_k_i : in std_logic_vector(1 downto 0) := "00";
phy_rx_enc_err_i : in std_logic := '0';
phy_rx_bitslide_i : in std_logic_vector(4 downto 0) := "00000";
gmii_tx_clk_i : in std_logic := '0';
gmii_txd_o : out std_logic_vector(7 downto 0);
gmii_tx_en_o : out std_logic;
gmii_tx_er_o : out std_logic;
gmii_rx_clk_i : in std_logic := '0';
gmii_rxd_i : in std_logic_vector(7 downto 0) := x"00";
gmii_rx_er_i : in std_logic := '0';
gmii_rx_dv_i : in std_logic := '0';
src_dat_o : out std_logic_vector(15 downto 0);
src_adr_o : out std_logic_vector(1 downto 0);
src_sel_o : out std_logic_vector(1 downto 0);
src_cyc_o : out std_logic;
src_stb_o : out std_logic;
src_we_o : out std_logic;
src_stall_i : in std_logic;
src_ack_i : in std_logic;
src_err_i : in std_logic;
snk_dat_i : in std_logic_vector(15 downto 0);
snk_adr_i : in std_logic_vector(1 downto 0);
snk_sel_i : in std_logic_vector(1 downto 0);
snk_cyc_i : in std_logic;
snk_stb_i : in std_logic;
snk_we_i : in std_logic;
snk_stall_o : out std_logic;
snk_ack_o : out std_logic;
snk_err_o : out std_logic;
snk_rty_o : out std_logic;
txtsu_port_id_o : out std_logic_vector(4 downto 0);
txtsu_frame_id_o : out std_logic_vector(16 -1 downto 0);
txtsu_ts_value_o : out std_logic_vector(28 + 4 - 1 downto 0);
txtsu_ts_incorrect_o : out std_logic;
txtsu_stb_o : out std_logic;
txtsu_ack_i : in std_logic := '1';
rtu_full_i : in std_logic := '0';
rtu_almost_full_i : in std_logic := '0';
rtu_rq_strobe_p1_o : out std_logic;
rtu_rq_smac_o : out std_logic_vector(48 - 1 downto 0);
rtu_rq_dmac_o : out std_logic_vector(48 - 1 downto 0);
rtu_rq_vid_o : out std_logic_vector(12 - 1 downto 0);
rtu_rq_has_vid_o : out std_logic;
rtu_rq_prio_o : out std_logic_vector(3 - 1 downto 0);
rtu_rq_has_prio_o : out std_logic;
wb_cyc_i : in std_logic;
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_adr_i : in std_logic_vector(7 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0);
wb_ack_o : out std_logic;
wb_stall_o : out std_logic;
led_link_o : out std_logic;
led_act_o : out std_logic);
end component;
constant c_xwr_endpoint_sdwb : t_sdwb_device := (
wbd_begin => x"0000000000000000",
wbd_end => x"00000000000000ff",
sdwb_child => x"0000000000000000",
wbd_flags => x"01", -- big-endian, no-child, present
wbd_width => x"07", -- 8/16/32-bit port granularity
abi_ver_major => x"01",
abi_ver_minor => x"01",
abi_class => x"00000000", -- undocumented device
dev_vendor => x"0000CE42", -- CERN
dev_device => x"650c2d4f",
dev_version => x"00000001",
dev_date => x"20120305",
description => "WR-Endpoint ");
component xwr_endpoint
generic (
g_interface_mode : t_wishbone_interface_mode := CLASSIC;
g_address_granularity : t_wishbone_address_granularity := WORD;
g_simulation : boolean := false;
g_pcs_16bit : boolean := false;
g_tx_force_gap_length : integer := 0;
g_rx_buffer_size : integer := 1024;
g_with_rx_buffer : boolean := true;
g_with_flow_control : boolean := true;
g_with_timestamper : boolean := true;
g_with_dpi_classifier : boolean := false;
g_with_vlans : boolean := false;
g_with_rtu : boolean := false;
g_with_leds : boolean := false;
g_with_dmtd : boolean := false);
port (
clk_ref_i : in std_logic;
clk_sys_i : in std_logic;
clk_dmtd_i : in std_logic := '0';
rst_n_i : in std_logic;
pps_csync_p1_i : in std_logic := '0';
pps_valid_i : in std_logic := '1';
phy_rst_o : out std_logic;
phy_loopen_o : out std_logic;
phy_enable_o : out std_logic;
phy_syncen_o : out std_logic;
phy_ref_clk_i : in std_logic;
phy_tx_data_o : out std_logic_vector(15 downto 0);
phy_tx_k_o : out std_logic_vector(1 downto 0);
phy_tx_disparity_i : in std_logic;
phy_tx_enc_err_i : in std_logic;
phy_rx_data_i : in std_logic_vector(15 downto 0);
phy_rx_clk_i : in std_logic;
phy_rx_k_i : in std_logic_vector(1 downto 0);
phy_rx_enc_err_i : in std_logic;
phy_rx_bitslide_i : in std_logic_vector(4 downto 0);
gmii_tx_clk_i : in std_logic := '0';
gmii_txd_o : out std_logic_vector(7 downto 0);
gmii_tx_en_o : out std_logic;
gmii_tx_er_o : out std_logic;
gmii_rx_clk_i : in std_logic := '0';
gmii_rxd_i : in std_logic_vector(7 downto 0) := x"00";
gmii_rx_er_i : in std_logic := '0';
gmii_rx_dv_i : in std_logic := '0';
src_o : out t_wrf_source_out;
src_i : in t_wrf_source_in;
snk_o : out t_wrf_sink_out;
snk_i : in t_wrf_sink_in;
txtsu_port_id_o : out std_logic_vector(4 downto 0);
txtsu_frame_id_o : out std_logic_vector(16 -1 downto 0);
txtsu_ts_value_o : out std_logic_vector(28 + 4 - 1 downto 0);
txtsu_ts_incorrect_o : out std_logic;
txtsu_stb_o : out std_logic;
txtsu_ack_i : in std_logic := '1';
rtu_full_i : in std_logic := '0';
rtu_almost_full_i : in std_logic := '0';
rtu_rq_strobe_p1_o : out std_logic;
rtu_rq_smac_o : out std_logic_vector(48 - 1 downto 0);
rtu_rq_dmac_o : out std_logic_vector(48 - 1 downto 0);
rtu_rq_vid_o : out std_logic_vector(12 - 1 downto 0);
rtu_rq_has_vid_o : out std_logic;
rtu_rq_prio_o : out std_logic_vector(3 - 1 downto 0);
rtu_rq_has_prio_o : out std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
led_link_o : out std_logic;
led_act_o : out std_logic);
end component;
end endpoint_pkg;
-------------------------------------------------------------------------------
-- Title : 1000Base-X Autonegotiation
-- Project : White Rabbit MAC/Endpoint
-------------------------------------------------------------------------------
-- File : ep_autonegotiation.vhd
-- Author : Tomasz Włostowski
-- Company : CERN BE-CO-HT
-- Created : 2010-11-18
-- Last update: 2011-10-18
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Module implements the 1000Base-X autonegotiation engine as
-- defined in IEEE802.3.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 CERN / BE-CO-HT
--
-- 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.1l.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-11-18 0.4 twlostow Initial release
-- 2011-02-07 0.5 twlostow Tested on Spartan6 GTP
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.endpoint_private_pkg.all;
entity ep_autonegotiation is
generic (
g_simulation : boolean);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- RX PCS signals
pcs_synced_i : in std_logic;
pcs_los_i : in std_logic;
pcs_link_ok_o : out std_logic;
an_idle_match_i : in std_logic;
an_rx_en_o : out std_logic;
an_rx_val_i : in std_logic_vector(15 downto 0);
an_rx_valid_i : in std_logic;
-- TX PCS signals
an_tx_en_o : out std_logic;
an_tx_val_o : out std_logic_vector(15 downto 0);
mdio_mcr_anrestart_i : in std_logic;
mdio_mcr_anenable_i : in std_logic;
mdio_msr_anegcomplete_o : out std_logic;
mdio_advertise_pause_i : in std_logic_vector(1 downto 0);
mdio_advertise_rfault_i : in std_logic_vector(1 downto 0);
mdio_lpa_full_o : out std_logic;
mdio_lpa_half_o : out std_logic;
mdio_lpa_pause_o : out std_logic_vector(1 downto 0);
mdio_lpa_rfault_o : out std_logic_vector(1 downto 0);
mdio_lpa_lpack_o : out std_logic;
mdio_lpa_npage_o : out std_logic
);
end ep_autonegotiation;
architecture syn of ep_autonegotiation is
type t_autoneg_state is (AN_ENABLE, AN_RESTART, AN_ABILITY_DETECT, AN_DISABLE_LINK_OK, AN_ACKNOWLEDGE_DETECT, AN_COMPLETE_ACKNOWLEDGE, AN_IDLE_DETECT, AN_LINK_OK);
signal state : t_autoneg_state;
function f_eval_link_timer_size
return integer is
begin -- f_eval_link_timer_size
if(g_simulation = false) then
return 20;
else
return 11;
end if;
end f_eval_link_timer_size;
constant c_link_timer_bits : integer := f_eval_link_timer_size;
signal link_timer : unsigned(c_link_timer_bits downto 0); -- 23 for normal operation
signal link_timer_restart : std_logic;
signal link_timer_expired : std_logic;
signal an_enable_changed, an_enable_d0 : std_logic;
signal toggle_tx, toggle_rx : std_logic;
signal rx_config_reg : std_logic_vector(15 downto 0);
signal acknowledge_match : std_logic;
signal ability_match : std_logic;
signal consistency_match : std_logic;
begin -- syn
-- process: link timer (counts until MSB of link_timer == 1).
-- inputs: link_timer_restart
-- outputs: link_timer_expired
p_link_timer : process(clk_sys_i, rst_n_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' or link_timer_restart ='1' then
link_timer <= (others => '0');
else
if(link_timer_expired = '0') then
link_timer <= link_timer + 1;
end if;
end if;
end if;
end process;
link_timer_expired <= std_logic(link_timer(link_timer'high)) and (not link_timer_restart);
-- process: detects the changes of Autonegotiation Enable bit.
-- inputs: mdio_mcr_anenable_i
-- outputs: an_enable_changed
p_detect_enable_changed : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
an_enable_d0 <= mdio_mcr_anenable_i;
an_enable_changed <= an_enable_d0 xor mdio_mcr_anenable_i;
end if;
end process;
-- generate some FSM conditions combinatorially outside the FSM process to
-- make the code more readable
ability_match <= an_rx_valid_i;
acknowledge_match <= an_rx_valid_i and an_rx_val_i(14);
consistency_match <= '1' when (an_rx_valid_i = '1' and rx_config_reg (15) = an_rx_val_i(15) and rx_config_reg(13 downto 0) = an_rx_val_i(13 downto 0));
-- process: main auto-negotiation state machine. More or less compatible with
-- IEEE 802.3.
p_autonegotation_fsm : process(clk_sys_i, rst_n_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
link_timer_restart <= '0';
state <= AN_ENABLE;
pcs_link_ok_o <= '0';
an_tx_en_o <= '0';
an_rx_en_o <= '1';
an_tx_val_o <= (others => '0');
mdio_lpa_lpack_o <= '0';
mdio_msr_anegcomplete_o <= '0';
rx_config_reg <= (others => '0');
else
if(mdio_mcr_anrestart_i = '1' or an_enable_changed = '1' or pcs_synced_i = '0') then
state <= AN_ENABLE;
else
case state is
when AN_ENABLE =>
mdio_msr_anegcomplete_o <= '0';
if mdio_mcr_anenable_i = '1' then
an_tx_val_o <= (others => '0'); -- send breaklink
an_tx_en_o <= '1';
link_timer_restart <= '1';
state <= AN_RESTART;
else
state <= AN_DISABLE_LINK_OK;
end if;
when AN_DISABLE_LINK_OK =>
an_tx_en_o <= '0';
pcs_link_ok_o <= '1';
when AN_RESTART =>
link_timer_restart <= '0';
if(link_timer_expired = '1') then
state <= AN_ABILITY_DETECT;
end if;
when AN_ABILITY_DETECT =>
-- toggle_tx <= mr_adv_ability<12> -- ???
an_rx_en_o <= '1';
an_tx_en_o <= '1';
an_tx_val_o (15) <= '0';
an_tx_val_o (14) <= '0';
an_tx_val_o (13 downto 12) <= mdio_advertise_rfault_i;
an_tx_val_o (11 downto 9) <= (others => '0');
an_tx_val_o (8 downto 7) <= mdio_advertise_pause_i;
an_tx_val_o (6) <= '0'; -- hdx not supported
an_tx_val_o (5) <= '1'; -- fdx supported
an_tx_val_o (4 downto 0) <= (others => '0');
if(an_rx_valid_i = '1' and an_rx_val_i /= x"0000") then -- ability_match=true
state <= AN_ACKNOWLEDGE_DETECT;
rx_config_reg <= an_rx_val_i;
end if;
when AN_ACKNOWLEDGE_DETECT =>
an_tx_val_o(14) <= '1';
if(acknowledge_match = '1' and consistency_match = '0')
or (ability_match = '1' and an_rx_val_i = x"0000") then
state <= AN_ENABLE;
elsif(acknowledge_match = '1' and consistency_match = '1') then
state <= AN_COMPLETE_ACKNOWLEDGE;
link_timer_restart <= '1';
end if;
when AN_COMPLETE_ACKNOWLEDGE =>
link_timer_restart <= '0';
mdio_lpa_npage_o <= an_rx_val_i(15);
mdio_lpa_lpack_o <= an_rx_val_i(14);
mdio_lpa_rfault_o <= an_rx_val_i(13 downto 12);
mdio_lpa_pause_o <= an_rx_val_i (8 downto 7);
mdio_lpa_half_o <= an_rx_val_i(6);
mdio_lpa_full_o <= an_rx_val_i(5);
if(ability_match = '1' and an_rx_val_i = x"0000")then
state <= AN_ENABLE;
elsif(link_timer_expired = '1' and (ability_match = '0' or an_rx_val_i /= x"0000")) then
link_timer_restart <= '1';
state <= AN_IDLE_DETECT;
end if;
when AN_IDLE_DETECT =>
link_timer_restart <= '0';
an_tx_en_o <= '0';
if(ability_match = '1' and an_rx_val_i = x"0000") then
state <= AN_ENABLE;
elsif (an_idle_match_i = '1' and link_timer_expired = '1') then
state <= AN_LINK_OK;
end if;
when AN_LINK_OK =>
mdio_msr_anegcomplete_o <= '1';
pcs_link_ok_o <= '1';
if(ability_match = '1') then
state <= AN_ENABLE;
end if;
when others => null;
end case;
end if;
end if;
end if;
end process;
end syn;
-------------------------------------------------------------------------------
-- Title : RX Clock Alignment FIFO
-- Project : White Rabbit MAC/Endpoint
-------------------------------------------------------------------------------
-- File : ep_clock_alignment_fifo.vhd
-- Author : Tomasz Włostowski
-- Company : CERN BE-CO-HT
-- Created : 2010-11-18
-- Last update: 2011-10-18
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Asynchronous FIFO with internal fabric (t_ep_internal_fabric)
-- interface used to pass packet data between the RX clock->system clock
-- domains.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009-2011 CERN / BE-CO-HT
--
-- 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;
use work.genram_pkg.all;
use work.endpoint_private_pkg.all;
entity ep_clock_alignment_fifo is
generic(
g_size : integer := 64;
g_almostfull_threshold : integer := 56);
port(
rst_n_rd_i : in std_logic;
clk_wr_i : in std_logic;
clk_rd_i : in std_logic;
dreq_i : in std_logic;
fab_i : in t_ep_internal_fabric;
fab_o : out t_ep_internal_fabric;
full_o : out std_logic;
empty_o : out std_logic;
almostfull_o : out std_logic;
-- number of data words which enables the output. Used
-- to control the minimum latency
pass_threshold_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0)
);
end ep_clock_alignment_fifo;
architecture structural of ep_clock_alignment_fifo is
signal fifo_in : std_logic_vector(17 downto 0);
signal fifo_out : std_logic_vector(17 downto 0);
signal rx_rdreq : std_logic;
signal empty_int : std_logic;
signal valid_int : std_logic;
signal count : std_logic_vector(f_log2_size(g_size)-1 downto 0);
signal dreq_mask : std_logic;
type t_state is (OUTSIDE_FRAME, INSIDE_FRAME);
signal state : t_stATE;
signal fab_int : t_ep_internal_fabric;
signal fifo_we : std_logic;
signal s_dummy : std_logic;
begin
f_pack_fifo_contents (fab_i, fifo_in, fifo_we, false);
-- Clock adjustment FIFO
U_FIFO : generic_async_fifo
generic map (
g_data_width => 18,
g_size => g_size,
g_with_wr_almost_full => true,
g_almost_full_threshold => g_almostfull_threshold,
g_with_rd_count => true)
port map (
rst_n_i => rst_n_rd_i,
clk_wr_i => clk_wr_i,
d_i => fifo_in,
we_i => fifo_we,
wr_empty_o => open,
wr_full_o => full_o,
wr_almost_empty_o => open,
wr_almost_full_o => almostfull_o,
wr_count_o => open,
clk_rd_i => clk_rd_i,
q_o => fifo_out,
rd_i => rx_rdreq,
rd_empty_o => empty_int,
rd_full_o => open,
rd_almost_empty_o => open,
rd_almost_full_o => open,
rd_count_o => count);
rx_rdreq <= (not empty_int) and dreq_i and dreq_mask;
p_readout : process (clk_rd_i)
begin
if rising_edge(clk_rd_i) then
if(rst_n_rd_i = '0') then
valid_int <= '0';
state <= OUTSIDE_FRAME;
dreq_mask <= '0';
else
valid_int <= rx_rdreq;
case state is
when OUTSIDE_FRAME =>
if(unsigned(count) >= unsigned(pass_threshold_i)) then
dreq_mask <= '1';
else
dreq_mask <= '0';
end if;
if(fab_int.sof = '1') then
state <= INSIDE_FRAME;
end if;
when INSIDE_FRAME =>
dreq_mask <= '1';
if(fab_int.eof = '1' or fab_int.error = '1') then
state <= OUTSIDE_FRAME;
end if;
end case;
end if;
end if;
end process;
-- FIFO output data formatting
f_unpack_fifo_contents(fifo_out, valid_int, fab_int, false);
fab_o <= fab_int;
empty_o <= empty_int;
end structural;
-------------------------------------------------------------------------------
-- Title : Ethernet Flow Control Unit
-- Project : White Rabbit MAC/Endpoint
-------------------------------------------------------------------------------
-- File : ep_flow_control.vhd
-- Author : Tomasz Włostowski
-- Company : CERN BE-CO-HT
-- Created : 2010-11-18
-- Last update: 2011-10-18
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Module implements the flow control unit, governing the both the
-- TX and RX path of the MAC.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 - 2011 CERN / BE-CO-HT
--
-- 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
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-11-18 0.4 twlostow Initial release
-- 2011-02-07 0.5 twlostow Tested on Spartan6 GTP
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.endpoint_private_pkg.all;
entity ep_flow_control is
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- RX Pause: if 1, we have received a valid PAUSE frame. The delay is in "rx_pause_delay_i"
rx_pause_p1_i : in std_logic;
rx_pause_delay_i : in std_logic_vector(15 downto 0);
-- TX Pause: if tx_pause_o == 1, the FC unit wants the MAC to send a PAUSE frame
-- with delay tx_pause_delay_o. The transmission should be acked by asserting
-- tx_pause_delay_o.
tx_pause_o : out std_logic;
tx_pause_delay_o : out std_logic_vector(15 downto 0);
tx_pause_ack_i : in std_logic;
-- TX flow enable: if 1, the TX part of the Endpoint is allowed to send packets
tx_flow_enable_o : out std_logic;
-- Amount of data in the RX buffer (0 = empty, max = full), at which the flow control
-- is triggered
rx_buffer_used_i : in std_logic_vector(7 downto 0);
ep_fcr_txpause_i : in std_logic;
ep_fcr_rxpause_i : in std_logic;
ep_fcr_tx_thr_i : in std_logic_vector(7 downto 0);
ep_fcr_tx_quanta_i : in std_logic_vector(15 downto 0);
rmon_rcvd_pause_o: out std_logic;
rmon_sent_pause_o: out std_logic
);
end ep_flow_control;
architecture behavioral of ep_flow_control is
type t_rxpause_fsm_state is (S_CHECK_BUFFER, S_ISSUE_PAUSE, S_WAIT_COUNTER_EXPIRE);
signal div512 : unsigned(4 downto 0);
signal advance_counter : std_logic;
signal tx_pause_counter : unsigned(15 downto 0);
signal rx_pause_counter : unsigned(15 downto 0);
signal state : t_rxpause_fsm_state;
begin -- behavioral
rmon_rcvd_pause_o <= rx_pause_p1_i and ep_fcr_rxpause_i;
gen_pause_timing : process (clk_sys_i, rst_n_i)
begin -- process
if rising_edge(clk_sys_i) then
if (rst_n_i = '0') then
div512 <= (others => '0');
advance_counter <= '0';
else
div512 <= div512 + 1;
if(div512 = to_unsigned(0, div512'length)) then
advance_counter <= '1';
else
advance_counter <= '0';
end if;
end if;
end if;
end process;
rx_pause_proc : process (clk_sys_i, rst_n_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_i = '0') then
tx_pause_counter <= (others => '0');
tx_flow_enable_o <= '1';
else
if(ep_fcr_rxpause_i = '1') then
if rx_pause_p1_i = '1' then
tx_pause_counter <= unsigned(rx_pause_delay_i);
tx_flow_enable_o <= '0';
elsif (advance_counter = '1') then
if(tx_pause_counter = to_unsigned(0, tx_pause_counter'length)) then
tx_flow_enable_o <= '1';
else
tx_pause_counter <= tx_pause_counter - 1;
end if; -- if tx_pause_counter == 0
end if; -- if advance_counter = '1'
else
tx_flow_enable_o <= '1';
end if;
end if;
end if;
end process;
tx_pause_proc : process(clk_sys_i, rst_n_i)
begin
if rising_edge(clk_sys_i) then
if (rst_n_i = '0' or ep_fcr_txpause_i = '0') then
rx_pause_counter <= (others => '0');
state <= S_CHECK_BUFFER;
tx_pause_o <= '0';
rmon_sent_pause_o<= '0';
tx_pause_delay_o <= (others => '0');
else
case state is
when S_CHECK_BUFFER =>
if(unsigned(rx_buffer_used_i) >= unsigned(ep_fcr_tx_thr_i)) then
tx_pause_o <= '1';
rmon_sent_pause_o <= '1';
tx_pause_delay_o <= ep_fcr_tx_quanta_i;
state <= S_ISSUE_PAUSE;
end if;
when S_ISSUE_PAUSE =>
rmon_sent_pause_o<='0';
if(tx_pause_ack_i = '1') then
tx_pause_o <= '0';
rx_pause_counter <= unsigned(ep_fcr_tx_quanta_i);
state <= S_WAIT_COUNTER_EXPIRE;
end if;
when S_WAIT_COUNTER_EXPIRE =>
if(advance_counter = '1') then
if(rx_pause_counter = to_unsigned(0, rx_pause_counter'length)) then
state <= S_CHECK_BUFFER;
else
rx_pause_counter <= rx_pause_counter - 1;
end if;
end if;
when others => null;
end case;
end if;
end if;
end process;
end behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.endpoint_private_pkg.all;
use work.gencores_pkg.all;
entity ep_leds_controller is
generic (
g_blink_period_log2 : integer := 21);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- data valid (from PCS <> framers)
dvalid_tx_i : in std_logic;
dvalid_rx_i : in std_logic;
link_ok_i : in std_logic;
led_link_o : out std_logic;
led_act_o : out std_logic
);
end ep_leds_controller;
architecture rtl of ep_leds_controller is
type t_state is (INACTIVE, BLINKING);
signal cnt : unsigned(g_blink_period_log2-1 downto 0);
signal cnt_reset, cnt_expired : std_logic;
signal state : t_state;
signal led_act : std_logic;
signal last_cycle_act : std_logic;
signal txrx, txrx_synced : std_logic;
begin -- rtl
led_link_o <= link_ok_i;
txrx <= dvalid_rx_i or dvalid_tx_i;
U_Sync_Activity : gc_sync_ffs
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_i,
data_i => txrx,
synced_o => txrx_synced);
p_counter : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_i = '0' or cnt_reset = '1')then
cnt <= (others => '0');
else
cnt <= cnt + 1;
if((not cnt) = 0) then
cnt_expired <= '1';
else
cnt_expired <= '0';
end if;
end if;
end if;
end process;
p_gen_act_led : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
state <= INACTIVE;
led_act <= '0';
cnt_reset <= '0';
else
case state is
when INACTIVE =>
if(txrx_synced = '1') then
state <= BLINKING;
led_act <= '1';
cnt_reset <= '1';
end if;
when BLINKING =>
cnt_reset <= '0';
if(cnt_expired = '1') then
led_act <= not led_act;
if(last_cycle_act = '0') then
led_act <= '0';
state <= INACTIVE;
end if;
last_cycle_act <= '0';
else
if(txrx_synced = '1') then
last_cycle_act <= '1';
end if;
end if;
end case;
end if;
end if;
end process;
led_act_o <= led_act;
end rtl;
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for WR switch endpoint controller
---------------------------------------------------------------------------------------
-- File : ep_registers_pkg.vhd
-- Author : auto-generated by wbgen2 from ep_wishbone_controller.wb
-- Created : Sun Oct 30 00:20:59 2011
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE ep_wishbone_controller.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wbgen2_pkg.all;
package ep_wbgen2_pkg is
-- Input registers (user design -> WB slave)
type t_ep_in_registers is record
ecr_feat_vlan_i : std_logic;
ecr_feat_dmtd_i : std_logic;
ecr_feat_ptp_i : std_logic;
ecr_feat_dpi_i : std_logic;
tscr_cs_done_i : std_logic;
mdio_asr_rdata_i : std_logic_vector(15 downto 0);
mdio_asr_ready_i : std_logic;
dsr_lstatus_i : std_logic;
dsr_lact_i : std_logic;
dmsr_ps_val_i : std_logic_vector(23 downto 0);
dmsr_ps_rdy_i : std_logic;
end record;
constant c_ep_in_registers_init_value: t_ep_in_registers := (
ecr_feat_vlan_i => '0',
ecr_feat_dmtd_i => '0',
ecr_feat_ptp_i => '0',
ecr_feat_dpi_i => '0',
tscr_cs_done_i => '0',
mdio_asr_rdata_i => (others => '0'),
mdio_asr_ready_i => '0',
dsr_lstatus_i => '0',
dsr_lact_i => '0',
dmsr_ps_val_i => (others => '0'),
dmsr_ps_rdy_i => '0'
);
-- Output registers (WB slave -> user design)
type t_ep_out_registers is record
ecr_portid_o : std_logic_vector(4 downto 0);
ecr_rst_cnt_o : std_logic;
ecr_tx_en_o : std_logic;
ecr_rx_en_o : std_logic;
tscr_en_txts_o : std_logic;
tscr_en_rxts_o : std_logic;
tscr_cs_start_o : std_logic;
rfcr_a_runt_o : std_logic;
rfcr_a_giant_o : std_logic;
rfcr_a_hp_o : std_logic;
rfcr_keep_crc_o : std_logic;
rfcr_hpap_o : std_logic_vector(7 downto 0);
rfcr_mru_o : std_logic_vector(13 downto 0);
vcr0_qmode_o : std_logic_vector(1 downto 0);
vcr0_fix_prio_o : std_logic;
vcr0_prio_val_o : std_logic_vector(2 downto 0);
vcr0_pvid_o : std_logic_vector(11 downto 0);
vcr1_vid_o : std_logic_vector(11 downto 0);
vcr1_vid_wr_o : std_logic;
vcr1_value_o : std_logic;
vcr1_value_wr_o : std_logic;
pfcr0_mm_addr_o : std_logic_vector(5 downto 0);
pfcr0_mm_addr_wr_o : std_logic;
pfcr0_mm_write_o : std_logic;
pfcr0_mm_write_wr_o : std_logic;
pfcr0_enable_o : std_logic;
pfcr0_mm_data_msb_o : std_logic_vector(23 downto 0);
pfcr0_mm_data_msb_wr_o : std_logic;
pfcr1_mm_data_lsb_o : std_logic_vector(11 downto 0);
tcar_pcp_map_o : std_logic_vector(23 downto 0);
fcr_rxpause_o : std_logic;
fcr_txpause_o : std_logic;
fcr_tx_thr_o : std_logic_vector(7 downto 0);
fcr_tx_quanta_o : std_logic_vector(15 downto 0);
mach_o : std_logic_vector(15 downto 0);
macl_o : std_logic_vector(31 downto 0);
mdio_cr_data_o : std_logic_vector(15 downto 0);
mdio_cr_data_wr_o : std_logic;
mdio_cr_addr_o : std_logic_vector(7 downto 0);
mdio_cr_rw_o : std_logic;
mdio_asr_phyad_o : std_logic_vector(7 downto 0);
dsr_lact_o : std_logic;
dsr_lact_load_o : std_logic;
dmcr_en_o : std_logic;
dmcr_n_avg_o : std_logic_vector(11 downto 0);
dmsr_ps_rdy_o : std_logic;
dmsr_ps_rdy_load_o : std_logic;
end record;
constant c_ep_out_registers_init_value: t_ep_out_registers := (
ecr_portid_o => (others => '0'),
ecr_rst_cnt_o => '0',
ecr_tx_en_o => '0',
ecr_rx_en_o => '0',
tscr_en_txts_o => '0',
tscr_en_rxts_o => '0',
tscr_cs_start_o => '0',
rfcr_a_runt_o => '0',
rfcr_a_giant_o => '0',
rfcr_a_hp_o => '0',
rfcr_keep_crc_o => '0',
rfcr_hpap_o => (others => '0'),
rfcr_mru_o => (others => '0'),
vcr0_qmode_o => (others => '0'),
vcr0_fix_prio_o => '0',
vcr0_prio_val_o => (others => '0'),
vcr0_pvid_o => (others => '0'),
vcr1_vid_o => (others => '0'),
vcr1_vid_wr_o => '0',
vcr1_value_o => '0',
vcr1_value_wr_o => '0',
pfcr0_mm_addr_o => (others => '0'),
pfcr0_mm_addr_wr_o => '0',
pfcr0_mm_write_o => '0',
pfcr0_mm_write_wr_o => '0',
pfcr0_enable_o => '0',
pfcr0_mm_data_msb_o => (others => '0'),
pfcr0_mm_data_msb_wr_o => '0',
pfcr1_mm_data_lsb_o => (others => '0'),
tcar_pcp_map_o => (others => '0'),
fcr_rxpause_o => '0',
fcr_txpause_o => '0',
fcr_tx_thr_o => (others => '0'),
fcr_tx_quanta_o => (others => '0'),
mach_o => (others => '0'),
macl_o => (others => '0'),
mdio_cr_data_o => (others => '0'),
mdio_cr_data_wr_o => '0',
mdio_cr_addr_o => (others => '0'),
mdio_cr_rw_o => '0',
mdio_asr_phyad_o => (others => '0'),
dsr_lact_o => '0',
dsr_lact_load_o => '0',
dmcr_en_o => '0',
dmcr_n_avg_o => (others => '0'),
dmsr_ps_rdy_o => '0',
dmsr_ps_rdy_load_o => '0'
);
function "or" (left, right: t_ep_in_registers) return t_ep_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
end package;
package body ep_wbgen2_pkg is
function f_x_to_zero (x:std_logic) return std_logic is
begin
if(x = 'X' or x = 'U') then
return '0';
else
return x;
end if;
end function;
function "or" (left, right: t_ep_in_registers) return t_ep_in_registers is
variable tmp: t_ep_in_registers;
begin
tmp.ecr_feat_vlan_i := left.ecr_feat_vlan_i or right.ecr_feat_vlan_i;
tmp.ecr_feat_dmtd_i := left.ecr_feat_dmtd_i or right.ecr_feat_dmtd_i;
tmp.ecr_feat_ptp_i := left.ecr_feat_ptp_i or right.ecr_feat_ptp_i;
tmp.ecr_feat_dpi_i := left.ecr_feat_dpi_i or right.ecr_feat_dpi_i;
tmp.tscr_cs_done_i := left.tscr_cs_done_i or right.tscr_cs_done_i;
tmp.mdio_asr_rdata_i := left.mdio_asr_rdata_i or right.mdio_asr_rdata_i;
tmp.mdio_asr_ready_i := left.mdio_asr_ready_i or right.mdio_asr_ready_i;
tmp.dsr_lstatus_i := left.dsr_lstatus_i or right.dsr_lstatus_i;
tmp.dsr_lact_i := left.dsr_lact_i or right.dsr_lact_i;
tmp.dmsr_ps_val_i := left.dmsr_ps_val_i or right.dmsr_ps_val_i;
tmp.dmsr_ps_rdy_i := left.dmsr_ps_rdy_i or right.dmsr_ps_rdy_i;
return tmp;
end function;
end package body;
library ieee;
use ieee.std_logic_1164.all;
use work.endpoint_private_pkg.all;
entity ep_rtu_header_extract is
generic(
g_with_rtu : boolean);
port(
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
snk_fab_i : in t_ep_internal_fabric;
snk_dreq_o : out std_logic;
src_fab_o : out t_ep_internal_fabric;
src_dreq_i : in std_logic;
rtu_rq_o : out t_ep_internal_rtu_request;
rtu_full_i : in std_logic;
rtu_rq_valid_o : out std_logic
);
end ep_rtu_header_extract;
architecture rtl of ep_rtu_header_extract is
signal hdr_offset : std_logic_vector(11 downto 0);
signal in_packet : std_logic;
procedure f_extract_rtu(signal q : out std_logic_vector;
signal fab : t_ep_internal_fabric;
signal at_offset : std_logic) is
begin
if(at_offset = '1' and fab.dvalid = '1') then
q <= fab.data;
end if;
end f_extract_rtu;
begin -- rtl
gen_with_rtu : if(g_with_rtu) generate
p_hdr_offset_sreg : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if (rst_n_i = '0' or snk_fab_i.sof = '1') then
hdr_offset(hdr_offset'left downto 1) <= (others => '0');
hdr_offset(0) <= '1';
elsif(snk_fab_i.dvalid = '1') then
hdr_offset <= hdr_offset(hdr_offset'left-1 downto 0) & '0';
end if;
end if;
end process;
p_gen_rtu_request : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
rtu_rq_o.smac <= (others => '0');
rtu_rq_o.dmac <= (others => '0');
rtu_rq_o.vid <= (others => '0');
rtu_rq_o.has_vid <= '0';
rtu_rq_o.prio <= (others => '0');
rtu_rq_o.has_prio <= '0';
in_packet <= '0';
else
if(snk_fab_i.sof = '1' and rtu_full_i = '0') then
in_packet <= '1';
end if;
if(snk_fab_i.eof = '1' or snk_fab_i.error = '1') then
in_packet <= '0';
end if;
f_extract_rtu(rtu_rq_o.dmac(47 downto 32), snk_fab_i, hdr_offset(0));
f_extract_rtu(rtu_rq_o.dmac(31 downto 16), snk_fab_i, hdr_offset(1));
f_extract_rtu(rtu_rq_o.dmac(15 downto 0), snk_fab_i, hdr_offset(2));
f_extract_rtu(rtu_rq_o.smac(47 downto 32), snk_fab_i, hdr_offset(3));
f_extract_rtu(rtu_rq_o.smac(31 downto 16), snk_fab_i, hdr_offset(4));
f_extract_rtu(rtu_rq_o.smac(15 downto 0), snk_fab_i, hdr_offset(5));
if(hdr_offset(5) = '1' and in_packet = '1') then
rtu_rq_valid_o <= '1';
else
rtu_rq_valid_o <= '0';
end if;
end if;
end if;
end process;
src_fab_o.sof <= snk_fab_i.sof and not rtu_full_i;
end generate gen_with_rtu;
gen_without_rtu : if (not g_with_rtu) generate
src_fab_o.sof <= snk_fab_i.sof;
end generate gen_without_rtu;
snk_dreq_o <= src_dreq_i;
src_fab_o.eof <= snk_fab_i.eof;
src_fab_o.dvalid <= snk_fab_i.dvalid;
src_fab_o.error <= snk_fab_i.error;
src_fab_o.bytesel <= snk_fab_i.bytesel;
src_fab_o.data <= snk_fab_i.data;
src_fab_o.addr <= snk_fab_i.addr;
src_fab_o.has_rx_timestamp <= snk_fab_i.has_rx_timestamp;
end rtl;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
files = [ "minic_packet_buffer.vhd",
"minic_wb_slave.vhd",
"minic_wbgen2_pkg.vhd",
"wr_mini_nic.vhd",
"xwr_mini_nic.vhd" ];
#!/bin/bash
mkdir -p doc
wbgen2 -D ./doc/minic.html -V minic_wb_slave.vhd -p minic_wbgen2_pkg.vhd --cstyle defines --lang vhdl -H record -K ../../sim/minic_regs.vh mini_nic.wb
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
files = ["pps_gen_wb.vhd",
"wr_pps_gen.vhd",
"xwr_pps_gen.vhd"];
#!/bin/bash
mkdir -p doc
wbgen2 -D ./doc/pps_gen.html -V pps_gen_wb.vhd -C pps_gen_regs.h --cstyle defines --lang vhdl -K ../../sim/pps_gen_regs.v pps_gen_wb.wb
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
files = [ "softpll_wb.vhd",
"wr_softpll.vhd",
"xwr_softpll.vhd" ];
#!/bin/bash
wbgen2 -C softpll_regs.h -V softpll_wb.vhd -K ../../sim/softpll_regs.v wr_softpll.wb -C softpll_regs.h
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
files = ["spll_period_detect.vhd",
"spll_bangbang_pd.vhd",
"spll_wbgen2_pkg.vhd",
"wr_softpll_ng.vhd",
"xwr_softpll_ng.vhd",
"spll_wb_slave.vhd"]
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment