Commit 423d90cc authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

removed references to common_components and global_defs packages

parents
-------------------------------------------------------------------------------
-- Title : Serial DAC interface
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : serial_dac.vhd
-- Author : paas, slayer
-- Company : CERN BE-Co-HT
-- Created : 2010-02-25
-- Last update: 2011-05-10
-- Platform : fpga-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: The dac unit provides an interface to a 16 bit serial Digita to Analogue converter (max5441, SPI?/QSPI?/MICROWIRE? compatible)
--
-------------------------------------------------------------------------------
-- Copyright (c) 2010 CERN
-------------------------------------------------------------------------------
-- Revisions :1
-- Date Version Author Description
-- 2009-01-24 1.0 paas Created
-- 2010-02-25 1.1 slayer Modified for rev 1.1 switch
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity spec_serial_dac is
generic (
g_num_data_bits : integer := 16;
g_num_extra_bits : integer := 8;
g_num_cs_select : integer := 2
);
port (
-- clock & reset
clk_i : in std_logic;
rst_n_i : in std_logic;
-- channel 1 value and value load strobe
value_i : in std_logic_vector(g_num_data_bits-1 downto 0);
cs_sel_i : in std_logic_vector(g_num_cs_select-1 downto 0);
load_i : in std_logic;
-- SCLK divider: 000 = clk_i/8 ... 111 = clk_i/1024
sclk_divsel_i : in std_logic_vector(2 downto 0);
-- DAC I/F
dac_cs_n_o : out std_logic_vector(g_num_cs_select-1 downto 0);
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic;
xdone_o : out std_logic
);
end spec_serial_dac;
architecture syn of spec_serial_dac is
signal divider : unsigned(11 downto 0);
signal dataSh : std_logic_vector(g_num_data_bits + g_num_extra_bits-1 downto 0);
signal bitCounter : std_logic_vector(g_num_data_bits + g_num_extra_bits+1 downto 0);
signal endSendingData : std_logic;
signal sendingData : std_logic;
signal iDacClk : std_logic;
signal iValidValue : std_logic;
signal divider_muxed : std_logic;
signal cs_sel_reg : std_logic_vector(g_num_cs_select-1 downto 0);
begin
select_divider : process (divider, sclk_divsel_i)
begin -- process
case sclk_divsel_i is
when "000" => divider_muxed <= divider(1); -- sclk = clk_i/8
when "001" => divider_muxed <= divider(2); -- sclk = clk_i/16
when "010" => divider_muxed <= divider(3); -- sclk = clk_i/32
when "011" => divider_muxed <= divider(4); -- sclk = clk_i/64
when "100" => divider_muxed <= divider(5); -- sclk = clk_i/128
when "101" => divider_muxed <= divider(6); -- sclk = clk_i/256
when "110" => divider_muxed <= divider(7); -- sclk = clk_i/512
when "111" => divider_muxed <= divider(8); -- sclk = clk_i/1024
when others => null;
end case;
end process;
iValidValue <= load_i;
process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
sendingData <= '0';
else
if iValidValue = '1' and sendingData = '0' then
sendingData <= '1';
elsif endSendingData = '1' then
sendingData <= '0';
end if;
end if;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
if iValidValue = '1' then
divider <= (others => '0');
elsif sendingData = '1' then
if(divider_muxed = '1') then
divider <= (others => '0');
else
divider <= divider + 1;
end if;
elsif endSendingData = '1' then
divider <= (others => '0');
end if;
end if;
end process;
process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
iDacClk <= '1'; -- 0
else
if iValidValue = '1' then
iDacClk <= '1'; -- 0
elsif divider_muxed = '1' then
iDacClk <= not(iDacClk);
elsif endSendingData = '1' then
iDacClk <= '1'; -- 0
end if;
end if;
end if;
end process;
process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
dataSh <= (others => '0');
else
if iValidValue = '1' and sendingData = '0' then
cs_sel_reg <= cs_sel_i;
dataSh(g_num_data_bits-1 downto 0) <= value_i;
dataSh(dataSh'left downto g_num_data_bits) <= (others => '0');
elsif sendingData = '1' and divider_muxed = '1' and iDacClk = '0' then
dataSh(0) <= dataSh(dataSh'left);
dataSh(dataSh'left downto 1) <= dataSh(dataSh'left - 1 downto 0);
end if;
end if;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
if iValidValue = '1' and sendingData = '0' then
bitCounter(0) <= '1';
bitCounter(bitCounter'left downto 1) <= (others => '0');
elsif sendingData = '1' and to_integer(divider) = 0 and iDacClk = '1' then
bitCounter(0) <= '0';
bitCounter(bitCounter'left downto 1) <= bitCounter(bitCounter'left - 1 downto 0);
end if;
end if;
end process;
endSendingData <= bitCounter(bitCounter'left);
xdone_o <= not SendingData;
dac_sdata_o <= dataSh(dataSh'left);
gen_cs_out : for i in 0 to g_num_cs_select-1 generate
dac_cs_n_o(i) <= not(sendingData) or (not cs_sel_reg(i));
end generate gen_cs_out;
dac_sclk_o <= iDacClk;
end syn;
library ieee;
use ieee.std_logic_1164.all;
use work.common_components.all;
entity spec_serial_dac_arb is
generic(
g_invert_sclk : boolean;
g_num_extra_bits : integer
);
port(
clk_i : in std_logic;
rst_n_i : in std_logic;
val1_i : in std_logic_vector(15 downto 0);
load1_i : in std_logic;
val2_i : in std_logic_vector(15 downto 0);
load2_i : in std_logic;
dac_cs_n_o : out std_logic_vector(1 downto 0);
dac_clr_n_o : out std_logic;
dac_sclk_o : out std_logic;
dac_din_o : out std_logic);
end spec_serial_dac_arb;
architecture behavioral of spec_serial_dac_arb is
component spec_serial_dac
generic (
g_num_data_bits : integer;
g_num_extra_bits : integer;
g_num_cs_select : integer);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
value_i : in std_logic_vector(g_num_data_bits-1 downto 0);
cs_sel_i : in std_logic_vector(g_num_cs_select-1 downto 0);
load_i : in std_logic;
sclk_divsel_i : in std_logic_vector(2 downto 0);
dac_cs_n_o : out std_logic_vector(g_num_cs_select-1 downto 0);
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic;
xdone_o : out std_logic);
end component;
signal d1, d2 : std_logic_vector(15 downto 0);
signal d1_ready, d2_ready : std_logic;
signal dac_data : std_logic_vector(15 downto 0);
signal dac_load : std_logic;
signal dac_cs_sel : std_logic_vector(1 downto 0);
signal dac_done : std_logic;
signal dac_sclk_int : std_logic;
type t_state is (WAIT_DONE, LOAD_DAC, WAIT_DATA);
signal state : t_state;
component chipscope_icon
port (
CONTROL0 : inout std_logic_vector (35 downto 0));
end component;
component chipscope_ila
port (
CLK : in std_logic := 'X';
TRIG0 : in std_logic_vector (31 downto 0);
TRIG1 : in std_logic_vector (31 downto 0);
TRIG2 : in std_logic_vector (31 downto 0);
TRIG3 : in std_logic_vector (31 downto 0);
CONTROL : inout std_logic_vector (35 downto 0));
end component;
signal trig0 : std_logic_vector(31 downto 0);
signal trig1 : std_logic_vector(31 downto 0);
signal trig2 : std_logic_vector(31 downto 0);
signal trig3 : std_logic_vector(31 downto 0);
signal CONTROL0 : std_logic_vector(35 downto 0);
begin -- behavioral
dac_clr_n_o <= '1';
U_DAC : spec_serial_dac
generic map (
g_num_data_bits => 16,
g_num_extra_bits => g_num_extra_bits,
g_num_cs_select => 2)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
value_i => dac_data,
cs_sel_i => dac_cs_sel,
load_i => dac_load,
sclk_divsel_i => "001",
dac_cs_n_o => dac_cs_n_o,
dac_sclk_o => dac_sclk_int,
dac_sdata_o => dac_din_o,
xdone_o => dac_done);
p_drive_sclk: process(dac_sclk_int)
begin
if(g_invert_sclk) then
dac_sclk_o <= not dac_sclk_int;
else
dac_sclk_o <= dac_sclk_int;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
d1 <= (others => '0');
d1_ready <= '0';
d2 <= (others => '0');
d2_ready <= '0';
dac_load <= '0';
dac_cs_sel <= (others => '0');
state <= WAIT_DATA;
else
if(load1_i = '1' or load2_i = '1') then
if(load1_i = '1') then
d1_ready <= '1';
d1 <= val1_i;
end if;
if(load2_i = '1') then
d2_ready <= '1';
d2 <= val2_i;
end if;
else
case state is
when WAIT_DATA =>
if(d1_ready = '1') then
dac_cs_sel <= "01";
dac_data <= d1;
dac_load <= '1';
d1_ready <= '0';
state <= LOAD_DAC;
elsif(d2_ready = '1') then
dac_cs_sel <= "10";
dac_data <= d2;
dac_load <= '1';
d2_ready <= '0';
state <= LOAD_DAC;
end if;
when LOAD_DAC=>
dac_load <= '0';
state <= WAIT_DONE;
when WAIT_DONE =>
if(dac_done = '1') then
state <= WAIT_DATA;
end if;
when others => null;
end case;
end if;
end if;
end if;
end process;
end behavioral;
files = ["dmtd_phase_meas.vhd",
"dmtd_with_deglitcher.vhd",
"multi_dmtd_with_deglitcher.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: 2011-04-18
-- 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.common_components.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
);
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;
-- [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;
signal clk_i_d0, clk_i_d1, clk_i_d2, clk_i_d3 : std_logic;
signal new_edge_sreg : std_logic_vector(3 downto 0);
signal new_edge_p : std_logic;
signal tag_int : unsigned(g_counter_bits-1 downto 0);
begin -- rtl
p_the_dmtd_itself : process(clk_dmtd_i)
begin
if rising_edge(clk_dmtd_i) then
clk_i_d0 <= clk_in_i;
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');
else
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 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;
end if;
when GOT_EDGE =>
if (clk_i_d3 = '0') then
tag_int <= tag_int + 1;
end if;
if (clk_i_d3 = '0') then
stab_cntr <= (others => '0');
else
stab_cntr <= stab_cntr + 1;
end if;
if stab_cntr = unsigned(deglitch_threshold_i) then
state <= WAIT_STABLE_0;
new_edge_sreg <= (others => '1');
end if;
end case;
end if;
end if;
end process deglitch;
U_sync_tag_strobe : 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);
dbg_dmtdout_o <= clk_i_d3;
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-05-11
-- 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, rst_n_sysclk_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.common_components.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 : 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;
files = [ "minic_packet_buffer.vhd",
"minic_wb_slave.vhd",
"wr_mini_nic.vhd",
"wr_minic_ep_combo.vhd"];
#!/bin/bash
mkdir -p doc
wbgen2 -D ./doc/minic.html -V minic_wb_slave.vhd -C ../../../software/include/hw/minic_regs.h --cstyle defines --lang vhdl -K ../../sim/minic_regs.v mini_nic.wb
\ No newline at end of file
-- -*- Mode: LUA; tab-width: 2 -*-
peripheral {
name = "Mini NIC for WhiteRabbit";
description = "Simple, embedded WhiteRabbit-compiliant Network Interface Controller (NIC) for use in WhiteRabbit embedded receivers";
prefix = "minic";
hdl_entity = "minic_wb_slave";
reg {
name = "miNIC Control Register";
prefix = "MCR";
field {
name = "TX DMA start";
prefix = "TX_START";
description = "write 1: starts the DMA transmission of TX descriptors placed in the DMA buffer, write 0: no effect";
type = MONOSTABLE;
};
field {
name = "TX DMA idle";
prefix = "TX_IDLE";
description = "1: TX DMA engine is idle.\n0: TX DMA engine is busy, don't touch the buffer";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "TX DMA error";
prefix = "TX_ERROR";
description = "1: an error occured during the TX DMA transfer. The address at which the error occured is kept in TX_ADDR register";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "RX DMA ready";
prefix = "RX_READY";
description = "1: RX buffer contains at least one packet";
type = BIT;
align = 8;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "RX DMA buffer full";
prefix = "RX_FULL";
description = "1: RX buffer is full";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "RX DMA enable";
prefix = "RX_EN";
description = "1: RX buffer is allocated and initialized by the host, the miNIC can receive packets\n0: RX buffer not ready, reception is disabled";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "TX DMA Address";
description = "Address of the start of TX buffer:\
read: base address of the last transmitted TX descriptor\
write: base address of the first descriptor to transmit";
prefix = "TX_ADDR";
field {
name = "TX DMA buffer address";
size = 24;
align = 2;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_WRITE;
load = LOAD_EXT;
};
};
reg {
name = "RX DMA Address";
description = "Address of the start of RX buffer:\
read: address of the last received RX descriptor\
write: base address of the RX buffer";
prefix = "RX_ADDR";
field {
name = "RX DMA buffer address";
size = 24;
align = 2;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_WRITE;
load = LOAD_EXT;
};
};
reg {
name = "RX buffer size register";
description = "Number of available 32-bit words in the RX buffer";
prefix = "RX_AVAIL";
field {
name = "RX available words";
size = 24;
align = 2;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_WRITE;
load = LOAD_EXT;
};
};
fifo_reg {
name = "TX timestamp FIFO";
prefix = "TSFIFO";
size = 16;
direction = CORE_TO_BUS;
flags_bus = {FIFO_EMPTY};
flags_dev = {FIFO_FULL, FIFO_EMPTY};
field {
name = "Timestamp value";
prefix = "TSVAL";
size = 32;
type = SLV;
};
field {
name = "Port ID";
prefix = "PID";
size = 5;
type = SLV;
};
field {
name = "Frame ID";
prefix = "FID";
size = 16;
type = SLV;
};
};
reg {
name = "Debug register";
prefix = "DBGR";
field {
name = "interrupt counter";
prefix = "IRQ_CNT";
size = 24;
type = SLV;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "status of wb_irq_o line";
prefix = "WB_IRQ_VAL";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
irq {
name = "TX DMA interrupt";
trigger = LEVEL_1;
ack_line = true;
mask_line = true;
prefix = "TX";
};
irq {
name = "RX DMA interrupt";
trigger = LEVEL_1;
ack_line = true;
prefix = "RX";
};
irq {
name = "TX timestamp available";
trigger = LEVEL_1;
prefix = "TXTS";
};
};
\ No newline at end of file
-------------------------------------------------------------------------------
-- Title : Mini Embedded DMA Network Interface Controller
-- Project : WhiteRabbit Core
-------------------------------------------------------------------------------
-- File : minic_packet_buffer.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-07-26
-- Last update: 2011-05-09
-- Platform : FPGA-generic
-- Standard : VHDL
-------------------------------------------------------------------------------
-- Description: RAM-based packet buffer for miNIC implementations which don't
-- use the DMA access to the system memory
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tomasz Wlostowski
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-07-26 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.genram_pkg.all;
entity minic_packet_buffer is
generic (
g_memsize_log2 : integer := 14);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
minic_addr_i : in std_logic_vector(g_memsize_log2-1 downto 0);
minic_data_i : in std_logic_vector(31 downto 0);
minic_wr_i : in std_logic;
minic_data_o : out std_logic_vector(31 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_addr_i : in std_logic_vector(g_memsize_log2-1 downto 0);
wb_cyc_i : in std_logic;
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic
);
end minic_packet_buffer;
architecture syn of minic_packet_buffer is
signal host_we : std_logic;
signal host_ack : std_logic;
begin -- syn
ack_gen : process(clk_sys_i, rst_n_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
host_ack <= '0';
else
host_ack <= (wb_cyc_i and wb_stb_i) and (not host_ack);
end if;
end if;
end process;
wb_ack_o <= host_ack;
host_we <= wb_cyc_i and wb_stb_i and (wb_we_i and not host_ack);
U_RAM: generic_dpram
generic map (
g_data_width => 32,
g_size => 2**g_memsize_log2,
g_with_byte_enable => false,
g_dual_clock => false)
port map (
rst_n_i => rst_n_i,
clka_i => clk_sys_i,
bwea_i => "0000",
wea_i => host_we,
aa_i => wb_addr_i,
da_i => wb_data_i,
qa_o => wb_data_o,
clkb_i => clk_sys_i,
bweb_i => "0000",
web_i => minic_wr_i,
ab_i => minic_addr_i,
db_i => minic_data_i,
qb_o => minic_data_o);
end syn;
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" ];
#!/bin/bash
wbgen2 -C softpll_regs.h -V softpll_wb.vhd -K ../../sim/softpll_regs.v wr_softpll.wb
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
-- -*- Mode: LUA; tab-width: 2 -*-
peripheral {
name = "WR Softcore PLL";
hdl_entity = "softpll_wb";
prefix = "SPLL";
reg {
name = "SPLL Control/Status Register";
prefix = "CSR";
field {
name = "Tagger enable";
prefix = "TAG_EN";
type = SLV;
size = 4;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Tag ready";
prefix = "TAG_RDY";
type = SLV;
size = 4;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "HPLL Frequency Error";
prefix = "PER_HPLL";
field {
name = "Period error value";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
ack_read = "tag_hpll_rd_period_o";
};
};
reg {
name = "DMPLL Tag ref";
prefix = "TAG_REF";
field {
name = "Tag value";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
ack_read = "tag_ref_rd_ack_o";
};
};
reg {
name = "DMPLL Tag fb";
prefix = "TAG_FB";
field {
name = "Tag value";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
ack_read = "tag_fb_rd_ack_o";
};
};
reg {
name = "HPLL DAC Output";
prefix = "DAC_HPLL";
field {
name = "DAC value";
type = PASS_THROUGH;
size = 16;
};
};
reg {
name = "DMPLL DAC Output";
prefix = "DAC_DMPLL";
field {
name = "DAC value";
type = PASS_THROUGH;
size = 16;
};
};
reg {
name = "Deglitcher threshold";
prefix = "DEGLITCH_THR";
field {
name = "Threshold";
type = SLV;
size = 16;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
irq {
name = "Got a tag";
prefix = "TAG";
trigger = LEVEL_1;
};
};
files = [ "wr_core.vhd",
"wrc_dpram.vhd",
"wrcore_pkg.vhd",
"wrc_periph.vhd",
"wb_reset.vhd",
"wrc_dumb_rx_packet_filter.vhd" ];
-------------------------------------------------------------------------------
-- Title : WhiteRabbit PTP Core ZPU reset generator
-- Project : WhiteRabbit
-------------------------------------------------------------------------------
-- File : wb_reset.vhd
-- Author : Grzegorz Daniluk
-- Company : Elproma
-- Created : 2011-04-04
-- Last update: 2011-04-04
-- Platform : FPGA-generics
-- Standard : VHDL
-------------------------------------------------------------------------------
-- Description:
-- WB_RESET is a reset signal generator for ZPU. It is controlled by wishbone
-- and is used by ZPU firmware loader(zpu-loader) to reset the processor during
-- copying the binary to dpram.
-------------------------------------------------------------------------------
-- Copyright (c) 2011 Grzegorz Daniluk
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-04-04 1.0 greg.d Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity wb_reset is
port(
clk_i : in std_logic;
rst_n_i : in std_logic;
genrst_n_o : out std_logic;
wb_addr_i : in std_logic_vector(1 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_cyc_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic
);
end wb_reset;
architecture behaviour of wb_reset is
constant c_RST_REG : std_logic_vector(1 downto 0) := "00";
signal rst_reg : std_logic_vector(7 downto 0);
signal grst_n : std_logic;
begin
process(clk_i, rst_n_i)
begin
if( rst_n_i = '0') then
wb_ack_o <= '0';
rst_reg <= (others=>'0');
elsif( rising_edge(clk_i) ) then
if(wb_stb_i='1' and wb_cyc_i='1' and wb_we_i='1') then
case wb_addr_i is
when c_RST_REG =>
rst_reg <= wb_data_i(7 downto 0);
when others =>
end case;
wb_ack_o <= '1';
else
wb_ack_o <= '0';
end if;
end if;
end process;
process(clk_i, rst_n_i)
variable cnt : integer range 1 to 5;
begin
if(rst_n_i = '0') then
grst_n <= '1';
elsif( rising_edge(clk_i) ) then
if(rst_reg(0) = '1') then
grst_n <= '0';
else
grst_n <= '1';
end if;
end if;
end process;
genrst_n_o <= grst_n;
end behaviour;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
files = [ "wrc_lm32.vhd", "lm32_top.v" ];
\ No newline at end of file
// Modified by GSI to use simple positive edge clocking and the JTAG capture state
module jtag_cores (
input [7:0] reg_d,
input [2:0] reg_addr_d,
output reg_update,
output [7:0] reg_q,
output [2:0] reg_addr_q,
output jtck,
output jrstn
);
wire tck;
wire tdi;
wire tdo;
wire capture;
wire shift;
wire update;
wire e1dr;
wire reset;
jtag_tap jtag_tap (
.tck(tck),
.tdi(tdi),
.tdo(tdo),
.capture(capture),
.shift(shift),
.e1dr(e1dr),
.update(update),
.reset(reset)
);
reg [10:0] jtag_shift;
reg [10:0] jtag_latched;
always @(posedge tck)
begin
if(reset)
jtag_shift <= 11'b0;
else begin
if (shift)
jtag_shift <= {tdi, jtag_shift[10:1]};
else if (capture)
jtag_shift <= {reg_d, reg_addr_d};
end
end
assign tdo = jtag_shift[0];
always @(posedge tck)
begin
if(reset)
jtag_latched <= 11'b0;
else begin
if (e1dr)
jtag_latched <= jtag_shift;
end
end
assign reg_update = update;
assign reg_q = jtag_latched[10:3];
assign reg_addr_q = jtag_latched[2:0];
assign jtck = tck;
assign jrstn = ~reset;
endmodule
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.
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