pax_global_header 0000666 0000000 0000000 00000000064 11653767173 0014532 g ustar 00root root 0000000 0000000 52 comment=6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/ 0000775 0000000 0000000 00000000000 11653767173 0020630 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/README 0000664 0000000 0000000 00000000540 11653767173 0021507 0 ustar 00root root 0000000 0000000 Time to Digital Converter core for Spartan-6 FPGAs
==================================================
Directory organization:
core/ VHDL sources of the TDC core.
demo/ Demonstration design for the SPEC board.
doc/ Documentation.
hostif/ Optional host interface.
tb/ Test benches.
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/ 0000775 0000000 0000000 00000000000 11653767173 0021560 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/Manifest.py 0000664 0000000 0000000 00000000361 11653767173 0023700 0 ustar 00root root 0000000 0000000 files = [
"tdc_controller.vhd", "tdc_freqc.vhd", "tdc_psync.vhd",
"tdc_channelbank.vhd", "tdc_delayline.vhd", "tdc_lbc.vhd", "tdc_ringosc.vhd",
"tdc_channel.vhd", "tdc_divider.vhd", "tdc_package.vhd", "tdc.vhd"
];
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc.vhd 0000664 0000000 0000000 00000020053 11653767173 0023035 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Top level module
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-17 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- Top level module of the TDC core, contains all logic except the optional
-- host interface.
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.tdc_package.all;
entity tdc is
generic(
-- Number of channels.
g_CHANNEL_COUNT : positive := 1;
-- Number of CARRY4 elements per channel.
g_CARRY4_COUNT : positive := 124;
-- Number of raw output bits.
g_RAW_COUNT : positive := 9;
-- Number of fractional part bits.
g_FP_COUNT : positive := 13;
-- Number of coarse counter bits.
g_COARSE_COUNT : positive := 25;
-- Length of each ring oscillator.
g_RO_LENGTH : positive := 31;
-- Frequency counter width.
g_FCOUNTER_WIDTH : positive := 13;
-- Frequency counter timer width.
g_FTIMER_WIDTH : positive := 14
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
ready_o : out std_logic;
-- Coarse counter control.
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
-- Per-channel deskew inputs.
deskew_i : in std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- Per-channel signal inputs.
signal_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
calib_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
-- Per-channel detection outputs.
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- Debug interface.
freeze_req_i : in std_logic;
freeze_ack_o : out std_logic;
cs_next_i : in std_logic;
cs_last_o : out std_logic;
calib_sel_i : in std_logic;
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc is
signal cs_next : std_logic;
signal cs_next_c : std_logic;
signal cs_last : std_logic;
signal calib_sel : std_logic;
signal calib_sel_c : std_logic;
signal lut_a : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal lut_a_c : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal lut_we : std_logic;
signal lut_d_w : std_logic_vector(g_FP_COUNT-1 downto 0);
signal lut_d_r : std_logic_vector(g_FP_COUNT-1 downto 0);
signal c_detect : std_logic;
signal c_raw : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal his_a : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal his_a_c : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal his_we : std_logic;
signal his_d_w : std_logic_vector(g_FP_COUNT-1 downto 0);
signal his_d_r : std_logic_vector(g_FP_COUNT-1 downto 0);
signal oc_start : std_logic;
signal oc_start_c : std_logic;
signal oc_ready : std_logic;
signal oc_freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal oc_store : std_logic;
signal oc_sfreq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal freeze_ack : std_logic;
begin
cmp_channelbank: tdc_channelbank
generic map(
g_CHANNEL_COUNT => g_CHANNEL_COUNT,
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH,
g_FCOUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_FTIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
cc_rst_i => cc_rst_i,
cc_cy_o => cc_cy_o,
next_i => cs_next,
last_o => cs_last,
calib_sel_i => calib_sel,
deskew_i => deskew_i,
signal_i => signal_i,
calib_i => calib_i,
detect_o => detect_o,
polarity_o => polarity_o,
raw_o => raw_o,
fp_o => fp_o,
lut_a_i => lut_a,
lut_we_i => lut_we,
lut_d_i => lut_d_w,
lut_d_o => lut_d_r,
c_detect_o => c_detect,
c_raw_o => c_raw,
his_a_i => his_a,
his_we_i => his_we,
his_d_i => his_d_w,
his_d_o => his_d_r,
oc_start_i => oc_start,
oc_ready_o => oc_ready,
oc_freq_o => oc_freq,
oc_store_i => oc_store,
oc_sfreq_o => oc_sfreq
);
cmp_controller: tdc_controller
generic map(
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_FCOUNTER_WIDTH => g_FCOUNTER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
ready_o => ready_o,
next_o => cs_next_c,
last_i => cs_last,
calib_sel_o => calib_sel_c,
lut_a_o => lut_a_c,
lut_we_o => lut_we,
lut_d_o => lut_d_w,
c_detect_i => c_detect,
c_raw_i => c_raw,
his_a_o => his_a_c,
his_we_o => his_we,
his_d_o => his_d_w,
his_d_i => his_d_r,
oc_start_o => oc_start_c,
oc_ready_i => oc_ready,
oc_freq_i => oc_freq,
oc_store_o => oc_store,
oc_sfreq_i => oc_sfreq,
freeze_req_i => freeze_req_i,
freeze_ack_o => freeze_ack
);
-- Debug interface signals.
cs_next <= cs_next_i when (freeze_ack = '1') else cs_next_c;
calib_sel <= calib_sel_i when (freeze_ack = '1') else calib_sel_c;
lut_a <= lut_a_i when (freeze_ack = '1') else lut_a_c;
his_a <= his_a_i when (freeze_ack = '1') else his_a_c;
oc_start <= oc_start_i when (freeze_ack = '1') else oc_start_c;
freeze_ack_o <= freeze_ack;
cs_last_o <= cs_last;
lut_d_o <= lut_d_r;
his_d_o <= his_d_r;
oc_ready_o <= oc_ready;
oc_freq_o <= oc_freq;
oc_sfreq_o <= oc_sfreq;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_channel.vhd 0000664 0000000 0000000 00000015327 11653767173 0024535 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_channel
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Per-channel processing
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-25 SB Disable ring oscillator on reset
-- 2011-08-03 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- This contains the elements needed for each channel:
-- * Delay line
-- * Encoder
-- * LUT
-- * Deskew stage
-- * Online calibration ring oscillator
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
use work.genram_pkg.all;
entity tdc_channel is
generic(
-- Number of CARRY4 elements.
g_CARRY4_COUNT : positive;
-- Number of raw output bits.
g_RAW_COUNT : positive;
-- Number of fractional part bits.
g_FP_COUNT : positive;
-- Number of coarse counter bits.
g_COARSE_COUNT : positive;
-- Length of the ring oscillator.
g_RO_LENGTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
-- Coarse counter and deskew inputs.
coarse_i : in std_logic_vector(g_COARSE_COUNT-1 downto 0);
deskew_i : in std_logic_vector((g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- Signal input.
signal_i : in std_logic;
calib_i : in std_logic;
calib_sel_i : in std_logic;
-- Detection outputs.
detect_o : out std_logic;
polarity_o : out std_logic;
raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector((g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- LUT access.
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Calibration ring oscillator.
ro_en_i : in std_logic;
ro_clk_o : out std_logic
);
end entity;
architecture rtl of tdc_channel is
signal calib_sel_d : std_logic;
signal muxed_signal : std_logic;
signal taps : std_logic_vector(4*g_CARRY4_COUNT-1 downto 0);
signal polarity : std_logic;
signal polarity_d1 : std_logic;
signal polarity_d2 : std_logic;
signal detect_d1 : std_logic;
signal raw : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal raw_d1 : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal raw_d2 : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal lut : std_logic_vector(g_FP_COUNT-1 downto 0);
signal ro_en : std_logic;
begin
-- register calibration select signal to avoid glitches
process(clk_i)
begin
if rising_edge(clk_i) then
calib_sel_d <= calib_sel_i;
end if;
end process;
with calib_sel_d select
muxed_signal <= calib_i when '1', signal_i when others;
cmp_delayline: tdc_delayline
generic map(
g_WIDTH => g_CARRY4_COUNT
)
port map(
clk_i => clk_i,
reset_i => reset_i,
signal_i => muxed_signal,
taps_o => taps
);
cmp_lbc: tdc_lbc
generic map(
g_N => g_RAW_COUNT,
g_NIN => g_CARRY4_COUNT*4
)
port map(
clk_i => clk_i,
reset_i => reset_i,
d_i => taps,
polarity_o => polarity,
count_o => raw
);
cmp_lut: generic_dpram
generic map(
g_data_width => g_FP_COUNT,
g_size => 2**g_RAW_COUNT,
g_with_byte_enable => false,
g_addr_conflict_resolution => "read_first",
g_init_file => "",
g_dual_clock => false
)
port map(
clka_i => clk_i,
clkb_i => '0',
wea_i => '0',
bwea_i => (others => '0'),
aa_i => raw,
da_i => (others => '0'),
qa_o => lut,
web_i => lut_we_i,
bweb_i => (others => '0'),
ab_i => lut_a_i,
db_i => lut_d_i,
qb_o => lut_d_o
);
cmp_ringosc: tdc_ringosc
generic map(
g_LENGTH => g_RO_LENGTH
)
port map(
en_i => ro_en,
clk_o => ro_clk_o
);
ro_en <= ro_en_i and not reset_i;
detect_d1 <= polarity_d1 xor polarity_d2;
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
detect_o <= '0';
polarity_d1 <= '1';
polarity_d2 <= '1';
raw_d1 <= (others => '0');
raw_d2 <= (others => '0');
else
detect_o <= detect_d1;
polarity_d1 <= polarity;
raw_d1 <= raw;
if detect_d1 = '1' then
polarity_d2 <= polarity_d1;
raw_d2 <= raw_d1;
end if;
end if;
end if;
end process;
polarity_o <= polarity_d2;
raw_o <= raw_d2;
-- Combine coarse counter value and deskew.
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
fp_o <= (others => '0');
else
if detect_d1 = '1' then
fp_o <= std_logic_vector(
unsigned(coarse_i & (lut'range => '0'))
- unsigned(lut)
+ unsigned(deskew_i));
end if;
end if;
end if;
end process;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_channelbank.vhd 0000664 0000000 0000000 00000017365 11653767173 0025375 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_channelbank
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Automatic channel bank
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-25 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- This module instantiates the single- or multi-channel bank depending
-- on the g_CHANNEL_COUNT generic.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
entity tdc_channelbank is
generic(
-- Number of channels.
g_CHANNEL_COUNT : positive;
-- Number of CARRY4 elements per channel.
g_CARRY4_COUNT : positive;
-- Number of raw output bits.
g_RAW_COUNT : positive;
-- Number of fractional part bits.
g_FP_COUNT : positive;
-- Number of coarse counter bits.
g_COARSE_COUNT : positive;
-- Length of each ring oscillator.
g_RO_LENGTH : positive;
-- Frequency counter width.
g_FCOUNTER_WIDTH : positive;
-- Frequency counter timer width.
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
-- Control.
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
-- Per-channel deskew inputs.
deskew_i : in std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- Per-channel signal inputs.
signal_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
calib_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
-- Per-channel detection outputs.
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- LUT access.
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Histogram.
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Online calibration.
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_channelbank is
begin
g_single: if g_CHANNEL_COUNT = 1 generate
cmp_channelbank: tdc_channelbank_single
generic map(
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH,
g_FCOUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_FTIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
cc_rst_i => cc_rst_i,
cc_cy_o => cc_cy_o,
next_i => next_i,
last_o => last_o,
calib_sel_i => calib_sel_i,
deskew_i => deskew_i,
signal_i => signal_i(0),
calib_i => calib_i(0),
detect_o => detect_o(0),
polarity_o => polarity_o(0),
raw_o => raw_o,
fp_o => fp_o,
lut_a_i => lut_a_i,
lut_we_i => lut_we_i,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o,
c_detect_o => c_detect_o,
c_raw_o => c_raw_o,
his_a_i => his_a_i,
his_we_i => his_we_i,
his_d_i => his_d_i,
his_d_o => his_d_o,
oc_start_i => oc_start_i,
oc_ready_o => oc_ready_o,
oc_freq_o => oc_freq_o,
oc_store_i => oc_store_i,
oc_sfreq_o => oc_sfreq_o
);
end generate;
g_multi: if g_CHANNEL_COUNT > 1 generate
cmp_channelbank: tdc_channelbank_multi
generic map(
g_CHANNEL_COUNT => g_CHANNEL_COUNT,
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH,
g_FCOUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_FTIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
cc_rst_i => cc_rst_i,
cc_cy_o => cc_cy_o,
next_i => next_i,
last_o => last_o,
calib_sel_i => calib_sel_i,
deskew_i => deskew_i,
signal_i => signal_i,
calib_i => calib_i,
detect_o => detect_o,
polarity_o => polarity_o,
raw_o => raw_o,
fp_o => fp_o,
lut_a_i => lut_a_i,
lut_we_i => lut_we_i,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o,
c_detect_o => c_detect_o,
c_raw_o => c_raw_o,
his_a_i => his_a_i,
his_we_i => his_we_i,
his_d_i => his_d_i,
his_d_o => his_d_o,
oc_start_i => oc_start_i,
oc_ready_o => oc_ready_o,
oc_freq_o => oc_freq_o,
oc_store_i => oc_store_i,
oc_sfreq_o => oc_sfreq_o
);
end generate;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_channelbank_multi.vhd 0000664 0000000 0000000 00000030671 11653767173 0026602 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_channelbank_multi
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Channel bank (multi-channel)
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-25 SB Renamed to channelbank_multi
-- 2011-08-18 SB Added histogram
-- 2011-08-17 SB Added frequency counter
-- 2011-08-08 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- This module instantiates all the channels and provides a control interface
-- independent of the number of channels.
-- It provides a simple two-wire interface to select the current channel to
-- operate one, using the next_i (switch to next channel) and last_o (current
-- channel is the current channel, next channel is the first channel).
-- It provides multiplexed access to the LUT of the current channel, to the
-- histogram of the current channel, and to the ring oscillator frequency
-- of the current channel.
--
-- To save resources:
-- * the histogram is implemented as one large block RAM common to all
-- channels
-- * the frequency counter logic is shared among all channels, each channel
-- only implements a ring oscillator.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
use work.genram_pkg.all;
entity tdc_channelbank_multi is
generic(
-- Number of channels.
g_CHANNEL_COUNT : positive;
-- Number of CARRY4 elements per channel.
g_CARRY4_COUNT : positive;
-- Number of raw output bits.
g_RAW_COUNT : positive;
-- Number of fractional part bits.
g_FP_COUNT : positive;
-- Number of coarse counter bits.
g_COARSE_COUNT : positive;
-- Length of each ring oscillator.
g_RO_LENGTH : positive;
-- Frequency counter width.
g_FCOUNTER_WIDTH : positive;
-- Frequency counter timer width.
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
-- Control.
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
-- Per-channel deskew inputs.
deskew_i : in std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- Per-channel signal inputs.
signal_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
calib_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
-- Per-channel detection outputs.
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
-- LUT access.
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Histogram.
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Online calibration.
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_channelbank_multi is
signal detect : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal raw : std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
signal coarse_counter : std_logic_vector(g_COARSE_COUNT-1 downto 0);
signal current_channel_onehot : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal current_channel : std_logic_vector(f_log2_size(g_CHANNEL_COUNT)-1 downto 0);
signal lut_d_o_s : std_logic_vector(g_CHANNEL_COUNT*g_FP_COUNT-1 downto 0);
signal his_full_a : std_logic_vector(f_log2_size(g_CHANNEL_COUNT)+g_RAW_COUNT-1 downto 0);
signal ro_clk_s : std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
signal ro_clk : std_logic;
signal freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal sfreq_s : std_logic_vector(g_CHANNEL_COUNT*g_FCOUNTER_WIDTH-1 downto 0);
begin
-- Per-channel processing.
g_channels: for i in 0 to g_CHANNEL_COUNT-1 generate
signal this_calib_sel : std_logic;
signal this_lut_we : std_logic;
begin
this_calib_sel <= current_channel_onehot(i) and calib_sel_i;
this_lut_we <= current_channel_onehot(i) and lut_we_i;
cmp_channel: tdc_channel
generic map(
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
coarse_i => coarse_counter,
deskew_i =>
deskew_i((i+1)*(g_COARSE_COUNT+g_FP_COUNT)-1 downto i*(g_COARSE_COUNT+g_FP_COUNT)),
signal_i => signal_i(i),
calib_i => calib_i(i),
calib_sel_i => this_calib_sel,
detect_o => detect(i),
polarity_o => polarity_o(i),
raw_o => raw((i+1)*g_RAW_COUNT-1 downto i*g_RAW_COUNT),
fp_o =>
fp_o((i+1)*(g_COARSE_COUNT+g_FP_COUNT)-1 downto i*(g_COARSE_COUNT+g_FP_COUNT)),
lut_a_i => lut_a_i,
lut_we_i => this_lut_we,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o_s((i+1)*g_FP_COUNT-1 downto i*g_FP_COUNT),
ro_en_i => current_channel_onehot(i),
ro_clk_o => ro_clk_s(i)
);
end generate;
detect_o <= detect;
raw_o <= raw;
-- Histogram memory.
cmp_histogram: generic_spram
generic map(
g_data_width => g_FP_COUNT,
g_size => g_CHANNEL_COUNT*2**g_RAW_COUNT,
g_with_byte_enable => false,
g_init_file => "",
g_addr_conflict_resolution => "read_first"
)
port map(
rst_n_i => '1',
clk_i => clk_i,
bwe_i => (others => '0'),
we_i => his_we_i,
a_i => his_full_a,
d_i => his_d_i,
q_o => his_d_o
);
his_full_a <= current_channel & his_a_i;
-- Frequency counter.
cmp_freqc: tdc_freqc
generic map(
g_COUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_TIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
clk_m_i => ro_clk,
start_i => oc_start_i,
ready_o => oc_ready_o,
freq_o => freq
);
oc_freq_o <= freq;
-- Coarse counter.
process(clk_i)
begin
if rising_edge(clk_i) then
if (reset_i = '1') or (cc_rst_i = '1') then
coarse_counter <= (coarse_counter'range => '0');
cc_cy_o <= '0';
else
coarse_counter <= std_logic_vector(unsigned(coarse_counter) + 1);
if coarse_counter = (coarse_counter'range => '1') then
cc_cy_o <= '1';
else
cc_cy_o <= '0';
end if;
end if;
end if;
end process;
-- Combine LUT outputs.
process(lut_d_o_s, current_channel_onehot)
variable v_lut_d_o: std_logic_vector(g_FP_COUNT-1 downto 0);
begin
v_lut_d_o := (v_lut_d_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_lut_d_o := v_lut_d_o or lut_d_o_s((i+1)*g_FP_COUNT-1 downto i*g_FP_COUNT);
end if;
end loop;
lut_d_o <= v_lut_d_o;
end process;
-- Select detect and raw outputs for histogram generation.
process(detect, raw, current_channel_onehot)
variable v_c_detect_o : std_logic;
variable v_c_raw_o : std_logic_vector(g_RAW_COUNT-1 downto 0);
begin
v_c_detect_o := '0';
v_c_raw_o := (v_c_raw_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_c_detect_o := v_c_detect_o or detect(i);
v_c_raw_o := v_c_raw_o or raw((i+1)*g_RAW_COUNT-1 downto i*g_RAW_COUNT);
end if;
end loop;
c_detect_o <= v_c_detect_o;
c_raw_o <= v_c_raw_o;
end process;
-- Combine ring oscillator outputs. When disabled, a ring oscillator
-- outputs 0, so we can simply OR all outputs together.
ro_clk <= '0' when (ro_clk_s = (ro_clk_s'range => '0')) else '1';
-- Store and retrieve per-channel ring oscillator frequencies.
process(clk_i)
begin
if rising_edge(clk_i) then
if oc_store_i = '1' then
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
sfreq_s((i+1)*g_FCOUNTER_WIDTH-1 downto i*g_FCOUNTER_WIDTH) <= freq;
end if;
end loop;
end if;
end if;
end process;
process(sfreq_s, current_channel_onehot)
variable v_oc_sfreq_o: std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
begin
v_oc_sfreq_o := (v_oc_sfreq_o'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_oc_sfreq_o := v_oc_sfreq_o
or sfreq_s((i+1)*g_FCOUNTER_WIDTH-1 downto i*g_FCOUNTER_WIDTH);
end if;
end loop;
oc_sfreq_o <= v_oc_sfreq_o;
end process;
-- Generate channel selection signals.
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
current_channel_onehot <= (0 => '1', others => '0');
else
if next_i = '1' then
current_channel_onehot <=
std_logic_vector(rotate_left(unsigned(current_channel_onehot), 1));
end if;
end if;
end if;
end process;
last_o <= current_channel_onehot(g_CHANNEL_COUNT-1);
process(current_channel_onehot)
variable v_current_channel: std_logic_vector(f_log2_size(g_CHANNEL_COUNT)-1 downto 0);
begin
v_current_channel := (v_current_channel'range => '0');
for i in 0 to g_CHANNEL_COUNT-1 loop
if current_channel_onehot(i) = '1' then
v_current_channel := v_current_channel
or std_logic_vector(to_unsigned(i, v_current_channel'length));
end if;
end loop;
current_channel <= v_current_channel;
end process;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_channelbank_single.vhd 0000664 0000000 0000000 00000016255 11653767173 0026733 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_channelbank_single
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Channel bank (single-channel)
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-25 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- Simplified version of tdc_channelbank_multi for the single-channel case.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
use work.genram_pkg.all;
entity tdc_channelbank_single is
generic(
-- Number of CARRY4 elements per channel.
g_CARRY4_COUNT : positive;
-- Number of raw output bits.
g_RAW_COUNT : positive;
-- Number of fractional part bits.
g_FP_COUNT : positive;
-- Number of coarse counter bits.
g_COARSE_COUNT : positive;
-- Length of each ring oscillator.
g_RO_LENGTH : positive;
-- Frequency counter width.
g_FCOUNTER_WIDTH : positive;
-- Frequency counter timer width.
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
-- Control.
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
-- Per-channel deskew inputs.
deskew_i : in std_logic_vector(g_COARSE_COUNT+g_FP_COUNT-1 downto 0);
-- Per-channel signal inputs.
signal_i : in std_logic;
calib_i : in std_logic;
-- Per-channel detection outputs.
detect_o : out std_logic;
polarity_o : out std_logic;
raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_COARSE_COUNT+g_FP_COUNT-1 downto 0);
-- LUT access.
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Histogram.
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
-- Online calibration.
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_channelbank_single is
signal detect : std_logic;
signal raw : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal coarse_counter : std_logic_vector(g_COARSE_COUNT-1 downto 0);
signal ro_clk : std_logic;
signal freq : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
signal sfreq_s : std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
begin
-- Per-channel processing.
cmp_channel: tdc_channel
generic map(
g_CARRY4_COUNT => g_CARRY4_COUNT,
g_RAW_COUNT => g_RAW_COUNT,
g_FP_COUNT => g_FP_COUNT,
g_COARSE_COUNT => g_COARSE_COUNT,
g_RO_LENGTH => g_RO_LENGTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
coarse_i => coarse_counter,
deskew_i => deskew_i,
signal_i => signal_i,
calib_i => calib_i,
calib_sel_i => calib_sel_i,
detect_o => detect,
polarity_o => polarity_o,
raw_o => raw,
fp_o => fp_o,
lut_a_i => lut_a_i,
lut_we_i => lut_we_i,
lut_d_i => lut_d_i,
lut_d_o => lut_d_o,
ro_en_i => '1',
ro_clk_o => ro_clk
);
detect_o <= detect;
raw_o <= raw;
c_detect_o <= detect;
c_raw_o <= raw;
-- Histogram memory.
cmp_histogram: generic_spram
generic map(
g_data_width => g_FP_COUNT,
g_size => 2**g_RAW_COUNT,
g_with_byte_enable => false,
g_init_file => "",
g_addr_conflict_resolution => "read_first"
)
port map(
rst_n_i => '1',
clk_i => clk_i,
bwe_i => (others => '0'),
we_i => his_we_i,
a_i => his_a_i,
d_i => his_d_i,
q_o => his_d_o
);
-- Frequency counter.
cmp_freqc: tdc_freqc
generic map(
g_COUNTER_WIDTH => g_FCOUNTER_WIDTH,
g_TIMER_WIDTH => g_FTIMER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
clk_m_i => ro_clk,
start_i => oc_start_i,
ready_o => oc_ready_o,
freq_o => freq
);
oc_freq_o <= freq;
-- Coarse counter.
process(clk_i)
begin
if rising_edge(clk_i) then
if (reset_i = '1') or (cc_rst_i = '1') then
coarse_counter <= (coarse_counter'range => '0');
cc_cy_o <= '0';
else
coarse_counter <= std_logic_vector(unsigned(coarse_counter) + 1);
if coarse_counter = (coarse_counter'range => '1') then
cc_cy_o <= '1';
else
cc_cy_o <= '0';
end if;
end if;
end if;
end process;
-- Store and retrieve per-channel ring oscillator frequencies.
process(clk_i)
begin
if rising_edge(clk_i) then
if oc_store_i = '1' then
sfreq_s <= freq;
end if;
end if;
end process;
oc_sfreq_o <= sfreq_s;
-- Generate channel selection signals.
last_o <= '1';
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_controller.vhd 0000664 0000000 0000000 00000030034 11653767173 0025300 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_controller
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Controller
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-27 SB Fix accumulator overflow
-- 2011-10-27 SB Fix LUT address offset
-- 2011-08-19 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- This is the controller for the channel bank. It is in charge of sequencing
-- and performing the startup and online calibrations for all channels.
-- It books the histograms and computes and loads the LUTs of the channels.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
entity tdc_controller is
generic(
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_FCOUNTER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
ready_o : out std_logic;
next_o : out std_logic;
last_i : in std_logic;
calib_sel_o : out std_logic;
lut_a_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_o : out std_logic;
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
c_detect_i : in std_logic;
c_raw_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_o : out std_logic;
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_o : out std_logic;
oc_ready_i : in std_logic;
oc_freq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_o : out std_logic;
oc_sfreq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
freeze_req_i : in std_logic;
freeze_ack_o : out std_logic
);
end entity;
architecture rtl of tdc_controller is
signal ready_p: std_logic;
signal hc_count : std_logic_vector(g_FP_COUNT-1 downto 0);
signal hc_reset : std_logic;
signal hc_dec : std_logic;
signal hc_zero : std_logic;
signal ha_count : std_logic_vector(g_RAW_COUNT-1 downto 0);
signal ha_reset : std_logic;
signal ha_inc : std_logic;
signal ha_last : std_logic;
signal ha_sel : std_logic;
signal acc : std_logic_vector(g_FP_COUNT-1 downto 0);
signal acc_reset : std_logic;
signal acc_en : std_logic;
signal mul : std_logic_vector(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto 0);
signal mul_d1 : std_logic_vector(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto 0);
signal div_start : std_logic;
signal div_ready : std_logic;
signal div_divisor : std_logic_vector(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto 0);
signal div_quotient : std_logic_vector(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto 0);
signal div_qsat : std_logic_vector(g_FP_COUNT-1 downto 0);
type t_state is (
-- startup calibration
SC_NEWCHANNEL, SC_CLEARHIST, SC_READ, SC_UPDATE, SC_STOREF0,
-- online calibration
OC_STARTM, OC_WAITM, OC_WAITMUL1, OC_WAITMUL2, OC_STARTDIV, OC_WAITDIV, OC_WRITELUT, OC_NEXTCHANNEL,
-- freeze state (transfer control to debug interface)
FREEZE
);
signal state: t_state;
begin
-- generate ready signal
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
ready_o <= '0';
else
if ready_p = '1' then
ready_o <= '1';
end if;
end if;
end if;
end process;
-- count histogram entries when recording
process(clk_i)
begin
if rising_edge(clk_i) then
if hc_reset = '1' then
hc_count <= (hc_count'range => '1');
elsif hc_dec = '1' then
hc_count <= std_logic_vector(unsigned(hc_count) - 1);
end if;
end if;
end process;
hc_zero <= '1' when (hc_count = (hc_count'range => '0')) else '0';
-- generate histogram memory address and write data
process(clk_i)
begin
if rising_edge(clk_i) then
if ha_reset = '1' then
ha_count <= (ha_count'range => '0');
elsif ha_inc = '1' then
ha_count <= std_logic_vector(unsigned(ha_count) + 1);
end if;
end if;
end process;
ha_last <= '1' when (ha_count = (ha_count'range => '1')) else '0';
his_a_o <= ha_count when (ha_sel = '1') else c_raw_i;
his_d_o <= (his_d_o'range => '0') when (ha_sel = '1')
else std_logic_vector(unsigned(his_d_i) + 1);
-- accumulator
process(clk_i)
begin
if rising_edge(clk_i) then
if acc_reset = '1' then
acc <= (acc'range => '0');
elsif acc_en = '1' then
acc <= std_logic_vector(unsigned(acc) + unsigned(his_d_i));
end if;
end if;
end process;
-- multiplier
process(clk_i)
begin
if rising_edge(clk_i) then
mul <= std_logic_vector(unsigned(acc) * unsigned(oc_sfreq_i));
mul_d1 <= mul;
end if;
end process;
-- divider
cmp_divider: tdc_divider
generic map(
g_WIDTH => g_FP_COUNT+g_FCOUNTER_WIDTH
)
port map(
clk_i => clk_i,
reset_i => reset_i,
start_i => div_start,
dividend_i => mul_d1,
divisor_i => div_divisor,
ready_o => div_ready,
quotient_o => div_quotient,
remainder_o => open
);
div_divisor <= (g_FP_COUNT-1 downto 0 => '0') & oc_freq_i;
process(div_quotient)
begin
if div_quotient(g_FP_COUNT+g_FCOUNTER_WIDTH-1 downto g_FP_COUNT)
= (g_FCOUNTER_WIDTH-1 downto 0 => '0') then
div_qsat <= div_quotient(g_FP_COUNT-1 downto 0);
else -- saturate
div_qsat <= (div_qsat'range => '1');
end if;
end process;
-- generate LUT address and write data
lut_a_o <= ha_count;
lut_d_o <= div_qsat;
-- main FSM
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
if freeze_req_i = '1' then
state <= FREEZE;
else
state <= SC_NEWCHANNEL;
end if;
else
case state is
when SC_NEWCHANNEL =>
state <= SC_CLEARHIST;
when SC_CLEARHIST =>
if ha_last = '1' then
state <= SC_READ;
end if;
when SC_READ =>
if c_detect_i = '1' then
state <= SC_UPDATE;
end if;
when SC_UPDATE =>
if hc_zero = '1' then
state <= SC_STOREF0;
else
state <= SC_READ;
end if;
when SC_STOREF0 =>
if oc_ready_i = '1' then
if last_i = '1' then
state <= OC_STARTM;
else
state <= SC_NEWCHANNEL;
end if;
end if;
when OC_STARTM =>
state <= OC_WAITM;
when OC_WAITM =>
if oc_ready_i = '1' then
state <= OC_WAITMUL1;
end if;
when OC_WAITMUL1 =>
state <= OC_WAITMUL2;
when OC_WAITMUL2 =>
state <= OC_STARTDIV;
when OC_STARTDIV =>
state <= OC_WAITDIV;
when OC_WAITDIV =>
if div_ready = '1' then
state <= OC_WRITELUT;
end if;
when OC_WRITELUT =>
if ha_last = '1' then
state <= OC_NEXTCHANNEL;
else
state <= OC_WAITMUL1;
end if;
when OC_NEXTCHANNEL =>
if freeze_req_i = '1' then
state <= FREEZE;
else
state <= OC_STARTM;
end if;
when FREEZE =>
if freeze_req_i = '0' then
state <= OC_STARTM;
end if;
end case;
end if;
end if;
end process;
process(state, hc_zero, oc_ready_i, last_i, c_detect_i)
begin
ready_p <= '0';
hc_reset <= '0';
hc_dec <= '0';
ha_reset <= '0';
ha_inc <= '0';
ha_sel <= '0';
acc_reset <= '0';
acc_en <= '0';
div_start <= '0';
next_o <= '0';
calib_sel_o <= '0';
lut_we_o <= '0';
his_we_o <= '0';
oc_start_o <= '0';
oc_store_o <= '0';
freeze_ack_o <= '0';
case state is
when SC_NEWCHANNEL =>
hc_reset <= '1';
ha_reset <= '1';
when SC_CLEARHIST =>
calib_sel_o <= '1';
ha_inc <= '1';
ha_sel <= '1';
his_we_o <= '1';
when SC_READ =>
calib_sel_o <= '1';
if c_detect_i = '1' then
hc_dec <= '1';
end if;
when SC_UPDATE =>
calib_sel_o <= '1';
his_we_o <= '1';
if hc_zero = '1' then
oc_start_o <= '1';
end if;
when SC_STOREF0 =>
if oc_ready_i = '1' then
oc_store_o <= '1';
next_o <= '1';
end if;
when OC_STARTM =>
oc_start_o <= '1';
ha_reset <= '1';
acc_reset <= '1';
ha_sel <= '1';
when OC_WAITM =>
ha_sel <= '1';
when OC_WAITMUL1 =>
ha_sel <= '1';
when OC_WAITMUL2 =>
ha_sel <= '1';
when OC_STARTDIV =>
div_start <= '1';
ha_sel <= '1';
when OC_WAITDIV =>
ha_sel <= '1';
when OC_WRITELUT =>
lut_we_o <= '1';
acc_en <= '1';
ha_inc <= '1';
ha_sel <= '1';
when OC_NEXTCHANNEL =>
next_o <= '1';
if last_i = '1' then
ready_p <= '1';
end if;
ha_sel <= '1';
when FREEZE =>
freeze_ack_o <= '1';
end case;
end process;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_delayline.vhd 0000664 0000000 0000000 00000010750 11653767173 0025066 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_delayline
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Delay line based on CARRY4 primitives
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-27 SB MSB first
-- 2011-08-01 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- The delay line uses a carry chain. It is made up of CARRY4 primitives whose
-- CO outputs are registered by the dedicated D flip flops of the same slices.
-- The signal is injected at the CYINIT pin at the bottom of the carry chain.
-- The CARRY4 primitives have their S inputs hardwired to 1, which means the
-- carry chain becomes a delay line with the signal going unchanged through the
-- MUXCY elements. Since each CARRY4 contains four MUXCY elements, the delay
-- line has four times as many taps as there are CARRY4 primitives.
--
-- There is a second layer of registers to prevent metastability.
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.all;
library work;
use work.tdc_package.all;
entity tdc_delayline is
generic(
-- Number of CARRY4 elements.
g_WIDTH: positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
signal_i : in std_logic;
taps_o : out std_logic_vector(4*g_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_delayline is
signal unreg_rev : std_logic_vector(4*g_WIDTH-1 downto 0);
signal reg1_rev : std_logic_vector(4*g_WIDTH-1 downto 0);
signal taps_rev : std_logic_vector(4*g_WIDTH-1 downto 0);
signal taps_rev_sorted : std_logic_vector(4*g_WIDTH-1 downto 0);
function f_bit_reverse(s: std_logic_vector) return std_logic_vector is
variable v_r: std_logic_vector(s'high downto s'low);
begin
for i in s'high downto s'low loop
v_r(i) := s(s'high-i);
end loop;
return v_r;
end function;
begin
-- generate a carry chain
g_carry4: for i in 0 to g_WIDTH-1 generate
g_firstcarry4: if i = 0 generate
cmp_CARRY4: CARRY4 port map(
CO => unreg_rev(3 downto 0),
CI => '0',
CYINIT => signal_i,
DI => "0000",
S => "1111"
);
end generate;
g_nextcarry4: if i > 0 generate
cmp_CARRY4: CARRY4 port map(
CO => unreg_rev(4*(i+1)-1 downto 4*i),
CI => unreg_rev(4*i-1),
CYINIT => '0',
DI => "0000",
S => "1111"
);
end generate;
end generate;
-- double latch the output
g_fd: for j in 0 to 4*g_WIDTH-1 generate
cmp_FDR_1: FDR
generic map(
INIT => '0'
)
port map(
C => clk_i,
R => reset_i,
D => unreg_rev(j),
Q => reg1_rev(j)
);
cmp_FDR_2: FDR
generic map(
INIT => '0'
)
port map(
C => clk_i,
R => reset_i,
D => reg1_rev(j),
Q => taps_rev(j)
);
end generate;
-- sort taps by increasing delays, according to static timing model
cmp_ordertaps: tdc_ordertaps
generic map(
g_WIDTH => g_WIDTH
)
port map(
unsorted_i => taps_rev,
sorted_o => taps_rev_sorted
);
-- sort output with the least delay in the most significant bit
taps_o <= f_bit_reverse(taps_rev_sorted);
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_divider.vhd 0000664 0000000 0000000 00000007466 11653767173 0024560 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_divider
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Multi-cycle unsigned integer divider
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-17 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- Sequentially computes the Euclidean division of dividend_i by divisor_i.
-- Returns quotient and remainder. Works with unsigned integers of g_WIDTH
-- bits each.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
entity tdc_divider is
generic(
-- Number of bits of the operands and results.
g_WIDTH: positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
start_i : in std_logic;
dividend_i : in std_logic_vector(g_WIDTH-1 downto 0);
divisor_i : in std_logic_vector(g_WIDTH-1 downto 0);
ready_o : out std_logic;
quotient_o : out std_logic_vector(g_WIDTH-1 downto 0);
remainder_o : out std_logic_vector(g_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_divider is
function f_log2_size(a : natural) return natural is
begin
for i in 1 to 64 loop -- Works for up to 64 bits
if 2**i >= a then
return i;
end if;
end loop;
return 63;
end function;
signal qr : std_logic_vector(2*g_WIDTH-1 downto 0);
signal counter : std_logic_vector(f_log2_size(g_WIDTH+1)-1 downto 0);
signal divisor_r : std_logic_vector(g_WIDTH-1 downto 0);
signal diff : std_logic_vector(g_WIDTH downto 0);
signal ready : std_logic;
begin
quotient_o <= qr(g_WIDTH-1 downto 0);
remainder_o <= qr(2*g_WIDTH-1 downto g_WIDTH);
ready <= '1' when (counter = (counter'range => '0')) else '0';
ready_o <= ready;
diff <= std_logic_vector(unsigned(qr(2*g_WIDTH-1 downto g_WIDTH-1))
- unsigned("0" & divisor_r));
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
qr <= (qr'range => '0');
counter <= (counter'range => '0');
divisor_r <= (divisor_r'range => '0');
else
if start_i = '1' then
counter <= std_logic_vector(to_unsigned(g_WIDTH, counter'length));
qr <= (g_WIDTH-1 downto 0 => '0') & dividend_i;
divisor_r <= divisor_i;
elsif ready = '0' then
if diff(g_WIDTH) = '1' then
qr <= qr(2*g_WIDTH-2 downto 0) & "0";
else
qr <= diff(g_WIDTH-1 downto 0) & qr(g_WIDTH-2 downto 0) & "1";
end if;
counter <= std_logic_vector(unsigned(counter) - 1);
end if;
end if;
end if;
end process;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_freqc.vhd 0000664 0000000 0000000 00000013040 11653767173 0024213 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_freqc
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Frequency counter
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-13 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- Counts the number of rising edges in clk_m_i for 2^g_TIMER_WIDTH-1 periods
-- of clk_i and returns the result. All signals are synchronous to clk_i.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.tdc_package.all;
entity tdc_freqc is
generic(
g_COUNTER_WIDTH : positive;
g_TIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
clk_m_i : in std_logic;
start_i : in std_logic;
ready_o : out std_logic;
freq_o : out std_logic_vector(g_COUNTER_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_freqc is
-- clk_m domain
signal m_counter : std_logic_vector(g_COUNTER_WIDTH-1 downto 0);
signal m_start : std_logic;
signal m_stop : std_logic;
signal m_started : std_logic;
-- clk domain
signal start : std_logic;
signal stop : std_logic;
signal stop_ack : std_logic;
signal counter_r : std_logic_vector(g_COUNTER_WIDTH-1 downto 0);
signal timer : std_logic_vector(g_TIMER_WIDTH-1 downto 0);
signal timer_start : std_logic;
signal timer_done : std_logic;
type t_state is (IDLE, MEASURING, TERMINATING);
signal state : t_state;
-- Prevent inference of a SRL* primitive, which does not
-- have good metastability resistance.
attribute keep: string;
attribute keep of counter_r: signal is "true";
begin
-- clk_m clock domain.
process(clk_m_i)
begin
if rising_edge(clk_m_i) then
if (m_started = '1') and (m_stop = '0') then
m_counter <= std_logic_vector(unsigned(m_counter) + 1);
end if;
if m_start = '1' then
m_started <= '1';
m_counter <= (m_counter'range => '0');
end if;
if m_stop = '1' then
m_started <= '0';
end if;
end if;
end process;
-- Synchronisers.
cmp_sync_start: tdc_psync
port map(
clk_src_i => clk_i,
p_i => start,
clk_dst_i => clk_m_i,
p_o => m_start
);
cmp_sync_stop: tdc_psync
port map(
clk_src_i => clk_i,
p_i => stop,
clk_dst_i => clk_m_i,
p_o => m_stop
);
cmp_sync_stop_ack: tdc_psync
port map(
clk_src_i => clk_m_i,
p_i => m_stop,
clk_dst_i => clk_i,
p_o => stop_ack
);
process(clk_i)
begin
if rising_edge(clk_i) then
counter_r <= m_counter;
freq_o <= counter_r;
end if;
end process;
-- Controller.
process(clk_i)
begin
if rising_edge(clk_i) then
if timer_start = '1' then
timer <= (timer'range => '1');
elsif timer_done = '0' then
timer <= std_logic_vector(unsigned(timer) - 1);
end if;
end if;
end process;
timer_done <= '1' when (timer = (timer'range => '0')) else '0';
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
state <= IDLE;
else
case state is
when IDLE =>
if start_i = '1' then
state <= MEASURING;
end if;
when MEASURING =>
if timer_done = '1' then
state <= TERMINATING;
end if;
when TERMINATING =>
if stop_ack = '1' then
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
process(state, start_i, timer_done, stop_ack)
begin
ready_o <= '0';
start <= '0';
stop <= '0';
timer_start <= '0';
case state is
when IDLE =>
ready_o <= '1';
if start_i = '1' then
start <= '1';
timer_start <= '1';
end if;
when MEASURING =>
if timer_done = '1' then
stop <= '1';
end if;
when TERMINATING =>
null;
end case;
end process;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_lbc.vhd 0000664 0000000 0000000 00000011233 11653767173 0023655 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_lbc
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Leading bit counter
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-27 SB Fix pipeline balance
-- 2011-08-01 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- Encoder for the delay line. Counts the number of leading bits equal to the
-- current polarity. The current polarity is the opposite of the most
-- significant bit of the input vector from the previous cycle.
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.tdc_package.all;
entity tdc_lbc is
generic(
-- Number of output bits.
g_N : positive;
-- Number of input bits. Maximum is 2^g_N-1.
g_NIN: positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
d_i : in std_logic_vector(g_NIN-1 downto 0);
polarity_o : out std_logic;
count_o : out std_logic_vector(g_N-1 downto 0)
);
end entity;
architecture rtl of tdc_lbc is
-- "Count leading symbol" function inspired by the post by Ulf Samuelsson
-- http://www.velocityreviews.com/forums/t25846-p4-how-to-count-zeros-in-registers.html
--
-- The idea is to use a divide-and-conquer approach to process a 2^N bit number.
-- We split the number in two equal halves of 2^(N-1) bits:
-- MMMMLLLL
-- then, we check if all bits of MMMM are of the counted symbol.
-- If it is,
-- then the number of leading symbols is 2^(N-1) + CLS(LLLL)
-- If it is not,
-- then the number of leading symbols is CLS(MMMM)
-- Recursion stops with CLS(0)=0 and CLS(1)=1.
--
-- If at least one bit of the input is not the symbol, we never propagate a carry
-- and the additions can be replaced by OR's, giving the result bit per bit.
-- We assume here an implicit LSB with a !symbol value, and work with inputs
-- widths that are a power of 2 minus one.
function f_cls(d: std_logic_vector; symbol: std_logic) return std_logic_vector is
variable v_d: std_logic_vector(d'length-1 downto 0);
begin
v_d := d; -- fix indices
if v_d'length = 1 then
if v_d(0) = symbol then
return "1";
else
return "0";
end if;
else
if v_d(v_d'length-1 downto v_d'length/2) = (v_d'length-1 downto v_d'length/2 => symbol) then
return "1" & f_cls(v_d(v_d'length/2-1 downto 0), symbol);
else
return "0" & f_cls(v_d(v_d'length-1 downto v_d'length/2+1), symbol);
end if;
end if;
end function;
signal polarity : std_logic;
signal polarity_d1 : std_logic;
signal count : std_logic_vector(g_N-1 downto 0);
signal count_d1 : std_logic_vector(g_N-1 downto 0);
signal d_completed : std_logic_vector(2**g_N-2 downto 0);
-- enable retiming
attribute register_balancing: string;
attribute register_balancing of count: signal is "backward";
attribute register_balancing of count_d1: signal is "backward";
begin
g_expand: if g_NIN < 2**g_N-1 generate
d_completed <= d_i & (2**g_N-1-g_NIN-1 downto 0 => not polarity);
end generate;
g_dontexpand: if g_NIN = 2**g_N-1 generate
d_completed <= d_i;
end generate;
process(clk_i)
begin
if rising_edge(clk_i) then
if reset_i = '1' then
polarity <= '1';
polarity_d1 <= '1';
count <= (others => '0');
count_d1 <= (others => '0');
else
polarity <= not d_completed(2**g_N-2);
polarity_d1 <= not polarity;
count <= f_cls(d_completed, polarity);
count_d1 <= count;
end if;
end if;
end process;
polarity_o <= polarity_d1;
count_o <= count_d1;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_ordertaps.vhd 0000664 0000000 0000000 00000060765 11653767173 0025136 0 ustar 00root root 0000000 0000000
-- This file was autogenerated by ordertaps.py
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.tdc_package.all;
entity tdc_ordertaps is
generic(
g_WIDTH: positive
);
port(
unsorted_i : in std_logic_vector(4*g_WIDTH-1 downto 0);
sorted_o : out std_logic_vector(4*g_WIDTH-1 downto 0)
);
end entity;
architecture rtl of tdc_ordertaps is
begin
sorted_o(0) <= unsorted_i(0); -- 0.843 ns
sorted_o(1) <= unsorted_i(1); -- 0.893 ns
sorted_o(2) <= unsorted_i(2); -- 0.894 ns
sorted_o(3) <= unsorted_i(3); -- 0.943 ns
sorted_o(4) <= unsorted_i(4); -- 0.965 ns
sorted_o(5) <= unsorted_i(5); -- 1.021 ns
sorted_o(6) <= unsorted_i(7); -- 1.023 ns
sorted_o(7) <= unsorted_i(6); -- 1.037 ns
sorted_o(8) <= unsorted_i(8); -- 1.046 ns
sorted_o(9) <= unsorted_i(9); -- 1.102 ns
sorted_o(10) <= unsorted_i(11); -- 1.104 ns
sorted_o(11) <= unsorted_i(10); -- 1.118 ns
sorted_o(12) <= unsorted_i(12); -- 1.128 ns
sorted_o(13) <= unsorted_i(13); -- 1.184 ns
sorted_o(14) <= unsorted_i(15); -- 1.186 ns
sorted_o(15) <= unsorted_i(14); -- 1.200 ns
sorted_o(16) <= unsorted_i(16); -- 1.209 ns
sorted_o(17) <= unsorted_i(17); -- 1.265 ns
sorted_o(18) <= unsorted_i(19); -- 1.267 ns
sorted_o(19) <= unsorted_i(18); -- 1.281 ns
sorted_o(20) <= unsorted_i(20); -- 1.290 ns
sorted_o(21) <= unsorted_i(21); -- 1.346 ns
sorted_o(22) <= unsorted_i(23); -- 1.348 ns
sorted_o(23) <= unsorted_i(22); -- 1.362 ns
sorted_o(24) <= unsorted_i(24); -- 1.448 ns
sorted_o(25) <= unsorted_i(25); -- 1.504 ns
sorted_o(26) <= unsorted_i(27); -- 1.506 ns
sorted_o(27) <= unsorted_i(26); -- 1.520 ns
sorted_o(28) <= unsorted_i(28); -- 1.525 ns
sorted_o(29) <= unsorted_i(29); -- 1.581 ns
sorted_o(30) <= unsorted_i(31); -- 1.583 ns
sorted_o(31) <= unsorted_i(30); -- 1.597 ns
sorted_o(32) <= unsorted_i(32); -- 1.602 ns
sorted_o(33) <= unsorted_i(33); -- 1.658 ns
sorted_o(34) <= unsorted_i(35); -- 1.660 ns
sorted_o(35) <= unsorted_i(34); -- 1.674 ns
sorted_o(36) <= unsorted_i(36); -- 1.678 ns
sorted_o(37) <= unsorted_i(37); -- 1.734 ns
sorted_o(38) <= unsorted_i(39); -- 1.736 ns
sorted_o(39) <= unsorted_i(38); -- 1.750 ns
sorted_o(40) <= unsorted_i(40); -- 1.755 ns
sorted_o(41) <= unsorted_i(41); -- 1.811 ns
sorted_o(42) <= unsorted_i(43); -- 1.813 ns
sorted_o(43) <= unsorted_i(42); -- 1.827 ns
sorted_o(44) <= unsorted_i(44); -- 1.832 ns
sorted_o(45) <= unsorted_i(45); -- 1.888 ns
sorted_o(46) <= unsorted_i(47); -- 1.890 ns
sorted_o(47) <= unsorted_i(46); -- 1.904 ns
sorted_o(48) <= unsorted_i(48); -- 1.910 ns
sorted_o(49) <= unsorted_i(49); -- 1.966 ns
sorted_o(50) <= unsorted_i(51); -- 1.968 ns
sorted_o(51) <= unsorted_i(50); -- 1.982 ns
sorted_o(52) <= unsorted_i(52); -- 1.988 ns
sorted_o(53) <= unsorted_i(53); -- 2.044 ns
sorted_o(54) <= unsorted_i(55); -- 2.046 ns
sorted_o(55) <= unsorted_i(54); -- 2.060 ns
sorted_o(56) <= unsorted_i(56); -- 2.095 ns
sorted_o(57) <= unsorted_i(57); -- 2.151 ns
sorted_o(58) <= unsorted_i(59); -- 2.153 ns
sorted_o(59) <= unsorted_i(58); -- 2.167 ns
sorted_o(60) <= unsorted_i(60); -- 2.175 ns
sorted_o(61) <= unsorted_i(61); -- 2.231 ns
sorted_o(62) <= unsorted_i(63); -- 2.233 ns
sorted_o(63) <= unsorted_i(62); -- 2.247 ns
sorted_o(64) <= unsorted_i(64); -- 2.255 ns
sorted_o(65) <= unsorted_i(65); -- 2.311 ns
sorted_o(66) <= unsorted_i(67); -- 2.313 ns
sorted_o(67) <= unsorted_i(66); -- 2.327 ns
sorted_o(68) <= unsorted_i(68); -- 2.335 ns
sorted_o(69) <= unsorted_i(69); -- 2.391 ns
sorted_o(70) <= unsorted_i(71); -- 2.393 ns
sorted_o(71) <= unsorted_i(70); -- 2.407 ns
sorted_o(72) <= unsorted_i(72); -- 2.417 ns
sorted_o(73) <= unsorted_i(73); -- 2.473 ns
sorted_o(74) <= unsorted_i(75); -- 2.475 ns
sorted_o(75) <= unsorted_i(74); -- 2.489 ns
sorted_o(76) <= unsorted_i(76); -- 2.498 ns
sorted_o(77) <= unsorted_i(77); -- 2.554 ns
sorted_o(78) <= unsorted_i(79); -- 2.556 ns
sorted_o(79) <= unsorted_i(78); -- 2.570 ns
sorted_o(80) <= unsorted_i(80); -- 2.580 ns
sorted_o(81) <= unsorted_i(81); -- 2.636 ns
sorted_o(82) <= unsorted_i(83); -- 2.638 ns
sorted_o(83) <= unsorted_i(82); -- 2.652 ns
sorted_o(84) <= unsorted_i(84); -- 2.661 ns
sorted_o(85) <= unsorted_i(85); -- 2.717 ns
sorted_o(86) <= unsorted_i(87); -- 2.719 ns
sorted_o(87) <= unsorted_i(86); -- 2.733 ns
sorted_o(88) <= unsorted_i(88); -- 2.819 ns
sorted_o(89) <= unsorted_i(89); -- 2.875 ns
sorted_o(90) <= unsorted_i(91); -- 2.877 ns
sorted_o(91) <= unsorted_i(90); -- 2.891 ns
sorted_o(92) <= unsorted_i(92); -- 2.896 ns
sorted_o(93) <= unsorted_i(93); -- 2.952 ns
sorted_o(94) <= unsorted_i(95); -- 2.954 ns
sorted_o(95) <= unsorted_i(94); -- 2.968 ns
sorted_o(96) <= unsorted_i(96); -- 2.972 ns
sorted_o(97) <= unsorted_i(97); -- 3.028 ns
sorted_o(98) <= unsorted_i(99); -- 3.030 ns
sorted_o(99) <= unsorted_i(98); -- 3.044 ns
sorted_o(100) <= unsorted_i(100); -- 3.049 ns
sorted_o(101) <= unsorted_i(101); -- 3.105 ns
sorted_o(102) <= unsorted_i(103); -- 3.107 ns
sorted_o(103) <= unsorted_i(102); -- 3.121 ns
sorted_o(104) <= unsorted_i(104); -- 3.125 ns
sorted_o(105) <= unsorted_i(105); -- 3.181 ns
sorted_o(106) <= unsorted_i(107); -- 3.183 ns
sorted_o(107) <= unsorted_i(106); -- 3.197 ns
sorted_o(108) <= unsorted_i(108); -- 3.203 ns
sorted_o(109) <= unsorted_i(109); -- 3.259 ns
sorted_o(110) <= unsorted_i(111); -- 3.261 ns
sorted_o(111) <= unsorted_i(110); -- 3.275 ns
sorted_o(112) <= unsorted_i(112); -- 3.281 ns
sorted_o(113) <= unsorted_i(113); -- 3.337 ns
sorted_o(114) <= unsorted_i(115); -- 3.339 ns
sorted_o(115) <= unsorted_i(114); -- 3.353 ns
sorted_o(116) <= unsorted_i(116); -- 3.359 ns
sorted_o(117) <= unsorted_i(117); -- 3.415 ns
sorted_o(118) <= unsorted_i(119); -- 3.417 ns
sorted_o(119) <= unsorted_i(118); -- 3.431 ns
sorted_o(120) <= unsorted_i(120); -- 3.441 ns
sorted_o(121) <= unsorted_i(121); -- 3.497 ns
sorted_o(122) <= unsorted_i(123); -- 3.499 ns
sorted_o(123) <= unsorted_i(122); -- 3.513 ns
sorted_o(124) <= unsorted_i(124); -- 3.521 ns
sorted_o(125) <= unsorted_i(125); -- 3.577 ns
sorted_o(126) <= unsorted_i(127); -- 3.579 ns
sorted_o(127) <= unsorted_i(126); -- 3.593 ns
sorted_o(128) <= unsorted_i(128); -- 3.601 ns
sorted_o(129) <= unsorted_i(129); -- 3.657 ns
sorted_o(130) <= unsorted_i(131); -- 3.659 ns
sorted_o(131) <= unsorted_i(130); -- 3.673 ns
sorted_o(132) <= unsorted_i(132); -- 3.681 ns
sorted_o(133) <= unsorted_i(133); -- 3.737 ns
sorted_o(134) <= unsorted_i(135); -- 3.739 ns
sorted_o(135) <= unsorted_i(134); -- 3.753 ns
sorted_o(136) <= unsorted_i(136); -- 3.762 ns
sorted_o(137) <= unsorted_i(137); -- 3.818 ns
sorted_o(138) <= unsorted_i(139); -- 3.820 ns
sorted_o(139) <= unsorted_i(138); -- 3.834 ns
sorted_o(140) <= unsorted_i(140); -- 3.844 ns
sorted_o(141) <= unsorted_i(141); -- 3.900 ns
sorted_o(142) <= unsorted_i(143); -- 3.902 ns
sorted_o(143) <= unsorted_i(142); -- 3.916 ns
sorted_o(144) <= unsorted_i(144); -- 3.926 ns
sorted_o(145) <= unsorted_i(145); -- 3.982 ns
sorted_o(146) <= unsorted_i(147); -- 3.984 ns
sorted_o(147) <= unsorted_i(146); -- 3.998 ns
sorted_o(148) <= unsorted_i(148); -- 4.007 ns
sorted_o(149) <= unsorted_i(149); -- 4.063 ns
sorted_o(150) <= unsorted_i(151); -- 4.065 ns
sorted_o(151) <= unsorted_i(150); -- 4.079 ns
sorted_o(152) <= unsorted_i(152); -- 4.165 ns
sorted_o(153) <= unsorted_i(153); -- 4.221 ns
sorted_o(154) <= unsorted_i(155); -- 4.223 ns
sorted_o(155) <= unsorted_i(154); -- 4.237 ns
sorted_o(156) <= unsorted_i(156); -- 4.242 ns
sorted_o(157) <= unsorted_i(157); -- 4.298 ns
sorted_o(158) <= unsorted_i(159); -- 4.300 ns
sorted_o(159) <= unsorted_i(158); -- 4.314 ns
sorted_o(160) <= unsorted_i(160); -- 4.318 ns
sorted_o(161) <= unsorted_i(161); -- 4.374 ns
sorted_o(162) <= unsorted_i(163); -- 4.376 ns
sorted_o(163) <= unsorted_i(162); -- 4.390 ns
sorted_o(164) <= unsorted_i(164); -- 4.394 ns
sorted_o(165) <= unsorted_i(165); -- 4.450 ns
sorted_o(166) <= unsorted_i(167); -- 4.452 ns
sorted_o(167) <= unsorted_i(166); -- 4.466 ns
sorted_o(168) <= unsorted_i(168); -- 4.471 ns
sorted_o(169) <= unsorted_i(169); -- 4.527 ns
sorted_o(170) <= unsorted_i(171); -- 4.529 ns
sorted_o(171) <= unsorted_i(170); -- 4.543 ns
sorted_o(172) <= unsorted_i(172); -- 4.549 ns
sorted_o(173) <= unsorted_i(173); -- 4.605 ns
sorted_o(174) <= unsorted_i(175); -- 4.607 ns
sorted_o(175) <= unsorted_i(174); -- 4.621 ns
sorted_o(176) <= unsorted_i(176); -- 4.627 ns
sorted_o(177) <= unsorted_i(177); -- 4.683 ns
sorted_o(178) <= unsorted_i(179); -- 4.685 ns
sorted_o(179) <= unsorted_i(178); -- 4.699 ns
sorted_o(180) <= unsorted_i(180); -- 4.705 ns
sorted_o(181) <= unsorted_i(184); -- 4.758 ns
sorted_o(182) <= unsorted_i(181); -- 4.761 ns
sorted_o(183) <= unsorted_i(183); -- 4.763 ns
sorted_o(184) <= unsorted_i(182); -- 4.777 ns
sorted_o(185) <= unsorted_i(185); -- 4.814 ns
sorted_o(186) <= unsorted_i(187); -- 4.816 ns
sorted_o(187) <= unsorted_i(186); -- 4.830 ns
sorted_o(188) <= unsorted_i(188); -- 4.838 ns
sorted_o(189) <= unsorted_i(189); -- 4.894 ns
sorted_o(190) <= unsorted_i(191); -- 4.896 ns
sorted_o(191) <= unsorted_i(190); -- 4.910 ns
sorted_o(192) <= unsorted_i(192); -- 4.918 ns
sorted_o(193) <= unsorted_i(193); -- 4.974 ns
sorted_o(194) <= unsorted_i(195); -- 4.976 ns
sorted_o(195) <= unsorted_i(194); -- 4.990 ns
sorted_o(196) <= unsorted_i(196); -- 4.998 ns
sorted_o(197) <= unsorted_i(197); -- 5.054 ns
sorted_o(198) <= unsorted_i(199); -- 5.056 ns
sorted_o(199) <= unsorted_i(198); -- 5.070 ns
sorted_o(200) <= unsorted_i(200); -- 5.079 ns
sorted_o(201) <= unsorted_i(201); -- 5.135 ns
sorted_o(202) <= unsorted_i(203); -- 5.137 ns
sorted_o(203) <= unsorted_i(202); -- 5.151 ns
sorted_o(204) <= unsorted_i(204); -- 5.161 ns
sorted_o(205) <= unsorted_i(205); -- 5.217 ns
sorted_o(206) <= unsorted_i(207); -- 5.219 ns
sorted_o(207) <= unsorted_i(206); -- 5.233 ns
sorted_o(208) <= unsorted_i(208); -- 5.243 ns
sorted_o(209) <= unsorted_i(209); -- 5.299 ns
sorted_o(210) <= unsorted_i(211); -- 5.301 ns
sorted_o(211) <= unsorted_i(210); -- 5.315 ns
sorted_o(212) <= unsorted_i(212); -- 5.324 ns
sorted_o(213) <= unsorted_i(213); -- 5.380 ns
sorted_o(214) <= unsorted_i(215); -- 5.382 ns
sorted_o(215) <= unsorted_i(214); -- 5.396 ns
sorted_o(216) <= unsorted_i(216); -- 5.482 ns
sorted_o(217) <= unsorted_i(217); -- 5.538 ns
sorted_o(218) <= unsorted_i(219); -- 5.540 ns
sorted_o(219) <= unsorted_i(218); -- 5.554 ns
sorted_o(220) <= unsorted_i(220); -- 5.559 ns
sorted_o(221) <= unsorted_i(221); -- 5.615 ns
sorted_o(222) <= unsorted_i(223); -- 5.617 ns
sorted_o(223) <= unsorted_i(222); -- 5.631 ns
sorted_o(224) <= unsorted_i(224); -- 5.635 ns
sorted_o(225) <= unsorted_i(225); -- 5.691 ns
sorted_o(226) <= unsorted_i(227); -- 5.693 ns
sorted_o(227) <= unsorted_i(226); -- 5.707 ns
sorted_o(228) <= unsorted_i(228); -- 5.711 ns
sorted_o(229) <= unsorted_i(229); -- 5.767 ns
sorted_o(230) <= unsorted_i(231); -- 5.769 ns
sorted_o(231) <= unsorted_i(230); -- 5.783 ns
sorted_o(232) <= unsorted_i(232); -- 5.788 ns
sorted_o(233) <= unsorted_i(233); -- 5.844 ns
sorted_o(234) <= unsorted_i(235); -- 5.846 ns
sorted_o(235) <= unsorted_i(234); -- 5.860 ns
sorted_o(236) <= unsorted_i(236); -- 5.866 ns
sorted_o(237) <= unsorted_i(237); -- 5.922 ns
sorted_o(238) <= unsorted_i(239); -- 5.924 ns
sorted_o(239) <= unsorted_i(238); -- 5.938 ns
sorted_o(240) <= unsorted_i(240); -- 5.944 ns
sorted_o(241) <= unsorted_i(241); -- 6.000 ns
sorted_o(242) <= unsorted_i(243); -- 6.002 ns
sorted_o(243) <= unsorted_i(242); -- 6.016 ns
sorted_o(244) <= unsorted_i(244); -- 6.022 ns
sorted_o(245) <= unsorted_i(245); -- 6.078 ns
sorted_o(246) <= unsorted_i(247); -- 6.080 ns
sorted_o(247) <= unsorted_i(246); -- 6.094 ns
sorted_o(248) <= unsorted_i(248); -- 6.206 ns
sorted_o(249) <= unsorted_i(249); -- 6.262 ns
sorted_o(250) <= unsorted_i(251); -- 6.264 ns
sorted_o(251) <= unsorted_i(250); -- 6.278 ns
sorted_o(252) <= unsorted_i(252); -- 6.286 ns
sorted_o(253) <= unsorted_i(253); -- 6.342 ns
sorted_o(254) <= unsorted_i(255); -- 6.344 ns
sorted_o(255) <= unsorted_i(254); -- 6.358 ns
sorted_o(256) <= unsorted_i(256); -- 6.366 ns
sorted_o(257) <= unsorted_i(257); -- 6.422 ns
sorted_o(258) <= unsorted_i(259); -- 6.424 ns
sorted_o(259) <= unsorted_i(258); -- 6.438 ns
sorted_o(260) <= unsorted_i(260); -- 6.446 ns
sorted_o(261) <= unsorted_i(261); -- 6.502 ns
sorted_o(262) <= unsorted_i(263); -- 6.504 ns
sorted_o(263) <= unsorted_i(262); -- 6.518 ns
sorted_o(264) <= unsorted_i(264); -- 6.527 ns
sorted_o(265) <= unsorted_i(265); -- 6.583 ns
sorted_o(266) <= unsorted_i(267); -- 6.585 ns
sorted_o(267) <= unsorted_i(266); -- 6.599 ns
sorted_o(268) <= unsorted_i(268); -- 6.609 ns
sorted_o(269) <= unsorted_i(269); -- 6.665 ns
sorted_o(270) <= unsorted_i(271); -- 6.667 ns
sorted_o(271) <= unsorted_i(270); -- 6.681 ns
sorted_o(272) <= unsorted_i(272); -- 6.691 ns
sorted_o(273) <= unsorted_i(273); -- 6.747 ns
sorted_o(274) <= unsorted_i(275); -- 6.749 ns
sorted_o(275) <= unsorted_i(274); -- 6.763 ns
sorted_o(276) <= unsorted_i(276); -- 6.772 ns
sorted_o(277) <= unsorted_i(277); -- 6.828 ns
sorted_o(278) <= unsorted_i(279); -- 6.830 ns
sorted_o(279) <= unsorted_i(278); -- 6.844 ns
sorted_o(280) <= unsorted_i(280); -- 6.930 ns
sorted_o(281) <= unsorted_i(281); -- 6.986 ns
sorted_o(282) <= unsorted_i(283); -- 6.988 ns
sorted_o(283) <= unsorted_i(282); -- 7.002 ns
sorted_o(284) <= unsorted_i(284); -- 7.007 ns
sorted_o(285) <= unsorted_i(285); -- 7.063 ns
sorted_o(286) <= unsorted_i(287); -- 7.065 ns
sorted_o(287) <= unsorted_i(286); -- 7.079 ns
sorted_o(288) <= unsorted_i(288); -- 7.083 ns
sorted_o(289) <= unsorted_i(289); -- 7.139 ns
sorted_o(290) <= unsorted_i(291); -- 7.141 ns
sorted_o(291) <= unsorted_i(290); -- 7.155 ns
sorted_o(292) <= unsorted_i(292); -- 7.159 ns
sorted_o(293) <= unsorted_i(293); -- 7.215 ns
sorted_o(294) <= unsorted_i(295); -- 7.217 ns
sorted_o(295) <= unsorted_i(294); -- 7.231 ns
sorted_o(296) <= unsorted_i(296); -- 7.236 ns
sorted_o(297) <= unsorted_i(297); -- 7.292 ns
sorted_o(298) <= unsorted_i(299); -- 7.294 ns
sorted_o(299) <= unsorted_i(298); -- 7.308 ns
sorted_o(300) <= unsorted_i(300); -- 7.314 ns
sorted_o(301) <= unsorted_i(301); -- 7.370 ns
sorted_o(302) <= unsorted_i(303); -- 7.372 ns
sorted_o(303) <= unsorted_i(302); -- 7.386 ns
sorted_o(304) <= unsorted_i(304); -- 7.392 ns
sorted_o(305) <= unsorted_i(305); -- 7.448 ns
sorted_o(306) <= unsorted_i(307); -- 7.450 ns
sorted_o(307) <= unsorted_i(306); -- 7.464 ns
sorted_o(308) <= unsorted_i(308); -- 7.470 ns
sorted_o(309) <= unsorted_i(309); -- 7.526 ns
sorted_o(310) <= unsorted_i(311); -- 7.528 ns
sorted_o(311) <= unsorted_i(310); -- 7.542 ns
sorted_o(312) <= unsorted_i(312); -- 7.575 ns
sorted_o(313) <= unsorted_i(313); -- 7.631 ns
sorted_o(314) <= unsorted_i(315); -- 7.633 ns
sorted_o(315) <= unsorted_i(314); -- 7.647 ns
sorted_o(316) <= unsorted_i(316); -- 7.655 ns
sorted_o(317) <= unsorted_i(317); -- 7.711 ns
sorted_o(318) <= unsorted_i(319); -- 7.713 ns
sorted_o(319) <= unsorted_i(318); -- 7.727 ns
sorted_o(320) <= unsorted_i(320); -- 7.735 ns
sorted_o(321) <= unsorted_i(321); -- 7.791 ns
sorted_o(322) <= unsorted_i(323); -- 7.793 ns
sorted_o(323) <= unsorted_i(322); -- 7.807 ns
sorted_o(324) <= unsorted_i(324); -- 7.815 ns
sorted_o(325) <= unsorted_i(325); -- 7.871 ns
sorted_o(326) <= unsorted_i(327); -- 7.873 ns
sorted_o(327) <= unsorted_i(326); -- 7.887 ns
sorted_o(328) <= unsorted_i(328); -- 7.896 ns
sorted_o(329) <= unsorted_i(329); -- 7.952 ns
sorted_o(330) <= unsorted_i(331); -- 7.954 ns
sorted_o(331) <= unsorted_i(330); -- 7.968 ns
sorted_o(332) <= unsorted_i(332); -- 7.978 ns
sorted_o(333) <= unsorted_i(333); -- 8.034 ns
sorted_o(334) <= unsorted_i(335); -- 8.036 ns
sorted_o(335) <= unsorted_i(334); -- 8.050 ns
sorted_o(336) <= unsorted_i(336); -- 8.060 ns
sorted_o(337) <= unsorted_i(337); -- 8.116 ns
sorted_o(338) <= unsorted_i(339); -- 8.118 ns
sorted_o(339) <= unsorted_i(338); -- 8.132 ns
sorted_o(340) <= unsorted_i(340); -- 8.141 ns
sorted_o(341) <= unsorted_i(341); -- 8.197 ns
sorted_o(342) <= unsorted_i(343); -- 8.199 ns
sorted_o(343) <= unsorted_i(342); -- 8.213 ns
sorted_o(344) <= unsorted_i(344); -- 8.299 ns
sorted_o(345) <= unsorted_i(345); -- 8.355 ns
sorted_o(346) <= unsorted_i(347); -- 8.357 ns
sorted_o(347) <= unsorted_i(346); -- 8.371 ns
sorted_o(348) <= unsorted_i(348); -- 8.376 ns
sorted_o(349) <= unsorted_i(349); -- 8.432 ns
sorted_o(350) <= unsorted_i(351); -- 8.434 ns
sorted_o(351) <= unsorted_i(350); -- 8.448 ns
sorted_o(352) <= unsorted_i(352); -- 8.452 ns
sorted_o(353) <= unsorted_i(353); -- 8.508 ns
sorted_o(354) <= unsorted_i(355); -- 8.510 ns
sorted_o(355) <= unsorted_i(354); -- 8.524 ns
sorted_o(356) <= unsorted_i(356); -- 8.528 ns
sorted_o(357) <= unsorted_i(357); -- 8.584 ns
sorted_o(358) <= unsorted_i(359); -- 8.586 ns
sorted_o(359) <= unsorted_i(358); -- 8.600 ns
sorted_o(360) <= unsorted_i(360); -- 8.605 ns
sorted_o(361) <= unsorted_i(361); -- 8.661 ns
sorted_o(362) <= unsorted_i(363); -- 8.663 ns
sorted_o(363) <= unsorted_i(362); -- 8.677 ns
sorted_o(364) <= unsorted_i(364); -- 8.683 ns
sorted_o(365) <= unsorted_i(365); -- 8.739 ns
sorted_o(366) <= unsorted_i(367); -- 8.741 ns
sorted_o(367) <= unsorted_i(366); -- 8.755 ns
sorted_o(368) <= unsorted_i(368); -- 8.761 ns
sorted_o(369) <= unsorted_i(369); -- 8.817 ns
sorted_o(370) <= unsorted_i(371); -- 8.819 ns
sorted_o(371) <= unsorted_i(370); -- 8.833 ns
sorted_o(372) <= unsorted_i(372); -- 8.839 ns
sorted_o(373) <= unsorted_i(373); -- 8.895 ns
sorted_o(374) <= unsorted_i(375); -- 8.897 ns
sorted_o(375) <= unsorted_i(374); -- 8.911 ns
sorted_o(376) <= unsorted_i(376); -- 8.931 ns
sorted_o(377) <= unsorted_i(377); -- 8.987 ns
sorted_o(378) <= unsorted_i(379); -- 8.989 ns
sorted_o(379) <= unsorted_i(378); -- 9.003 ns
sorted_o(380) <= unsorted_i(380); -- 9.010 ns
sorted_o(381) <= unsorted_i(381); -- 9.066 ns
sorted_o(382) <= unsorted_i(383); -- 9.068 ns
sorted_o(383) <= unsorted_i(382); -- 9.082 ns
sorted_o(384) <= unsorted_i(384); -- 9.090 ns
sorted_o(385) <= unsorted_i(385); -- 9.146 ns
sorted_o(386) <= unsorted_i(387); -- 9.148 ns
sorted_o(387) <= unsorted_i(386); -- 9.162 ns
sorted_o(388) <= unsorted_i(388); -- 9.171 ns
sorted_o(389) <= unsorted_i(389); -- 9.227 ns
sorted_o(390) <= unsorted_i(391); -- 9.229 ns
sorted_o(391) <= unsorted_i(390); -- 9.243 ns
sorted_o(392) <= unsorted_i(392); -- 9.252 ns
sorted_o(393) <= unsorted_i(393); -- 9.308 ns
sorted_o(394) <= unsorted_i(395); -- 9.310 ns
sorted_o(395) <= unsorted_i(394); -- 9.324 ns
sorted_o(396) <= unsorted_i(396); -- 9.334 ns
sorted_o(397) <= unsorted_i(397); -- 9.390 ns
sorted_o(398) <= unsorted_i(399); -- 9.392 ns
sorted_o(399) <= unsorted_i(398); -- 9.406 ns
sorted_o(400) <= unsorted_i(400); -- 9.415 ns
sorted_o(401) <= unsorted_i(401); -- 9.471 ns
sorted_o(402) <= unsorted_i(403); -- 9.473 ns
sorted_o(403) <= unsorted_i(402); -- 9.487 ns
sorted_o(404) <= unsorted_i(404); -- 9.497 ns
sorted_o(405) <= unsorted_i(405); -- 9.553 ns
sorted_o(406) <= unsorted_i(407); -- 9.555 ns
sorted_o(407) <= unsorted_i(406); -- 9.569 ns
sorted_o(408) <= unsorted_i(408); -- 9.655 ns
sorted_o(409) <= unsorted_i(409); -- 9.711 ns
sorted_o(410) <= unsorted_i(411); -- 9.713 ns
sorted_o(411) <= unsorted_i(410); -- 9.727 ns
sorted_o(412) <= unsorted_i(412); -- 9.731 ns
sorted_o(413) <= unsorted_i(413); -- 9.787 ns
sorted_o(414) <= unsorted_i(415); -- 9.789 ns
sorted_o(415) <= unsorted_i(414); -- 9.803 ns
sorted_o(416) <= unsorted_i(416); -- 9.808 ns
sorted_o(417) <= unsorted_i(417); -- 9.864 ns
sorted_o(418) <= unsorted_i(419); -- 9.866 ns
sorted_o(419) <= unsorted_i(418); -- 9.880 ns
sorted_o(420) <= unsorted_i(420); -- 9.884 ns
sorted_o(421) <= unsorted_i(421); -- 9.940 ns
sorted_o(422) <= unsorted_i(423); -- 9.942 ns
sorted_o(423) <= unsorted_i(422); -- 9.956 ns
sorted_o(424) <= unsorted_i(424); -- 9.961 ns
sorted_o(425) <= unsorted_i(425); -- 10.017 ns
sorted_o(426) <= unsorted_i(427); -- 10.019 ns
sorted_o(427) <= unsorted_i(426); -- 10.033 ns
sorted_o(428) <= unsorted_i(428); -- 10.038 ns
sorted_o(429) <= unsorted_i(429); -- 10.094 ns
sorted_o(430) <= unsorted_i(431); -- 10.096 ns
sorted_o(431) <= unsorted_i(430); -- 10.110 ns
sorted_o(432) <= unsorted_i(432); -- 10.116 ns
sorted_o(433) <= unsorted_i(433); -- 10.172 ns
sorted_o(434) <= unsorted_i(435); -- 10.174 ns
sorted_o(435) <= unsorted_i(434); -- 10.188 ns
sorted_o(436) <= unsorted_i(436); -- 10.195 ns
sorted_o(437) <= unsorted_i(440); -- 10.246 ns
sorted_o(438) <= unsorted_i(437); -- 10.251 ns
sorted_o(439) <= unsorted_i(439); -- 10.253 ns
sorted_o(440) <= unsorted_i(438); -- 10.267 ns
sorted_o(441) <= unsorted_i(441); -- 10.302 ns
sorted_o(442) <= unsorted_i(443); -- 10.304 ns
sorted_o(443) <= unsorted_i(442); -- 10.318 ns
sorted_o(444) <= unsorted_i(444); -- 10.325 ns
sorted_o(445) <= unsorted_i(445); -- 10.381 ns
sorted_o(446) <= unsorted_i(447); -- 10.383 ns
sorted_o(447) <= unsorted_i(446); -- 10.397 ns
sorted_o(448) <= unsorted_i(448); -- 10.405 ns
sorted_o(449) <= unsorted_i(449); -- 10.461 ns
sorted_o(450) <= unsorted_i(451); -- 10.463 ns
sorted_o(451) <= unsorted_i(450); -- 10.477 ns
sorted_o(452) <= unsorted_i(452); -- 10.486 ns
sorted_o(453) <= unsorted_i(453); -- 10.542 ns
sorted_o(454) <= unsorted_i(455); -- 10.544 ns
sorted_o(455) <= unsorted_i(454); -- 10.558 ns
sorted_o(456) <= unsorted_i(456); -- 10.567 ns
sorted_o(457) <= unsorted_i(457); -- 10.623 ns
sorted_o(458) <= unsorted_i(459); -- 10.625 ns
sorted_o(459) <= unsorted_i(458); -- 10.639 ns
sorted_o(460) <= unsorted_i(460); -- 10.649 ns
sorted_o(461) <= unsorted_i(461); -- 10.705 ns
sorted_o(462) <= unsorted_i(463); -- 10.707 ns
sorted_o(463) <= unsorted_i(462); -- 10.721 ns
sorted_o(464) <= unsorted_i(464); -- 10.731 ns
sorted_o(465) <= unsorted_i(465); -- 10.787 ns
sorted_o(466) <= unsorted_i(467); -- 10.789 ns
sorted_o(467) <= unsorted_i(466); -- 10.803 ns
sorted_o(468) <= unsorted_i(468); -- 10.812 ns
sorted_o(469) <= unsorted_i(469); -- 10.868 ns
sorted_o(470) <= unsorted_i(471); -- 10.870 ns
sorted_o(471) <= unsorted_i(470); -- 10.884 ns
sorted_o(472) <= unsorted_i(472); -- 10.970 ns
sorted_o(473) <= unsorted_i(473); -- 11.026 ns
sorted_o(474) <= unsorted_i(475); -- 11.028 ns
sorted_o(475) <= unsorted_i(474); -- 11.042 ns
sorted_o(476) <= unsorted_i(476); -- 11.047 ns
sorted_o(477) <= unsorted_i(477); -- 11.103 ns
sorted_o(478) <= unsorted_i(479); -- 11.105 ns
sorted_o(479) <= unsorted_i(478); -- 11.119 ns
sorted_o(480) <= unsorted_i(480); -- 11.123 ns
sorted_o(481) <= unsorted_i(481); -- 11.179 ns
sorted_o(482) <= unsorted_i(483); -- 11.181 ns
sorted_o(483) <= unsorted_i(482); -- 11.195 ns
sorted_o(484) <= unsorted_i(484); -- 11.199 ns
sorted_o(485) <= unsorted_i(485); -- 11.255 ns
sorted_o(486) <= unsorted_i(487); -- 11.257 ns
sorted_o(487) <= unsorted_i(486); -- 11.271 ns
sorted_o(488) <= unsorted_i(488); -- 11.276 ns
sorted_o(489) <= unsorted_i(489); -- 11.332 ns
sorted_o(490) <= unsorted_i(491); -- 11.334 ns
sorted_o(491) <= unsorted_i(490); -- 11.348 ns
sorted_o(492) <= unsorted_i(492); -- 11.354 ns
sorted_o(493) <= unsorted_i(493); -- 11.410 ns
sorted_o(494) <= unsorted_i(495); -- 11.412 ns
sorted_o(495) <= unsorted_i(494); -- 11.426 ns
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_package.vhd 0000664 0000000 0000000 00000033442 11653767173 0024516 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_package
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Component declarations for the TDC core
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-25 SB Added single/multi channel bank components
-- 2011-08-03 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- This contains component declarations for all the modules of the TDC core.
-- It is used both internally to instantiate modules, and by the user to
-- instantiate the top-level "tdc" module.
library ieee;
use ieee.std_logic_1164.all;
package tdc_package is
component tdc is
generic(
g_CHANNEL_COUNT : positive := 2;
g_CARRY4_COUNT : positive := 100;
g_RAW_COUNT : positive := 9;
g_FP_COUNT : positive := 13;
g_COARSE_COUNT : positive := 25;
g_RO_LENGTH : positive := 20;
g_FCOUNTER_WIDTH : positive := 13;
g_FTIMER_WIDTH : positive := 10
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
ready_o : out std_logic;
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
deskew_i : in std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
signal_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
calib_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
freeze_req_i : in std_logic;
freeze_ack_o : out std_logic;
cs_next_i : in std_logic;
cs_last_o : out std_logic;
calib_sel_i : in std_logic;
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end component;
component tdc_controller is
generic(
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_FCOUNTER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
ready_o : out std_logic;
next_o : out std_logic;
last_i : in std_logic;
calib_sel_o : out std_logic;
lut_a_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_o : out std_logic;
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
c_detect_i : in std_logic;
c_raw_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_o : out std_logic;
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_o : out std_logic;
oc_ready_i : in std_logic;
oc_freq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_o : out std_logic;
oc_sfreq_i : in std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
freeze_req_i : in std_logic;
freeze_ack_o : out std_logic
);
end component;
component tdc_channelbank is
generic(
g_CHANNEL_COUNT : positive;
g_CARRY4_COUNT : positive;
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_COARSE_COUNT : positive;
g_RO_LENGTH : positive;
g_FCOUNTER_WIDTH : positive;
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
deskew_i : in std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
signal_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
calib_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end component;
component tdc_channelbank_single is
generic(
g_CARRY4_COUNT : positive;
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_COARSE_COUNT : positive;
g_RO_LENGTH : positive;
g_FCOUNTER_WIDTH : positive;
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
deskew_i : in std_logic_vector(g_COARSE_COUNT+g_FP_COUNT-1 downto 0);
signal_i : in std_logic;
calib_i : in std_logic;
detect_o : out std_logic;
polarity_o : out std_logic;
raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_COARSE_COUNT+g_FP_COUNT-1 downto 0);
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end component;
component tdc_channelbank_multi is
generic(
g_CHANNEL_COUNT : positive;
g_CARRY4_COUNT : positive;
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_COARSE_COUNT : positive;
g_RO_LENGTH : positive;
g_FCOUNTER_WIDTH : positive;
g_FTIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
cc_rst_i : in std_logic;
cc_cy_o : out std_logic;
next_i : in std_logic;
last_o : out std_logic;
calib_sel_i : in std_logic;
deskew_i : in std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
signal_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
calib_i : in std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
detect_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
polarity_o : out std_logic_vector(g_CHANNEL_COUNT-1 downto 0);
raw_o : out std_logic_vector(g_CHANNEL_COUNT*g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector(g_CHANNEL_COUNT*(g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
c_detect_o : out std_logic;
c_raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
his_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
his_we_i : in std_logic;
his_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
his_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
oc_start_i : in std_logic;
oc_ready_o : out std_logic;
oc_freq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0);
oc_store_i : in std_logic;
oc_sfreq_o : out std_logic_vector(g_FCOUNTER_WIDTH-1 downto 0)
);
end component;
component tdc_freqc is
generic(
g_COUNTER_WIDTH : positive;
g_TIMER_WIDTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
clk_m_i : in std_logic;
start_i : in std_logic;
ready_o : out std_logic;
freq_o : out std_logic_vector(g_COUNTER_WIDTH-1 downto 0)
);
end component;
component tdc_channel is
generic(
g_CARRY4_COUNT : positive;
g_RAW_COUNT : positive;
g_FP_COUNT : positive;
g_COARSE_COUNT : positive;
g_RO_LENGTH : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
coarse_i : in std_logic_vector(g_COARSE_COUNT-1 downto 0);
deskew_i : in std_logic_vector((g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
signal_i : in std_logic;
calib_i : in std_logic;
calib_sel_i : in std_logic;
detect_o : out std_logic;
polarity_o : out std_logic;
raw_o : out std_logic_vector(g_RAW_COUNT-1 downto 0);
fp_o : out std_logic_vector((g_COARSE_COUNT+g_FP_COUNT)-1 downto 0);
lut_a_i : in std_logic_vector(g_RAW_COUNT-1 downto 0);
lut_we_i : in std_logic;
lut_d_i : in std_logic_vector(g_FP_COUNT-1 downto 0);
lut_d_o : out std_logic_vector(g_FP_COUNT-1 downto 0);
ro_en_i : in std_logic;
ro_clk_o : out std_logic
);
end component;
component tdc_ringosc is
generic(
g_LENGTH: positive
);
port(
en_i : in std_logic;
clk_o : out std_logic
);
end component;
component tdc_lbc is
generic(
g_N : positive;
g_NIN : positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
d_i : in std_logic_vector(g_NIN-1 downto 0);
polarity_o : out std_logic;
count_o : out std_logic_vector(g_N-1 downto 0)
);
end component;
component tdc_delayline is
generic(
g_WIDTH: positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
signal_i : in std_logic;
taps_o : out std_logic_vector(4*g_WIDTH-1 downto 0)
);
end component;
component tdc_ordertaps is
generic(
g_WIDTH: positive
);
port(
unsorted_i : in std_logic_vector(4*g_WIDTH-1 downto 0);
sorted_o : out std_logic_vector(4*g_WIDTH-1 downto 0)
);
end component;
component tdc_divider is
generic(
g_WIDTH: positive
);
port(
clk_i : in std_logic;
reset_i : in std_logic;
start_i : in std_logic;
dividend_i : in std_logic_vector(g_WIDTH-1 downto 0);
divisor_i : in std_logic_vector(g_WIDTH-1 downto 0);
ready_o : out std_logic;
quotient_o : out std_logic_vector(g_WIDTH-1 downto 0);
remainder_o : out std_logic_vector(g_WIDTH-1 downto 0)
);
end component;
component tdc_psync is
port(
clk_src_i : in std_logic;
p_i : in std_logic;
clk_dst_i : in std_logic;
p_o : out std_logic
);
end component;
end package;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_psync.vhd 0000664 0000000 0000000 00000005614 11653767173 0024257 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_psync
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Pulse synchronizer
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-14 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- Converts a single clock cycle pulse in the clk_src_i domain into a single
-- clock cycle pulse in the clk_dst_i domain.
-- It does so by converting the pulse into a level change, synchronizing
-- this level change into the destination domain by double latching, and
-- finally restoring the pulse in the destination domain.
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.tdc_package.all;
entity tdc_psync is
port(
clk_src_i : in std_logic;
p_i : in std_logic;
clk_dst_i : in std_logic;
p_o : out std_logic
);
end entity;
architecture rtl of tdc_psync is
-- Initialize registers at FPGA configuration.
signal level : std_logic := '0';
signal level_d1 : std_logic := '0';
signal level_d2 : std_logic := '0';
signal level_d3 : std_logic := '0';
-- Prevent inference of a SRL* primitive, which does not
-- have good metastability resistance.
attribute keep: string;
attribute keep of level_d1: signal is "true";
attribute keep of level_d2: signal is "true";
attribute keep of level_d3: signal is "true";
begin
-- Convert incoming pulses into level flips.
process(clk_src_i)
begin
if rising_edge(clk_src_i) then
if p_i = '1' then
level <= not level;
end if;
end if;
end process;
-- Synchronize level to clk_dst domain and register.
process(clk_dst_i)
begin
if rising_edge(clk_dst_i) then
level_d1 <= level;
level_d2 <= level_d1;
level_d3 <= level_d2;
end if;
end process;
-- Convert level flips back into pulses synchronous to clk_dst domain.
p_o <= level_d2 xor level_d3;
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/core/tdc_ringosc.vhd 0000664 0000000 0000000 00000005571 11653767173 0024571 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: tdc_ringosc
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Ring oscillator based on LUT primitives
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-08-05 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- Ring oscillator built by chaining together an odd number of LUTs used
-- as inverters. The first LUT has a second input which forces its output
-- to 0. This is useful to initialize the ring oscillator and make sure
-- that only one wave is traveling through it, and to force the output of the
-- oscillator to 0 at any time.
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.all;
library work;
use work.tdc_package.all;
entity tdc_ringosc is
generic(
-- Number of LUT elements. Must be odd!
g_LENGTH: positive
);
port(
-- Enable/reset_n input. The oscillator should be reset at least once.
-- When disabled, the output is 0.
en_i : in std_logic;
-- Oscillator output.
clk_o : out std_logic
);
end entity;
architecture rtl of tdc_ringosc is
signal s: std_logic_vector(g_LENGTH downto 0);
attribute keep: string;
attribute keep of s: signal is "true";
begin
g_luts: for i in 0 to g_LENGTH-1 generate
g_firstlut: if i = 0 generate
cmp_LUT: LUT2
generic map(
INIT => "0100"
)
port map(
I0 => s(i),
I1 => en_i,
O => s(i+1)
);
end generate;
g_nextlut: if i > 0 generate
cmp_LUT: LUT1
generic map(
INIT => "01"
)
port map(
I0 => s(i),
O => s(i+1)
);
end generate;
end generate;
s(0) <= s(g_LENGTH);
clk_o <= s(g_LENGTH);
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/ 0000775 0000000 0000000 00000000000 11653767173 0021554 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/ 0000775 0000000 0000000 00000000000 11653767173 0023026 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/ 0000775 0000000 0000000 00000000000 11653767173 0023760 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rotest/ 0000775 0000000 0000000 00000000000 11653767173 0025300 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rotest/Makefile 0000664 0000000 0000000 00000001522 11653767173 0026740 0 ustar 00root root 0000000 0000000 TDC_DIR=../../../..
SRC=rotest.vhd $(TDC_DIR)/core/tdc_package.vhd $(TDC_DIR)/core/tdc_ringosc.vhd
all: build/rotest.bit
build/rotest.prj: $(SRC)
rm -f build/rotest.prj
for i in `echo $(SRC)`; do \
echo "vhdl work ../$$i" >> build/rotest.prj; \
done
build/rotest.ngc: build/rotest.prj
cd build && xst -ifn ../rotest.xst
build/rotest.ngd: build/rotest.ngc rotest.ucf
cd build && ngdbuild -uc ../rotest.ucf rotest.ngc
build/rotest.ncd: build/rotest.ngd
cd build && map -ol high -w rotest.ngd
build/rotest-routed.ncd: build/rotest.ncd
cd build && par -ol high -w rotest.ncd rotest-routed.ncd
build/rotest.bit: build/rotest-routed.ncd
cd build && bitgen -w rotest-routed.ncd rotest.bit
build/rotest-routed.twr: build/rotest-routed.ncd
cd build && trce -v 10 rotest-routed.ncd rotest.pcf
clean:
rm -rf build/*
.PHONY: timing clean
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rotest/build/ 0000775 0000000 0000000 00000000000 11653767173 0026377 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rotest/build/.keep_me 0000664 0000000 0000000 00000000000 11653767173 0027773 0 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rotest/rotest.ucf 0000664 0000000 0000000 00000000356 11653767173 0027323 0 ustar 00root root 0000000 0000000 NET "en" LOC = C22 | IOSTANDARD = "LVCMOS18";
NET "led" LOC = G19 | IOSTANDARD = "LVCMOS18";
NET "out_p" LOC = W17 | IOSTANDARD = "LVDS_25";
NET "out_n" LOC = Y18 | IOSTANDARD = "LVDS_25";
NET "oe_n" LOC = V17 | IOSTANDARD = "LVCMOS25";
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rotest/rotest.vhd 0000664 0000000 0000000 00000004366 11653767173 0027334 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- TDC Core / CERN
-------------------------------------------------------------------------------
--
-- unit name: rotest
--
-- author: Sebastien Bourdeauducq, sebastien@milkymist.org
--
-- description: Ring oscillator HW test
--
-- references: http://www.ohwr.org/projects/tdc-core
--
-------------------------------------------------------------------------------
-- last changes:
-- 2011-10-22 SB Created file
-------------------------------------------------------------------------------
-- Copyright (C) 2011 CERN
-- This program 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, version 3 of the License.
-- This program 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 General Public License for more details.
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see .
-- DESCRIPTION:
-- Instantiates the ring oscillator and connects the output to the first LEMO
-- connector of the FMC 5ch DIO (J2), for easy observation of the signal.
-- Push button 0 is connected to the enable input of the ring oscillator.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library unisim;
use unisim.vcomponents.all;
library work;
use work.tdc_package.all;
entity rotest is
port(
en : in std_logic;
led : out std_logic;
out_p : out std_logic;
out_n : out std_logic;
oe_n : out std_logic
);
end entity;
architecture rtl of rotest is
signal out_se : std_logic;
begin
cmp_obuf: OBUFDS
generic map(
IOSTANDARD => "DEFAULT"
)
port map(
O => out_p,
OB => out_n,
I => out_se
);
cmp_ringosc: tdc_ringosc
generic map(
g_LENGTH => 31
)
port map(
en_i => en,
clk_o => out_se
);
led <= not en;
oe_n <= '0';
end architecture;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rotest/rotest.xst 0000664 0000000 0000000 00000000157 11653767173 0027363 0 ustar 00root root 0000000 0000000 run
-ifn rotest.prj
-top rotest
-ifmt MIXED
-opt_mode SPEED
-opt_level 2
-ofn rotest.ngc
-p xc6slx45t-fgg484-3
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rtl/ 0000775 0000000 0000000 00000000000 11653767173 0024561 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rtl/lm32_include.v 0000664 0000000 0000000 00000027275 11653767173 0027245 0 ustar 00root root 0000000 0000000 // =============================================================================
// COPYRIGHT NOTICE
// Copyright 2006 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorised by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement from
// Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court 408-826-6000 (other locations)
// Hillsboro, OR 97124 web : http://www.latticesemi.com/
// U.S.A email: techsupport@latticesemi.com
// =============================================================================/
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_include.v
// Title : CPU global macros
// Version : 6.1.17
// : Initial Release
// Version : 7.0SP2, 3.0
// : No Change
// Version : 3.1
// : No Change
// Version : 3.2
// : No Change
// Version : 3.3
// : Support for extended configuration register
// =============================================================================
`ifdef LM32_INCLUDE_V
`else
`define LM32_INCLUDE_V
//
// Common configuration options
//
`define CFG_EBA_RESET 32'h0
`define CFG_DEBA_RESET 32'h0
//`define CFG_PL_MULTIPLY_ENABLED
//`define CFG_PL_BARREL_SHIFT_ENABLED
//`define CFG_SIGN_EXTEND_ENABLED
//`define CFG_MC_DIVIDE_ENABLED
//`define CFG_ICACHE_ENABLED
`define CFG_ICACHE_ASSOCIATIVITY 2
`define CFG_ICACHE_SETS 256
`define CFG_ICACHE_BYTES_PER_LINE 16
`define CFG_ICACHE_BASE_ADDRESS 32'h0
`define CFG_ICACHE_LIMIT 32'h7fffffff
//`define CFG_DCACHE_ENABLED
`define CFG_DCACHE_ASSOCIATIVITY 2
`define CFG_DCACHE_SETS 512
`define CFG_DCACHE_BYTES_PER_LINE 16
`define CFG_DCACHE_BASE_ADDRESS 32'h0
`define CFG_DCACHE_LIMIT 32'h7fffffff
//
// End of common configuration options
//
`ifdef TRUE
`else
`define TRUE 1'b1
`define FALSE 1'b0
`define TRUE_N 1'b0
`define FALSE_N 1'b1
`endif
// Wishbone configuration
`define CFG_IWB_ENABLED
`define CFG_DWB_ENABLED
// Data-path width
`define LM32_WORD_WIDTH 32
`define LM32_WORD_RNG (`LM32_WORD_WIDTH-1):0
`define LM32_SHIFT_WIDTH 5
`define LM32_SHIFT_RNG (`LM32_SHIFT_WIDTH-1):0
`define LM32_BYTE_SELECT_WIDTH 4
`define LM32_BYTE_SELECT_RNG (`LM32_BYTE_SELECT_WIDTH-1):0
// Register file size
`define LM32_REGISTERS 32
`define LM32_REG_IDX_WIDTH 5
`define LM32_REG_IDX_RNG (`LM32_REG_IDX_WIDTH-1):0
// Standard register numbers
`define LM32_RA_REG `LM32_REG_IDX_WIDTH'd29
`define LM32_EA_REG `LM32_REG_IDX_WIDTH'd30
`define LM32_BA_REG `LM32_REG_IDX_WIDTH'd31
// Range of Program Counter. Two LSBs are always 0.
// `ifdef CFG_ICACHE_ENABLED
// `define LM32_PC_WIDTH (clogb2(`CFG_ICACHE_LIMIT-`CFG_ICACHE_BASE_ADDRESS)-2)
// `else
// `ifdef CFG_IWB_ENABLED
`define LM32_PC_WIDTH (`LM32_WORD_WIDTH-2)
// `else
// `define LM32_PC_WIDTH `LM32_IROM_ADDRESS_WIDTH
// `endif
// `endif
`define LM32_PC_RNG (`LM32_PC_WIDTH+2-1):2
// Range of an instruction
`define LM32_INSTRUCTION_WIDTH 32
`define LM32_INSTRUCTION_RNG (`LM32_INSTRUCTION_WIDTH-1):0
// Adder operation
`define LM32_ADDER_OP_ADD 1'b0
`define LM32_ADDER_OP_SUBTRACT 1'b1
// Shift direction
`define LM32_SHIFT_OP_RIGHT 1'b0
`define LM32_SHIFT_OP_LEFT 1'b1
// Currently always enabled
`define CFG_BUS_ERRORS_ENABLED
// Derive macro that indicates whether we have single-stepping or not
`ifdef CFG_ROM_DEBUG_ENABLED
`define LM32_SINGLE_STEP_ENABLED
`else
`ifdef CFG_HW_DEBUG_ENABLED
`define LM32_SINGLE_STEP_ENABLED
`endif
`endif
// Derive macro that indicates whether JTAG interface is required
`ifdef CFG_JTAG_UART_ENABLED
`define LM32_JTAG_ENABLED
`else
`ifdef CFG_DEBUG_ENABLED
`define LM32_JTAG_ENABLED
`else
`endif
`endif
// Derive macro that indicates whether we have a barrel-shifter or not
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
`define LM32_BARREL_SHIFT_ENABLED
`else // CFG_PL_BARREL_SHIFT_ENABLED
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
`define LM32_BARREL_SHIFT_ENABLED
`else
`define LM32_NO_BARREL_SHIFT
`endif
`endif // CFG_PL_BARREL_SHIFT_ENABLED
// Derive macro that indicates whether we have a multiplier or not
`ifdef CFG_PL_MULTIPLY_ENABLED
`define LM32_MULTIPLY_ENABLED
`else
`ifdef CFG_MC_MULTIPLY_ENABLED
`define LM32_MULTIPLY_ENABLED
`endif
`endif
// Derive a macro that indicates whether or not the multi-cycle arithmetic unit is required
`ifdef CFG_MC_DIVIDE_ENABLED
`define LM32_MC_ARITHMETIC_ENABLED
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
`define LM32_MC_ARITHMETIC_ENABLED
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
`define LM32_MC_ARITHMETIC_ENABLED
`endif
// Derive macro that indicates if we are using an EBR register file
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
`define LM32_EBR_REGISTER_FILE
`endif
`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
`define LM32_EBR_REGISTER_FILE
`endif
// Revision number
`define LM32_REVISION 6'h02
// Logical operations - Function encoded directly in instruction
`define LM32_LOGIC_OP_RNG 3:0
// Conditions for conditional branches
`define LM32_CONDITION_WIDTH 3
`define LM32_CONDITION_RNG (`LM32_CONDITION_WIDTH-1):0
`define LM32_CONDITION_E 3'b001
`define LM32_CONDITION_G 3'b010
`define LM32_CONDITION_GE 3'b011
`define LM32_CONDITION_GEU 3'b100
`define LM32_CONDITION_GU 3'b101
`define LM32_CONDITION_NE 3'b111
`define LM32_CONDITION_U1 3'b000
`define LM32_CONDITION_U2 3'b110
// Size of load or store instruction - Encoding corresponds to opcode
`define LM32_SIZE_WIDTH 2
`define LM32_SIZE_RNG 1:0
`define LM32_SIZE_BYTE 2'b00
`define LM32_SIZE_HWORD 2'b11
`define LM32_SIZE_WORD 2'b10
`define LM32_ADDRESS_LSBS_WIDTH 2
// Width and range of a CSR index
`ifdef CFG_DEBUG_ENABLED
`define LM32_CSR_WIDTH 5
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
`else
`ifdef CFG_JTAG_ENABLED
`define LM32_CSR_WIDTH 4
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
`else
`define LM32_CSR_WIDTH 3
`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0
`endif
`endif
// CSR indices
`define LM32_CSR_IE `LM32_CSR_WIDTH'h0
`define LM32_CSR_IM `LM32_CSR_WIDTH'h1
`define LM32_CSR_IP `LM32_CSR_WIDTH'h2
`define LM32_CSR_ICC `LM32_CSR_WIDTH'h3
`define LM32_CSR_DCC `LM32_CSR_WIDTH'h4
`define LM32_CSR_CC `LM32_CSR_WIDTH'h5
`define LM32_CSR_CFG `LM32_CSR_WIDTH'h6
`define LM32_CSR_EBA `LM32_CSR_WIDTH'h7
`ifdef CFG_DEBUG_ENABLED
`define LM32_CSR_DC `LM32_CSR_WIDTH'h8
`define LM32_CSR_DEBA `LM32_CSR_WIDTH'h9
`endif
`define LM32_CSR_CFG2 `LM32_CSR_WIDTH'ha
`ifdef CFG_JTAG_ENABLED
`define LM32_CSR_JTX `LM32_CSR_WIDTH'he
`define LM32_CSR_JRX `LM32_CSR_WIDTH'hf
`endif
`ifdef CFG_DEBUG_ENABLED
`define LM32_CSR_BP0 `LM32_CSR_WIDTH'h10
`define LM32_CSR_BP1 `LM32_CSR_WIDTH'h11
`define LM32_CSR_BP2 `LM32_CSR_WIDTH'h12
`define LM32_CSR_BP3 `LM32_CSR_WIDTH'h13
`define LM32_CSR_WP0 `LM32_CSR_WIDTH'h18
`define LM32_CSR_WP1 `LM32_CSR_WIDTH'h19
`define LM32_CSR_WP2 `LM32_CSR_WIDTH'h1a
`define LM32_CSR_WP3 `LM32_CSR_WIDTH'h1b
`endif
// Values for WPC CSR
`define LM32_WPC_C_RNG 1:0
`define LM32_WPC_C_DISABLED 2'b00
`define LM32_WPC_C_READ 2'b01
`define LM32_WPC_C_WRITE 2'b10
`define LM32_WPC_C_READ_WRITE 2'b11
// Exception IDs
`define LM32_EID_WIDTH 3
`define LM32_EID_RNG (`LM32_EID_WIDTH-1):0
`define LM32_EID_RESET 3'h0
`define LM32_EID_BREAKPOINT 3'd1
`define LM32_EID_INST_BUS_ERROR 3'h2
`define LM32_EID_WATCHPOINT 3'd3
`define LM32_EID_DATA_BUS_ERROR 3'h4
`define LM32_EID_DIVIDE_BY_ZERO 3'h5
`define LM32_EID_INTERRUPT 3'h6
`define LM32_EID_SCALL 3'h7
// Pipeline result selection mux controls
`define LM32_D_RESULT_SEL_0_RNG 0:0
`define LM32_D_RESULT_SEL_0_REG_0 1'b0
`define LM32_D_RESULT_SEL_0_NEXT_PC 1'b1
`define LM32_D_RESULT_SEL_1_RNG 1:0
`define LM32_D_RESULT_SEL_1_ZERO 2'b00
`define LM32_D_RESULT_SEL_1_REG_1 2'b01
`define LM32_D_RESULT_SEL_1_IMMEDIATE 2'b10
`define LM32_USER_OPCODE_WIDTH 11
`define LM32_USER_OPCODE_RNG (`LM32_USER_OPCODE_WIDTH-1):0
// Derive a macro to indicate if either of the caches are implemented
`ifdef CFG_ICACHE_ENABLED
`define LM32_CACHE_ENABLED
`else
`ifdef CFG_DCACHE_ENABLED
`define LM32_CACHE_ENABLED
`endif
`endif
/////////////////////////////////////////////////////
// Interrupts
/////////////////////////////////////////////////////
// Always enable interrupts
`define CFG_INTERRUPTS_ENABLED
// Currently this is fixed to 32 and should not be changed
`define CFG_INTERRUPTS 32
`define LM32_INTERRUPT_WIDTH `CFG_INTERRUPTS
`define LM32_INTERRUPT_RNG (`LM32_INTERRUPT_WIDTH-1):0
/////////////////////////////////////////////////////
// General
/////////////////////////////////////////////////////
// Sub-word range types
`define LM32_BYTE_WIDTH 8
`define LM32_BYTE_RNG 7:0
`define LM32_HWORD_WIDTH 16
`define LM32_HWORD_RNG 15:0
// Word sub-byte indicies
`define LM32_BYTE_0_RNG 7:0
`define LM32_BYTE_1_RNG 15:8
`define LM32_BYTE_2_RNG 23:16
`define LM32_BYTE_3_RNG 31:24
// Word sub-halfword indices
`define LM32_HWORD_0_RNG 15:0
`define LM32_HWORD_1_RNG 31:16
// Use a synchronous reset
`define CFG_RESET_SENSITIVITY
// V.T. Srce
`define SRCE
// Whether to include context registers for debug exceptions
// in addition to standard exception handling registers
// Bizarre - Removing this increases LUT count!
`define CFG_DEBUG_EXCEPTIONS_ENABLED
// Wishbone defines
// Refer to Wishbone System-on-Chip Interconnection Architecture
// These should probably be moved to a Wishbone common file
// Wishbone cycle types
`define LM32_CTYPE_WIDTH 3
`define LM32_CTYPE_RNG (`LM32_CTYPE_WIDTH-1):0
`define LM32_CTYPE_CLASSIC 3'b000
`define LM32_CTYPE_CONSTANT 3'b001
`define LM32_CTYPE_INCREMENTING 3'b010
`define LM32_CTYPE_END 3'b111
// Wishbone burst types
`define LM32_BTYPE_WIDTH 2
`define LM32_BTYPE_RNG (`LM32_BTYPE_WIDTH-1):0
`define LM32_BTYPE_LINEAR 2'b00
`define LM32_BTYPE_4_BEAT 2'b01
`define LM32_BTYPE_8_BEAT 2'b10
`define LM32_BTYPE_16_BEAT 2'b11
`endif
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rtl/setup.v 0000664 0000000 0000000 00000001647 11653767173 0026120 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009, 2011 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* System clock frequency in Hz.
*/
`define CLOCK_FREQUENCY 125000000
/*
* System clock period in ns (must be in sync with CLOCK_FREQUENCY).
*/
`define CLOCK_PERIOD 8
/*
* Default baudrate for the debug UART.
*/
`define BAUD_RATE 115200
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/rtl/system.v 0000664 0000000 0000000 00000024223 11653767173 0026277 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
* Copyright (C) 2011 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
`include "setup.v"
module system(
input clkin_p,
input clkin_n,
input resetin_n,
// UART
input uart_rxd,
output uart_txd,
// GPIO
input btn,
output [3:0] led,
inout onewire,
// TDC
input tdc_signal
);
//------------------------------------------------------------------
// Clock and Reset Generation
//------------------------------------------------------------------
wire sys_clk;
wire resetin = ~resetin_n;
wire hard_reset;
IBUFGDS clkbuf(
.I(clkin_p),
.IB(clkin_n),
.O(sys_clk)
);
`ifndef SIMULATION
/* Synchronize the reset input */
reg rst0;
reg rst1;
always @(posedge sys_clk) rst0 <= resetin;
always @(posedge sys_clk) rst1 <= rst0;
/* Debounce it
* and generate power-on reset.
*/
reg [19:0] rst_debounce;
reg sys_rst;
initial rst_debounce <= 20'hFFFFF;
initial sys_rst <= 1'b1;
always @(posedge sys_clk) begin
if(rst1 | hard_reset)
rst_debounce <= 20'hFFFFF;
else if(rst_debounce != 20'd0)
rst_debounce <= rst_debounce - 20'd1;
sys_rst <= rst_debounce != 20'd0;
end
`else
wire sys_rst;
assign sys_rst = resetin;
`endif
//------------------------------------------------------------------
// Wishbone master wires
//------------------------------------------------------------------
wire [31:0] cpuibus_adr,
cpudbus_adr;
wire [2:0] cpuibus_cti,
cpudbus_cti;
wire [31:0] cpuibus_dat_r,
cpudbus_dat_r,
cpudbus_dat_w;
wire [3:0] cpudbus_sel;
wire cpudbus_we;
wire cpuibus_cyc,
cpudbus_cyc;
wire cpuibus_stb,
cpudbus_stb;
wire cpuibus_ack,
cpudbus_ack;
//------------------------------------------------------------------
// Wishbone slave wires
//------------------------------------------------------------------
wire [31:0] brg_adr,
bram_adr,
sram_adr,
csrbrg_adr,
tdc_adr;
wire [2:0] brg_cti,
bram_cti,
sram_cti;
wire [31:0] bram_dat_r,
sram_dat_r,
sram_dat_w,
csrbrg_dat_r,
csrbrg_dat_w,
tdc_dat_r,
tdc_dat_w;
wire [3:0] bram_sel,
sram_sel,
tdc_sel;
wire csrbrg_we,
sram_we,
tdc_we;
wire bram_cyc,
sram_cyc,
csrbrg_cyc,
tdc_cyc;
wire bram_stb,
sram_stb,
csrbrg_stb,
tdc_stb;
wire bram_ack,
sram_ack,
csrbrg_ack,
tdc_ack;
//---------------------------------------------------------------------------
// Wishbone switch
//---------------------------------------------------------------------------
conbus #(
.s_addr_w(3),
.s0_addr(3'b000), // bram 0x00000000
.s1_addr(3'b001), // free 0x20000000
.s2_addr(3'b010), // sram 0x40000000
.s3_addr(3'b100), // CSR bridge 0x80000000
.s4_addr(3'b101), // TDC 0xa0000000
.s5_addr(3'b110), // free 0xc0000000
) conbus (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
// Master 0
.m0_dat_i(32'hx),
.m0_dat_o(cpuibus_dat_r),
.m0_adr_i(cpuibus_adr),
.m0_cti_i(cpuibus_cti),
.m0_we_i(1'b0),
.m0_sel_i(4'hf),
.m0_cyc_i(cpuibus_cyc),
.m0_stb_i(cpuibus_stb),
.m0_ack_o(cpuibus_ack),
// Master 1
.m1_dat_i(cpudbus_dat_w),
.m1_dat_o(cpudbus_dat_r),
.m1_adr_i(cpudbus_adr),
.m1_cti_i(cpudbus_cti),
.m1_we_i(cpudbus_we),
.m1_sel_i(cpudbus_sel),
.m1_cyc_i(cpudbus_cyc),
.m1_stb_i(cpudbus_stb),
.m1_ack_o(cpudbus_ack),
// Master 2
.m2_dat_i(32'bx),
.m2_dat_o(),
.m2_adr_i(32'bx),
.m2_cti_i(3'bx),
.m2_we_i(1'bx),
.m2_sel_i(4'bx),
.m2_cyc_i(1'b0),
.m2_stb_i(1'b0),
.m2_ack_o(),
// Master 3
.m3_dat_i(32'bx),
.m3_dat_o(),
.m3_adr_i(32'bx),
.m3_cti_i(3'bx),
.m3_we_i(1'bx),
.m3_sel_i(4'bx),
.m3_cyc_i(1'b0),
.m3_stb_i(1'b0),
.m3_ack_o(),
// Master 4
.m4_dat_i(32'bx),
.m4_dat_o(),
.m4_adr_i(32'bx),
.m4_cti_i(3'bx),
.m4_we_i(1'bx),
.m4_sel_i(4'bx),
.m4_cyc_i(1'b0),
.m4_stb_i(1'b0),
.m4_ack_o(),
// Master 5
.m5_dat_i(32'bx),
.m5_dat_o(),
.m5_adr_i(32'bx),
.m5_cti_i(3'bx),
.m5_we_i(1'bx),
.m5_sel_i(4'bx),
.m5_cyc_i(1'b0),
.m5_stb_i(1'b0),
.m5_ack_o(),
// Slave 0
.s0_dat_i(bram_dat_r),
.s0_dat_o(),
.s0_adr_o(bram_adr),
.s0_cti_o(bram_cti),
.s0_sel_o(bram_sel),
.s0_we_o(),
.s0_cyc_o(bram_cyc),
.s0_stb_o(bram_stb),
.s0_ack_i(bram_ack),
// Slave 1
.s1_dat_i(32'bx),
.s1_adr_o(),
.s1_cyc_o(),
.s1_stb_o(),
.s1_ack_i(1'b0),
// Slave 2
.s2_dat_i(sram_dat_r),
.s2_dat_o(sram_dat_w),
.s2_adr_o(sram_adr),
.s2_cti_o(sram_cti),
.s2_sel_o(sram_sel),
.s2_we_o(sram_we),
.s2_cyc_o(sram_cyc),
.s2_stb_o(sram_stb),
.s2_ack_i(sram_ack),
// Slave 3
.s3_dat_i(csrbrg_dat_r),
.s3_dat_o(csrbrg_dat_w),
.s3_adr_o(csrbrg_adr),
.s3_we_o(csrbrg_we),
.s3_cyc_o(csrbrg_cyc),
.s3_stb_o(csrbrg_stb),
.s3_ack_i(csrbrg_ack),
// Slave 4
.s4_dat_i(tdc_dat_r),
.s4_dat_o(tdc_dat_w),
.s4_adr_o(tdc_adr),
.s4_we_o(tdc_we),
.s4_cyc_o(tdc_cyc),
.s4_stb_o(tdc_stb),
.s4_sel_o(tdc_sel),
.s4_ack_i(tdc_ack),
// Slave 5
.s5_dat_i(32'bx),
.s5_adr_o(),
.s5_cyc_o(),
.s5_stb_o(),
.s5_ack_i(1'b0)
);
//------------------------------------------------------------------
// CSR bus
//------------------------------------------------------------------
wire [13:0] csr_a;
wire csr_we;
wire [31:0] csr_dw;
wire [31:0] csr_dr_uart,
csr_dr_sysctl;
//---------------------------------------------------------------------------
// WISHBONE to CSR bridge
//---------------------------------------------------------------------------
csrbrg csrbrg(
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.wb_adr_i(csrbrg_adr),
.wb_dat_i(csrbrg_dat_w),
.wb_dat_o(csrbrg_dat_r),
.wb_cyc_i(csrbrg_cyc),
.wb_stb_i(csrbrg_stb),
.wb_we_i(csrbrg_we),
.wb_ack_o(csrbrg_ack),
.csr_a(csr_a),
.csr_we(csr_we),
.csr_do(csr_dw),
/* combine all slave->master data lines with an OR */
.csr_di(
csr_dr_uart
|csr_dr_sysctl
)
);
//---------------------------------------------------------------------------
// Interrupts
//---------------------------------------------------------------------------
wire gpio_irq;
wire timer0_irq;
wire timer1_irq;
wire uartrx_irq;
wire uarttx_irq;
wire tdc_irq;
wire [31:0] cpu_interrupt;
assign cpu_interrupt = {26'd0,
tdc_irq,
uarttx_irq,
uartrx_irq,
timer1_irq,
timer0_irq,
gpio_irq
};
//---------------------------------------------------------------------------
// LM32 CPU
//---------------------------------------------------------------------------
lm32_top cpu(
.clk_i(sys_clk),
.rst_i(sys_rst),
.interrupt(cpu_interrupt),
.I_ADR_O(cpuibus_adr),
.I_DAT_I(cpuibus_dat_r),
.I_DAT_O(),
.I_SEL_O(),
.I_CYC_O(cpuibus_cyc),
.I_STB_O(cpuibus_stb),
.I_ACK_I(cpuibus_ack),
.I_WE_O(),
.I_CTI_O(cpuibus_cti),
.I_LOCK_O(),
.I_BTE_O(),
.I_ERR_I(1'b0),
.I_RTY_I(1'b0),
.D_ADR_O(cpudbus_adr),
.D_DAT_I(cpudbus_dat_r),
.D_DAT_O(cpudbus_dat_w),
.D_SEL_O(cpudbus_sel),
.D_CYC_O(cpudbus_cyc),
.D_STB_O(cpudbus_stb),
.D_ACK_I(cpudbus_ack),
.D_WE_O (cpudbus_we),
.D_CTI_O(cpudbus_cti),
.D_LOCK_O(),
.D_BTE_O(),
.D_ERR_I(1'b0),
.D_RTY_I(1'b0)
);
//---------------------------------------------------------------------------
// BRAM/SRAM
//---------------------------------------------------------------------------
bram #(
.adr_width(15),
.init0("../../../software/demo/demo.h0"),
.init1("../../../software/demo/demo.h1"),
.init2("../../../software/demo/demo.h2"),
.init3("../../../software/demo/demo.h3")
) bram (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.wb_adr_i(bram_adr),
.wb_dat_o(bram_dat_r),
.wb_dat_i(32'bx),
.wb_sel_i(bram_sel),
.wb_stb_i(bram_stb),
.wb_cyc_i(bram_cyc),
.wb_ack_o(bram_ack),
.wb_we_i(1'b0)
);
bram #(
.adr_width(14)
) sram (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.wb_adr_i(sram_adr),
.wb_dat_o(sram_dat_r),
.wb_dat_i(sram_dat_w),
.wb_sel_i(sram_sel),
.wb_stb_i(sram_stb),
.wb_cyc_i(sram_cyc),
.wb_ack_o(sram_ack),
.wb_we_i(sram_we)
);
//---------------------------------------------------------------------------
// UART
//---------------------------------------------------------------------------
uart #(
.csr_addr(4'h0),
.clk_freq(`CLOCK_FREQUENCY),
.baud(`BAUD_RATE)
) uart (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.csr_a(csr_a),
.csr_we(csr_we),
.csr_di(csr_dw),
.csr_do(csr_dr_uart),
.rx_irq(uartrx_irq),
.tx_irq(uarttx_irq),
.uart_rxd(uart_rxd),
.uart_txd(uart_txd)
);
//---------------------------------------------------------------------------
// System Controller
//---------------------------------------------------------------------------
wire onewire_drivelow;
sysctl #(
.csr_addr(4'h1),
.ninputs(2),
.noutputs(5),
.systemid(32'h53504543) /* SPEC */
) sysctl (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.gpio_irq(gpio_irq),
.timer0_irq(timer0_irq),
.timer1_irq(timer1_irq),
.csr_a(csr_a),
.csr_we(csr_we),
.csr_di(csr_dw),
.csr_do(csr_dr_sysctl),
.gpio_inputs({onewire, btn}),
.gpio_outputs({onewire_drivelow, led}),
.hard_reset(hard_reset)
);
assign onewire = onewire_drivelow ? 1'b0 : 1'bz;
//---------------------------------------------------------------------------
// TDC
//---------------------------------------------------------------------------
wire tdc_calib;
tdc_hostif #(
.g_CHANNEL_COUNT(1),
.g_CARRY4_COUNT(124),
.g_RAW_COUNT(9),
.g_FP_COUNT(13),
.g_COARSE_COUNT(25),
.g_RO_LENGTH(31),
.g_FCOUNTER_WIDTH(13),
.g_FTIMER_WIDTH(14)
) tdc (
.rst_n_i(~sys_rst),
.wb_clk_i(sys_clk),
.wb_addr_i(tdc_adr[7:2]),
.wb_data_i(tdc_dat_w),
.wb_data_o(tdc_dat_r),
.wb_cyc_i(tdc_cyc),
.wb_sel_i(tdc_sel),
.wb_stb_i(tdc_stb),
.wb_we_i(tdc_we),
.wb_ack_o(tdc_ack),
.wb_irq_o(tdc_irq),
.cc_rst_i(1'b0),
.cc_cy_o(),
.signal_i(tdc_signal),
.calib_i(tdc_calib)
);
// startup calibration oscillator
wire cal_clk16x;
wire cal_clk;
tdc_ringosc #(
.g_LENGTH(31)
) calib_osc (
.en_i(~sys_rst),
.clk_o(cal_clk16x)
);
reg [3:0] cal_clkdiv;
always @(posedge cal_clk16x) cal_clkdiv <= cal_clkdiv + 4'd1;
assign cal_clk = cal_clkdiv[3];
assign tdc_calib = cal_clk;
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/sources.mak 0000664 0000000 0000000 00000002150 11653767173 0026133 0 ustar 00root root 0000000 0000000 BOARD_SRC=$(wildcard $(BOARD_DIR)/*.v)
CONBUS_SRC=$(wildcard $(CORES_DIR)/conbus/rtl/*.v)
LM32_SRC= \
$(CORES_DIR)/lm32/rtl/lm32_cpu.v \
$(CORES_DIR)/lm32/rtl/lm32_instruction_unit.v \
$(CORES_DIR)/lm32/rtl/lm32_decoder.v \
$(CORES_DIR)/lm32/rtl/lm32_load_store_unit.v \
$(CORES_DIR)/lm32/rtl/lm32_adder.v \
$(CORES_DIR)/lm32/rtl/lm32_addsub.v \
$(CORES_DIR)/lm32/rtl/lm32_logic_op.v \
$(CORES_DIR)/lm32/rtl/lm32_shifter.v \
$(CORES_DIR)/lm32/rtl/lm32_interrupt.v \
$(CORES_DIR)/lm32/rtl/lm32_top.v
CSRBRG_SRC=$(wildcard $(CORES_DIR)/csrbrg/rtl/*.v)
BRAM_SRC=$(wildcard $(CORES_DIR)/bram/rtl/*.v)
UART_SRC=$(wildcard $(CORES_DIR)/uart/rtl/*.v)
SYSCTL_SRC=$(wildcard $(CORES_DIR)/sysctl/rtl/*.v)
CORES_SRC=$(CONBUS_SRC) $(LM32_SRC) $(CSRBRG_SRC) $(BRAM_SRC) $(UART_SRC) $(SYSCTL_SRC)
TDC_SRC=$(wildcard $(TDC_DIR)/core/*.vhd)
TDCHI_SRC=$(wildcard $(TDC_DIR)/hostif/*.vhd)
GENRAMS_SRC=$(wildcard $(GENCORES_DIR)/modules/genrams/*.vhd) $(wildcard $(GENCORES_DIR)/modules/genrams/xilinx/*.vhd)
WBGEN_SRC=$(wildcard $(WBGEN_DIR)/lib/*.vhd)
CORES_SRC_VHDL=$(GENRAMS_SRC) $(WBGEN_SRC) $(TDC_SRC) $(TDCHI_SRC)
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/ 0000775 0000000 0000000 00000000000 11653767173 0026011 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/Makefile.xst 0000664 0000000 0000000 00000001370 11653767173 0030267 0 ustar 00root root 0000000 0000000 BOARD_DIR=../rtl
CORES_DIR=../../../cores
GENCORES_DIR=../../../../../general-cores
WBGEN_DIR=../../../../../wishbone-gen
TDC_DIR=../../../..
include ../sources.mak
SRC=$(BOARD_SRC) $(CORES_SRC)
SRC_VHDL=$(CORES_SRC_VHDL)
all: build/system.bit
build/system.ucf: common.ucf xst.ucf
cat common.ucf xst.ucf > build/system.ucf
build/system.prj: $(SRC) $(SRC_VHDL)
rm -f build/system.prj
for i in `echo $(SRC)`; do \
echo "verilog work ../$$i" >> build/system.prj; \
done
for i in `echo $(SRC_VHDL)`; do \
echo "vhdl work ../$$i" >> build/system.prj; \
done
build/system.ngc: build/system.prj
cd build && xst -ifn ../system.xst
build/system.ngd: build/system.ngc build/system.ucf
cd build && ngdbuild -uc system.ucf system.ngc
include common.mak
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/build/ 0000775 0000000 0000000 00000000000 11653767173 0027110 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/build/.keep_me 0000664 0000000 0000000 00000000000 11653767173 0030504 0 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/common.mak 0000664 0000000 0000000 00000001017 11653767173 0027772 0 ustar 00root root 0000000 0000000 timing: build/system-routed.twr
load: build/system.bit
cd build && impact -batch ../load.cmd
build/system.ncd: build/system.ngd
cd build && map -ol high -w system.ngd
build/system-routed.ncd: build/system.ncd
cd build && par -ol high -w system.ncd system-routed.ncd
build/system.bit: build/system-routed.ncd
cd build && bitgen -w system-routed.ncd system.bit
build/system-routed.twr: build/system-routed.ncd
cd build && trce -v 10 system-routed.ncd system.pcf
clean:
rm -rf build/*
.PHONY: timing usage load clean
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/common.ucf 0000664 0000000 0000000 00000001757 11653767173 0030012 0 ustar 00root root 0000000 0000000 # ==== Clock input ====
NET "sys_clk" TNM_NET = CLK_125MHZ;
TIMESPEC TS_CLK_125MHZ = PERIOD CLK_125MHZ 8 ns;
# FPGA_CLK from CDCM61004, 125MHz
NET "clkin_p" LOC = G9 | IOSTANDARD = "LVDS_25";
NET "clkin_n" LOC = F10 | IOSTANDARD = "LVDS_25";
# AUX button 0
NET "resetin_n" LOC = C22 | IOSTANDARD = "LVCMOS18";
# ==== UART ====
NET "uart_rxd" LOC = A2 | IOSTANDARD = "LVCMOS25"; # FPGA input
NET "uart_txd" LOC = B2 | IOSTANDARD = "LVCMOS25"; # FPGA output
# ==== GPIO ====
NET "btn" LOC = D21 | IOSTANDARD = "LVCMOS18"; # AUX button 1
NET "led[0]" LOC = G19 | IOSTANDARD = "LVCMOS18"; # AUX LEDs
NET "led[1]" LOC = F20 | IOSTANDARD = "LVCMOS18";
NET "led[2]" LOC = F18 | IOSTANDARD = "LVCMOS18";
NET "led[3]" LOC = C20 | IOSTANDARD = "LVCMOS18";
NET "onewire" LOC = D4 | IOSTANDARD = "LVCMOS25";
# ==== TDC inputs ====
# FIXME
NET "tdc_signal" LOC = AB11 | IOSTANDARD = LVCMOS25 | PULLDOWN;
# ==== TDC core ====
NET "tdc/cmp_tdc/cmp_channelbank/g_single.cmp_channelbank/cmp_channel/muxed_signal" TIG;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/load.cmd 0000664 0000000 0000000 00000000134 11653767173 0027413 0 ustar 00root root 0000000 0000000 setMode -bscan
setCable -p auto
identify
assignfile -p 1 -file system.bit
program -p 1
quit
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/system.xst 0000664 0000000 0000000 00000000157 11653767173 0030100 0 ustar 00root root 0000000 0000000 run
-ifn system.prj
-top system
-ifmt MIXED
-opt_mode SPEED
-opt_level 2
-ofn system.ngc
-p xc6slx45t-fgg484-3
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/boards/spec/synthesis/xst.ucf 0000664 0000000 0000000 00000000000 11653767173 0027314 0 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/ 0000775 0000000 0000000 00000000000 11653767173 0022667 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/bram/ 0000775 0000000 0000000 00000000000 11653767173 0023610 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/bram/doc/ 0000775 0000000 0000000 00000000000 11653767173 0024355 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/bram/doc/Makefile 0000664 0000000 0000000 00000000411 11653767173 0026011 0 ustar 00root root 0000000 0000000 TEX=bram.tex
DVI=$(TEX:.tex=.dvi)
PS=$(TEX:.tex=.ps)
PDF=$(TEX:.tex=.pdf)
AUX=$(TEX:.tex=.aux)
LOG=$(TEX:.tex=.log)
all: $(PDF)
%.dvi: %.tex
latex $<
%.ps: %.dvi
dvips $<
%.pdf: %.ps
ps2pdf $<
clean:
rm -f $(DVI) $(PS) $(PDF) $(AUX) $(LOG)
.PHONY: clean
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/bram/doc/bram.tex 0000664 0000000 0000000 00000002361 11653767173 0026022 0 ustar 00root root 0000000 0000000 \documentclass[a4paper,11pt]{article}
\usepackage{fullpage}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[normalem]{ulem}
\usepackage[english]{babel}
\usepackage{listings,babel}
\lstset{breaklines=true,basicstyle=\ttfamily}
\usepackage{graphicx}
\usepackage{moreverb}
\usepackage{url}
\title{Wishbone Block RAM}
\author{S\'ebastien Bourdeauducq}
\date{December 2009}
\begin{document}
\setlength{\parindent}{0pt}
\setlength{\parskip}{5pt}
\maketitle{}
\section{Specifications}
This core creates 32-bit storage RAM on the Wishbone bus by using FPGA Block RAM.
Byte-wide writes are supported. Burst access is not supported.
The typical use case is to provide initial memory for softcore CPUs.
\section{Using the core}
You should specify the block RAM storage depth, in bytes, by using the \verb!adr_width! parameter.
\section*{Copyright notice}
Copyright \copyright 2007-2009 S\'ebastien Bourdeauducq. \\
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the LICENSE.FDL file at the root of the Milkymist source distribution.
\end{document}
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/bram/rtl/ 0000775 0000000 0000000 00000000000 11653767173 0024411 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/bram/rtl/bram.v 0000664 0000000 0000000 00000005735 11653767173 0025533 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
* Copyright (C) 2011 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
module bram #(
parameter adr_width = 11, // in bytes
parameter init0 = "",
parameter init1 = "",
parameter init2 = "",
parameter init3 = ""
) (
input sys_clk,
input sys_rst,
input wb_stb_i,
input wb_cyc_i,
input wb_we_i,
output reg wb_ack_o,
input [31:0] wb_adr_i,
output [31:0] wb_dat_o,
input [31:0] wb_dat_i,
input [3:0] wb_sel_i
);
//-----------------------------------------------------------------
// Storage depth in 32 bit words
//-----------------------------------------------------------------
parameter word_width = adr_width - 2;
parameter word_depth = (1 << word_width);
//-----------------------------------------------------------------
// Actual RAM
//-----------------------------------------------------------------
reg [7:0] ram0 [0:word_depth-1];
reg [7:0] ram1 [0:word_depth-1];
reg [7:0] ram2 [0:word_depth-1];
reg [7:0] ram3 [0:word_depth-1];
initial begin
if(init0 != "")
$readmemh(init0, ram0);
if(init1 != "")
$readmemh(init1, ram1);
if(init2 != "")
$readmemh(init2, ram2);
if(init3 != "")
$readmemh(init3, ram3);
end
wire [word_width-1:0] adr;
wire [7:0] ram0di;
wire ram0we;
wire [7:0] ram1di;
wire ram1we;
wire [7:0] ram2di;
wire ram2we;
wire [7:0] ram3di;
wire ram3we;
reg [7:0] ram0do;
reg [7:0] ram1do;
reg [7:0] ram2do;
reg [7:0] ram3do;
always @(posedge sys_clk) begin
if(ram0we)
ram0[adr] <= ram0di;
ram0do <= ram0[adr];
end
always @(posedge sys_clk) begin
if(ram1we)
ram1[adr] <= ram1di;
ram1do <= ram1[adr];
end
always @(posedge sys_clk) begin
if(ram2we)
ram2[adr] <= ram2di;
ram2do <= ram2[adr];
end
always @(posedge sys_clk) begin
if(ram3we)
ram3[adr] <= ram3di;
ram3do <= ram3[adr];
end
assign ram0we = wb_cyc_i & wb_stb_i & wb_we_i & wb_sel_i[0];
assign ram1we = wb_cyc_i & wb_stb_i & wb_we_i & wb_sel_i[1];
assign ram2we = wb_cyc_i & wb_stb_i & wb_we_i & wb_sel_i[2];
assign ram3we = wb_cyc_i & wb_stb_i & wb_we_i & wb_sel_i[3];
assign ram0di = wb_dat_i[7:0];
assign ram1di = wb_dat_i[15:8];
assign ram2di = wb_dat_i[23:16];
assign ram3di = wb_dat_i[31:24];
assign wb_dat_o = {ram3do, ram2do, ram1do, ram0do};
assign adr = wb_adr_i[adr_width-1:2];
always @(posedge sys_clk) begin
if(sys_rst)
wb_ack_o <= 1'b0;
else begin
if(wb_cyc_i & wb_stb_i)
wb_ack_o <= ~wb_ack_o;
else
wb_ack_o <= 1'b0;
end
end
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/ 0000775 0000000 0000000 00000000000 11653767173 0024160 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/doc/ 0000775 0000000 0000000 00000000000 11653767173 0024725 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/doc/Makefile 0000664 0000000 0000000 00000000413 11653767173 0026363 0 ustar 00root root 0000000 0000000 TEX=conbus.tex
DVI=$(TEX:.tex=.dvi)
PS=$(TEX:.tex=.ps)
PDF=$(TEX:.tex=.pdf)
AUX=$(TEX:.tex=.aux)
LOG=$(TEX:.tex=.log)
all: $(PDF)
%.dvi: %.tex
latex $<
%.ps: %.dvi
dvips $<
%.pdf: %.ps
ps2pdf $<
clean:
rm -f $(DVI) $(PS) $(PDF) $(AUX) $(LOG)
.PHONY: clean
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/doc/conbus.tex 0000664 0000000 0000000 00000002666 11653767173 0026752 0 ustar 00root root 0000000 0000000 \documentclass[a4paper,11pt]{article}
\usepackage{fullpage}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[normalem]{ulem}
\usepackage[english]{babel}
\usepackage{listings,babel}
\lstset{breaklines=true,basicstyle=\ttfamily}
\usepackage{graphicx}
\usepackage{moreverb}
\usepackage{url}
\title{Wishbone bus arbiter and address decoder}
\author{S\'ebastien Bourdeauducq}
\date{December 2009}
\begin{document}
\setlength{\parindent}{0pt}
\setlength{\parskip}{5pt}
\maketitle{}
\section{Specifications}
This core allows up to several masters to communicate with up to several slaves on a shared Wishbone bus.
It takes care of bus arbitration and remapping of the slave base addresses. It is very simple and does not take care of priorities. Scheduling occurs when a master releases the bus, and then the next master which requested the bus takes ownership.
It is based on \verb!wb_conbus! from OpenCores.
\section{Using the core}
All parameters and ports should be self-explanatory. No special care should be taken.
\section*{Copyright notice}
Copyright \copyright 2007-2009 S\'ebastien Bourdeauducq. \\
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the LICENSE.FDL file at the root of the Milkymist source distribution.
\end{document}
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/rtl/ 0000775 0000000 0000000 00000000000 11653767173 0024761 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/rtl/conbus.v 0000664 0000000 0000000 00000016345 11653767173 0026452 0 ustar 00root root 0000000 0000000 /*
* Wishbone Arbiter and Address Decoder
* Copyright (C) 2008, 2009, 2010 Sebastien Bourdeauducq
* Copyright (C) 2000 Johny Chi - chisuhua@yahoo.com.cn
* This file is part of Milkymist.
*
* This source file may be used and distributed without
* restriction provided that this copyright statement is not
* removed from the file and that any derivative work contains
* the original copyright notice and the associated disclaimer.
*
* 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.opencores.org/lgpl.shtml.
*/
module conbus #(
parameter s_addr_w = 4,
parameter s0_addr = 4'h0,
parameter s1_addr = 4'h1,
parameter s2_addr = 4'h2,
parameter s3_addr = 4'h3,
parameter s4_addr = 4'h4,
parameter s5_addr = 4'h5
) (
input sys_clk,
input sys_rst,
// Master 0 Interface
input [31:0] m0_dat_i,
output [31:0] m0_dat_o,
input [31:0] m0_adr_i,
input [2:0] m0_cti_i,
input [3:0] m0_sel_i,
input m0_we_i,
input m0_cyc_i,
input m0_stb_i,
output m0_ack_o,
// Master 1 Interface
input [31:0] m1_dat_i,
output [31:0] m1_dat_o,
input [31:0] m1_adr_i,
input [2:0] m1_cti_i,
input [3:0] m1_sel_i,
input m1_we_i,
input m1_cyc_i,
input m1_stb_i,
output m1_ack_o,
// Master 2 Interface
input [31:0] m2_dat_i,
output [31:0] m2_dat_o,
input [31:0] m2_adr_i,
input [2:0] m2_cti_i,
input [3:0] m2_sel_i,
input m2_we_i,
input m2_cyc_i,
input m2_stb_i,
output m2_ack_o,
// Master 3 Interface
input [31:0] m3_dat_i,
output [31:0] m3_dat_o,
input [31:0] m3_adr_i,
input [2:0] m3_cti_i,
input [3:0] m3_sel_i,
input m3_we_i,
input m3_cyc_i,
input m3_stb_i,
output m3_ack_o,
// Master 4 Interface
input [31:0] m4_dat_i,
output [31:0] m4_dat_o,
input [31:0] m4_adr_i,
input [2:0] m4_cti_i,
input [3:0] m4_sel_i,
input m4_we_i,
input m4_cyc_i,
input m4_stb_i,
output m4_ack_o,
// Master 5 Interface
input [31:0] m5_dat_i,
output [31:0] m5_dat_o,
input [31:0] m5_adr_i,
input [2:0] m5_cti_i,
input [3:0] m5_sel_i,
input m5_we_i,
input m5_cyc_i,
input m5_stb_i,
output m5_ack_o,
// Slave 0 Interface
input [31:0] s0_dat_i,
output [31:0] s0_dat_o,
output [31:0] s0_adr_o,
output [2:0] s0_cti_o,
output [3:0] s0_sel_o,
output s0_we_o,
output s0_cyc_o,
output s0_stb_o,
input s0_ack_i,
// Slave 1 Interface
input [31:0] s1_dat_i,
output [31:0] s1_dat_o,
output [31:0] s1_adr_o,
output [2:0] s1_cti_o,
output [3:0] s1_sel_o,
output s1_we_o,
output s1_cyc_o,
output s1_stb_o,
input s1_ack_i,
// Slave 2 Interface
input [31:0] s2_dat_i,
output [31:0] s2_dat_o,
output [31:0] s2_adr_o,
output [2:0] s2_cti_o,
output [3:0] s2_sel_o,
output s2_we_o,
output s2_cyc_o,
output s2_stb_o,
input s2_ack_i,
// Slave 3 Interface
input [31:0] s3_dat_i,
output [31:0] s3_dat_o,
output [31:0] s3_adr_o,
output [2:0] s3_cti_o,
output [3:0] s3_sel_o,
output s3_we_o,
output s3_cyc_o,
output s3_stb_o,
input s3_ack_i,
// Slave 4 Interface
input [31:0] s4_dat_i,
output [31:0] s4_dat_o,
output [31:0] s4_adr_o,
output [2:0] s4_cti_o,
output [3:0] s4_sel_o,
output s4_we_o,
output s4_cyc_o,
output s4_stb_o,
input s4_ack_i,
// Slave 5 Interface
input [31:0] s5_dat_i,
output [31:0] s5_dat_o,
output [31:0] s5_adr_o,
output [2:0] s5_cti_o,
output [3:0] s5_sel_o,
output s5_we_o,
output s5_cyc_o,
output s5_stb_o,
input s5_ack_i
);
// address + CTI + data + byte select
// + cyc + we + stb
`define mbusw_ls 32 + 3 + 32 + 4 + 3
wire [5:0] slave_sel;
wire [5:0] gnt;
wire [`mbusw_ls -1:0] i_bus_m; // internal shared bus, master data and control to slave
wire [31:0] i_dat_s; // internal shared bus, slave data to master
wire i_bus_ack; // internal shared bus, ack signal
// master 0
assign m0_dat_o = i_dat_s;
assign m0_ack_o = i_bus_ack & gnt[0];
// master 1
assign m1_dat_o = i_dat_s;
assign m1_ack_o = i_bus_ack & gnt[1];
// master 2
assign m2_dat_o = i_dat_s;
assign m2_ack_o = i_bus_ack & gnt[2];
// master 3
assign m3_dat_o = i_dat_s;
assign m3_ack_o = i_bus_ack & gnt[3];
// master 4
assign m4_dat_o = i_dat_s;
assign m4_ack_o = i_bus_ack & gnt[4];
// master 5
assign m5_dat_o = i_dat_s;
assign m5_ack_o = i_bus_ack & gnt[5];
assign i_bus_ack = s0_ack_i | s1_ack_i | s2_ack_i | s3_ack_i | s4_ack_i | s5_ack_i;
// slave 0
assign {s0_adr_o, s0_cti_o, s0_sel_o, s0_dat_o, s0_we_o, s0_cyc_o} = i_bus_m[`mbusw_ls -1:1];
assign s0_stb_o = i_bus_m[1] & i_bus_m[0] & slave_sel[0]; // stb_o = cyc_i & stb_i & slave_sel
// slave 1
assign {s1_adr_o, s1_cti_o, s1_sel_o, s1_dat_o, s1_we_o, s1_cyc_o} = i_bus_m[`mbusw_ls -1:1];
assign s1_stb_o = i_bus_m[1] & i_bus_m[0] & slave_sel[1];
// slave 2
assign {s2_adr_o, s2_cti_o, s2_sel_o, s2_dat_o, s2_we_o, s2_cyc_o} = i_bus_m[`mbusw_ls -1:1];
assign s2_stb_o = i_bus_m[1] & i_bus_m[0] & slave_sel[2];
// slave 3
assign {s3_adr_o, s3_cti_o, s3_sel_o, s3_dat_o, s3_we_o, s3_cyc_o} = i_bus_m[`mbusw_ls -1:1];
assign s3_stb_o = i_bus_m[1] & i_bus_m[0] & slave_sel[3];
// slave 4
assign {s4_adr_o, s4_cti_o, s4_sel_o, s4_dat_o, s4_we_o, s4_cyc_o} = i_bus_m[`mbusw_ls -1:1];
assign s4_stb_o = i_bus_m[1] & i_bus_m[0] & slave_sel[4];
// slave 5
assign {s5_adr_o, s5_cti_o, s5_sel_o, s5_dat_o, s5_we_o, s5_cyc_o} = i_bus_m[`mbusw_ls -1:1];
assign s5_stb_o = i_bus_m[1] & i_bus_m[0] & slave_sel[5];
assign i_bus_m =
({`mbusw_ls{gnt[0]}} & {m0_adr_i, m0_cti_i, m0_sel_i, m0_dat_i, m0_we_i, m0_cyc_i, m0_stb_i})
|({`mbusw_ls{gnt[1]}} & {m1_adr_i, m1_cti_i, m1_sel_i, m1_dat_i, m1_we_i, m1_cyc_i, m1_stb_i})
|({`mbusw_ls{gnt[2]}} & {m2_adr_i, m2_cti_i, m2_sel_i, m2_dat_i, m2_we_i, m2_cyc_i, m2_stb_i})
|({`mbusw_ls{gnt[3]}} & {m3_adr_i, m3_cti_i, m3_sel_i, m3_dat_i, m3_we_i, m3_cyc_i, m3_stb_i})
|({`mbusw_ls{gnt[4]}} & {m4_adr_i, m4_cti_i, m4_sel_i, m4_dat_i, m4_we_i, m4_cyc_i, m4_stb_i})
|({`mbusw_ls{gnt[5]}} & {m5_adr_i, m5_cti_i, m5_sel_i, m5_dat_i, m5_we_i, m5_cyc_i, m5_stb_i});
assign i_dat_s =
({32{slave_sel[ 0]}} & s0_dat_i)
|({32{slave_sel[ 1]}} & s1_dat_i)
|({32{slave_sel[ 2]}} & s2_dat_i)
|({32{slave_sel[ 3]}} & s3_dat_i)
|({32{slave_sel[ 4]}} & s4_dat_i)
|({32{slave_sel[ 5]}} & s5_dat_i);
wire [5:0] req = {m5_cyc_i, m4_cyc_i, m3_cyc_i, m2_cyc_i, m1_cyc_i, m0_cyc_i};
conbus_arb conbus_arb(
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.req(req),
.gnt(gnt)
);
assign slave_sel[0] = (i_bus_m[`mbusw_ls-1 : `mbusw_ls-s_addr_w] == s0_addr);
assign slave_sel[1] = (i_bus_m[`mbusw_ls-1 : `mbusw_ls-s_addr_w] == s1_addr);
assign slave_sel[2] = (i_bus_m[`mbusw_ls-1 : `mbusw_ls-s_addr_w] == s2_addr);
assign slave_sel[3] = (i_bus_m[`mbusw_ls-1 : `mbusw_ls-s_addr_w] == s3_addr);
assign slave_sel[4] = (i_bus_m[`mbusw_ls-1 : `mbusw_ls-s_addr_w] == s4_addr);
assign slave_sel[5] = (i_bus_m[`mbusw_ls-1 : `mbusw_ls-s_addr_w] == s5_addr);
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/rtl/conbus_arb.v 0000664 0000000 0000000 00000005313 11653767173 0027267 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
module conbus_arb(
input sys_clk,
input sys_rst,
input [5:0] req,
output [5:0] gnt
);
parameter [5:0] grant0 = 6'b000001,
grant1 = 6'b000010,
grant2 = 6'b000100,
grant3 = 6'b001000,
grant4 = 6'b010000,
grant5 = 6'b100000;
reg [5:0] state;
reg [5:0] next_state;
assign gnt = state;
always @(posedge sys_clk) begin
if(sys_rst)
state <= grant0;
else
state <= next_state;
end
always @(*) begin
next_state = state;
case(state)
grant0: begin
if(~req[0]) begin
if(req[1]) next_state = grant1;
else if(req[2]) next_state = grant2;
else if(req[3]) next_state = grant3;
else if(req[4]) next_state = grant4;
else if(req[5]) next_state = grant5;
end
end
grant1: begin
if(~req[1]) begin
if(req[2]) next_state = grant2;
else if(req[3]) next_state = grant3;
else if(req[4]) next_state = grant4;
else if(req[5]) next_state = grant5;
else if(req[0]) next_state = grant0;
end
end
grant2: begin
if(~req[2]) begin
if(req[3]) next_state = grant3;
else if(req[4]) next_state = grant4;
else if(req[5]) next_state = grant5;
else if(req[0]) next_state = grant0;
else if(req[1]) next_state = grant1;
end
end
grant3: begin
if(~req[3]) begin
if(req[4]) next_state = grant4;
else if(req[5]) next_state = grant5;
else if(req[0]) next_state = grant0;
else if(req[1]) next_state = grant1;
else if(req[2]) next_state = grant2;
end
end
grant4: begin
if(~req[4]) begin
if(req[5]) next_state = grant5;
else if(req[0]) next_state = grant0;
else if(req[1]) next_state = grant1;
else if(req[2]) next_state = grant2;
else if(req[3]) next_state = grant3;
end
end
grant5: begin
if(~req[5]) begin
if(req[0]) next_state = grant0;
else if(req[1]) next_state = grant1;
else if(req[2]) next_state = grant2;
else if(req[3]) next_state = grant3;
else if(req[4]) next_state = grant4;
end
end
endcase
end
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/test/ 0000775 0000000 0000000 00000000000 11653767173 0025137 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/test/Makefile 0000664 0000000 0000000 00000000410 11653767173 0026572 0 ustar 00root root 0000000 0000000 SOURCES=tb_conbus.v master.v slave.v $(wildcard ../rtl/*.v)
all: tb_conbus
sim: tb_conbus
./tb_conbus
cversim: $(SOURCES)
cver $(SOURCES)
clean:
rm -f tb_conbus verilog.log
tb_conbus: $(SOURCES)
iverilog -o tb_conbus $(SOURCES)
.PHONY: clean sim cversim
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/test/master.v 0000664 0000000 0000000 00000003753 11653767173 0026631 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
module master #(
parameter id = 0,
parameter nreads = 128,
parameter nwrites = 128,
parameter p = 4
) (
input sys_clk,
input sys_rst,
output reg [31:0] dat_w,
input [31:0] dat_r,
output reg [31:0] adr,
output [2:0] cti,
output reg we,
output reg [3:0] sel,
output cyc,
output stb,
input ack,
output reg tend
);
integer rcounter;
integer wcounter;
reg active;
assign cyc = active;
assign stb = active;
assign cti = 0;
always @(posedge sys_clk) begin
if(sys_rst) begin
dat_w = 0;
adr = 0;
we = 0;
sel = 0;
active = 0;
rcounter = 0;
wcounter = 0;
tend = 0;
end else begin
if(ack) begin
if(~active)
$display("[M%d] Spurious ack", id);
else begin
if(we)
$display("[M%d] Ack W: %x:%x [%x]", id, adr, dat_w, sel);
else
$display("[M%d] Ack R: %x:%x [%x]", id, adr, dat_r, sel);
end
active = 1'b0;
end else if(~active) begin
if(($random % p) == 0) begin
adr = $random;
adr = adr % 5;
adr = (adr << (32-3)) + id;
sel = sel + 1;
active = 1'b1;
if(($random % 2) == 0) begin
/* Read */
we = 1'b0;
rcounter = rcounter + 1;
end else begin
/* Write */
we = 1'b1;
dat_w = ($random << 16) + id;
wcounter = wcounter + 1;
end
end
end
tend = (rcounter >= nreads) && (wcounter >= nwrites);
end
end
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/test/slave.v 0000664 0000000 0000000 00000002471 11653767173 0026444 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
module slave #(
parameter id = 0,
parameter p = 3
) (
input sys_clk,
input sys_rst,
input [31:0] dat_w,
output reg [31:0] dat_r,
input [31:0] adr,
input [2:0] cti,
input we,
input [3:0] sel,
input cyc,
input stb,
output reg ack
);
always @(posedge sys_clk) begin
if(sys_rst) begin
dat_r = 0;
ack = 0;
end else begin
if(cyc & stb & ~ack) begin
if(($random % p) == 0) begin
ack = 1;
if(~we)
dat_r = ($random << 16) + id;
if(we)
$display("[S%d] Ack W: %x:%x [%x]", id, adr, dat_w, sel);
else
$display("[S%d] Ack R: %x:%x [%x]", id, adr, dat_r, sel);
end
end else
ack = 0;
end
end
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/conbus/test/tb_conbus.v 0000664 0000000 0000000 00000016176 11653767173 0027317 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
module tb_conbus();
reg sys_rst;
reg sys_clk;
//------------------------------------------------------------------
// Wishbone master wires
//------------------------------------------------------------------
wire [31:0] m0_adr,
m1_adr,
m2_adr,
m3_adr,
m4_adr;
wire [2:0] m0_cti,
m1_cti,
m2_cti,
m3_cti,
m4_cti;
wire [31:0] m0_dat_r,
m0_dat_w,
m1_dat_r,
m1_dat_w,
m2_dat_r,
m2_dat_w,
m3_dat_r,
m3_dat_w,
m4_dat_r,
m4_dat_w;
wire [3:0] m0_sel,
m1_sel,
m2_sel,
m3_sel,
m4_sel;
wire m0_we,
m1_we,
m2_we,
m3_we,
m4_we;
wire m0_cyc,
m1_cyc,
m2_cyc,
m3_cyc,
m4_cyc;
wire m0_stb,
m1_stb,
m2_stb,
m3_stb,
m4_stb;
wire m0_ack,
m1_ack,
m2_ack,
m3_ack,
m4_ack;
//------------------------------------------------------------------
// Wishbone slave wires
//------------------------------------------------------------------
wire [31:0] s0_adr,
s1_adr,
s2_adr,
s3_adr,
s4_adr;
wire [2:0] s0_cti,
s1_cti,
s2_cti,
s3_cti,
s4_cti;
wire [31:0] s0_dat_r,
s0_dat_w,
s1_dat_r,
s1_dat_w,
s2_dat_r,
s2_dat_w,
s3_dat_r,
s3_dat_w,
s4_dat_r,
s4_dat_w;
wire [3:0] s0_sel,
s1_sel,
s2_sel,
s3_sel,
s4_sel;
wire s0_we,
s1_we,
s2_we,
s3_we,
s4_we;
wire s0_cyc,
s1_cyc,
s2_cyc,
s3_cyc,
s4_cyc;
wire s0_stb,
s1_stb,
s2_stb,
s3_stb,
s4_stb;
wire s0_ack,
s1_ack,
s2_ack,
s3_ack,
s4_ack;
//---------------------------------------------------------------------------
// Wishbone switch
//---------------------------------------------------------------------------
conbus #(
.s_addr_w(3),
.s0_addr(3'b000), // 0x00000000
.s1_addr(3'b001), // 0x20000000
.s2_addr(3'b010), // 0x40000000
.s3_addr(3'b011), // 0x60000000
.s4_addr(3'b100) // 0x80000000
) dut (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
// Master 0
.m0_dat_i(m0_dat_w),
.m0_dat_o(m0_dat_r),
.m0_adr_i(m0_adr),
.m0_cti_i(m0_cti),
.m0_we_i(m0_we),
.m0_sel_i(m0_sel),
.m0_cyc_i(m0_cyc),
.m0_stb_i(m0_stb),
.m0_ack_o(m0_ack),
// Master 1
.m1_dat_i(m1_dat_w),
.m1_dat_o(m1_dat_r),
.m1_adr_i(m1_adr),
.m1_cti_i(m1_cti),
.m1_we_i(m1_we),
.m1_sel_i(m1_sel),
.m1_cyc_i(m1_cyc),
.m1_stb_i(m1_stb),
.m1_ack_o(m1_ack),
// Master 2
.m2_dat_i(m2_dat_w),
.m2_dat_o(m2_dat_r),
.m2_adr_i(m2_adr),
.m2_cti_i(m2_cti),
.m2_we_i(m2_we),
.m2_sel_i(m2_sel),
.m2_cyc_i(m2_cyc),
.m2_stb_i(m2_stb),
.m2_ack_o(m2_ack),
// Master 3
.m3_dat_i(m3_dat_w),
.m3_dat_o(m3_dat_r),
.m3_adr_i(m3_adr),
.m3_cti_i(m3_cti),
.m3_we_i(m3_we),
.m3_sel_i(m3_sel),
.m3_cyc_i(m3_cyc),
.m3_stb_i(m3_stb),
.m3_ack_o(m3_ack),
// Master 4
.m4_dat_i(m4_dat_w),
.m4_dat_o(m4_dat_r),
.m4_adr_i(m4_adr),
.m4_cti_i(m4_cti),
.m4_we_i(m4_we),
.m4_sel_i(m4_sel),
.m4_cyc_i(m4_cyc),
.m4_stb_i(m4_stb),
.m4_ack_o(m4_ack),
// Slave 0
.s0_dat_i(s0_dat_r),
.s0_dat_o(s0_dat_w),
.s0_adr_o(s0_adr),
.s0_cti_o(s0_cti),
.s0_sel_o(s0_sel),
.s0_we_o(s0_we),
.s0_cyc_o(s0_cyc),
.s0_stb_o(s0_stb),
.s0_ack_i(s0_ack),
// Slave 1
.s1_dat_i(s1_dat_r),
.s1_dat_o(s1_dat_w),
.s1_adr_o(s1_adr),
.s1_cti_o(s1_cti),
.s1_sel_o(s1_sel),
.s1_we_o(s1_we),
.s1_cyc_o(s1_cyc),
.s1_stb_o(s1_stb),
.s1_ack_i(s1_ack),
// Slave 2
.s2_dat_i(s2_dat_r),
.s2_dat_o(s2_dat_w),
.s2_adr_o(s2_adr),
.s2_cti_o(s2_cti),
.s2_sel_o(s2_sel),
.s2_we_o(s2_we),
.s2_cyc_o(s2_cyc),
.s2_stb_o(s2_stb),
.s2_ack_i(s2_ack),
// Slave 3
.s3_dat_i(s3_dat_r),
.s3_dat_o(s3_dat_w),
.s3_adr_o(s3_adr),
.s3_cti_o(s3_cti),
.s3_sel_o(s3_sel),
.s3_we_o(s3_we),
.s3_cyc_o(s3_cyc),
.s3_stb_o(s3_stb),
.s3_ack_i(s3_ack),
// Slave 4
.s4_dat_i(s4_dat_r),
.s4_dat_o(s4_dat_w),
.s4_adr_o(s4_adr),
.s4_cti_o(s4_cti),
.s4_sel_o(s4_sel),
.s4_we_o(s4_we),
.s4_cyc_o(s4_cyc),
.s4_stb_o(s4_stb),
.s4_ack_i(s4_ack)
);
//---------------------------------------------------------------------------
// Masters
//---------------------------------------------------------------------------
wire m0_end;
master #(
.id(0)
) m0 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(m0_dat_w),
.dat_r(m0_dat_r),
.adr(m0_adr),
.cti(m0_cti),
.we(m0_we),
.sel(m0_sel),
.cyc(m0_cyc),
.stb(m0_stb),
.ack(m0_ack),
.tend(m0_end)
);
wire m1_end;
master #(
.id(1)
) m1 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(m1_dat_w),
.dat_r(m1_dat_r),
.adr(m1_adr),
.cti(m1_cti),
.we(m1_we),
.sel(m1_sel),
.cyc(m1_cyc),
.stb(m1_stb),
.ack(m1_ack),
.tend(m1_end)
);
wire m2_end;
master #(
.id(2)
) m2 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(m2_dat_w),
.dat_r(m2_dat_r),
.adr(m2_adr),
.cti(m2_cti),
.we(m2_we),
.sel(m2_sel),
.cyc(m2_cyc),
.stb(m2_stb),
.ack(m2_ack),
.tend(m2_end)
);
wire m3_end;
master #(
.id(3)
) m3 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(m3_dat_w),
.dat_r(m3_dat_r),
.adr(m3_adr),
.cti(m3_cti),
.we(m3_we),
.sel(m3_sel),
.cyc(m3_cyc),
.stb(m3_stb),
.ack(m3_ack),
.tend(m3_end)
);
wire m4_end;
master #(
.id(4)
) m4 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(m4_dat_w),
.dat_r(m4_dat_r),
.adr(m4_adr),
.cti(m4_cti),
.we(m4_we),
.sel(m4_sel),
.cyc(m4_cyc),
.stb(m4_stb),
.ack(m4_ack),
.tend(m4_end)
);
//---------------------------------------------------------------------------
// Slaves
//---------------------------------------------------------------------------
slave #(
.id(0)
) s0 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(s0_dat_w),
.dat_r(s0_dat_r),
.adr(s0_adr),
.cti(s0_cti),
.we(s0_we),
.sel(s0_sel),
.cyc(s0_cyc),
.stb(s0_stb),
.ack(s0_ack)
);
slave #(
.id(1)
) s1 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(s1_dat_w),
.dat_r(s1_dat_r),
.adr(s1_adr),
.cti(s1_cti),
.we(s1_we),
.sel(s1_sel),
.cyc(s1_cyc),
.stb(s1_stb),
.ack(s1_ack)
);
slave #(
.id(2)
) s2 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(s2_dat_w),
.dat_r(s2_dat_r),
.adr(s2_adr),
.cti(s2_cti),
.we(s2_we),
.sel(s2_sel),
.cyc(s2_cyc),
.stb(s2_stb),
.ack(s2_ack)
);
slave #(
.id(3)
) s3 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(s3_dat_w),
.dat_r(s3_dat_r),
.adr(s3_adr),
.cti(s3_cti),
.we(s3_we),
.sel(s3_sel),
.cyc(s3_cyc),
.stb(s3_stb),
.ack(s3_ack)
);
slave #(
.id(4)
) s4 (
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.dat_w(s4_dat_w),
.dat_r(s4_dat_r),
.adr(s4_adr),
.cti(s4_cti),
.we(s4_we),
.sel(s4_sel),
.cyc(s4_cyc),
.stb(s4_stb),
.ack(s4_ack)
);
initial sys_clk = 1'b0;
always #5 sys_clk = ~sys_clk;
wire all_end = m0_end & m1_end & m2_end & m3_end & m4_end;
always begin
sys_rst = 1'b1;
@(posedge sys_clk);
#1 sys_rst = 1'b0;
@(posedge all_end);
$finish;
end
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/csrbrg/ 0000775 0000000 0000000 00000000000 11653767173 0024151 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/csrbrg/rtl/ 0000775 0000000 0000000 00000000000 11653767173 0024752 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/csrbrg/rtl/csrbrg.v 0000664 0000000 0000000 00000003625 11653767173 0026431 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
module csrbrg(
input sys_clk,
input sys_rst,
/* WB */
input [31:0] wb_adr_i,
input [31:0] wb_dat_i,
output reg [31:0] wb_dat_o,
input wb_cyc_i,
input wb_stb_i,
input wb_we_i,
output reg wb_ack_o,
/* CSR */
output reg [13:0] csr_a,
output reg csr_we,
output reg [31:0] csr_do,
input [31:0] csr_di
);
/* Datapath: WB <- CSR */
always @(posedge sys_clk) begin
wb_dat_o <= csr_di;
end
/* Datapath: CSR -> WB */
reg next_csr_we;
always @(posedge sys_clk) begin
csr_a <= wb_adr_i[15:2];
csr_we <= next_csr_we;
csr_do <= wb_dat_i;
end
/* Controller */
reg [1:0] state;
reg [1:0] next_state;
parameter IDLE = 2'd0;
parameter DELAYACK1 = 2'd1;
parameter DELAYACK2 = 2'd2;
parameter ACK = 2'd3;
always @(posedge sys_clk) begin
if(sys_rst)
state <= IDLE;
else
state <= next_state;
end
always @(*) begin
next_state = state;
wb_ack_o = 1'b0;
next_csr_we = 1'b0;
case(state)
IDLE: begin
if(wb_cyc_i & wb_stb_i) begin
/* We have a request for us */
next_csr_we = wb_we_i;
if(wb_we_i)
next_state = ACK;
else
next_state = DELAYACK1;
end
end
DELAYACK1: next_state = DELAYACK2;
DELAYACK2: next_state = ACK;
ACK: begin
wb_ack_o = 1'b1;
next_state = IDLE;
end
endcase
end
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/csrbrg/test/ 0000775 0000000 0000000 00000000000 11653767173 0025130 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/csrbrg/test/Makefile 0000664 0000000 0000000 00000000172 11653767173 0026570 0 ustar 00root root 0000000 0000000 SOURCES=tb_csrbrg.v $(wildcard ../rtl/*.v)
all: sim
sim:
cver $(SOURCES)
clean:
rm -f verilog.log
.PHONY: clean sim
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/csrbrg/test/tb_csrbrg.v 0000664 0000000 0000000 00000005673 11653767173 0027301 0 ustar 00root root 0000000 0000000 /*
* Milkymist SoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
module tb_csrbrg();
reg sys_clk;
reg sys_rst;
reg [31:0] wb_adr_i;
reg [31:0] wb_dat_i;
wire [31:0] wb_dat_o;
reg wb_cyc_i;
reg wb_stb_i;
reg wb_we_i;
wire wb_ack_o;
wire [13:0] csr_a;
wire csr_we;
wire [31:0] csr_do;
reg [31:0] csr_di;
/* 100MHz system clock */
initial sys_clk = 1'b0;
always #5 sys_clk = ~sys_clk;
csrbrg dut(
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.wb_adr_i(wb_adr_i),
.wb_dat_i(wb_dat_i),
.wb_dat_o(wb_dat_o),
.wb_cyc_i(wb_cyc_i),
.wb_stb_i(wb_stb_i),
.wb_we_i(wb_we_i),
.wb_ack_o(wb_ack_o),
/* CSR bus master */
.csr_a(csr_a),
.csr_we(csr_we),
.csr_do(csr_do),
.csr_di(csr_di)
);
task waitclock;
begin
@(posedge sys_clk);
#1;
end
endtask
task wbwrite;
input [31:0] address;
input [31:0] data;
integer i;
begin
wb_adr_i = address;
wb_dat_i = data;
wb_cyc_i = 1'b1;
wb_stb_i = 1'b1;
wb_we_i = 1'b1;
i = 0;
while(~wb_ack_o) begin
i = i+1;
waitclock;
end
waitclock;
$display("WB Write: %x=%x acked in %d clocks", address, data, i);
wb_cyc_i = 1'b0;
wb_stb_i = 1'b0;
wb_we_i = 1'b0;
end
endtask
task wbread;
input [31:0] address;
integer i;
begin
wb_adr_i = address;
wb_cyc_i = 1'b1;
wb_stb_i = 1'b1;
wb_we_i = 1'b0;
i = 0;
while(~wb_ack_o) begin
i = i+1;
waitclock;
end
$display("WB Read : %x=%x acked in %d clocks", address, wb_dat_o, i);
waitclock;
wb_cyc_i = 1'b0;
wb_stb_i = 1'b0;
wb_we_i = 1'b0;
end
endtask
/* Simulate CSR slave */
reg [31:0] csr1;
reg [31:0] csr2;
wire csr_selected = (csr_a[13:10] == 4'ha);
always @(posedge sys_clk) begin
if(csr_selected) begin
if(csr_we) begin
$display("Writing %x to CSR %x", csr_do, csr_a[0]);
case(csr_a[0])
1'b0: csr1 <= csr_do;
1'b1: csr2 <= csr_do;
endcase
end
case(csr_a[0])
1'b0: csr_di <= csr1;
1'b1: csr_di <= csr2;
endcase
end else
/* we must set data to 0 to be able to use a distributed OR topology
* in the slaves->master datapath.
*/
csr_di <= 32'd0;
end
always begin
/* Reset / Initialize our logic */
sys_rst = 1'b1;
wb_adr_i = 32'd0;
wb_dat_i = 32'd0;
wb_cyc_i = 1'b0;
wb_stb_i = 1'b0;
wb_we_i = 1'b0;
waitclock;
sys_rst = 1'b0;
waitclock;
/* Try some transfers */
wbwrite(32'h0000a000, 32'hcafebabe);
wbwrite(32'h0000a004, 32'habadface);
wbread(32'h0000a000);
wbread(32'h0000a004);
$finish;
end
endmodule
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/ 0000775 0000000 0000000 00000000000 11653767173 0023626 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/TODO.txt 0000664 0000000 0000000 00000000302 11653767173 0025127 0 ustar 00root root 0000000 0000000 - integrator with anti-windup
- frequency error overflow checking/clamping (no recovery after loss-of-lock event)
- clock multiplexing: allow for UP0/UP1/local reference clock dynamic switching
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/build_wb.sh 0000775 0000000 0000000 00000000303 11653767173 0025750 0 ustar 00root root 0000000 0000000 #!/bin/bash
mkdir -p doc
wbgen2 -D ./doc/wrsw_helper_pll.html -V hpll_wb_slave.vhd -C ../../../software/include/hw/hpll_regs.h --cstyle defines --lang vhdl -K ../../sim/hpll_wb_regs.v hpll_wb.wb tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/hpll_bangbang_pd.vhd 0000664 0000000 0000000 00000031173 11653767173 0027577 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- Title : DMTD Helper PLL (HPLL) - bang-bang phase/frequency detector
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : hpll_bangbang_pd.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2011-01-14
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Bang-bang type phase detector. clk_ref_i and clk_fbck_i clocks
-- are divided by hpll_divr_div_ref_i and hpll_divr_div_fb_i respectively and
-- compared. The phase error is outputted every (2^hpll_pcr_pd_gate_i + 10)
-- clk_fbck_i cycles. Divider counters can be synchronized at any moment
-- by pulsing the sync_dividers_p_i signal.
-------------------------------------------------------------------------------
-- 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.common_components.all;
entity hpll_bangbang_pd is
port (
-------------------------------------------------------------------------------
-- Clocks & resets
-------------------------------------------------------------------------------
-- reference clock
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;
-------------------------------------------------------------------------------
-- I/O
-------------------------------------------------------------------------------
sync_dividers_p_i : in std_logic;
phase_err_o : out std_logic_vector(11 downto 0);
phase_err_stb_p_o : out std_logic;
-------------------------------------------------------------------------------
-- Wishbone regs
-------------------------------------------------------------------------------
-- phase counter gating
hpll_pcr_pd_gate_i : in std_logic_vector(2 downto 0);
-- reference divider
hpll_divr_div_ref_i : in std_logic_vector(15 downto 0);
-- feedback divider
hpll_divr_div_fb_i : in std_logic_vector(15 downto 0);
-------------------------------------------------------------------------------
-- Debug outputs
-------------------------------------------------------------------------------
dbg_ref_divided_o : out std_logic;
dbg_fbck_divided_o : out std_logic;
dbg_pd_up_o : out std_logic;
dbg_pd_down_o : out std_logic
);
attribute rom_extract: string;
attribute rom_extract of hpll_bangbang_pd : entity is "no";
end hpll_bangbang_pd;
architecture rtl of hpll_bangbang_pd is
constant c_COUNTER_BITS : integer := 18;
constant c_ONES : std_logic_vector(63 downto 0) := (others => '1');
constant c_ZEROS : std_logic_vector(63 downto 0) := (others => '0');
signal gate_counter : unsigned(c_COUNTER_BITS-1 downto 0);
signal gate_p : std_logic;
signal updown_counter : signed(c_COUNTER_BITS-1 downto 0);
-- phase error clamping stuff
signal ph_err_sign : std_logic;
signal ph_err_extrabits : std_logic_vector(c_COUNTER_BITS - 12 downto 0);
signal ph_err_clamp_plus : std_logic;
signal ph_err_clamp_minus : std_logic;
signal ph_sreg_delay : std_logic_vector(4 downto 0);
signal ph_err : signed(c_COUNTER_BITS-1 downto 0);
signal ph_err_p : std_logic;
signal ph_err_avg_slv : std_logic_vector(11 downto 0);
signal ph_err_avg_p : std_logic;
signal clk_ref_div2 : std_logic; -- reference clock/2
-- phase detector input signals (after division)
signal pd_in_ref : std_logic;
signal pd_in_fbck : std_logic;
-- phase detector outputs
signal pd_a, pd_b, pd_t, pd_ta : std_logic;
signal pd_up, pd_down : std_logic;
signal atb_together : std_logic_vector(2 downto 0);
-- divider counters
signal div_ctr_ref : unsigned(15 downto 0); -- max N = 65535
signal div_ctr_fbck : unsigned(15 downto 0); -- max N = 65535
-- counter sync signals
signal sync_dividers_ref_p : std_logic;
signal sync_dividers_fbck_p : std_logic;
-- disable RAM extraction (XST is trying to implement the phase detector in a
-- RAM)
-- attribute ram_extract of pd_down : signal is "no";
begin -- rtl
sync_ffs_sync_dividers_ref : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_ref_i,
rst_n_i => rst_n_refclk_i,
data_i => sync_dividers_p_i,
synced_o => open,
npulse_o => open,
ppulse_o => sync_dividers_ref_p);
sync_ffs_sync_dividers_fbck : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_fbck_i,
rst_n_i => rst_n_fbck_i,
data_i => sync_dividers_p_i,
synced_o => open,
npulse_o => open,
ppulse_o => sync_dividers_fbck_p);
-- divide the reference clock by 2 - the reference clock must be 2x slower
-- than the VCO clock for proper operation of the BB detector
divide_ref_2 : process(clk_ref_i, rst_n_refclk_i)
begin
if rising_edge(clk_ref_i) then
if rst_n_refclk_i = '0' then
clk_ref_div2 <= '0';
else
clk_ref_div2 <= not clk_ref_div2;
end if;
end if;
end process;
-- Divides the reference clock by DIV_REF, output signal: pd_in_ref.
divide_ref_N : process (clk_ref_i, rst_n_refclk_i)
begin -- process
if rising_edge(clk_ref_i) then
if rst_n_refclk_i = '0' or sync_dividers_ref_p = '1' then
div_ctr_ref <= to_unsigned(1, div_ctr_ref'length);
pd_in_ref <= '0';
else
if(clk_ref_div2 = '1') then -- reference clock must be at the half rate of
-- the VCO clock
if (div_ctr_ref = unsigned(hpll_divr_div_ref_i)) then
div_ctr_ref <= to_unsigned(1, div_ctr_ref'length);
pd_in_ref <= not pd_in_ref; -- divide the clock :)
else
div_ctr_ref <= div_ctr_ref + 1;
end if;
end if;
end if;
end if;
end process;
-- Divides the VCO clock by DIV_FB, output signal: pd_in_fbck
divide_fbck_N : process (clk_fbck_i, rst_n_fbck_i)
begin -- process
if rising_edge(clk_fbck_i) then
if rst_n_fbck_i = '0' or sync_dividers_fbck_p = '1' then
div_ctr_fbck <= to_unsigned(1, div_ctr_fbck'length);
pd_in_fbck <= '0';
else
if (div_ctr_fbck = unsigned(hpll_divr_div_fb_i)) then
div_ctr_fbck <= to_unsigned(1, div_ctr_fbck'length);
pd_in_fbck <= not pd_in_fbck; -- divide the clock :)
else
div_ctr_fbck <= div_ctr_fbck + 1;
end if;
end if;
end if;
end process;
-------------------------------------------------------------------------------
-- Bang-bang PD
-------------------------------------------------------------------------------
bb_pd_negedge : process(pd_in_fbck)
begin
if falling_edge(pd_in_fbck) then
pd_ta <= pd_in_ref;
end if;
end process;
bb_pd_posedge : process(pd_in_fbck)
begin
if rising_edge(pd_in_fbck) then
pd_b <= pd_in_ref;
pd_a <= pd_b;
pd_t <= pd_ta;
end if;
end process;
atb_together <= pd_a & pd_t & pd_b;
decode_bangbang : process(atb_together)
begin
case (atb_together) is
when "000" => -- no transition
pd_up <= '0';
pd_down <= '0';
when "001" => -- too fast
pd_up <= '0';
pd_down <= '1';
when "010" => -- invalid
pd_up <= '1';
pd_down <= '1';
when "011" => -- too slow
pd_up <= '1';
pd_down <= '0';
when "100" => -- too slow
pd_up <= '1';
pd_down <= '0';
when "101" => -- invalid
pd_up <= '1';
pd_down <= '1';
when "110" => -- too fast
pd_up <= '0';
pd_down <= '1';
when "111" => -- no transition
pd_up <= '0';
pd_down <= '0';
when others => null;
end case;
end process;
-- decodes the PD_GATE field from PCR register and generates the gating pulse
-- on gate_p.
phase_gating_decode : process (hpll_pcr_pd_gate_i, gate_counter)
begin
case hpll_pcr_pd_gate_i is
when "000" => gate_p <= gate_counter(10); -- gating: 1024
when "001" => gate_p <= gate_counter(11); -- gating: 2048
when "010" => gate_p <= gate_counter(12); -- gating: 4096
when "011" => gate_p <= gate_counter(13); -- gating: 8192
when "100" => gate_p <= gate_counter(14); -- gating: 16384
when "101" => gate_p <= gate_counter(15); -- gating: 32768
when "110" => gate_p <= gate_counter(16); -- gating: 65536
when "111" => gate_p <= gate_counter(17); -- gating: 131072
when others => null;
end case;
end process;
-- error counter: accumulates UP/DOWN pulses from the phase detector in
-- updown_counter. The counter value is outputted to ph_err when there's a
-- pulse on gate_p signal and then the accumulating counter is reset.
count_updown : process(clk_fbck_i, rst_n_fbck_i)
begin
if rising_edge(clk_fbck_i) then
if rst_n_fbck_i = '0' then
ph_err <= (others => '0');
ph_sreg_delay <= (others => '0');
updown_counter <= (others => '0');
gate_counter <= to_unsigned(1, gate_counter'length);
else
if(gate_p = '1') then
-- got a gating pulse? output the new phase value
gate_counter <= to_unsigned(1, gate_counter'length);
ph_sreg_delay <= (others => '1');
-- check if we have a up/down pulse during counter reset
if(pd_up = '1' and pd_down = '0') then
updown_counter <= to_signed(1, updown_counter'length);
elsif (pd_up = '0' and pd_down = '1') then
updown_counter <= to_signed(-1, updown_counter'length);
else
updown_counter <= (others => '0');
end if;
ph_err <= updown_counter;
else
gate_counter <= gate_counter + 1;
ph_sreg_delay <= '0' & ph_sreg_delay (ph_sreg_delay'length -1 downto 1);
-- count the PD detector pulses
if(pd_up = '1' and pd_down = '0') then
updown_counter <= updown_counter + 1;
elsif (pd_up = '0' and pd_down = '1') then
updown_counter <= updown_counter - 1;
end if;
end if;
end if;
end if;
end process;
-- sync chain (from clk_fbck_i to clk_sys_i) for the new phase error pulse (ph_err_p).
sync_ffs_phase_p : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
data_i => ph_sreg_delay(0),
synced_o => open,
npulse_o => open,
ppulse_o => ph_err_p);
-- phase error clamping stuff:
ph_err_sign <= std_logic(ph_err(ph_err'length-1));
ph_err_extrabits <= std_logic_vector(ph_err(ph_err'length-1 downto phase_err_o'length-1));
ph_err_clamp_minus <= '1' when ph_err_sign = '1' and (ph_err_extrabits /= c_ONES(ph_err_extrabits'length-1 downto 0)) else '0';
ph_err_clamp_plus <= '1' when ph_err_sign = '0' and (ph_err_extrabits /= c_ZEROS(ph_err_extrabits'length-1 downto 0)) else '0';
error_output : process (clk_sys_i, rst_n_sysclk_i)
begin -- process
if rising_edge(clk_sys_i) then
if (rst_n_sysclk_i = '0') then
ph_err_avg_slv <= (others => '0');
ph_err_avg_p <= '0';
else
-- got new value of the phase error? output it with clamping:)
if(ph_err_clamp_minus = '1') then
ph_err_avg_slv <= '1' & c_ZEROS(phase_err_o'length-2 downto 0);
elsif (ph_err_clamp_plus = '1') then
ph_err_avg_slv <= '0' & c_ONES(phase_err_o'length-2 downto 0);
else
ph_err_avg_slv <= std_logic_vector(ph_err(phase_err_o'length-1 downto 0));
end if;
ph_err_avg_p <= ph_err_p;
end if;
end if;
end process;
phase_err_o <= ph_err_avg_slv;
phase_err_stb_p_o <= ph_err_avg_p;
-- drive the "debug" outputs
dbg_pd_down_o <= pd_down;
dbg_pd_up_o <= pd_up;
dbg_fbck_divided_o <= pd_in_fbck;
dbg_ref_divided_o <= pd_in_ref;
end rtl;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/hpll_controller.vhd 0000664 0000000 0000000 00000030015 11653767173 0027532 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- Title : DMTD Helper PLL (HPLL) - programmable PI controller
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : hpll_controller.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2010-06-21
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Dual, programmable PI controller:
-- - first channel processes the frequency error (gain defined by P_KP/P_KI)
-- - second channel processes the phase error (gain defined by F_KP/F_KI)
-- The PI controller starts in the frequency lock mode (using 1st channel).
-- After locking on the frequency, it switches to phase mode (2nd channel).
-------------------------------------------------------------------------------
-- 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;
entity hpll_controller is
generic(
g_error_bits : integer := 12;
g_dacval_bits : integer := 16;
g_output_bias : integer := 32767;
g_integrator_fracbits : integer := 16;
g_integrator_overbits : integer := 6;
g_coef_bits : integer := 16
);
port (
clk_sys_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-------------------------------------------------------------------------------
-- Phase & frequency error inputs
-------------------------------------------------------------------------------
phase_err_i : in std_logic_vector(g_error_bits-1 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(g_error_bits-1 downto 0);
freq_err_stb_p_i : in std_logic;
-------------------------------------------------------------------------------
-- DAC Output
-------------------------------------------------------------------------------
dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_val_stb_p_o : out std_logic;
sync_dividers_p_o : out std_logic;
-------------------------------------------------------------------------------
-- Wishbone regs
-------------------------------------------------------------------------------
-- PLL enable
hpll_pcr_enable_i : in std_logic;
-- PI force freq mode. '1' causes the PI to stay in frequency lock mode all the
-- time.
hpll_pcr_force_f_i : in std_logic;
-- Frequency Kp/Ki
hpll_fbgr_f_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_fbgr_f_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
-- Phase Kp/Ki
hpll_pbgr_p_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
-- Lock detect
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
-- Flags: frequency lock
hpll_psr_freq_lk_o : out std_logic;
-- Flags: phase lock
hpll_psr_phase_lk_o : out std_logic;
-- Flags: loss-of-lock indicator
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
-- phase/freq error recording FIFO
hpll_rfifo_wr_req_o : out std_logic;
hpll_rfifo_wr_full_i : in std_logic;
hpll_rfifo_fp_mode_o : out std_logic;
hpll_rfifo_err_val_o : out std_logic_vector(g_error_bits-1 downto 0);
hpll_rfifo_dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0)
);
end hpll_controller;
architecture behavioral of hpll_controller is
component hpll_lock_detect
port (
rst_n_sysclk_i : std_logic;
clk_sys_i : std_logic;
phase_err_i : in std_logic_vector(11 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(11 downto 0);
freq_err_stb_p_i : in std_logic;
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
hpll_psr_freq_lk_o : out std_logic;
hpll_psr_phase_lk_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
freq_mode_o : out std_logic);
end component;
type t_hpll_state is (HPLL_WAIT_SAMPLE, HPLL_MUL_KI, HPLL_INTEGRATE, HPLL_MUL_KP, HPLL_CALC_SUM, HPLL_ROUND_SUM);
-- integrator size: 12 error bits + 16 coefficient bits + 6 overflow bits
constant c_INTEGRATOR_BITS : integer := g_error_bits + g_integrator_overbits + g_coef_bits;
constant c_ZEROS : unsigned (63 downto 0) := (others => '0');
constant c_ONES : unsigned (63 downto 0) := (others => '1');
-- DAC DC bias (extended by c_INTEGRATOR_FRACBITS). By default it's half of the
-- output voltage scale.
constant c_OUTPUT_BIAS : signed(g_dacval_bits + g_integrator_fracbits-1 downto 0) := to_signed(g_output_bias, g_dacval_bits) & to_signed(0, g_integrator_fracbits);
-- Multiplier size. A = error value, B = coefficient value
constant c_MUL_A_BITS : integer := g_error_bits;
constant c_MUL_B_BITS : integer := g_coef_bits;
-- the integrator
signal i_reg : signed(c_INTEGRATOR_BITS-1 downto 0);
-- multiplier IO
signal mul_A : signed(c_MUL_A_BITS - 1 downto 0);
signal mul_B : signed(c_MUL_B_BITS - 1 downto 0);
signal mul_OUT : signed(c_MUL_A_BITS + c_MUL_B_BITS - 1 downto 0);
signal mul_out_reg : signed(c_MUL_A_BITS + c_MUL_B_BITS - 1 downto 0);
signal pi_state : t_hpll_state;
-- 1: we are in the frequency mode, 0: we are in phase mode.
signal freq_mode : std_logic;
signal freq_mode_ld : std_logic;
signal output_val : unsigned(c_INTEGRATOR_BITS-1 downto 0);
signal output_val_unrounded : unsigned(g_dacval_bits-1 downto 0);
signal output_val_round_up : std_logic;
signal dac_val_int : std_logic_vector(g_dacval_bits-1 downto 0);
begin -- behavioral
LOCK_DET : hpll_lock_detect
port map (
rst_n_sysclk_i => rst_n_sysclk_i,
clk_sys_i => clk_sys_i,
phase_err_i => phase_err_i,
phase_err_stb_p_i => phase_err_stb_p_i,
freq_err_i => freq_err_i,
freq_err_stb_p_i => freq_err_stb_p_i,
hpll_ldcr_ld_samp_i => hpll_ldcr_ld_samp_i,
hpll_ldcr_ld_thr_i => hpll_ldcr_ld_thr_i,
hpll_psr_freq_lk_o => hpll_psr_freq_lk_o,
hpll_psr_phase_lk_o => hpll_psr_phase_lk_o,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_i,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_o,
hpll_psr_lock_lost_load_i => hpll_psr_lock_lost_load_i,
freq_mode_o => freq_mode_ld);
-- shared multiplier
multiplier : process (mul_A, mul_B)
begin -- process
mul_OUT <= mul_A * mul_B;
end process;
output_val_unrounded <= output_val(g_integrator_fracbits + g_dacval_bits - 1 downto g_integrator_fracbits);
output_val_round_up <= std_logic(output_val(g_integrator_fracbits - 1));
main_fsm : process (clk_sys_i, rst_n_sysclk_i)
begin -- process
if rising_edge(clk_sys_i) then
if rst_n_sysclk_i = '0' then
i_reg <= (others => '0');
freq_mode <= '1'; -- start in frequency lock mode
pi_state <= HPLL_WAIT_SAMPLE;
dac_val_stb_p_o <= '0';
dac_val_int <= (others => '0');
sync_dividers_p_o <= '0';
freq_mode <= '1';
else
if hpll_pcr_enable_i = '0' then
pi_state <= HPLL_WAIT_SAMPLE;
dac_val_stb_p_o <= '0';
freq_mode <= '1';
else
case pi_state is
-------------------------------------------------------------------------------
-- State: HPLL wait for input sample. When a frequency error (or phase error)
-- sample arrives from the detector, start the PI update.
-------------------------------------------------------------------------------
when HPLL_WAIT_SAMPLE =>
dac_val_stb_p_o <= '0';
hpll_rfifo_wr_req_o <= '0';
-- frequency lock mode, got a frequency sample
if(freq_mode = '1' and freq_err_stb_p_i = '1') then
pi_state <= HPLL_MUL_KI;
mul_A <= signed(freq_err_i);
mul_B <= signed(hpll_fbgr_f_ki_i);
-- phase lock mode, got a phase sample
elsif (freq_mode = '0' and phase_err_stb_p_i = '1') then
pi_state <= HPLL_MUL_KI;
mul_A <= signed(phase_err_i);
mul_B <= signed(hpll_pbgr_p_ki_i);
end if;
-------------------------------------------------------------------------------
-- State: HPLL multiply by Ki: multiples the phase/freq error by an appropriate
-- Kp/Ki coefficient, set up the multipler for (error * Kp) operation.
-------------------------------------------------------------------------------
when HPLL_MUL_KI =>
sync_dividers_p_o <= '0';
if(freq_mode = '1') then
mul_B <= signed(hpll_fbgr_f_kp_i);
else
mul_B <= signed(hpll_pbgr_p_kp_i);
end if;
mul_out_reg <= mul_OUT; -- just keep the result
pi_state <= HPLL_INTEGRATE;
-------------------------------------------------------------------------------
-- State: HPLL integrate: add the (Error * Ki) to the integrator register
-------------------------------------------------------------------------------
when HPLL_INTEGRATE =>
i_reg <= i_reg + mul_out_reg;
pi_state <= HPLL_MUL_KP;
-------------------------------------------------------------------------------
-- State: HPLL multiply by Kp: does the same as HPLL_MUL_KI but for the proportional
-- branch.
-------------------------------------------------------------------------------
when HPLL_MUL_KP =>
mul_out_reg <= mul_OUT;
pi_state <= HPLL_CALC_SUM;
when HPLL_CALC_SUM =>
output_val <= unsigned(c_OUTPUT_BIAS + resize(mul_out_reg, output_val'length) + resize(i_reg, output_val'length));
pi_state <= HPLL_ROUND_SUM;
-------------------------------------------------------------------------------
-- State: HPLL round sum: calculates the final DAC value, with 0.5LSB rounding.
-- Also checks for the frequency lock.
-------------------------------------------------------------------------------
when HPLL_ROUND_SUM =>
dac_val_stb_p_o <= '1';
-- +-0.5 rounding of the output value
if(output_val_round_up = '1') then
dac_val_int <= std_logic_vector(output_val_unrounded + 1);
else
dac_val_int <= std_logic_vector(output_val_unrounded);
end if;
pi_state <= HPLL_WAIT_SAMPLE;
if(hpll_pcr_force_f_i = '0') then
freq_mode <= freq_mode_ld;
else
freq_mode <= '1';
end if;
if(freq_mode = '1' and freq_mode_ld = '0') then
sync_dividers_p_o <= '1';
end if;
hpll_rfifo_wr_req_o <= not hpll_rfifo_wr_full_i;
when others => null;
end case;
end if;
end if;
end if;
end process;
-- record some diagnostic stuff (error, dac val) into a FIFO
hpll_rfifo_fp_mode_o <= freq_mode;
hpll_rfifo_dac_val_o <= dac_val_int;
hpll_rfifo_err_val_o <= phase_err_i when freq_mode = '0' else freq_err_i;
dac_val_o <= dac_val_int;
end behavioral;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/hpll_lock_detect.vhd 0000664 0000000 0000000 00000013733 11653767173 0027637 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- Title : DMTD Helper PLL (HPLL) - lock detection logic
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : hpll_controller.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2010-08-23
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description:
-------------------------------------------------------------------------------
-- 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;
entity hpll_lock_detect is
port (
rst_n_sysclk_i : std_logic;
clk_sys_i : std_logic;
phase_err_i : in std_logic_vector(11 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(11 downto 0);
freq_err_stb_p_i : in std_logic;
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
-- Flags: frequency lock
hpll_psr_freq_lk_o : out std_logic;
-- Flags: phase lock
hpll_psr_phase_lk_o : out std_logic;
-- Flags: loss-of-lock indicator
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
-- PI frequency/phase mode select
freq_mode_o : out std_logic
);
end hpll_lock_detect;
architecture syn of hpll_lock_detect is
type t_lock_detect_state is (LD_WAIT_FREQ_LOCK, LD_WAIT_PHASE_LOCK, LD_LOCKED);
signal ph_err_sign_d0 : std_logic;
signal ph_err_sign : std_logic;
signal ph_err_valid : std_logic;
signal ph_err_duty_cntr : unsigned(7 downto 0);
signal ph_err_lock_cntr : unsigned(7 downto 0);
signal f_err_lock_cntr : unsigned(7 downto 0);
signal phase_lock : std_logic;
signal freq_lock : std_logic;
signal state : t_lock_detect_state;
signal f_err_int : integer;
begin
ph_err_sign <= phase_err_i(phase_err_i'length-1);
lock_detect_phase : process (clk_sys_i, rst_n_sysclk_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_sysclk_i = '0') then
ph_err_valid <= '0';
ph_err_sign_d0 <= '0';
ph_err_valid <= '0';
ph_err_duty_cntr <= (others => '0');
ph_err_lock_cntr <= (others => '0');
phase_lock <= '0';
else
-- new phase error value arrived
if(phase_err_stb_p_i = '1') then
ph_err_sign_d0 <= ph_err_sign;
-- the sign of the phase error has changed, check how long it will
-- take to flip again
if(ph_err_sign /= ph_err_sign_d0) then
ph_err_duty_cntr <= (others => '0');
-- if the phase error has been changing its sign frequent enough
-- for a given number of samples, we assume the PLL is locked
if(std_logic_vector(ph_err_lock_cntr) = hpll_ldcr_ld_samp_i) then
phase_lock <= '1';
else
ph_err_lock_cntr <= ph_err_lock_cntr + 1;
phase_lock <= '0';
end if;
else
-- if the phase error remains positive or negative for too long,
-- we are out of lock
if(std_logic_vector(ph_err_duty_cntr) = hpll_ldcr_ld_thr_i) then
ph_err_lock_cntr <= (others => '0');
phase_lock <= '0';
else
ph_err_duty_cntr <= ph_err_duty_cntr + 1;
end if;
end if;
end if;
end if;
end if;
end process;
f_err_int <= to_integer(signed(freq_err_i));
lock_detect_freq : process(clk_sys_i, rst_n_sysclk_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_sysclk_i = '0') then
freq_lock <= '0';
f_err_lock_cntr <= (others => '0');
else
if(freq_err_stb_p_i = '1') then
if(f_err_int > -300 and f_err_int < 300) then
if(std_logic_vector(f_err_lock_cntr) = hpll_ldcr_ld_samp_i) then
freq_lock <= '1';
else
f_err_lock_cntr <= f_err_lock_cntr + 1;
freq_lock <= '0';
end if;
else
f_err_lock_cntr <= (others => '0');
freq_lock <= '0';
end if;
end if;
end if;
end if;
end process;
lock_fsm : process(clk_sys_i, rst_n_sysclk_i)
begin -- process
if rising_edge(clk_sys_i) then
if (rst_n_sysclk_i = '0') then
state <= LD_WAIT_FREQ_LOCK;
freq_mode_o <= '1';
hpll_psr_lock_lost_o <= '0';
else
if(hpll_psr_lock_lost_load_i = '1' and hpll_psr_lock_lost_i = '1') then
hpll_psr_lock_lost_o <= '0';
end if;
case state is
when LD_WAIT_FREQ_LOCK =>
if(freq_lock = '1') then
state <= LD_WAIT_PHASE_LOCK;
freq_mode_o <= '0';
else
freq_mode_o <= '1';
end if;
when LD_WAIT_PHASE_LOCK =>
if(phase_lock = '1') then
state <= LD_LOCKED;
end if;
when LD_LOCKED =>
if(phase_lock = '0' or freq_lock = '0') then
hpll_psr_lock_lost_o <= '1';
end if;
if(phase_lock = '0') then
state <= LD_WAIT_PHASE_LOCK;
elsif freq_lock = '0' then
state <= LD_WAIT_FREQ_LOCK;
end if;
when others => null;
end case;
end if;
end if;
end process;
hpll_psr_phase_lk_o <= phase_lock;
hpll_psr_freq_lk_o <= freq_lock;
end syn;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/hpll_period_detect.vhd 0000664 0000000 0000000 00000021601 11653767173 0030162 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- 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-04-08
-- 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.common_components.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 : 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 : 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;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/hpll_wb.wb 0000664 0000000 0000000 00000016053 11653767173 0025614 0 ustar 00root root 0000000 0000000 -- -*- Mode: LUA; tab-width: 2 -*-
peripheral
{
name = "DMTD Helper PLL";
description = "PLL controller for generating the DMTD offset clock.";
prefix = "HPLL";
hdl_entity = "hpll_wb_slave";
reg {
name = "HPLL Control Register";
description = "HPLL Control register";
prefix = "PCR";
field {
name = "PLL Enable";
description = "1: PLL is enabled \
0: PLL is disabled";
type = BIT;
prefix = "ENABLE";
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "PLL Force Freq mode";
type = BIT;
prefix = "FORCE_F";
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "DAC serial clock select";
description = "Selects the DAC serial clock frequency: \
0: f = refclk / 8 (~ 16 MHz) \
1: f = refclk / 16 (~ 8 MHz) \
2: f = refclk / 32 (~ 4 MHz) \
3: f = refclk / 64 (~ 2 MHz) \
4: f = refclk / 128 (~ 1 MHz) \
5: f = refclk / 256 (~ 500 kHz) \
6: f = refclk / 512 (~ 250 kHz) \
7: f = refclk / 1024 (~ 125 kHz)";
prefix = "DAC_CLKSEL";
align = 4;
type = SLV;
size = 3;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Phase detector gating period";
description = "Gating period for the phase detector: \
0: period = 1024 \
1: period = 2048 \
2: period = 4096 \
3: period = 8192 \
4: period = 16384 \
5: period = 32768 \
6: period = 65536 \
7: period = 131072";
prefix = "PD_GATE";
type = SLV;
size = 3;
align = 4;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Reference clock input select";
description = "00: local reference (from TCXO)\
01: uplink 0 recovered clock\
10: uplink 1 recovered clock";
size = 2;
type = SLV;
prefix = "REFSEL";
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "PLL Reset";
descritpion = "write 1: causes PLL reset\nwrite 0: no effect";
type = MONOSTABLE;
prefix = "SWRST";
access_bus = READ_WRITE;
access_dev = READ_ONLY;
align=31;
};
};
reg {
name = "HPLL Divider Register";
description = "Register controlling the frequency PLL frequency divider. The output frequency is f_ref * (DIV_FB / DIV_REF)";
prefix = "DIVR";
field {
name = "Reference divider";
prefix = "DIV_REF";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Feedback divider";
prefix = "DIV_FB";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Frequency Branch Gain Register";
description = "Register containing the PI gain factors for the frequency branch.";
prefix = "FBGR";
field {
name = "Proportional gain (Kp)";
prefix = "F_KP";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Integral gain (Ki)";
prefix = "F_KI";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Phase Branch Gain Register";
prefix = "PBGR";
field {
name = "Proportional gain (Kp)";
prefix = "P_KP";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Integral gain (Ki)";
prefix = "P_KI";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Lock Detect Control Register";
prefix = "LDCR";
field {
name = "Phase Lock detect threshold";
prefix = "LD_THR";
description = "A maximum time between bang-bang PD phase error sign changes that keeps the PLL locked";
type = SLV;
size = 8;
align = 4;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Lock detect samples";
prefix = "LD_SAMP";
description = "Number of subsequent phase error samples smaller than LD_THR or frequency error samples in (-1, 1) after which the PLL assumes to be locked.";
type =SLV;
size = 8;
align = 8;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Frequency branch control register";
prefix = "FBCR";
field {
name = "Frequency detector gating period";
description = "Gating period for the frequency detector: \
0: period = 16384 \
1: period = 32768 \
2: period = 65536 \
3: period = 131072 \
4: period = 262144 \
5: period = 524288 \
6: period = 1048576 \
7: period = 2097152";
prefix = "FD_GATE";
type = SLV;
size = 3;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
align =4;
};
field {
name = "Frequency error setpoint";
description = "Value of desired frequency error in the lock state. Computed as: f_err = FD_GATE[real value] * (1 - (N / (N+DELTA)))";
prefix = "FERR_SET";
align = 4;
size = 12;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Status Register";
description = "Register containing the current status of the PLL";
prefix = "PSR";
field {
name = "Frequency lock";
type = BIT;
prefix = "FREQ_LK";
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Phase lock";
type = BIT;
prefix = "PHASE_LK";
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Loss-of-lock indicator";
description = "read 0: PLL is locked\
read 1: PLL has lost the lock since the last poll of this bit\
write 0: no effect\
write 1: clears the field";
type = BIT;
prefix = "LOCK_LOST";
access_bus = READ_WRITE;
access_dev = READ_WRITE;
load = LOAD_EXT;
};
};
fifo_reg {
name = "HPLL Phase/Output record FIFO";
description = "A FIFO recording the phase/freq error, the DAC output and other PLL parameters for debugging/optimization purposes";
prefix = "RFIFO";
direction = CORE_TO_BUS;
size = 1024;
flags_bus = {FIFO_EMPTY};
flags_dev = {FIFO_FULL};
field {
name = "Freq/phase error";
description = "Current frequency/phase error value";
prefix = "ERR_VAL";
type = SLV;
size = 12;
};
field {
name = "Freq/phase mode";
description = "1: frequency mode operation,\n 0: phase mode operation";
prefix = "FP_MODE";
type = BIT;
align = 15;
size = 1;
};
field {
name = "DAC output";
description = "Current DAC output value";
prefix = "DAC_VAL";
type = SLV;
size = 16;
align = 16;
};
};
}; tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/hpll_wb_slave.vhd 0000664 0000000 0000000 00000051406 11653767173 0027160 0 ustar 00root root 0000000 0000000 ---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for DMTD Helper PLL
---------------------------------------------------------------------------------------
-- File : hpll_wb_slave.vhd
-- Author : auto-generated by wbgen2 from hpll_wb.wb
-- Created : Mon Jun 21 14:16:43 2010
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE hpll_wb.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library wbgen2;
use wbgen2.wbgen2_pkg.all;
entity hpll_wb_slave is
port (
rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
-- Port for BIT field: 'PLL Enable' in reg: 'HPLL Control Register'
hpll_pcr_enable_o : out std_logic;
-- Port for BIT field: 'PLL Force Freq mode' in reg: 'HPLL Control Register'
hpll_pcr_force_f_o : out std_logic;
-- Port for std_logic_vector field: 'DAC serial clock select' in reg: 'HPLL Control Register'
hpll_pcr_dac_clksel_o : out std_logic_vector(2 downto 0);
-- Port for std_logic_vector field: 'Phase detector gating period' in reg: 'HPLL Control Register'
hpll_pcr_pd_gate_o : out std_logic_vector(2 downto 0);
-- Port for std_logic_vector field: 'Reference clock input select' in reg: 'HPLL Control Register'
hpll_pcr_refsel_o : out std_logic_vector(1 downto 0);
-- Port for MONOSTABLE field: 'PLL Reset' in reg: 'HPLL Control Register'
hpll_pcr_swrst_o : out std_logic;
-- Port for std_logic_vector field: 'Reference divider' in reg: 'HPLL Divider Register'
hpll_divr_div_ref_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Feedback divider' in reg: 'HPLL Divider Register'
hpll_divr_div_fb_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Proportional gain (Kp)' in reg: 'HPLL Frequency Branch Gain Register'
hpll_fbgr_f_kp_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Integral gain (Ki)' in reg: 'HPLL Frequency Branch Gain Register'
hpll_fbgr_f_ki_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Proportional gain (Kp)' in reg: 'HPLL Phase Branch Gain Register'
hpll_pbgr_p_kp_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Integral gain (Ki)' in reg: 'HPLL Phase Branch Gain Register'
hpll_pbgr_p_ki_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Phase Lock detect threshold' in reg: 'HPLL Lock Detect Control Register'
hpll_ldcr_ld_thr_o : out std_logic_vector(7 downto 0);
-- Port for std_logic_vector field: 'Lock detect samples' in reg: 'HPLL Lock Detect Control Register'
hpll_ldcr_ld_samp_o : out std_logic_vector(7 downto 0);
-- Port for std_logic_vector field: 'Frequency detector gating period' in reg: 'HPLL Frequency branch control register'
hpll_fbcr_fd_gate_o : out std_logic_vector(2 downto 0);
-- Port for std_logic_vector field: 'Frequency error setpoint' in reg: 'HPLL Frequency branch control register'
hpll_fbcr_ferr_set_o : out std_logic_vector(11 downto 0);
-- Port for BIT field: 'Frequency lock' in reg: 'HPLL Status Register'
hpll_psr_freq_lk_i : in std_logic;
-- Port for BIT field: 'Phase lock' in reg: 'HPLL Status Register'
hpll_psr_phase_lk_i : in std_logic;
-- Ports for BIT field: 'Loss-of-lock indicator' in reg: 'HPLL Status Register'
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_load_o : out std_logic;
-- FIFO write request
hpll_rfifo_wr_req_i : in std_logic;
-- FIFO full flag
hpll_rfifo_wr_full_o : out std_logic;
hpll_rfifo_err_val_i : in std_logic_vector(11 downto 0);
hpll_rfifo_fp_mode_i : in std_logic;
hpll_rfifo_dac_val_i : in std_logic_vector(15 downto 0)
);
end hpll_wb_slave;
architecture syn of hpll_wb_slave is
signal hpll_pcr_enable_int : std_logic ;
signal hpll_pcr_force_f_int : std_logic ;
signal hpll_pcr_dac_clksel_int : std_logic_vector(2 downto 0);
signal hpll_pcr_pd_gate_int : std_logic_vector(2 downto 0);
signal hpll_pcr_refsel_int : std_logic_vector(1 downto 0);
signal hpll_pcr_swrst_dly0 : std_logic ;
signal hpll_pcr_swrst_int : std_logic ;
signal hpll_divr_div_ref_int : std_logic_vector(15 downto 0);
signal hpll_divr_div_fb_int : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_kp_int : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_ki_int : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_kp_int : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_ki_int : std_logic_vector(15 downto 0);
signal hpll_ldcr_ld_thr_int : std_logic_vector(7 downto 0);
signal hpll_ldcr_ld_samp_int : std_logic_vector(7 downto 0);
signal hpll_fbcr_fd_gate_int : std_logic_vector(2 downto 0);
signal hpll_fbcr_ferr_set_int : std_logic_vector(11 downto 0);
signal hpll_rfifo_in_int : std_logic_vector(28 downto 0);
signal hpll_rfifo_out_int : std_logic_vector(28 downto 0);
signal hpll_rfifo_rdreq_int : std_logic ;
signal hpll_rfifo_rdreq_int_d0 : std_logic ;
signal hpll_rfifo_empty_int : std_logic ;
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(3 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal bus_clock_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments. For (foreseen) compatibility with other bus standards.
wrdata_reg <= wb_data_i;
bwsel_reg <= wb_sel_i;
bus_clock_int <= wb_clk_i;
rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i));
wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i);
allones <= (others => '1');
allzeros <= (others => '0');
--
-- Main register bank access process.
process (bus_clock_int, rst_n_i)
begin
if (rst_n_i = '0') then
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
hpll_pcr_enable_int <= '0';
hpll_pcr_force_f_int <= '0';
hpll_pcr_dac_clksel_int <= "000";
hpll_pcr_pd_gate_int <= "000";
hpll_pcr_refsel_int <= "00";
hpll_pcr_swrst_int <= '0';
hpll_divr_div_ref_int <= "0000000000000000";
hpll_divr_div_fb_int <= "0000000000000000";
hpll_fbgr_f_kp_int <= "0000000000000000";
hpll_fbgr_f_ki_int <= "0000000000000000";
hpll_pbgr_p_kp_int <= "0000000000000000";
hpll_pbgr_p_ki_int <= "0000000000000000";
hpll_ldcr_ld_thr_int <= "00000000";
hpll_ldcr_ld_samp_int <= "00000000";
hpll_fbcr_fd_gate_int <= "000";
hpll_fbcr_ferr_set_int <= "000000000000";
hpll_psr_lock_lost_load_o <= '0';
hpll_rfifo_rdreq_int <= '0';
elsif rising_edge(bus_clock_int) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
ack_sreg(9) <= '0';
if (ack_in_progress = '1') then
if (ack_sreg(0) = '1') then
hpll_pcr_swrst_int <= '0';
hpll_psr_lock_lost_load_o <= '0';
ack_in_progress <= '0';
else
hpll_psr_lock_lost_load_o <= '0';
end if;
else
if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then
case rwaddr_reg(3 downto 0) is
when "0000" =>
if (wb_we_i = '1') then
hpll_pcr_enable_int <= wrdata_reg(0);
hpll_pcr_force_f_int <= wrdata_reg(1);
hpll_pcr_dac_clksel_int <= wrdata_reg(6 downto 4);
hpll_pcr_pd_gate_int <= wrdata_reg(10 downto 8);
hpll_pcr_refsel_int <= wrdata_reg(12 downto 11);
hpll_pcr_swrst_int <= wrdata_reg(31);
else
rddata_reg(0) <= hpll_pcr_enable_int;
rddata_reg(1) <= hpll_pcr_force_f_int;
rddata_reg(6 downto 4) <= hpll_pcr_dac_clksel_int;
rddata_reg(10 downto 8) <= hpll_pcr_pd_gate_int;
rddata_reg(12 downto 11) <= hpll_pcr_refsel_int;
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
end if;
ack_sreg(2) <= '1';
ack_in_progress <= '1';
when "0001" =>
if (wb_we_i = '1') then
hpll_divr_div_ref_int <= wrdata_reg(15 downto 0);
hpll_divr_div_fb_int <= wrdata_reg(31 downto 16);
else
rddata_reg(15 downto 0) <= hpll_divr_div_ref_int;
rddata_reg(31 downto 16) <= hpll_divr_div_fb_int;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0010" =>
if (wb_we_i = '1') then
hpll_fbgr_f_kp_int <= wrdata_reg(15 downto 0);
hpll_fbgr_f_ki_int <= wrdata_reg(31 downto 16);
else
rddata_reg(15 downto 0) <= hpll_fbgr_f_kp_int;
rddata_reg(31 downto 16) <= hpll_fbgr_f_ki_int;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0011" =>
if (wb_we_i = '1') then
hpll_pbgr_p_kp_int <= wrdata_reg(15 downto 0);
hpll_pbgr_p_ki_int <= wrdata_reg(31 downto 16);
else
rddata_reg(15 downto 0) <= hpll_pbgr_p_kp_int;
rddata_reg(31 downto 16) <= hpll_pbgr_p_ki_int;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0100" =>
if (wb_we_i = '1') then
hpll_ldcr_ld_thr_int <= wrdata_reg(7 downto 0);
hpll_ldcr_ld_samp_int <= wrdata_reg(15 downto 8);
else
rddata_reg(7 downto 0) <= hpll_ldcr_ld_thr_int;
rddata_reg(15 downto 8) <= hpll_ldcr_ld_samp_int;
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0101" =>
if (wb_we_i = '1') then
hpll_fbcr_fd_gate_int <= wrdata_reg(2 downto 0);
hpll_fbcr_ferr_set_int <= wrdata_reg(15 downto 4);
else
rddata_reg(2 downto 0) <= hpll_fbcr_fd_gate_int;
rddata_reg(15 downto 4) <= hpll_fbcr_ferr_set_int;
rddata_reg(3) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0110" =>
if (wb_we_i = '1') then
hpll_psr_lock_lost_load_o <= '1';
else
rddata_reg(0) <= hpll_psr_freq_lk_i;
rddata_reg(1) <= hpll_psr_phase_lk_i;
rddata_reg(2) <= hpll_psr_lock_lost_i;
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0111" =>
if (wb_we_i = '1') then
else
if (hpll_rfifo_rdreq_int_d0 = '0') then
hpll_rfifo_rdreq_int <= not hpll_rfifo_rdreq_int;
else
rddata_reg(11 downto 0) <= hpll_rfifo_out_int(11 downto 0);
rddata_reg(15) <= hpll_rfifo_out_int(12);
rddata_reg(31 downto 16) <= hpll_rfifo_out_int(28 downto 13);
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end if;
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
end if;
when "1000" =>
if (wb_we_i = '1') then
else
rddata_reg(17) <= hpll_rfifo_empty_int;
rddata_reg(0) <= 'X';
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
end if;
end if;
end if;
end process;
-- Drive the data output bus
wb_data_o <= rddata_reg;
-- PLL Enable
hpll_pcr_enable_o <= hpll_pcr_enable_int;
-- PLL Force Freq mode
hpll_pcr_force_f_o <= hpll_pcr_force_f_int;
-- DAC serial clock select
hpll_pcr_dac_clksel_o <= hpll_pcr_dac_clksel_int;
-- Phase detector gating period
hpll_pcr_pd_gate_o <= hpll_pcr_pd_gate_int;
-- Reference clock input select
hpll_pcr_refsel_o <= hpll_pcr_refsel_int;
-- PLL Reset
process (bus_clock_int, rst_n_i)
begin
if (rst_n_i = '0') then
hpll_pcr_swrst_dly0 <= '0';
hpll_pcr_swrst_o <= '0';
elsif rising_edge(bus_clock_int) then
hpll_pcr_swrst_dly0 <= hpll_pcr_swrst_int;
hpll_pcr_swrst_o <= hpll_pcr_swrst_int and (not hpll_pcr_swrst_dly0);
end if;
end process;
-- Reference divider
hpll_divr_div_ref_o <= hpll_divr_div_ref_int;
-- Feedback divider
hpll_divr_div_fb_o <= hpll_divr_div_fb_int;
-- Proportional gain (Kp)
hpll_fbgr_f_kp_o <= hpll_fbgr_f_kp_int;
-- Integral gain (Ki)
hpll_fbgr_f_ki_o <= hpll_fbgr_f_ki_int;
-- Proportional gain (Kp)
hpll_pbgr_p_kp_o <= hpll_pbgr_p_kp_int;
-- Integral gain (Ki)
hpll_pbgr_p_ki_o <= hpll_pbgr_p_ki_int;
-- Phase Lock detect threshold
hpll_ldcr_ld_thr_o <= hpll_ldcr_ld_thr_int;
-- Lock detect samples
hpll_ldcr_ld_samp_o <= hpll_ldcr_ld_samp_int;
-- Frequency detector gating period
hpll_fbcr_fd_gate_o <= hpll_fbcr_fd_gate_int;
-- Frequency error setpoint
hpll_fbcr_ferr_set_o <= hpll_fbcr_ferr_set_int;
-- Frequency lock
-- Phase lock
-- Loss-of-lock indicator
hpll_psr_lock_lost_o <= wrdata_reg(2);
-- extra code for reg/fifo/mem: HPLL Phase/Output record FIFO
hpll_rfifo_in_int(11 downto 0) <= hpll_rfifo_err_val_i;
hpll_rfifo_in_int(12) <= hpll_rfifo_fp_mode_i;
hpll_rfifo_in_int(28 downto 13) <= hpll_rfifo_dac_val_i;
hpll_rfifo_INST : wbgen2_fifo_sync
generic map (
g_size => 1024,
g_width => 29,
g_usedw_size => 10
)
port map (
wr_req_i => hpll_rfifo_wr_req_i,
wr_full_o => hpll_rfifo_wr_full_o,
rd_full_o => open,
rd_empty_o => hpll_rfifo_empty_int,
rd_usedw_o => open,
rd_req_i => hpll_rfifo_rdreq_int,
clk_i => bus_clock_int,
wr_data_i => hpll_rfifo_in_int,
rd_data_o => hpll_rfifo_out_int
);
-- extra code for reg/fifo/mem: FIFO 'HPLL Phase/Output record FIFO' data output register 0
process (bus_clock_int, rst_n_i)
begin
if (rst_n_i = '0') then
hpll_rfifo_rdreq_int_d0 <= '0';
elsif rising_edge(bus_clock_int) then
hpll_rfifo_rdreq_int_d0 <= hpll_rfifo_rdreq_int;
end if;
end process;
rwaddr_reg <= wb_addr_i;
-- ACK signal generation. Just pass the LSB of ACK counter.
wb_ack_o <= ack_sreg(0);
end syn;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/manifest.py 0000664 0000000 0000000 00000000313 11653767173 0026003 0 ustar 00root root 0000000 0000000 files = [ "hpll_controller.vhd",
"wrsw_helper_pll.vhd",
"hpll_lock_detect.vhd",
"hpll_bangbang_pd.vhd",
"hpll_wb_slave.vhd",
"hpll_period_detect.vhd",
"wr_helper_pll.vhd"];
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/serial_dac.vhd 0000664 0000000 0000000 00000013051 11653767173 0026417 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- 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: 2010-06-21
-- 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 serial_dac is
generic (
g_num_data_bits : integer := 16;
g_num_extra_bits : integer := 8
);
port (
-- clock & reset
clk_i : in std_logic;
rst_n_i : in std_logic;
-- channel 1 value and value load strobe
value1_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value1_stb_i : in std_logic;
-- channel 2 value and value load strobe
value2_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value2_stb_i : in std_logic;
-- channel select: 0 = channel 1, 1 = channel 2
driver_sel_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;
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic
);
end serial_dac;
architecture syn of 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;
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 <= value1_stb_i when driver_sel_i = '0' else value2_stb_i;
process(clk_i, rst_n_i)
begin
if rst_n_i = '0' then
sendingData <= '0';
elsif rising_edge(clk_i) then
if iValidValue = '1' and sendingData = '0' then
sendingData <= '1';
elsif endSendingData = '1' then
sendingData <= '0';
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 rst_n_i = '0' then
iDacClk <= '1'; -- 0
elsif rising_edge(clk_i) then
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 process;
process(clk_i, rst_n_i)
begin
if rst_n_i = '0' then
dataSh <= (others => '0');
elsif rising_edge(clk_i) then
if iValidValue = '1' and sendingData = '0' then
if driver_sel_i = '1' then
dataSh <= std_logic_vector(to_unsigned(0, g_num_extra_bits)) & value2_i;
else
dataSh <= std_logic_vector(to_unsigned(0, g_num_extra_bits)) & value1_i;
end if;
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 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);
dac_sdata_o <= dataSh(dataSh'left);
dac_cs_n_o <= not(sendingData);
dac_sclk_o <= iDacClk;
end syn;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/wr_helper_pll.vhd 0000664 0000000 0000000 00000045753 11653767173 0027205 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- Project : Helper PLL for generation of DMTD offset clock
-------------------------------------------------------------------------------
-- File : wr_helper_pll.vhd
-- Author : Javier Serrano, Tomasz Wlostowski
-- Institute : CERN
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: This is a generic PLL that assumes a DAC and VCO outside the
-- FPGA. The reset is assumed to be synchronized with the system clock outside
-- this block. The block receives a reference clock of frequency f and derives
-- from it a clock of frequency f*(num/den) where num and den are two 16-bit
-- unsigned numbers. The PI loop filter has controllable proportional and
-- integral gains which are also 16-bit unsigned. The output to the DAC is a
-- 16-bit signed number.
-------------------------------------------------------------------------------
-- Revisions:
-- Date Version Author Description
-- 4 April 2010 1.0 J.Serrano Created
-- 15 June 2010 1.1 twlostow redesigned....
-- 12 Jan 2011 1.2 twlostow added generic configuration options
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.platform_specific.all;
use work.common_components.all;
entity wr_helper_pll is
generic (
g_num_ref_inputs : integer := 1;
g_with_wishbone : integer := 1;
g_dacval_bits : integer := 16;
g_output_bias : integer := 32767;
g_div_ref : integer := 0;
g_div_fb : integer := 0;
g_kp_freq : integer := 0;
g_ki_freq : integer := 0;
g_kp_phase : integer := 0;
g_ki_phase : integer := 0;
g_ld_threshold : integer := 0;
g_ld_samples : integer := 0;
g_fd_gating : integer := 0;
g_pd_gating : integer := 0;
g_ferr_setpoint : integer := 0
);
port (
rst_n_i : in std_logic; -- Synchronous reset
cfg_enable_i : in std_logic;
cfg_force_freq_i : in std_logic;
cfg_clear_status_i : in std_logic;
cfg_refsel_i : in std_logic_vector(1 downto 0);
stat_flock_o : out std_logic;
stat_plock_o : out std_logic;
stat_lock_lost_o : out std_logic;
clk_ref_i : in std_logic_vector(g_num_ref_inputs-1 downto 0);
clk_sys_i : in std_logic; -- System clock
clk_fbck_i : in std_logic; -- Fed-back clock
dac_data_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_load_p1_o : out std_logic;
auxout1_o : out std_logic;
auxout2_o : out std_logic;
auxout3_o : out std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic
);
end wr_helper_pll;
architecture rtl of wr_helper_pll is
component hpll_wb_slave
port (
rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
hpll_pcr_enable_o : out std_logic;
hpll_pcr_force_f_o : out std_logic;
hpll_pcr_dac_clksel_o : out std_logic_vector(2 downto 0);
hpll_pcr_pd_gate_o : out std_logic_vector(2 downto 0);
hpll_pcr_swrst_o : out std_logic;
hpll_pcr_refsel_o : out std_logic_vector(1 downto 0);
hpll_divr_div_ref_o : out std_logic_vector(15 downto 0);
hpll_divr_div_fb_o : out std_logic_vector(15 downto 0);
hpll_fbgr_f_kp_o : out std_logic_vector(15 downto 0);
hpll_fbgr_f_ki_o : out std_logic_vector(15 downto 0);
hpll_pbgr_p_kp_o : out std_logic_vector(15 downto 0);
hpll_pbgr_p_ki_o : out std_logic_vector(15 downto 0);
hpll_ldcr_ld_thr_o : out std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_o : out std_logic_vector(7 downto 0);
hpll_fbcr_fd_gate_o : out std_logic_vector(2 downto 0);
hpll_fbcr_ferr_set_o : out std_logic_vector(11 downto 0);
hpll_psr_freq_lk_i : in std_logic;
hpll_psr_phase_lk_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_load_o : out std_logic;
hpll_rfifo_wr_req_i : in std_logic;
hpll_rfifo_wr_full_o : out std_logic;
hpll_rfifo_fp_mode_i : in std_logic;
hpll_rfifo_err_val_i : in std_logic_vector(11 downto 0);
hpll_rfifo_dac_val_i : in std_logic_vector(15 downto 0));
end component;
component hpll_period_detect
port (
clk_ref_i : in std_logic;
clk_fbck_i : in std_logic;
clk_sys_i : in std_logic;
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
freq_err_o : out std_logic_vector(11 downto 0);
freq_err_stb_p_o : out std_logic;
hpll_fbcr_fd_gate_i : in std_logic_vector(2 downto 0);
hpll_fbcr_ferr_set_i : in std_logic_vector(11 downto 0));
end component;
component hpll_bangbang_pd
port (
clk_ref_i : in std_logic;
clk_fbck_i : in std_logic;
clk_sys_i : in std_logic;
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
sync_dividers_p_i : in std_logic;
phase_err_o : out std_logic_vector(11 downto 0);
phase_err_stb_p_o : out std_logic;
hpll_pcr_pd_gate_i : in std_logic_vector(2 downto 0);
hpll_divr_div_ref_i : in std_logic_vector(15 downto 0);
hpll_divr_div_fb_i : in std_logic_vector(15 downto 0);
dbg_ref_divided_o : out std_logic;
dbg_fbck_divided_o : out std_logic;
dbg_pd_up_o : out std_logic;
dbg_pd_down_o : out std_logic);
end component;
component hpll_controller
generic (
g_error_bits : integer;
g_dacval_bits : integer;
g_output_bias : integer;
g_integrator_fracbits : integer;
g_integrator_overbits : integer;
g_coef_bits : integer);
port (
clk_sys_i : in std_logic;
rst_n_sysclk_i : in std_logic;
phase_err_i : in std_logic_vector(g_error_bits-1 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(g_error_bits-1 downto 0);
freq_err_stb_p_i : in std_logic;
dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_val_stb_p_o : out std_logic;
sync_dividers_p_o : out std_logic;
hpll_pcr_enable_i : in std_logic;
hpll_pcr_force_f_i : in std_logic;
hpll_fbgr_f_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_fbgr_f_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
hpll_psr_freq_lk_o : out std_logic;
hpll_psr_phase_lk_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
hpll_rfifo_wr_req_o : out std_logic;
hpll_rfifo_wr_full_i : in std_logic;
hpll_rfifo_fp_mode_o : out std_logic;
hpll_rfifo_err_val_o : out std_logic_vector(g_error_bits-1 downto 0);
hpll_rfifo_dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0));
end component;
component serial_dac
generic (
g_num_data_bits : integer;
g_num_extra_bits : integer);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
value1_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value1_stb_i : in std_logic;
value2_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value2_stb_i : in std_logic;
driver_sel_i : in std_logic;
sclk_divsel_i : in std_logic_vector(2 downto 0);
dac_cs_n_o : out std_logic;
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic);
end component;
-- Software reset, synced to different clocks.
signal rst_n_refclk, rst_n_fbck, rst_n_sysclk : std_logic;
-- freq & phase error
signal freq_err : std_logic_vector(11 downto 0);
signal phase_err : std_logic_vector(11 downto 0);
signal freq_err_stb_p, phase_err_stb_p : std_logic;
-- DAC drive value
signal dac_val : std_logic_vector(15 downto 0);
signal dac_val_stb_p : std_logic;
signal sync_dividers_p : std_logic;
signal dbg_ref_divided : std_logic;
signal dbg_fbck_divided : std_logic;
signal dbg_pd_up : std_logic;
signal dbg_pd_down : std_logic;
-- wishbone regs
signal hpll_pcr_enable : std_logic;
signal hpll_pcr_force_f : std_logic;
signal hpll_pcr_dac_clksel : std_logic_vector(2 downto 0);
signal hpll_pcr_pd_gate : std_logic_vector(2 downto 0);
signal hpll_pcr_swrst : std_logic;
signal hpll_pcr_refsel : std_logic_vector(1 downto 0);
signal hpll_divr_div_ref : std_logic_vector(15 downto 0);
signal hpll_divr_div_fb : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_kp : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_ki : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_kp : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_ki : std_logic_vector(15 downto 0);
signal hpll_ldcr_ld_thr : std_logic_vector(7 downto 0);
signal hpll_ldcr_ld_samp : std_logic_vector(7 downto 0);
signal hpll_fbcr_fd_gate : std_logic_vector(2 downto 0);
signal hpll_fbcr_ferr_set : std_logic_vector(11 downto 0);
signal hpll_psr_freq_lk : std_logic;
signal hpll_psr_phase_lk : std_logic;
signal hpll_psr_lock_lost_out : std_logic;
signal hpll_psr_lock_lost_in : std_logic;
signal hpll_psr_lock_lost_load : std_logic;
signal hpll_rfifo_wr_req : std_logic;
signal hpll_rfifo_wr_full : std_logic;
signal hpll_rfifo_fp_mode : std_logic;
signal hpll_rfifo_err_val : std_logic_vector(11 downto 0);
signal hpll_rfifo_dac_val : std_logic_vector(15 downto 0);
signal clk_ref_muxed : std_logic;
begin -- architecture rtl
rst_n_sysclk <= not hpll_pcr_swrst;
-- warning: this is NOT GOOD, but works :)
mux_clocks : process(hpll_pcr_refsel, clk_ref_i)
begin
clk_ref_muxed <= '0';
for i in 0 to g_num_ref_inputs-1 loop
if(to_integer(unsigned(hpll_pcr_refsel)) = i) then
clk_ref_muxed <= clk_ref_i(i);
end if;
end loop; -- i
end process;
sync_reset_refclk : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_ref_muxed,
rst_n_i => rst_n_i,
data_i => rst_n_sysclk,
synced_o => rst_n_refclk,
npulse_o => open,
ppulse_o => open);
sync_reset_fbck : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_fbck_i,
rst_n_i => rst_n_i,
data_i => rst_n_sysclk,
synced_o => rst_n_fbck,
npulse_o => open,
ppulse_o => open);
FREQ_DETECT : hpll_period_detect
port map (
clk_ref_i => clk_ref_muxed,
clk_fbck_i => clk_fbck_i,
clk_sys_i => clk_sys_i,
rst_n_refclk_i => rst_n_refclk,
rst_n_fbck_i => rst_n_fbck,
rst_n_sysclk_i => rst_n_sysclk,
freq_err_o => freq_err,
freq_err_stb_p_o => freq_err_stb_p,
hpll_fbcr_fd_gate_i => hpll_fbcr_fd_gate,
hpll_fbcr_ferr_set_i => hpll_fbcr_ferr_set);
BB_DETECT : hpll_bangbang_pd
port map (
clk_ref_i => clk_ref_muxed,
clk_fbck_i => clk_fbck_i,
clk_sys_i => clk_sys_i,
rst_n_refclk_i => rst_n_refclk,
rst_n_fbck_i => rst_n_fbck,
rst_n_sysclk_i => rst_n_sysclk,
sync_dividers_p_i => sync_dividers_p,
phase_err_o => phase_err,
phase_err_stb_p_o => phase_err_stb_p,
hpll_pcr_pd_gate_i => hpll_pcr_pd_gate,
hpll_divr_div_ref_i => hpll_divr_div_ref,
hpll_divr_div_fb_i => hpll_divr_div_fb,
dbg_ref_divided_o => dbg_ref_divided,
dbg_fbck_divided_o => dbg_fbck_divided,
dbg_pd_up_o => dbg_pd_up,
dbg_pd_down_o => dbg_pd_down);
PI_CTL : hpll_controller
generic map (
g_error_bits => 12,
g_dacval_bits => g_dacval_bits,
g_output_bias => g_output_bias,
g_integrator_fracbits => 16,
g_integrator_overbits => 6,
g_coef_bits => 16)
port map (
clk_sys_i => clk_sys_i,
rst_n_sysclk_i => rst_n_sysclk,
phase_err_i => phase_err,
phase_err_stb_p_i => phase_err_stb_p,
freq_err_i => freq_err,
freq_err_stb_p_i => freq_err_stb_p,
dac_val_o => dac_val,
dac_val_stb_p_o => dac_val_stb_p,
sync_dividers_p_o => sync_dividers_p,
hpll_pcr_enable_i => hpll_pcr_enable,
hpll_pcr_force_f_i => hpll_pcr_force_f,
hpll_fbgr_f_kp_i => hpll_fbgr_f_kp,
hpll_fbgr_f_ki_i => hpll_fbgr_f_ki,
hpll_pbgr_p_kp_i => hpll_pbgr_p_kp,
hpll_pbgr_p_ki_i => hpll_pbgr_p_ki,
hpll_ldcr_ld_thr_i => hpll_ldcr_ld_thr,
hpll_ldcr_ld_samp_i => hpll_ldcr_ld_samp,
hpll_psr_freq_lk_o => hpll_psr_freq_lk,
hpll_psr_phase_lk_o => hpll_psr_phase_lk,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_out,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_in,
hpll_psr_lock_lost_load_i => hpll_psr_lock_lost_load,
hpll_rfifo_wr_req_o => hpll_rfifo_wr_req,
hpll_rfifo_wr_full_i => hpll_rfifo_wr_full,
hpll_rfifo_fp_mode_o => hpll_rfifo_fp_mode,
hpll_rfifo_err_val_o => hpll_rfifo_err_val,
hpll_rfifo_dac_val_o => hpll_rfifo_dac_val
);
dac_data_o <= dac_val;
dac_load_p1_o <= dac_val_stb_p;
gen_wb_slave : if(g_with_wishbone /= 0) generate
WB_SLAVE : hpll_wb_slave
port map (
rst_n_i => rst_n_i,
wb_clk_i => clk_sys_i,
wb_addr_i => wb_addr_i,
wb_data_i => wb_data_i,
wb_data_o => wb_data_o,
wb_cyc_i => wb_cyc_i,
wb_sel_i => wb_sel_i,
wb_stb_i => wb_stb_i,
wb_we_i => wb_we_i,
wb_ack_o => wb_ack_o,
hpll_pcr_enable_o => hpll_pcr_enable,
hpll_pcr_force_f_o => hpll_pcr_force_f,
hpll_pcr_dac_clksel_o => hpll_pcr_dac_clksel,
hpll_pcr_pd_gate_o => hpll_pcr_pd_gate,
hpll_pcr_swrst_o => hpll_pcr_swrst,
hpll_pcr_refsel_o => hpll_pcr_refsel,
hpll_divr_div_ref_o => hpll_divr_div_ref,
hpll_divr_div_fb_o => hpll_divr_div_fb,
hpll_fbgr_f_kp_o => hpll_fbgr_f_kp,
hpll_fbgr_f_ki_o => hpll_fbgr_f_ki,
hpll_pbgr_p_kp_o => hpll_pbgr_p_kp,
hpll_pbgr_p_ki_o => hpll_pbgr_p_ki,
hpll_ldcr_ld_thr_o => hpll_ldcr_ld_thr,
hpll_ldcr_ld_samp_o => hpll_ldcr_ld_samp,
hpll_fbcr_fd_gate_o => hpll_fbcr_fd_gate,
hpll_fbcr_ferr_set_o => hpll_fbcr_ferr_set,
hpll_psr_freq_lk_i => hpll_psr_freq_lk,
hpll_psr_phase_lk_i => hpll_psr_phase_lk,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_out,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_in,
hpll_psr_lock_lost_load_o => hpll_psr_lock_lost_load,
hpll_rfifo_wr_req_i => hpll_rfifo_wr_req,
hpll_rfifo_wr_full_o => hpll_rfifo_wr_full,
hpll_rfifo_fp_mode_i => hpll_rfifo_fp_mode,
hpll_rfifo_err_val_i => hpll_rfifo_err_val,
hpll_rfifo_dac_val_i => hpll_rfifo_dac_val
);
end generate gen_wb_slave;
gen_no_wb_slave : if(g_with_wishbone = 0) generate
hpll_pcr_enable <= cfg_enable_i;
hpll_pcr_force_f <= cfg_force_freq_i;
hpll_pcr_pd_gate <= std_logic_vector(to_unsigned(g_pd_gating, hpll_pcr_pd_gate'length));
hpll_pcr_swrst <= '0';
hpll_pcr_refsel <= cfg_refsel_i;
hpll_divr_div_ref <= std_logic_vector(to_unsigned(g_div_ref, hpll_divr_div_ref'length));
hpll_divr_div_fb <= std_logic_vector(to_unsigned(g_div_fb, hpll_divr_div_fb'length));
hpll_fbgr_f_kp <= std_logic_vector(to_unsigned(g_kp_freq, hpll_fbgr_f_kp'length));
hpll_fbgr_f_ki <= std_logic_vector(to_unsigned(g_ki_freq, hpll_fbgr_f_ki'length));
hpll_pbgr_p_kp <= std_logic_vector(to_unsigned(g_kp_phase, hpll_pbgr_p_kp'length));
hpll_pbgr_p_ki <= std_logic_vector(to_unsigned(g_ki_phase, hpll_pbgr_p_ki'length));
hpll_ldcr_ld_thr <= std_logic_vector(to_unsigned(g_ld_threshold, hpll_ldcr_ld_thr'length));
hpll_ldcr_ld_samp <= std_logic_vector(to_unsigned(g_ld_samples, hpll_ldcr_ld_samp'length));
hpll_fbcr_fd_gate <= std_logic_vector(to_unsigned(g_fd_gating, hpll_fbcr_fd_gate'length));
hpll_fbcr_ferr_set <= std_logic_vector(to_unsigned(g_ferr_setpoint, hpll_fbcr_ferr_set'length));
stat_flock_o <= hpll_psr_freq_lk;
stat_plock_o <= hpll_psr_phase_lk;
stat_lock_lost_o <= hpll_psr_lock_lost_in;
hpll_psr_lock_lost_out <= '1';
hpll_psr_lock_lost_load <= cfg_clear_status_i;
hpll_rfifo_wr_full <= '0';
end generate gen_no_wb_slave;
auxout1_o <= dbg_fbck_divided;
auxout2_o <= dbg_ref_divided;
end architecture rtl;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/hpll/wrsw_helper_pll.vhd 0000664 0000000 0000000 00000042006 11653767173 0027543 0 ustar 00root root 0000000 0000000 -------------------------------------------------------------------------------
-- Project : Phase-Locked Loop
-------------------------------------------------------------------------------
-- File : pll.vhd
-- Author : Javier Serrano, Tomasz Wlostowski
-- Institute : CERN
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: This is a generic PLL that assumes a DAC and VCO outside the
-- FPGA. The reset is assumed to be synchronized with the system clock outside
-- this block. The block receives a reference clock of frequency f and derives
-- from it a clock of frequency f*(num/den) where num and den are two 16-bit
-- unsigned numbers. The PI loop filter has controllable proportional and
-- integral gains which are also 16-bit unsigned. The output to the DAC is a
-- 16-bit signed number.
-------------------------------------------------------------------------------
-- Revisions:
-- Date Version Author Description
-- 4 April 2010 1.0 J.Serrano Created
-- 15 June 2010 1.1 twlostow redesigned....
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.platform_specific.all;
use work.common_components.all;
entity wrsw_helper_pll is
port (
rst_n_i : in std_logic; -- Synchronous reset
clk_ref_local_i : in std_logic; -- Reference clock (from TCXO)
clk_ref_up0_i : in std_logic; -- Reference clock (from uplink 0)
clk_ref_up1_i : in std_logic; -- Reference clock (from uplink 1)
clk_sys_i : in std_logic; -- System clock
clk_fbck_i : in std_logic; -- Fed-back clock
dac_cs_n_o : out std_logic;
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic;
auxout1_o : out std_logic;
auxout2_o : out std_logic;
auxout3_o : out std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic
);
end wrsw_helper_pll;
architecture rtl of wrsw_helper_pll is
component hpll_wb_slave
port (
rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
hpll_pcr_enable_o : out std_logic;
hpll_pcr_force_f_o : out std_logic;
hpll_pcr_dac_clksel_o : out std_logic_vector(2 downto 0);
hpll_pcr_pd_gate_o : out std_logic_vector(2 downto 0);
hpll_pcr_swrst_o : out std_logic;
hpll_pcr_refsel_o : out std_logic_vector(1 downto 0);
hpll_divr_div_ref_o : out std_logic_vector(15 downto 0);
hpll_divr_div_fb_o : out std_logic_vector(15 downto 0);
hpll_fbgr_f_kp_o : out std_logic_vector(15 downto 0);
hpll_fbgr_f_ki_o : out std_logic_vector(15 downto 0);
hpll_pbgr_p_kp_o : out std_logic_vector(15 downto 0);
hpll_pbgr_p_ki_o : out std_logic_vector(15 downto 0);
hpll_ldcr_ld_thr_o : out std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_o : out std_logic_vector(7 downto 0);
hpll_fbcr_fd_gate_o : out std_logic_vector(2 downto 0);
hpll_fbcr_ferr_set_o : out std_logic_vector(11 downto 0);
hpll_psr_freq_lk_i : in std_logic;
hpll_psr_phase_lk_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_load_o : out std_logic;
hpll_rfifo_wr_req_i : in std_logic;
hpll_rfifo_wr_full_o : out std_logic;
hpll_rfifo_fp_mode_i : in std_logic;
hpll_rfifo_err_val_i : in std_logic_vector(11 downto 0);
hpll_rfifo_dac_val_i : in std_logic_vector(15 downto 0));
end component;
component hpll_period_detect
generic(
g_freq_err_frac_bits:integer := 7
);
port (
clk_ref_i : in std_logic;
clk_fbck_i : in std_logic;
clk_sys_i : in std_logic;
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
freq_err_o : out std_logic_vector(11 downto 0);
freq_err_stb_p_o : out std_logic;
hpll_fbcr_fd_gate_i : in std_logic_vector(2 downto 0);
hpll_fbcr_ferr_set_i : in std_logic_vector(11 downto 0));
end component;
component hpll_bangbang_pd
port (
clk_ref_i : in std_logic;
clk_fbck_i : in std_logic;
clk_sys_i : in std_logic;
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
sync_dividers_p_i : in std_logic;
phase_err_o : out std_logic_vector(11 downto 0);
phase_err_stb_p_o : out std_logic;
hpll_pcr_pd_gate_i : in std_logic_vector(2 downto 0);
hpll_divr_div_ref_i : in std_logic_vector(15 downto 0);
hpll_divr_div_fb_i : in std_logic_vector(15 downto 0);
dbg_ref_divided_o : out std_logic;
dbg_fbck_divided_o : out std_logic;
dbg_pd_up_o : out std_logic;
dbg_pd_down_o : out std_logic);
end component;
component hpll_controller
generic (
g_error_bits : integer;
g_dacval_bits : integer;
g_output_bias : integer;
g_integrator_fracbits : integer;
g_integrator_overbits : integer;
g_coef_bits : integer);
port (
clk_sys_i : in std_logic;
rst_n_sysclk_i : in std_logic;
phase_err_i : in std_logic_vector(g_error_bits-1 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(g_error_bits-1 downto 0);
freq_err_stb_p_i : in std_logic;
dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_val_stb_p_o : out std_logic;
sync_dividers_p_o : out std_logic;
hpll_pcr_enable_i : in std_logic;
hpll_pcr_force_f_i : in std_logic;
hpll_fbgr_f_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_fbgr_f_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
hpll_psr_freq_lk_o : out std_logic;
hpll_psr_phase_lk_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
hpll_rfifo_wr_req_o : out std_logic;
hpll_rfifo_wr_full_i : in std_logic;
hpll_rfifo_fp_mode_o : out std_logic;
hpll_rfifo_err_val_o : out std_logic_vector(g_error_bits-1 downto 0);
hpll_rfifo_dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0));
end component;
component serial_dac
generic (
g_num_data_bits : integer;
g_num_extra_bits : integer);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
value1_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value1_stb_i : in std_logic;
value2_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value2_stb_i : in std_logic;
driver_sel_i : in std_logic;
sclk_divsel_i : in std_logic_vector(2 downto 0);
dac_cs_n_o : out std_logic;
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic);
end component;
-- Software reset, synced to different clocks.
signal rst_n_refclk, rst_n_fbck, rst_n_sysclk : std_logic;
-- freq & phase error
signal freq_err : std_logic_vector(11 downto 0);
signal phase_err : std_logic_vector(11 downto 0);
signal freq_err_stb_p, phase_err_stb_p : std_logic;
-- DAC drive value
signal dac_val : std_logic_vector(15 downto 0);
signal dac_val_stb_p : std_logic;
signal sync_dividers_p : std_logic;
signal dbg_ref_divided : std_logic;
signal dbg_fbck_divided : std_logic;
signal dbg_pd_up : std_logic;
signal dbg_pd_down : std_logic;
-- wishbone regs
signal hpll_pcr_enable : std_logic;
signal hpll_pcr_force_f : std_logic;
signal hpll_pcr_dac_clksel : std_logic_vector(2 downto 0);
signal hpll_pcr_pd_gate : std_logic_vector(2 downto 0);
signal hpll_pcr_swrst : std_logic;
signal hpll_pcr_refsel : std_logic_vector(1 downto 0);
signal hpll_divr_div_ref : std_logic_vector(15 downto 0);
signal hpll_divr_div_fb : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_kp : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_ki : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_kp : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_ki : std_logic_vector(15 downto 0);
signal hpll_ldcr_ld_thr : std_logic_vector(7 downto 0);
signal hpll_ldcr_ld_samp : std_logic_vector(7 downto 0);
signal hpll_fbcr_fd_gate : std_logic_vector(2 downto 0);
signal hpll_fbcr_ferr_set : std_logic_vector(11 downto 0);
signal hpll_psr_freq_lk : std_logic;
signal hpll_psr_phase_lk : std_logic;
signal hpll_psr_lock_lost_out : std_logic;
signal hpll_psr_lock_lost_in : std_logic;
signal hpll_psr_lock_lost_load : std_logic;
signal hpll_rfifo_wr_req : std_logic;
signal hpll_rfifo_wr_full : std_logic;
signal hpll_rfifo_fp_mode : std_logic;
signal hpll_rfifo_err_val : std_logic_vector(11 downto 0);
signal hpll_rfifo_dac_val : std_logic_vector(15 downto 0);
signal clk_ref_muxed : std_logic;
signal clk_ref_vec: std_logic_vector(2 downto 0);
begin -- architecture rtl
rst_n_sysclk <= not hpll_pcr_swrst;
clk_ref_vec(0) <= clk_ref_local_i;
clk_ref_vec(1) <= clk_ref_up1_i;
clk_ref_vec(2) <= clk_ref_up0_i;
-- warning: this is NOT GOOD, but works :)
mux_clocks : process(hpll_pcr_refsel, clk_ref_vec)
begin
clk_ref_muxed <= '0';
for i in 0 to 2 loop
if(to_integer(unsigned(hpll_pcr_refsel)) = i) then
clk_ref_muxed <= clk_ref_vec(i);
end if;
end loop; -- i
end process;
-- clk_ref_muxed <= clk_ref_up1_i;
sync_reset_refclk : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_ref_muxed,
rst_n_i => rst_n_i,
data_i => rst_n_sysclk,
synced_o => rst_n_refclk,
npulse_o => open,
ppulse_o => open);
sync_reset_fbck : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_fbck_i,
rst_n_i => rst_n_i,
data_i => rst_n_sysclk,
synced_o => rst_n_fbck,
npulse_o => open,
ppulse_o => open);
FREQ_DETECT : hpll_period_detect
port map (
clk_ref_i => clk_ref_muxed,
clk_fbck_i => clk_fbck_i,
clk_sys_i => clk_sys_i,
rst_n_refclk_i => rst_n_refclk,
rst_n_fbck_i => rst_n_fbck,
rst_n_sysclk_i => rst_n_sysclk,
freq_err_o => freq_err,
freq_err_stb_p_o => freq_err_stb_p,
hpll_fbcr_fd_gate_i => hpll_fbcr_fd_gate,
hpll_fbcr_ferr_set_i => hpll_fbcr_ferr_set);
BB_DETECT : hpll_bangbang_pd
port map (
clk_ref_i => clk_ref_muxed,
clk_fbck_i => clk_fbck_i,
clk_sys_i => clk_sys_i,
rst_n_refclk_i => rst_n_refclk,
rst_n_fbck_i => rst_n_fbck,
rst_n_sysclk_i => rst_n_sysclk,
sync_dividers_p_i => sync_dividers_p,
phase_err_o => phase_err,
phase_err_stb_p_o => phase_err_stb_p,
hpll_pcr_pd_gate_i => hpll_pcr_pd_gate,
hpll_divr_div_ref_i => hpll_divr_div_ref,
hpll_divr_div_fb_i => hpll_divr_div_fb,
dbg_ref_divided_o => dbg_ref_divided,
dbg_fbck_divided_o => dbg_fbck_divided,
dbg_pd_up_o => dbg_pd_up,
dbg_pd_down_o => dbg_pd_down);
PI_CTL : hpll_controller
generic map (
g_error_bits => 12,
g_dacval_bits => 16,
g_output_bias => 32767,
g_integrator_fracbits => 16,
g_integrator_overbits => 6,
g_coef_bits => 16)
port map (
clk_sys_i => clk_sys_i,
rst_n_sysclk_i => rst_n_sysclk,
phase_err_i => phase_err,
phase_err_stb_p_i => phase_err_stb_p,
freq_err_i => freq_err,
freq_err_stb_p_i => freq_err_stb_p,
dac_val_o => dac_val,
dac_val_stb_p_o => dac_val_stb_p,
sync_dividers_p_o => sync_dividers_p,
hpll_pcr_enable_i => hpll_pcr_enable,
hpll_pcr_force_f_i => hpll_pcr_force_f,
hpll_fbgr_f_kp_i => hpll_fbgr_f_kp,
hpll_fbgr_f_ki_i => hpll_fbgr_f_ki,
hpll_pbgr_p_kp_i => hpll_pbgr_p_kp,
hpll_pbgr_p_ki_i => hpll_pbgr_p_ki,
hpll_ldcr_ld_thr_i => hpll_ldcr_ld_thr,
hpll_ldcr_ld_samp_i => hpll_ldcr_ld_samp,
hpll_psr_freq_lk_o => hpll_psr_freq_lk,
hpll_psr_phase_lk_o => hpll_psr_phase_lk,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_out,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_in,
hpll_psr_lock_lost_load_i => hpll_psr_lock_lost_load,
hpll_rfifo_wr_req_o => hpll_rfifo_wr_req,
hpll_rfifo_wr_full_i => hpll_rfifo_wr_full,
hpll_rfifo_fp_mode_o => hpll_rfifo_fp_mode,
hpll_rfifo_err_val_o => hpll_rfifo_err_val,
hpll_rfifo_dac_val_o => hpll_rfifo_dac_val
);
DAC : serial_dac
generic map (
g_num_data_bits => 16,
g_num_extra_bits => 8
)
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_i,
value1_i => dac_val,
value1_stb_i => dac_val_stb_p,
value2_i => (others => '0'),
value2_stb_i => '0',
driver_sel_i => '0',
sclk_divsel_i => hpll_pcr_dac_clksel,
dac_cs_n_o => dac_cs_n_o,
dac_sclk_o => dac_sclk_o,
dac_sdata_o => dac_sdata_o);
WB_SLAVE : hpll_wb_slave
port map (
rst_n_i => rst_n_i,
wb_clk_i => clk_sys_i,
wb_addr_i => wb_addr_i,
wb_data_i => wb_data_i,
wb_data_o => wb_data_o,
wb_cyc_i => wb_cyc_i,
wb_sel_i => wb_sel_i,
wb_stb_i => wb_stb_i,
wb_we_i => wb_we_i,
wb_ack_o => wb_ack_o,
hpll_pcr_enable_o => hpll_pcr_enable,
hpll_pcr_force_f_o => hpll_pcr_force_f,
hpll_pcr_dac_clksel_o => hpll_pcr_dac_clksel,
hpll_pcr_pd_gate_o => hpll_pcr_pd_gate,
hpll_pcr_swrst_o => hpll_pcr_swrst,
hpll_pcr_refsel_o => hpll_pcr_refsel,
hpll_divr_div_ref_o => hpll_divr_div_ref,
hpll_divr_div_fb_o => hpll_divr_div_fb,
hpll_fbgr_f_kp_o => hpll_fbgr_f_kp,
hpll_fbgr_f_ki_o => hpll_fbgr_f_ki,
hpll_pbgr_p_kp_o => hpll_pbgr_p_kp,
hpll_pbgr_p_ki_o => hpll_pbgr_p_ki,
hpll_ldcr_ld_thr_o => hpll_ldcr_ld_thr,
hpll_ldcr_ld_samp_o => hpll_ldcr_ld_samp,
hpll_fbcr_fd_gate_o => hpll_fbcr_fd_gate,
hpll_fbcr_ferr_set_o => hpll_fbcr_ferr_set,
hpll_psr_freq_lk_i => hpll_psr_freq_lk,
hpll_psr_phase_lk_i => hpll_psr_phase_lk,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_out,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_in,
hpll_psr_lock_lost_load_o => hpll_psr_lock_lost_load,
hpll_rfifo_wr_req_i => hpll_rfifo_wr_req,
hpll_rfifo_wr_full_o => hpll_rfifo_wr_full,
hpll_rfifo_fp_mode_i => hpll_rfifo_fp_mode,
hpll_rfifo_err_val_i => hpll_rfifo_err_val,
hpll_rfifo_dac_val_i => hpll_rfifo_dac_val
);
auxout1_o <= dbg_fbck_divided;
auxout2_o <= dbg_ref_divided;
end architecture rtl;
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/lm32/ 0000775 0000000 0000000 00000000000 11653767173 0023444 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/lm32/CHANGELOG 0000664 0000000 0000000 00000000264 11653767173 0024660 0 ustar 00root root 0000000 0000000 * 2009-12-21 Upgrade to LatticeMico32 3.5.
* 2009-11-12 Active-high interrupts (lekernel)
* 2009-07-01 Based on LatticeMico32 core from mico32_72_linux.tar.
(LatticeMico32 v3.3)
tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/lm32/doc/ 0000775 0000000 0000000 00000000000 11653767173 0024211 5 ustar 00root root 0000000 0000000 tdc-core-6553bd461e3b5dfe7fd7ee91f7dfecbd21d71d25/demo/cores/lm32/doc/ds_icon.jpg 0000664 0000000 0000000 00000033620 11653767173 0026335 0 ustar 00root root 0000000 0000000 ÿØÿà JFIF H H ÿáÝExif MM * b j( 1 r2 ‡i ¤ Ð H H Adobe Photoshop CS Windows 2006:05:31 15:29:52 &( . § H H ÿØÿà JFIF H H ÿí Adobe_CM ÿî Adobe d€ ÿÛ „
ÿÀ " ÿÝ ÿÄ?
3 !1AQa"q2‘¡±B#$RÁb34r‚ÑC%’Sðáñcs5¢²ƒ&D“TdE£t6ÒUâeò³„ÃÓuãóF'”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷ 5 !1AQaq"2‘¡±B#ÁRÑð3$bár‚’CScs4ñ%¢²ƒ&5ÂÒD“T£dEU6teâò³„ÃÓuãóF”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö'7GWgw‡—§·ÇÿÚ ? êGÚºÎpÎϦ³Ñý"ìZ¬{v¸1ìÉ´?ü5þGèª>Þ„á^7Ds;\ìŠÚHüÒæŒGíÿ =ZÆ· t^U,¸~«C´¾–ŸæÃ}3ö£ÿ |MÖ3r˱½ë±¬»Ñy~÷\×þ—¯m_ÍWþÅhP» Ñaß̺?WëÇ«?$cWU5Y‹‹nÌxô‹žìÍÏÌmm³sZÏÒìý#êÁèVÙgVÏe h£«{lÍvfço`gï~uUÅåù_§ýÂÿ Ðúÿ Ý?ÿÐêpÛ‚:~9ØY‘Eu?~ÖAcC\ÆÙöwµÍßûŽØÍÄ®Ç?™xÆzv|ÚLÌwô_ÍrêÒSÜõôŸ·ÒÇQîòý*¼lÛ²-i¤dì§-cêôíµô^Ênk,¯¨>ûïþo'ôk¨XŸXþÁµ¾¿©¿Óèz{¾Í¬}£íß³þïø__ù•¯ú?å}å}üŸþ
•úî½Uòÿ o÷SÓ}/wÿÙÿí ˆPhotoshop 3.0 8BIM 8BIM% Fò‰&¸VÚ°œ¡°§w8BIMí H H 8BIM&