Commit ee836b80 authored by Jan Michel's avatar Jan Michel
Browse files

add 16 clock TDC test

parent 060a100f
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.trb_net_std.all;
entity ffarray is
generic(
CHANNELS : integer := 1
);
port(
CLK : in std_logic;
SYSCLK : in std_logic;
RESET_IN : in std_logic;
SIGNAL_IN : in std_logic_vector(CHANNELS-1 downto 0);
SPIKE_REJECT: in std_logic;
-- DATA_OUT : out std_logic_vector(31 downto 0);
-- READ_IN : in std_logic := '0';
BUS_RX : in CTRLBUS_RX;
BUS_TX : out CTRLBUS_TX;
EMPTY_OUT : out std_logic := '0'
);
end entity;
architecture ffarray_arch of ffarray is
attribute syn_hier : string;
attribute syn_hier of ffarray_arch : architecture is "hard";
signal CLKt : std_logic_vector(3 downto 0);
signal CLKa : std_logic_vector(15 downto 0);
signal clk_tdc_i : std_logic_vector(1 downto 0);
signal clk_tdc : std_logic;
type vector_arr_5 is array (0 to CHANNELS-1) of std_logic_vector(6 downto 0);
type vector_arr_8 is array (0 to CHANNELS-1) of std_logic_vector(15 downto 0);
type vector_arr_9 is array (0 to CHANNELS-1) of std_logic_vector(17 downto 0);
signal final1, final2 : vector_arr_8;
signal final_t : vector_arr_8;
signal final : vector_arr_9;
type ffarr_t is array(0 to 2) of vector_arr_8;
signal ffarr : ffarr_t;
signal finalval : vector_arr_5;
signal inpgate : std_logic_vector(CHANNELS-1 downto 0);
signal buffer_read : std_logic_vector(CHANNELS-1 downto 0);
type buffer_t is array(0 to 1) of std_logic_vector(30 downto 0);
type buffers_t is array(CHANNELS-1 downto 0) of buffer_t;
signal buffer_data : buffers_t;
signal buffer_empty_0, buffer_empty_1 : std_logic_vector(CHANNELS-1 downto 0);
signal spike_reject_f : std_logic;
type ram_t is array(0 to 1023) of std_logic_vector(7 downto 0);
signal ram : ram_t;
signal fifo_write, last, fifo_write_val : std_logic_vector(CHANNELS-1 downto 0);
signal fifo_real_write, fifo_empty, valid_read : std_logic;
signal fifo_data : std_logic_vector(35 downto 0);
signal fifo_data_out : std_logic_vector(35 downto 0);
attribute syn_preserve : boolean;
attribute syn_keep : boolean;
attribute syn_preserve of CLKa : signal is true;
attribute syn_keep of CLKa : signal is true;
attribute syn_preserve of CLKt : signal is true;
attribute syn_keep of CLKt : signal is true;
signal timer : unsigned(20 downto 0) := (others => '0');
signal read_q, read_qq : std_logic;
begin
timer <= timer + 1 when rising_edge(clk_tdc);
spike_reject_f <= SPIKE_REJECT when rising_edge(clk_tdc);
THE_PLL_FIRST : entity work.pll_125_375
port map(
CLKI => CLK,
CLKOP => open,
CLKOS => clk_tdc_i(0),
CLKOS2 => clk_tdc_i(1),
CLKOS3 => clk_tdc
);
THE_PLL_SECOND_1 : entity work.pll_375_1
port map(
CLKI => clk_tdc_i(0),
CLKOP => CLKa(0),
CLKOS => CLKa(1),
CLKOS2 => CLKa(2),
CLKOS3 => CLKa(3)
);
THE_PLL_SECOND_2 : entity work.pll_375_1
port map(
CLKI => clk_tdc_i(1),
CLKOP => CLKa(4),
CLKOS => CLKa(5),
CLKOS2 => CLKa(6),
CLKOS3 => CLKa(7)
);
-- CLKa(3 downto 0) <= CLKt(3 downto 0);
CLKa(15 downto 8) <= not CLKa(7 downto 0);
gen_channels : for c in 0 to CHANNELS-1 generate
inpgate(c) <= SIGNAL_IN(c);
gen_ffarr_first : for i in 0 to 15 generate
ffarr(0)(c)(i) <= inpgate(c) when rising_edge(CLKa(i));
ffarr(1)(c)(i) <= ffarr(0)(c)(i) when rising_edge(CLKa((i/8)*8));
ffarr(2)(c)(i) <= ffarr(1)(c)(i) when rising_edge(CLKa(0));
end generate;
process begin
wait until rising_edge(CLKa(0));
final_t(c) <= ffarr(2)(c);
end process;
process begin
wait until rising_edge(clk_tdc);
final1(c) <= final_t(c);
final2(c) <= ffarr(2)(c);
last(c) <= final2(c)(15);
if (final1(c)(15) xor last(c)) = '1' then
fifo_write(c) <= '1';
final(c) <= '0' & final1(c) & last(c);
elsif (final2(c)(15) xor final1(c)(15)) = '1' then
fifo_write(c) <= '1';
final(c) <= '1' & final2(c) & final1(c)(15);
else
fifo_write(c) <= '0';
end if;
end process;
process begin
wait until rising_edge(clk_tdc);
if fifo_write(c) = '1' then
finalval(c) <= (others => '0');
case final(c)(15 downto 0) is
when x"0001" | x"fffe" => finalval(c)(3 downto 0) <= "0000";
when x"0003" | x"fffc" => finalval(c)(3 downto 0) <= "0001";
when x"0007" | x"fff8" => finalval(c)(3 downto 0) <= "0010";
when x"000f" | x"fff0" => finalval(c)(3 downto 0) <= "0011";
when x"001f" | x"ffe0" => finalval(c)(3 downto 0) <= "0100";
when x"003f" | x"ffc0" => finalval(c)(3 downto 0) <= "0101";
when x"007f" | x"ff80" => finalval(c)(3 downto 0) <= "0110";
when x"00ff" | x"ff00" => finalval(c)(3 downto 0) <= "0111";
when x"01ff" | x"fe00" => finalval(c)(3 downto 0) <= "1000";
when x"03ff" | x"fc00" => finalval(c)(3 downto 0) <= "1001";
when x"07ff" | x"f800" => finalval(c)(3 downto 0) <= "1010";
when x"0fff" | x"f000" => finalval(c)(3 downto 0) <= "1011";
when x"1fff" | x"e000" => finalval(c)(3 downto 0) <= "1100";
when x"3fff" | x"c000" => finalval(c)(3 downto 0) <= "1101";
when x"7fff" | x"8000" => finalval(c)(3 downto 0) <= "1110";
when x"ffff" | x"0000" => finalval(c)(3 downto 0) <= "1111";
when others => finalval(c)(6) <= '1';
end case;
finalval(c)(5) <= final(c)(17);
finalval(c)(4) <= final(c)(16);
if(final(c)(0) = final1(c)(0) or spike_reject = '0') then
fifo_write_val(c) <= '1';
end if;
else
fifo_write_val(c) <= '0';
end if;
end process;
PROC_BUFFER : process begin
wait until rising_edge(clk_tdc);
if fifo_write_val(c) = '1' then
if buffer_empty_0(c) = '1' then
buffer_data(c)(0)(3 downto 0) <= finalval(c)(3 downto 0);
buffer_data(c)(0)(4) <= finalval(c)(6);
buffer_data(c)(0)(5) <= finalval(c)(5);
buffer_data(c)(0)(25 downto 6) <= std_logic_vector(timer(19 downto 0));
buffer_data(c)(0)(29 downto 26) <= (others => '0');
buffer_data(c)(0)(30) <= finalval(c)(4);
buffer_empty_0(c) <= '0';
end if;
end if;
if buffer_read(c) = '1' then
buffer_empty_1(c) <= '1';
end if;
if buffer_empty_0(c) = '0' and buffer_empty_1(c) = '1' then
buffer_data(c)(1) <= buffer_data(c)(0);
buffer_empty_0(c) <= '1';
buffer_empty_1(c) <= '0';
end if;
end process;
end generate;
process
variable chan : integer range 0 to 16 := 0;
begin
wait until rising_edge(clk_tdc);
fifo_real_write <= '0';
buffer_read <= (others => '0');
if buffer_empty_1(chan) = '0' then
fifo_data(30 downto 0) <= buffer_data(chan)(1);
fifo_data(29 downto 26)<= std_logic_vector(to_unsigned(chan,4));
if(chan = 0) then --!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
fifo_real_write <= '1';
end if; --!!!!!!!!!!!
buffer_read(chan) <= '1';
end if;
chan := chan + 1;
if chan = 9 then chan := 0; end if;
end process;
THE_FIFO : entity work.fifo_36x1k
port map(
-- Data => fifo_data,
Data(17 downto 0) => final(0),
WrClock => clk_tdc,
RdClock => SYSCLK,
WrEn => fifo_write(0),
-- WrEn => fifo_real_write,
RdEn => BUS_RX.read,
Reset => RESET_IN,
RPReset => RESET_IN,
Q => fifo_data_out,
Empty => fifo_empty,
Full => open,
AlmostEmpty => open,
AlmostFull => open
);
process begin
wait until rising_edge(SYSCLK);
if BUS_RX.read = '1' then
valid_read <= not fifo_empty;
end if;
read_q <= BUS_RX.read;
read_qq <= read_q;
end process;
EMPTY_OUT <= fifo_empty;
BUS_TX.data <= valid_read & fifo_data_out(30 downto 0);
BUS_TX.ack <= read_qq;
BUS_TX.nack <= '0';
BUS_TX.unknown <= '0';
end architecture;
../../trb3sc/scripts/compile.pl
\ No newline at end of file
library ieee;
USE IEEE.std_logic_1164.ALL;
use ieee.numeric_std.all;
use work.trb_net_std.all;
package config is
------------------------------------------------------------------------------
--Begin of design configuration
------------------------------------------------------------------------------
--set to 0 for backplane serdes, set to 1 for SFP serdes
constant SERDES_NUM : integer := 1;
--TDC settings
constant FPGA_TYPE : integer := 5; --3: ECP3, 5: ECP5
constant NUM_TDC_MODULES : integer range 1 to 4 := 1; -- number of tdc modules to implement
constant NUM_TDC_CHANNELS : integer range 1 to 65 := 33; -- number of tdc channels per module
constant NUM_TDC_CHANNELS_POWER2 : integer range 0 to 6 := 5; --the nearest power of two, for convenience reasons
constant DOUBLE_EDGE_TYPE : integer range 0 to 3 := 3; --double edge type: 0, 1, 2, 3
-- 0: single edge only,
-- 1: same channel,
-- 2: alternating channels,
-- 3: same channel with stretcher
constant RING_BUFFER_SIZE : integer range 0 to 7 := 7; --ring buffer size
-- mode: 0, 1, 2, 3, 7
-- size: 32, 64, 96, 128, dyn
constant TDC_DATA_FORMAT : integer range 0 to 3 := 0; --type of data format for the TDC
-- 0: Single fine time as the sum of the two transitions
-- 1: Double fine time, individual transitions
-- 13: Debug - fine time + (if 0x3ff full chain)
-- 14: Debug - single fine time and the ROM addresses for the two transitions
-- 15: Debug - complete carry chain dump
constant EVENT_BUFFER_SIZE : integer range 9 to 13 := 10; -- size of the event buffer, 2**N
constant EVENT_MAX_SIZE : integer := 500; --maximum event size. Must not exceed EVENT_BUFFER_SIZE/2
--Runs with 120 MHz instead of 100 MHz
constant USE_120_MHZ : integer := c_NO;
--Use sync mode, RX clock for all parts of the FPGA
constant USE_RXCLOCK : integer := c_NO;
--Address settings
constant INIT_ADDRESS : std_logic_vector := x"F570";
constant BROADCAST_SPECIAL_ADDR : std_logic_vector := x"81";
constant INCLUDE_UART : integer := c_NO; --300 slices
constant INCLUDE_SPI : integer := c_YES; --300 slices
constant INCLUDE_LCD : integer := c_NO; --800 slices
constant INCLUDE_DEBUG_INTERFACE: integer := c_NO; --300 slices
--input monitor and trigger generation logic
constant INCLUDE_TRIGGER_LOGIC : integer := c_NO; --400 slices @32->2
constant INCLUDE_STATISTICS : integer := c_NO; --1300 slices, 1 RAM @32
constant TRIG_GEN_INPUT_NUM : integer := 32;
constant TRIG_GEN_OUTPUT_NUM : integer := 4;
constant MONITOR_INPUT_NUM : integer := 32;
------------------------------------------------------------------------------
--End of design configuration
------------------------------------------------------------------------------
type data_t is array (0 to 1023) of std_logic_vector(7 downto 0);
constant LCD_DATA : data_t := (others => x"00");
------------------------------------------------------------------------------
--Select settings by configuration
------------------------------------------------------------------------------
type intlist_t is array(0 to 7) of integer;
type hw_info_t is array(0 to 7) of unsigned(31 downto 0);
constant HW_INFO_BASE : unsigned(31 downto 0) := x"A5000000";
constant CLOCK_FREQUENCY_ARR : intlist_t := (100,120, others => 0);
constant MEDIA_FREQUENCY_ARR : intlist_t := (200,240, others => 0);
--declare constants, filled in body
constant HARDWARE_INFO : std_logic_vector(31 downto 0);
constant CLOCK_FREQUENCY : integer;
constant MEDIA_FREQUENCY : integer;
constant INCLUDED_FEATURES : std_logic_vector(63 downto 0);
end;
package body config is
--compute correct configuration mode
constant HARDWARE_INFO : std_logic_vector(31 downto 0) := std_logic_vector( HW_INFO_BASE );
constant CLOCK_FREQUENCY : integer := CLOCK_FREQUENCY_ARR(USE_120_MHZ);
constant MEDIA_FREQUENCY : integer := MEDIA_FREQUENCY_ARR(USE_120_MHZ);
function generateIncludedFeatures return std_logic_vector is
variable t : std_logic_vector(63 downto 0);
begin
t := (others => '0');
t(63 downto 56) := std_logic_vector(to_unsigned(2,8)); --table version 1
t(7 downto 0) := std_logic_vector(to_unsigned(1,8));
t(11 downto 8) := std_logic_vector(to_unsigned(DOUBLE_EDGE_TYPE,4));
t(14 downto 12) := std_logic_vector(to_unsigned(RING_BUFFER_SIZE,3));
t(15) := '1'; --TDC
t(17 downto 16) := std_logic_vector(to_unsigned(NUM_TDC_MODULES-1,2));
t(40 downto 40) := std_logic_vector(to_unsigned(INCLUDE_LCD,1));
t(42 downto 42) := std_logic_vector(to_unsigned(INCLUDE_SPI,1));
t(43 downto 43) := std_logic_vector(to_unsigned(INCLUDE_UART,1));
t(44 downto 44) := std_logic_vector(to_unsigned(INCLUDE_STATISTICS,1));
t(51 downto 48) := std_logic_vector(to_unsigned(INCLUDE_TRIGGER_LOGIC,4));
t(52 downto 52) := std_logic_vector(to_unsigned(USE_120_MHZ,1));
t(53 downto 53) := std_logic_vector(to_unsigned(USE_RXCLOCK,1));
t(54 downto 54) := "0";--std_logic_vector(to_unsigned(USE_EXTERNAL_CLOCK,1));
return t;
end function;
constant INCLUDED_FEATURES : std_logic_vector(63 downto 0) := generateIncludedFeatures;
end package body;
Familyname => 'ECP5UM',
Devicename => 'LFE5UM-85F',
Package => 'CABGA756',
Speedgrade => '8',
TOPNAME => "trb5sc_mdctdc",
lm_license_file_for_synplify => "27020\@jspc29", #"27000\@lxcad01.gsi.de";
lm_license_file_for_par => "1702\@jspc29",
lattice_path => '/d/jspc29/lattice/diamond/3.10_x64',
synplify_path => '/d/jspc29/lattice/synplify/O-2018.09-SP1/',
nodelist_file => '../nodelist_frankfurt.txt',
pinout_file => 'trb5sc_tdc',
par_options => '../par.p2t',
#Include only necessary lpf files
include_TDC => 0,
include_GBE => 0,
#Report settings
firefox_open => 0,
twr_number_of_errors => 20,
no_ltxt2ptxt => 1, #if there is no serdes being used
-w
#-y
-l 5
#-m nodelist.txt # Controlled by the compile.pl script.
#-n 1 # Controlled by the compile.pl script.
-s 10
-t 2
-c 2
-e 2
-i 10
#-exp parPlcInLimit=0
#-exp parPlcInNeighborSize=1
#General PAR Command Line Options
# -w With this option, any files generated will overwrite existing files
# (e.g., any .par, .pad files).
# -y Adds the Delay Summary Report in the .par file and creates the delay
# file (in .dly format) at the end of the par run.
#
#PAR Placement Command Line Options
# -l Specifies the effort level of the design from 1 (simplest designs)
# to 5 (most complex designs).
# -m Multi-tasking option. Controlled by the compile.pl script.
# -n Sets the number of iterations performed at the effort level
# specified by the -l option. Controlled by the compile.pl script.
# -s Save the number of best results for this run.
# -t Start placement at the specified cost table. Default is 1.
#
#PAR Routing Command Line Options
# -c Run number of cost-based cleanup passes of the router.
# -e Run number of delay-based cleanup passes of the router on
# completely-routed designs only.
# -i Run a maximum number of passes, stopping earlier only if the routing
# goes to 100 percent completion and all constraints are met.
#
#PAR Explorer Command Line Options
# parCDP Enable the congestion-driven placement (CDP) algorithm. CDP is
# compatible with all Lattice FPGA device families; however, most
# benefit has been demonstrated with benchmarks targeted to ECP5,
# LatticeECP2/M, LatticeECP3, and LatticeXP2 device families.
# parCDR Enable the congestion-driven router (CDR) algorithm.
# Congestion-driven options like parCDR and parCDP can improve
# performance given a design with multiple congestion “hotspots.” The
# Layer > Congestion option of the Design Planner Floorplan View can
# help visualize routing congestion. Large congested areas may prevent
# the options from finding a successful solution.
# CDR is compatible with all Lattice FPGA device families however most
# benefit has been demonstrated with benchmarks targeted to ECP5,
# LatticeECP2/M,LatticeECP3, and LatticeXP2 device families.
# paruseNBR NBR Router or Negotiation-based routing option. Supports all
# FPGA device families except LatticeXP and MachXO.
# When turned on, an alternate routing engine from the traditional
# Rip-up-based routing selection (RBR) is used. This involves an
# iterative routing algorithm that routes connections to achieve
# minimum delay cost. It does so by computing the demand on each
# routing resource and applying cost values per node. It will
# complete when an optimal solution is arrived at or the number of
# iterations is reached.
# parPathBased Path-based placement option. Path-based timing driven
# placement will yield better performance and more
# predictable results in many cases.
# parHold Additional hold time correction option. This option
# forces the router to automatically insert extra wires to compensate for the
# hold time violation.
# parHoldLimit This option allows you to set a limit on the number of
# hold time violations to be processed by the auto hold time correction option
# parHold.
# parPlcInLimit Cannot find in the online help
# parPlcInNeighborSize Cannot find in the online help
-exp parHold=ON:parHoldLimit=10000:parCDP=1:parCDR=1:parPathBased=OFF:paruseNBR=1
#!/usr/bin/perl
use strict;
use warnings;
use feature 'state';
use URI::Escape;
use Data::Dumper;
use HADES::TrbNet;
use Time::HiRes qw( usleep);
use Getopt::Long;
use Fcntl;
use HADES::TrbNet;
if (!defined $ENV{'DAQOPSERVER'}) {
die "DAQOPSERVER not set in environment";
}
if (!defined &trb_init_ports()) {
die("can not connect to trbnet-daemon on the $ENV{'DAQOPSERVER'}");
}
my @counters;
my $port;
my $help;
my $ser_dev;
my $isTrbNet = 0;
my $poll = 0;
my $cmd = "";
my $verbose = 0;
my $invert_trigger = 0;
my $fh;
Getopt::Long::Configure(qw(gnu_getopt));
GetOptions(
'help|h' => \$help,
'device|d=s' => \$ser_dev,
# 'poll|p' => \$poll,
'verbose|v' => \$verbose,
'invert_trigger|i' => \$invert_trigger,
) ;
if ($help || (defined $ARGV[0] && $ARGV[0] =~ /help/)) {
exit;
}
#
# $ser_dev = "/dev/ttyUSB1" unless defined $ser_dev;
# $cmd = "RD0" if $poll;
my $last = 0;
#
#
# my $c = "stty -F $ser_dev 921600 raw";
# #my $c = "stty -F $ser_dev -isig -icanon -iexten speed 921600 time 100";
# my $r = qx($c);
# print $r;
#
# $r = open ($fh, "+<", $ser_dev);
# unless ($fh) {
# print "can't open serial interface $ser_dev\n";
# exit;
# }
#
# $|=1;
sub Stream {
my $v = 0;
while(1) {
my $d = trb_register_read_mem(0xf570,0xc000,1,1000);
foreach my $v (@{$d->{0xf570}}) {
# if ($_ =~ /([A-Fa-f0-9]{8})/) {$v = hex($1);}
# next if ($v>>16 & 0xffff) == 0xdead;
unless ($v & 0x80000000) {next;}
next if $last == $v;
$counters[($v&0x1f) + (($v>>30 & 1) << 16)]++;
my $diff = ($v>>5 & 0x1fffff)*16+($v & 0xf) - ($last>>5 & 0x1fffff)*16-($last & 0xf);
$diff += 2**24 if $diff < 0;
printf("%i\t%i\t%03x\t%i\t%i\n",$v>>30 & 1, $v>>26 & 0xf, ($v & 0x1f), $v>>5 & 0x1fffff, $diff) if $verbose;
$last = $v if (($v>>30 & 1)==$invert_trigger) && (($v>>26&0xf) == 8) ;
}
}
}
# sub Cmd {
# my ($c) = @_;
# #print "send command '$c'\n";
# if ($c ne "") {
# my $s = $c . "T"x0 . "\n";
# #print "send string '$s'\n";
# print $fh $s;
# }
# #usleep(10);
# #sleep 1;
# #sleep 1;
# my $timeout = 1;
# #return;
# #print "try to read \n";
# my ($rec) = eval {
# local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
# alarm $timeout;
# #my $rec2 = <$fh>;
# my $rec2 ="";
# my $nread = sysread $fh, $rec2, 100;
# #print "received (n words: $nread) in eval: $rec2\n";
# alarm 0;
# $rec2;
# };
# if ($@) {
# die unless $@ eq "alarm\n"; # propagate unexpected errors
# print "timed out\n";
# # timed out
# }
# else {
# #print "received: $rec\n";
# }
#
# # return $rec;
#
# if ($rec =~ /R([A-Fa-f0-9]{8})/) {return hex($1);}
#
# return 0xdeadde99 if $poll;
#
# #print "%\n";
# #return 0xdeaddead;
# }