Commit 5eedf6e9 authored by egousiou's avatar egousiou

folders restructuring; one core for both spec and svec

git-svn-id: http://svn.ohwr.org/fmc-tdc@125 85dfdc96-de2c-444c-878d-45b388be74a9
parent 512fe0df
I found the code quite clear, even if there are not many comments.
------------------------------------------
data_engine, data_formatting and circular_buffer
------------------------------------------
I would suggest a bit cleaner names for the WBs:
stb/ack/.. in the data_engine could be renamed to acam_stb/ acam_ack..
stb/ack/.. in the data_formatting could be renamed to internal_stb/ internal_ack..
classic_stb/ classic_ack/.. in the circular_buffer could be renamed to gnum_classic_stb/ gnum_classic_ack..
pipe_stb/ pipe_ack/.. in the circular_buffer could be renamed to gnum_pipe_stb/ gnum_pipe_ack..
one_hz_gen and acam_timecontrol_interface
------------------------------------------
synchronization and edge detection of refclk takes place in both units
one_hz_gen lines 153-170; acam_timecontrol_interface lines 240-258
refclk_edge is a pulse (refclk_edge_p)
use of the first DFF s_acam_refclk(3) should be avoided
acam_timecontrol_interface
------------------------------------------
lines 260: start_trig_edge is a pulses (_p)
use of the first DFF (start_trig_r(2)) should be avoided
lines 120-146 : good!-)
acam_databus_interface
------------------------------------------
lines 227-241: signals ef1/2, lf1/2 shouldn t be synchronized as well (use one more DFF)?
acam_databus_interface and circular_buffer
------------------------------------------
The ack signals are pulses (_p)
acam_databus_interface, ack, line 63
circular_buffer, classic_ack, line 123
circular_buffer
------------------------------------------
lines 37, 50: class_clk_i and pipe_clk_i are actually the same clock; maybe they could just be named gnum_clk_i
Disclaimer: not enough time to do this design justice. Looking at VHDL
constructs independently, not trying to make sense of the design as a
whole.
top_tdc.vhd
===========
- Line 1057 (and others). The wait until spec_clk = '1'; at the end of
the process looks awkward to me. I guess it means this is a
synchronous process working on the rising edge of spec_clk. Is there
any advantage to using this notation?
acam_databus_interface.vhd
==========================
- Line 73. "read" and "write" are not VHDL reserved words but they are
names of functions people use to do I/O. Probably wise to chose
other names for states.
- Line 244. address_o going to the ACAM is not registered. This signal
is driven by adr_i, the wishbone input address. These lines are
being used in another entity (data_engine.vhd) as inputs to other
processes so chances are they will not use IOB FFs, which might be
important to respect setup and hold constraints of the ACAM.
acam_timecontrol_interface.vhd
==============================
- Line 246 (and others). This can be written in one line:
"start_trig_r <= start_trig & start_trig_r(1 downto 0);"
- Line 255 (and others). This edge detector uses signal ref_clk_r(3),
which is potentially metastable. It also relies very heavily on the
fact that ref_clk should be at a given frequency.
clk_rst_managr.vhd
==================
Line 284. This process can create metastability in signal gral_incr,
which is then going to many destinations inside the incr_counter
block, possibly leading to non-deterministic behavior of the counter.
Line 309. Signal cs seems to be negative logic. This should be visible
in its name.
Line 571. cs will not use an IOB FF because it is read in line
366. Please check all other cases when this can happen.
one_hz_gen.vhd
==============
Line 153. Similar comments on metastability as before. Also, the
assumption on the clock frequency of s_acam_refclk is very strong and
might be in trouble if sampling happens close to the edges and the
signals are a bit jittery. Why is this "frequency test" needed?
Summary of all the comments to the code by authors.
General:
========
TOM
- Wait statements in synthesizable code look suspicious...
They indeed synthesize correctly, but to be honest, I've never seen processes
coded in such way.
- (googled a bit) Technically, it should be "wait until rising_edge(clk)" or
" wait until (clk'event and clk = '1')".
- Are I/O always assigned to internal signals for some particular reason?
- I'd suggest declaring commonly used components (e.g. counters) in a shared
package to avoid repetitive declarations.
- Clock signal assignments are dangerous.
On a simulation, there is a big risk of getting timing errors when co-simulated
with Verilog code due to incompatibilities between the way events are
scheduled in VHDL and Verilog simulators
(in VHDL, a continuous assignment is scheduled as an event, while in verilog
it's purely continous).
top_tdc.vhd
===========
JAVIER
- Line 1057 (and others). The wait until spec_clk = '1'; at the end of
the process looks awkward to me. I guess it means this is a
synchronous process working on the rising edge of spec_clk. Is there
any advantage to using this notation?
TOM
- what are g_span and g_width generics (a comment would be helpful)
- gnum_reset signal is asynchronous, but used throughout the design as
synchronous. Add a sync chain.
- put together all the components which form the TDC core into a single VHDL
entity, with the ACAM I/F on one side and Wishbone on other side
(i.e. without the gennum or other platform-specific stuff inside)
- lines 1024, 1039: when decoding addresses, define base addrs as constants
instead of using hardcoded values
acam_databus_interface.vhd
==========================
JAVIER
- Line 73. "read" and "write" are not VHDL reserved words but they are
names of functions people use to do I/O. Probably wise to chose
other names for states.
- Line 244. address_o going to the ACAM is not registered. This signal
is driven by adr_i, the wishbone input address. These lines are
being used in another entity (data_engine.vhd) as inputs to other
processes so chances are they will not use IOB FFs, which might be
important to respect setup and hold constraints of the ACAM.
TOM
- line 192: these signals (efX, lfX) are asynchronous. I'd suggest using a
sync chain of 2-3 flip-flops.
EVA
- lines 227-241: signals ef1/2, lf1/2 shouldn t be synchronized as well
(use one more DFF)?
- The ack signals are pulses (_p)
acam_databus_interface, ack, line 63
acam_timecontrol_interface.vhd
==============================
JAVIER
- Line 246 (and others). This can be written in one line:
"start_trig_r <= start_trig & start_trig_r(1 downto 0);"
- Line 255 (and others). This edge detector uses signal ref_clk_r(3),
which is potentially metastable. It also relies very heavily on the
fact that ref_clk should be at a given frequency.
TOM
- line 89: the name doesn't explain the purpose of this constant. What delay
does it describe?
- line 125: are you sure this will work correctly? err_flag_r(2) is written
twice.
How about using slice & join instead?
err_flag_r <= err_flag_r(err_flag_r'left-1 downto 0) & err_flag_i;
- line 249: acam_refclk and clk are normally phase aligned by the AD9516 PLL,
so there may be a setup time violation here. Is the AD9516 shifter programmed
to ensure the FPGA will correctly sample acam_refclk signal?
(otherwise, the 1st stage could sample on the falling edge of clk).
- line 255: refclk_r(3) can be metastable, causing refclk_edge signal to be
unreliable.
Consider adding 1 more sync stage (or using only (1) and (0) indices)
- line 260: the same for start_trig_edge
EVA
- synchronization and edge detection of refclk takes place in both units
one_hz_gen lines 153-170; acam_timecontrol_interface lines 240-258
refclk_edge is a pulse (refclk_edge_p)
use of the first DFF s_acam_refclk(3) should be avoided
- lines 260: start_trig_edge is a pulses (_p)
use of the first DFF (start_trig_r(2)) should be avoided
- lines 120-146 : good!-)
clk_rst_managr.vhd
==================
JAVIER
- Line 284. This process can create metastability in signal gral_incr,
which is then going to many destinations inside the incr_counter
block, possibly leading to non-deterministic behavior of the counter.
- Line 309. Signal cs seems to be negative logic. This should be visible
in its name.
- Line 571. cs will not use an IOB FF because it is read in line
366. Please check all other cases when this can happen.
TOM
- line 166: IBUFDS + BUFG can be merged into single IBUFGDS
- line 225: chain of two global buffers on spec_clk_i
(IBUFG drives a global clock net, so there's no need to follow it with another
BUFG)
- lines 409+: I'd suggest defining these regs as an array of records?
- lines 289+: I couldn't understand the way the power-on-reset is generated.
A comment would be greatly appreciated.
one_hz_gen.vhd
==============
JAVIER
- Line 153. Similar comments on metastability as before. Also, the
assumption on the clock frequency of s_acam_refclk is very strong and
might be in trouble if sampling happens close to the edges and the
signals are a bit jittery. Why is this "frequency test" needed?
TOM
- lines 161+: you're syncing the same signal (tdc refclock) twice in the design
(here and in acam_timecontrol_interface). Due to possible metastability,
you can get inconsistent pulses in these two modules.
EVA
synchronization and edge detection of refclk takes place in both units
one_hz_gen lines 153-170; acam_timecontrol_interface lines 240-258
refclk_edge is a pulse (refclk_edge_p)
use of the first DFF s_acam_refclk(3) should be avoided
data_engine
===========
TOM
- state names look like signal names, consider using uppercase or prefixes to
avoid confusion.
- line 294: is the others block ever reached?
- define addresses of commonly used ACAM regs as constants
(e.g. c_ACAM_IFIFO1 for x"08", etc...) to improve readability.
EVA
- I would suggest a bit cleaner names for the WBs:
stb/ack/.. in the data_engine could be renamed to
acam_stb/ acam_ack..
circular_buffer
===============
TOM
- pipelined WB is not that complex, there's no need for an FSM.
In case of a non-stalling peripheral (stall == 0 always), the ack signal can
be generated like this:
process(clk)
ack <= stb and cyc;
(adr and dat go straight to the block ram).
- Consider replacing Coregen cores with generic ones. The circular buffer can
be done as a simple array.
EVA
- I would suggest a bit cleaner names for the WBs:
classic_stb/ classic_ack/.. in the circular_buffer renamed to
gnum_classic_stb/ gnum_classic_ack..
pipe_stb/ pipe_ack/.. in the circular_buffer renamed to
gnum_pipe_stb/ gnum_pipe_ack..
- lines 37, 50: class_clk_i and pipe_clk_i are actually the same clock;
maybe they could just be named gnum_clk_i
- The ack signals are pulses (_p)
circular_buffer, classic_ack, line 123
countdown_counter:
free_counter:
incr_counter:
=============
TOM
- line 49, 52: (un)signeds can be compared with integers directly
(numeric_std supports this).
if (value = 0) ...
- coding style (_i suffix for inputs, etc.).
reg_ctrl:
=========
- use constants for defining register adresses
- line 135+: avoid repetitive assignments. Use loop construct instead.
- line 126+: reg_ack <= reg_stb and reg_cyc and not reg_ack;
tdc_core_pkg:
============
- lines 73+: consider defining these constants in decimal format
(these are timeouts, and in decimal they are easier to understand).
sim/
----------------
- Try to avoid uploading binary files if they are not absolutely necessary
(i.e. compiled Xilinx libraries).
- A system-level testbench should be provided (tb_tdc.vhd doesn't include
any actual testbench code, just the models connected together).
Disclaimer. I didn't have too much time to review. Apologize for eventual typos or errors in my comments.
T.
General:
------------------
- Wait statements in synthesizable code look suspicious... They indeed synthesize correctly, but to be honest, I've never seen processes coded in such way.
- (googled a bit) Technically, it should be "wait until rising_edge(clk)" or "wait until (clk'event and clk = '1')".
- Are I/O always assigned to internal signals for some particular reason?
- I'd suggest declaring commonly used components (e.g. counters) in a shared package to avoid repetitive declarations.
- Clock signal assignments are dangerous. On a simulation, there is a big risk of getting timing errors when co-simulated with Verilog code due to incompatibilities between the way events are scheduled in VHDL and Verilog simulators (in VHDL, a continuous assignment is scheduled as an event, while in verilog it's purely continous).
acam_databus_interface:
-------------------------
- line 192: these signals (efX, lfX) are asynchronous. I'd suggest using a sync chain of 2-3 flip-flops.
acam_timecontrol_interface:
----------------------------
- line 89: the name doesn't explain the purpose of this constant. What delay does it describe?
- line 125: are you sure this will work correctly? err_flag_r(2) is written twice.
How about using slice & join instead?
err_flag_r <= err_flag_r(err_flag_r'left-1 downto 0) & err_flag_i;
- line 249: acam_refclk and clk are normally phase aligned by the AD9516 PLL, so there may be a setup time violation here. Is the AD9516 shifter programmed to ensure the FPGA will correctly sample acam_refclk signal? (otherwise, the 1st stage could sample on the falling edge of clk).
- line 255: refclk_r(3) can be metastable, causing refclk_edge signal to be unreliable. Consider adding 1 more sync stage (or using only (1) and (0) indices)
- line 260: the same for start_trig_edge
circular_buffer:
-------------------------
- pipelined WB is not that complex, there's no need for an FSM.
In case of a non-stalling peripheral (stall == 0 always), the ack signal can be generated like this:
process(clk)
ack <= stb and cyc;
(adr and dat go straight to the block ram).
- Consider replacing Coregen cores with generic ones. The circular buffer can be done as a simple array.
clk_rst_managr:
---------------------------
- line 166: IBUFDS + BUFG can be merged into single IBUFGDS
- line 225: chain of two global buffers on spec_clk_i (IBUFG drives a global clock net, so there's no need to follow it with another BUFG)
- lines 409+: I'd suggest defining these regs as an array of records?
- lines 289+: I couldn't understand the way the power-on-reset is generated. A comment would be greatly appreciated.
countdown_counter:
free_counter:
incr_counter:
-----------------------
- line 49, 52: (un)signeds can be compared with integers directly (numeric_std supports this).
if (value = 0) ...
- coding style (_i suffix for inputs, etc.).
data_engine:
-----------------
- state names look like signal names, consider using uppercase or prefixes to avoid confusion.
- line 294: is the others block ever reached?
- define addresses of commonly used ACAM regs as constants (e.g. c_ACAM_IFIFO1 for x"08", etc...) to improve readability.
one_hz_counter:
-----------------
- lines 161+: you're syncing the same signal (tdc refclock) twice in the design (here and in acam_timecontrol_interface). Due to possible metastability, you can get inconsistent pulses in these two modules.
reg_ctrl:
-----------------
- use constants for defining register adresses
- line 135+: avoid repetitive assignments. Use loop construct instead.
- line 126+: reg_ack <= reg_stb and reg_cyc and not reg_ack;
tdc_core_pkg:
---------------------
- lines 73+: consider defining these constants in decimal format (these are timeouts, and in decimal they are easier to understand).
top_tdc:
---------------------
- what are g_span and g_width generics (a comment would be helpful)
- gnum_reset signal is asynchronous, but used throughout the design as synchronous. Add a sync chain.
- put together all the components which form the TDC core into a single VHDL entity, with the ACAM I/F on one side and Wishbone on other side (i.e. without the gennum or other platform-specific stuff inside)
- lines 1024, 1039: when decoding addresses, define base addrs as constants instead of using hardcoded values
sim/
----------------
- Try to avoid uploading binary files if they are not absolutely necessary (i.e. compiled Xilinx libraries).
- A system-level testbench should be provided (tb_tdc.vhd doesn't include any actual testbench code, just the models connected together).
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- acam_databus_interface |
-- |
---------------------------------------------------------------------------------------------------
-- File acam_databus_interface.vhd |
-- |
-- Description The unit interfaces with the ACAM chip pins for the configuration of the registers|
-- and the aquisition of the timestamps. |
-- The ACAM proprietary interface is converted to a WISHBONE classic interface, with |
-- which the unit communicates with the data_engine unit. |
-- The WISHBONE master is implemented in the data_engine and the slave in this unit. |
-- |
-- ___________ ____________ ___________ |
-- | |___WRn_______| | | | |
-- | |___RDn_______| |___stb______| | |
-- | |___CSn_______| |___cyc______| | |
-- | ACAM |___OEn_______| acam_ |___we_______| data_ | |
-- | |___EF________| databus_ |___ack______| engine | |
-- | | | interface |___adr______| | |
-- | |___ADR_______| |___datI_____| | |
-- | |___DatabusIO_| |___datO_____| | |
-- |___________| |____________| |___________| |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 10/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.std_logic_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for acam_databus_interface
--=================================================================================================
entity acam_databus_interface is
port
-- INPUTS
-- Signals from the clk_rst_manager unit
(clk_i : in std_logic; -- 125 MHz clock
rst_i : in std_logic; -- global reset
-- Signals from the ACAM chip
ef1_i : in std_logic; -- FIFO1 empty flag
ef2_i : in std_logic; -- FIFO1 empty flag
data_bus_io : inout std_logic_vector(27 downto 0);
-- Signals from the data_engine unit
cyc_i : in std_logic; -- WISHBONE cycle
stb_i : in std_logic; -- WISHBONE strobe
we_i : in std_logic; -- WISHBONE write enable
adr_i : in std_logic_vector(7 downto 0); -- address of Acam to write to/ read from (only 4 LSB are output)
dat_i : in std_logic_vector(31 downto 0); -- data to load to Acam (only 28 LSB are output)
-- OUTPUTS
-- signals internal to the chip: interface with other modules
ef1_o : out std_logic; -- acam FIFO1 empty flag (bouble registered with clk_i)
ef1_synch1_o : out std_logic; -- acam FIFO1 empty flag (after 1 clk_i register)
ef2_o : out std_logic; -- acam FIFO2 empty flag (bouble registered with clk_i)
ef2_synch1_o : out std_logic; -- acam FIFO2 empty flag (after 1 clk_i register)
-- Signals to ACAM interface
adr_o : out std_logic_vector(3 downto 0); -- acam address
cs_n_o : out std_logic; -- acam chip select, active low
oe_n_o : out std_logic; -- acam output enble, active low
rd_n_o : out std_logic; -- acam read enable, active low
wr_n_o : out std_logic; -- acam write enable, active low
-- Signals to the data_engine unit
ack_o : out std_logic; -- WISHBONE ack
dat_o : out std_logic_vector(31 downto 0)); -- ef1 & ef2 & 0 & 0 & 28 bits acam data_bus_io
end acam_databus_interface;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of acam_databus_interface is
type t_acam_interface is (IDLE, RD_START, RD_FETCH, RD_ACK, WR_START, WR_PUSH, WR_ACK);
signal acam_data_st, nxt_acam_data_st : t_acam_interface;
signal ef1_synch, ef2_synch : std_logic_vector(1 downto 0);
signal ack, cs, cs_extend, rd, rd_extend, wr, wr_extend, wr_remove : std_logic;
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- Input Synchronizers --
---------------------------------------------------------------------------------------------------
input_registers: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
ef1_synch <= (others =>'1');
ef2_synch <= (others =>'1');
else
ef1_synch <= ef1_i & ef1_synch(1);
ef2_synch <= ef2_i & ef2_synch(1);
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- FSM --
---------------------------------------------------------------------------------------------------
-- The following state machine implements the slave side of the WISHBONE interface
-- and converts the signals for the ACAM proprietary bus interface. The interface respects the
-- timings specified in page 7 of the ACAM datasheet.
databus_access_seq_fsm: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
acam_data_st <= IDLE;
else
acam_data_st <= nxt_acam_data_st;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
databus_access_comb_fsm: process (acam_data_st, stb_i, cyc_i, we_i)
begin
case acam_data_st is
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when IDLE =>
-----------------------------------------------
ack <= '0';
cs_extend <= '0';
rd_extend <= '0';
wr_extend <= '0';
wr_remove <= '0';
-----------------------------------------------
if stb_i = '1' and cyc_i = '1' then
if we_i = '1' then
nxt_acam_data_st <= WR_START;
else
nxt_acam_data_st <= RD_START;
end if;
else
nxt_acam_data_st <= IDLE;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_START =>
-----------------------------------------------
ack <= '0';
cs_extend <= '1';
rd_extend <= '1';
wr_extend <= '0';
wr_remove <= '0';
-----------------------------------------------
nxt_acam_data_st <= RD_FETCH;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_FETCH =>
-----------------------------------------------
ack <= '0';
cs_extend <= '1';
rd_extend <= '1';
wr_extend <= '0';
wr_remove <= '0';
-----------------------------------------------
nxt_acam_data_st <= RD_ACK;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_ACK =>
-----------------------------------------------
ack <= '1';
cs_extend <= '0';
rd_extend <= '0';
wr_extend <= '0';
wr_remove <= '0';
-----------------------------------------------
nxt_acam_data_st <= IDLE;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when WR_START =>
-----------------------------------------------
ack <= '0';
cs_extend <= '1';
rd_extend <= '0';
wr_extend <= '1';
wr_remove <= '0';
-----------------------------------------------
nxt_acam_data_st <= WR_PUSH;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when WR_PUSH =>
-----------------------------------------------
ack <= '0';
cs_extend <= '0';
rd_extend <= '0';
wr_extend <= '0';
wr_remove <= '1';
-----------------------------------------------
nxt_acam_data_st <= WR_ACK;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when WR_ACK =>
-----------------------------------------------
ack <= '1';
cs_extend <= '0';
rd_extend <= '0';
wr_extend <= '0';
wr_remove <= '0';
-----------------------------------------------
nxt_acam_data_st <= IDLE;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when others =>
-----------------------------------------------
ack <= '0';
cs_extend <= '0';
rd_extend <= '0';
wr_extend <= '0';
wr_remove <= '0';
-----------------------------------------------
nxt_acam_data_st <= IDLE;
end case;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
ack_o <= ack;
-- to the 28 bits databus output we add the ef flags to arrive to a 32 bits word
dat_o <= ef1_synch(0) & ef2_synch(0) & "00" & data_bus_io;
---------------------------------------------------------------------------------------------------
-- Outputs to ACAM --
---------------------------------------------------------------------------------------------------
output_registers: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
cs_n_o <= '1';
rd_n_o <= '1';
wr_n_o <= '1';
else
cs_n_o <= not(cs);
rd_n_o <= not(rd);
wr_n_o <= not(wr);
end if;
end if;
end process;
oe_n_o <= '1';
cs <= ((stb_i and cyc_i) or cs_extend) and not(ack);
rd <= ((stb_i and cyc_i and not(we_i)) or rd_extend) and not(ack);
wr <= ((stb_i and cyc_i and we_i) or wr_extend) and not(wr_remove) and not(ack);
-- the wr signal has to be removed to respect the Acam specs
data_bus_io <= dat_i(27 downto 0) when we_i='1' else (others =>'Z');
adr_o <= adr_i(3 downto 0);
---------------------------------------------------------------------------------------------------
-- EF to the data_engine --
---------------------------------------------------------------------------------------------------
ef1_o <= ef1_synch(0); -- ef1 after two synchronization registers
ef1_synch1_o <= ef1_synch(1); -- ef1 after one synchronization register
ef2_o <= ef2_synch(0); -- ef1 after two synchronization registers
ef2_synch1_o <= ef2_synch(1); -- ef1 after one synchronization register
end rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- acam_timecontrol_interface |
-- |
---------------------------------------------------------------------------------------------------
-- File acam_timecontrol_interface.vhd |
-- |
-- Description interface with the acam chip pins for control and timing |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for acam_timecontrol_interface
--=================================================================================================
entity acam_timecontrol_interface is
port
-- INPUTS
-- Signals from the clk_rst_manager unit
(clk_i : in std_logic; -- 125 MHz clock
rst_i : in std_logic; -- reset
acam_refclk_r_edge_p_i : in std_logic; -- pulse upon ACAM RefClk rising edge
-- Signals from the ACAM chip
err_flag_i : in std_logic; -- ACAM error flag, active HIGH; through ACAM config
-- reg 11 is set to report for any HitFIFOs full flags
int_flag_i : in std_logic; -- ACAM interrupt flag, active HIGH; through ACAM config
-- reg 12 it is set to the MSB of Start#
-- Signals from the reg_ctrl unit
activate_acq_p_i : in std_logic; -- signal from PCIe to start following the ACAM chip
-- for tstamps aquisition
window_delay_i : in std_logic_vector(31 downto 0); -- eva: don t know yet:s
-- OUTPUTS
-- Signals to the ACAM chip
start_from_fpga_o : out std_logic;
-- Signals to the
acam_errflag_r_edge_p_o : out std_logic; -- ACAM ErrFlag rising edge
acam_errflag_f_edge_p_o : out std_logic; -- ACAM ErrFlag falling edge
acam_intflag_f_edge_p_o : out std_logic);-- ACAM IntFlag falling edge
end acam_timecontrol_interface;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of acam_timecontrol_interface is
constant constant_delay : unsigned(31 downto 0) := x"00000004";
-- the delay between the referenc clock and the start window is the Total Delay
-- the Total delay is always obtained by adding the constant delay and the
-- window delay configured by the PCI-e
-- the start_from_fpga_o signal is generated in the middle of the start window
signal counter_reset : std_logic;
signal total_delay, counter_value : std_logic_vector(31 downto 0);
signal int_flag_synch, err_flag_synch : std_logic_vector(2 downto 0);
signal start_trig_received, waitingfor_refclk_i : std_logic;
signal window_start, window_prepulse : std_logic;
signal start_trig_r : std_logic_vector(2 downto 0);
signal start_trig_edge : std_logic;
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- IntFlag and ERRflag Input Synchronizers --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
sync_err_flag: process (clk_i) -- synchronisation registers for ERR external signal
begin
if rising_edge (clk_i) then
if rst_i ='1' then
err_flag_synch <= (others => '0');
int_flag_synch <= (others => '0');
else
err_flag_synch <= err_flag_i & err_flag_synch(2 downto 1);
int_flag_synch <= int_flag_i & int_flag_synch(2 downto 1);
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
acam_errflag_f_edge_p_o <= not(err_flag_synch(1)) and err_flag_synch(0);
acam_errflag_r_edge_p_o <= err_flag_synch(1) and not(err_flag_synch(0));
acam_intflag_f_edge_p_o <= not(int_flag_synch(1)) and int_flag_synch(0);
---------------------------------------------------------------------------------------------------
-- Input Synchronizers --
---------------------------------------------------------------------------------------------------
-- Generation of the start pulse and the enable window:
-- the start pulse originates from an internal signal at the same time, the StartDis is de-asserted.
-- After many tests with the ACAM chip, the start Disable feature doesn't seem to be stable.
-- It has therefore been decided to avoid its usage. The generation of the window is maintained
-- to allow the control of the delay between the Start_From_FPGA pulse and the ACAM RefClk edge
window_delayer_counter: decr_counter -- all signals are synchronized
generic map -- to the refclk_i of the ACAM
(width => 32) -- But their delays are configurable.
port map
(clk_i => clk_i,
rst_i => rst_i,
counter_top_i => total_delay,
counter_load_i => window_prepulse,
counter_is_zero_o => window_start,
counter_o => open);
window_prepulse <= waitingfor_refclk_i and acam_refclk_r_edge_p_i;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
window_active_counter: incr_counter -- Defines the de-assertion window
generic map -- for the StartDisable signal
(width => 32)
port map
(clk_i => clk_i,
rst_i => counter_reset,
counter_top_i => x"00000004",
counter_incr_en_i => start_trig_received,
counter_is_full_o => open,
counter_o => counter_value);
counter_reset <= rst_i or window_start;
total_delay <= std_logic_vector(unsigned(window_delay_i)+constant_delay);
start_pulse_from_fpga: process (clk_i) -- start pulse in the middle of the
begin -- de-assertion window of StartDisable
if rising_edge (clk_i) then
if rst_i ='1' then
start_from_fpga_o <= '0';
elsif counter_value >= x"00000001" and counter_value <= x"00000002" then
start_from_fpga_o <= '1';
else
start_from_fpga_o <= '0';
end if;
end if;
end process;
-- Synchronization of the activate_acq_p with the acam_refclk_p_i
ready_to_trigger: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
waitingfor_refclk_i <= '0';
elsif start_trig_edge ='1' then
waitingfor_refclk_i <= '1';
elsif acam_refclk_r_edge_p_i ='1' then
waitingfor_refclk_i <= '0';
end if;
end if;
end process;
actual_trigger_received: process (clk_i) -- signal needed to exclude the generation of
begin -- the start_from_fpga_o after a general rst_i
if rising_edge (clk_i) then
if rst_i ='1' then
start_trig_received <= '0';
elsif window_start ='1' then
start_trig_received <= '1';
elsif counter_value = x"00000004" then
start_trig_received <= '0';
end if;
end if;
end process;
inputs_synchronizer: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
start_trig_r <= (others=>'0');
else
start_trig_r <= activate_acq_p_i & start_trig_r(2 downto 1);
end if;
end if;
end process;
start_trig_edge <= start_trig_r(1) and not(start_trig_r(0));
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- circular_buffer |
-- |
---------------------------------------------------------------------------------------------------
-- File circular_buffer.vhd |
-- |
-- Description Dual port RAM circular buffer for timestamp storage; contains the RAM block and |
-- the WISHBONE slave interfaces: |
-- o The data_formatting unit is writing 128-bit long timestamps, using a WISHBONE |
-- classic interface. The unit implements a WISHBONE classic slave. |
-- As figure 1 indicates, from this side the memory is of size: 255 * 128. |
-- o The GNUM core is reading 32-bit words. Readings take place using a pipelined |
-- WISHBONE interface, allowing for Direct Memory Access from the PCI-e. |
-- The unit implements a WISHBONE pipelined slave. |
-- As figure 1 indicates, from this side the memory is of size: 1024 * 32. |
-- |
-- Note also that in principle the data_formatting unit is only writing in the RAM |
-- and the GNUM core is only reading from it. |
-- |
-- |
-- RAM as seen from the RAM as seen from the |
-- data_formatting unit GNUM core |
-- ____________________________________________________________ _______________ |
-- 0 | 128 bits | 0 | 32 bits | |
-- |____________________________________________________________| |_______________| |
-- 1 | 128 bits | 1 | 32 bits | |
-- |____________________________________________________________| |_______________| |
-- . | 128 bits | 2 | 32 bits | |
-- |____________________________________________________________| <==> |_______________| |
-- . | 128 bits | 3 | 32 bits | |
-- |____________________________________________________________| |_______________| |
-- | 128 bits | 4 | 32 bits | |
-- 255|____________________________________________________________| |_______________| |
-- . | 32 bits | |
-- |_______________| |
-- . | 32 bits | |
-- |_______________| |
-- . | 32 bits | |
-- |_______________| |
-- . | 32 bits | |
-- |_______________| |
-- 1021 | 32 bits | |
-- |_______________| |
-- 1022 | 32 bits | |
-- |_______________| |
-- 1023 | 32 bits | |
-- |_______________| |
-- Figuure 1: RAM configuration |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 10/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.std_logic_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for circular_buffer
--=================================================================================================
entity circular_buffer is
port
-- INPUTS
-- Signal from the clk_rst_manager
(clk_i : in std_logic; -- 125 MHz clock; same for both ports
-- Signals from the data_formatting unit (WISHBONE classic): timestamps writing
tstamp_wr_rst_i : in std_logic; -- timestamp writing WISHBONE reset
tstamp_wr_stb_i : in std_logic; -- timestamp writing WISHBONE strobe
tstamp_wr_cyc_i : in std_logic; -- timestamp writing WISHBONE cycle
tstamp_wr_we_i : in std_logic; -- timestamp writing WISHBONE write enable
tstamp_wr_adr_i : in std_logic_vector(7 downto 0); -- adr 8 bits long 2^8 = 255
tstamp_wr_dat_i : in std_logic_vector(127 downto 0); -- timestamp 128 bits long
-- Signals from the GNUM core unit (WISHBONE pipelined): timestamps reading
gnum_dma_rst_i : in std_logic; -- timestamp reading WISHBONE reset
gnum_dma_stb_i : in std_logic; -- timestamp reading WISHBONE strobe
gnum_dma_cyc_i : in std_logic; -- timestamp reading WISHBONE cycle
gnum_dma_we_i : in std_logic; -- timestamp reading WISHBONE write enable; not used
gnum_dma_adr_i : in std_logic_vector(31 downto 0); -- adr 10 bits long 2^10 = 1024
gnum_dma_dat_i : in std_logic_vector(31 downto 0); -- not used
-- OUTPUTS
-- Signals to the data_formatting unit (WISHBONE classic): timestamps writing
tstamp_wr_ack_p_o : out std_logic; -- timestamp writing WISHBONE classic acknowledge
tstamp_wr_dat_o : out std_logic_vector(127 downto 0); -- not used
-- Signals to the GNUM core unit (WISHBONE pipelined): timestamps reading
gnum_dma_ack_o : out std_logic; -- timestamp reading WISHBONE pepelined acknowledge
gnum_dma_dat_o : out std_logic_vector(31 downto 0); -- 32 bit words
gnum_dma_stall_o : out std_logic);-- timestamp reading WISHBONE pipelined stall
end circular_buffer;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of circular_buffer is
type t_wb_wr is (IDLE, MEM_ACCESS, MEM_ACCESS_AND_ACKNOWLEDGE, ACKNOWLEDGE);
signal tstamp_rd_wb_st, nxt_tstamp_rd_wb_st : t_wb_wr;
signal tstamp_wr_ack_p : std_logic;
signal tstamp_rd_we, tstamp_wr_we : std_logic_vector(0 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- TIMESTAMP WRITINGS WISHBONE CLASSIC ACK --
---------------------------------------------------------------------------------------------------
-- WISHBONE classic interface compatible slave
classic_interface: process (clk_i)
begin
if rising_edge (clk_i) then
if tstamp_wr_rst_i ='1' then
tstamp_wr_ack_p <= '0';
elsif tstamp_wr_stb_i = '1' and tstamp_wr_cyc_i = '1' and tstamp_wr_ack_p = '0' then
tstamp_wr_ack_p <= '1'; -- a new 1 clk-wide ack is given for each stb
else
tstamp_wr_ack_p <= '0';
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
tstamp_wr_ack_p_o <= tstamp_wr_ack_p;
---------------------------------------------------------------------------------------------------
-- TIMESTAMP READINGS WISHBONE PIPELINE ACK --
---------------------------------------------------------------------------------------------------
-- FSM for the generation of the pipelined WISHBONE ACK signal.
-- Note that the first output from the memory comes 2 clk cycles after the address setting.
-- CLK : --|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__
-- STB : _____|-----------------------------------|_________________
-- CYC : _____|-----------------------------------|_________________
-- ADR : <ADR0><ADR1><ADR2><ADR3><ADR4><ADR5>
-- ACK : _________________|-----------------------------------|_____
-- DATO: <DAT0><DAT1><DAT2><DAT3><DAT4><DAT5>
WB_pipe_ack_fsm_seq: process (clk_i)
begin
if rising_edge (clk_i) then
if gnum_dma_rst_i ='1' then
tstamp_rd_wb_st <= IDLE;
else
tstamp_rd_wb_st <= nxt_tstamp_rd_wb_st;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
WB_pipe_ack_fsm_comb: process (tstamp_rd_wb_st, gnum_dma_stb_i, gnum_dma_cyc_i)
begin
case tstamp_rd_wb_st is
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when IDLE =>
-----------------------------------------------
gnum_dma_ack_o <= '0';
-----------------------------------------------
if gnum_dma_stb_i = '1' and gnum_dma_cyc_i = '1' then
nxt_tstamp_rd_wb_st <= MEM_ACCESS;
else
nxt_tstamp_rd_wb_st <= IDLE;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when MEM_ACCESS =>
-----------------------------------------------
gnum_dma_ack_o <= '0';
-----------------------------------------------
if gnum_dma_stb_i = '1' and gnum_dma_cyc_i = '1' then
nxt_tstamp_rd_wb_st <= MEM_ACCESS_AND_ACKNOWLEDGE;
else
nxt_tstamp_rd_wb_st <= ACKNOWLEDGE;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when MEM_ACCESS_AND_ACKNOWLEDGE =>
-----------------------------------------------
gnum_dma_ack_o <= '1';
-----------------------------------------------
if gnum_dma_stb_i = '1' and gnum_dma_cyc_i = '1' then
nxt_tstamp_rd_wb_st <= MEM_ACCESS_AND_ACKNOWLEDGE;
else
nxt_tstamp_rd_wb_st <= ACKNOWLEDGE;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when ACKNOWLEDGE =>
-----------------------------------------------
gnum_dma_ack_o <= '1';
-----------------------------------------------
if gnum_dma_stb_i = '1' and gnum_dma_cyc_i = '1' then
nxt_tstamp_rd_wb_st <= MEM_ACCESS;
else
nxt_tstamp_rd_wb_st <= IDLE;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when others =>
-----------------------------------------------
gnum_dma_ack_o <= '0';
-----------------------------------------------
nxt_tstamp_rd_wb_st <= IDLE;
end case;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
gnum_dma_stall_o <= '0';
---------------------------------------------------------------------------------------------------
-- DUAL PORT BLOCK RAM --
---------------------------------------------------------------------------------------------------
memory_block: blk_mem_circ_buff_v6_4
port map(
-- Port A: attached to the data_formatting unit
clka => clk_i,
addra => tstamp_wr_adr_i(7 downto 0), -- 2^8 = 256 addresses
dina => tstamp_wr_dat_i, -- 128-bit long timestamps
ena => tstamp_wr_cyc_i,
wea => tstamp_wr_we,
douta => tstamp_wr_dat_o, -- not used
-- Port B: attached to the GNUM_core unit
clkb => clk_i,
addrb => gnum_dma_adr_i(9 downto 0), -- 2^10 = 1024 addresses
dinb => gnum_dma_dat_i, -- not used
enb => gnum_dma_cyc_i,
web => tstamp_rd_we,
--------------------------------------------------
doutb => gnum_dma_dat_o); -- 32-bit long words
--------------------------------------------------
tstamp_wr_we(0) <= tstamp_wr_we_i;
tstamp_rd_we(0) <= gnum_dma_we_i;
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- clks_rsts_manager |
-- |
---------------------------------------------------------------------------------------------------
-- File clks_rsts_manager.vhd |
-- |
-- Description Independent block that uses the spec_clk_i to parameterize the TDC mezzanine PLL |
-- and DAC that will be used by all the other blocks. |
-- Includes input clk buffers for Xilinx Spartan6. |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Date 05/2012 |
-- Version v0.3 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v0.1 GP First version |
-- 04/2012 v0.2 EG Added DFFs to the pll_sdi_o, pll_cs_o outputs |
-- Changed completely the internal reset generation; now it depends |
-- on the pll_status activation |
-- General revamping, comments added, signals renamed |
-- 05/2012 v0.3 EG Added logic for DAC configuration |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
-- Specific libraries
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
library UNISIM;
use UNISIM.vcomponents.all;
--=================================================================================================
-- Entity declaration for clks_rsts_manager
--=================================================================================================
entity clks_rsts_manager is
generic
(nb_of_reg : integer := 68);
port
-- INPUTS
-- Clock signal from SPEC board
(spec_clk_i : in std_logic; -- 20 MHz OSC on SPEC board
-- Clock signals from the PLL
acam_refclk_p_i : in std_logic; -- 31.25 MHz differential clock generated by the mezzanine PLL, clock of ACAM
acam_refclk_n_i : in std_logic; -- 31.25 MHz differential clock generated by the mezzanine PLL, clock of ACAM
tdc_clk_p_i : in std_logic; -- 125 MHz clock generated by the mezzanine PLL, clock of all other TDC core logic
tdc_clk_n_i : in std_logic;
-- Other signals from the PLL
pll_status_i : in std_logic; -- PLL lock detect
pll_sdo_i : in std_logic; -- not used
-- Signal from the GNUM
rst_n_a_i : in std_logic; -- reset signal from the GNUM interface
-- Signals from the reg_ctrl unit for the reconfiguration of the DAC
send_dac_word_p_i : in std_logic; -- pulse upon PCI-e request for a DAC reconfiguration
dac_word_i : in std_logic_vector(23 downto 0); -- DAC Vout = Vref (dac_word/65536)
-- OUTPUTS
-- Signals to the rest of the modules of the TDC core
tdc_clk_o : out std_logic; -- 125 MHZ clock
internal_rst_o : out std_logic; -- internal reset asserted until the 125 MHZ clock from the PLL is available
-- Signals to the SPI interface for the PLL and DAC
pll_cs_o : out std_logic; -- SPI PLL chip select /!\ negative logic _n to be added
pll_dac_sync_o : out std_logic; -- SPI DAC chip select /!\ negative logic _n to be added
pll_sdi_o : out std_logic; -- SPI data
pll_sclk_o : out std_logic; -- SPI clock
-- Signal to the one_hz_gen and acam_timecontrol_interface units
acam_refclk_o : out std_logic; -- 31.25 MHz reference clock for ACAM chip
acam_refclk_r_edge_p_o : out std_logic; -- pulse upon acam_refclk rising edge
-- Signals to the leds_manager unit
gnum_rst_o : out std_logic; -- GENUM reset synched with 20 MHz clock
spec_clk_o : out std_logic; -- 20 MHz clock
pll_status_o : out std_logic);-- PLL lock detect synched with 20 MHz clock
end clks_rsts_manager;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of clks_rsts_manager is
subtype t_wd is std_logic_vector(15 downto 0);
subtype t_byte is std_logic_vector(7 downto 0);
type t_instr is array (nb_of_reg-1 downto 0) of t_wd;
type t_stream is array (nb_of_reg-1 downto 0) of t_byte;
type t_pll_init_st is (config_start, sending_dac_word, sending_pll_instruction,
sending_pll_data, rest, done);
-- The PLL circuit AD9516-4 needs to be configured through 68 registers.
-- The values and addresses are obtained through the dedicated Analog Devices software & the datasheet.
constant REG_000 : t_byte := x"18";
constant REG_001 : t_byte := x"00";
constant REG_002 : t_byte := x"10";
constant REG_003 : t_byte := x"C3";
constant REG_004 : t_byte := x"00";
constant REG_010 : t_byte := x"7C";
constant REG_011 : t_byte := x"01";
constant REG_012 : t_byte := x"00";
constant REG_013 : t_byte := x"03";
constant REG_014 : t_byte := x"09";
constant REG_015 : t_byte := x"00";
constant REG_016 : t_byte := x"04";
constant REG_017 : t_byte := x"B4"; -- PLL_STATUS
constant REG_018 : t_byte := x"07";
constant REG_019 : t_byte := x"00";
constant REG_01A : t_byte := x"00";
constant REG_01B : t_byte := x"00";
constant REG_01C : t_byte := x"02";
constant REG_01D : t_byte := x"00";
constant REG_01E : t_byte := x"00";
constant REG_01F : t_byte := x"0E";
constant REG_0A0 : t_byte := x"01";
constant REG_0A1 : t_byte := x"00";
constant REG_0A2 : t_byte := x"00";
constant REG_0A3 : t_byte := x"01";
constant REG_0A4 : t_byte := x"00";
constant REG_0A5 : t_byte := x"00";
constant REG_0A6 : t_byte := x"01";
constant REG_0A7 : t_byte := x"00";
constant REG_0A8 : t_byte := x"00";
constant REG_0A9 : t_byte := x"01";
constant REG_0AA : t_byte := x"00";
constant REG_0AB : t_byte := x"00";
constant REG_0F0 : t_byte := x"0A";
constant REG_0F1 : t_byte := x"0A";
constant REG_0F2 : t_byte := x"0A";
constant REG_0F3 : t_byte := x"0A";
constant REG_0F4 : t_byte := x"0A";
constant REG_0F5 : t_byte := x"0A";
constant REG_140 : t_byte := x"42"; -----REF_CLK
constant REG_141 : t_byte := x"5A";
constant REG_142 : t_byte := x"43";
constant REG_143 : t_byte := x"42";
constant REG_190 : t_byte := x"00";
constant REG_191 : t_byte := x"80";
constant REG_192 : t_byte := x"00";
constant REG_193 : t_byte := x"00";
constant REG_194 : t_byte := x"80";
constant REG_195 : t_byte := x"00";
constant REG_196 : t_byte := x"00";
constant REG_197 : t_byte := x"80";
constant REG_198 : t_byte := x"00";
constant REG_199 : t_byte := x"22";
constant REG_19A : t_byte := x"00";
constant REG_19B : t_byte := x"11";
constant REG_19C : t_byte := x"00";
constant REG_19D : t_byte := x"00";
constant REG_19E : t_byte := x"22";
constant REG_19F : t_byte := x"00";
constant REG_1A0 : t_byte := x"11";
constant REG_1A1 : t_byte := x"20";
constant REG_1A2 : t_byte := x"00";
constant REG_1A3 : t_byte := x"00";
constant REG_1E0 : t_byte := x"00";
constant REG_1E1 : t_byte := x"02";
constant REG_230 : t_byte := x"00";
constant REG_231 : t_byte := x"00";
constant REG_232 : t_byte := x"01";
constant SIM_RST : std_logic_vector(31 downto 0):= x"00000400";
constant SYN_RST : std_logic_vector(31 downto 0):= x"00004E20";
-- this value may still need adjustment according to the dispersion
-- in the performance of the PLL observed during the production tests
-- PLL and DAC configuration state machine
signal config_st, nxt_config_st : t_pll_init_st;
signal config_reg : t_stream;
signal addr : t_instr;
signal pll_word_being_sent : t_wd;
signal pll_bit_being_sent, dac_bit_being_sent : std_logic;
signal bit_being_sent, send_dac_word_r_edge_p : std_logic;
signal pll_bit_index : integer range 15 downto 0;
signal dac_bit_index : integer range 23 downto 0;
signal dac_word : std_logic_vector(23 downto 0);
signal pll_byte_index : integer range nb_of_reg-1 downto 0;
signal pll_cs_n, dac_cs_n : std_logic;
-- Synchronizers
signal pll_status_synch, internal_rst_synch, gnum_rst_synch : std_logic_vector (1 downto 0);
signal acam_refclk_synch, send_dac_word_p_synch : std_logic_vector (2 downto 0);
-- Clock buffers
signal spec_clk_buf, tdc_clk_buf, acam_refclk_buf : std_logic;
signal sclk, spec_clk, tdc_clk, acam_refclk : std_logic;
-- Resets
signal rst, internal_rst, gnum_rst : std_logic;
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- Clock buffers instantiations --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
tdc_clk125_ibuf : IBUFDS
generic map
(DIFF_TERM => true, -- Differential Termination
IBUF_LOW_PWR => false, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
IOSTANDARD => "DEFAULT")
port map
(O => tdc_clk_buf, -- Buffer output
I => tdc_clk_p_i, -- Diff_p buffer input (connect directly to top-level port)
IB => tdc_clk_n_i); -- Diff_n buffer input (connect directly to top-level port)
tdc_clk125_gbuf : BUFG
port map
(O => tdc_clk,
I => tdc_clk_buf);
-- -- -- -- -- -- -- --
tdc_clk_o <= tdc_clk;
---------------------------------------------------------------------------------------------------
spec_clk_ibuf : IBUFG
port map
(I => spec_clk_i,
O => spec_clk_buf);
spec_clk_gbuf : BUFG
port map
(O => spec_clk,
I => spec_clk_buf);
-- -- -- -- -- -- -- --
spec_clk_o <= spec_clk;
---------------------------------------------------------------------------------------------------
-- General Internal Reset --
---------------------------------------------------------------------------------------------------
-- The following processes generate a general internal reset signal for all the rest of the core.
-- This internal reset is triggered by the reset signal coming from the GNUM chip. The idea is to
-- keep the internal reset asserted until the clock signal received from the PLL is stable.
---------------------------------------------------------------------------------------------------
-- Synchronous process rst_n_a_i_synchronizer: Synchronization of the rst_n_a_i input to the
-- spec_clk, using a set of 2 registers
rst_n_a_i_synchronizer: process (spec_clk)
begin
if rising_edge (spec_clk) then
gnum_rst_synch <= gnum_rst_synch(0) & not(rst_n_a_i);
end if;
end process;
-- -- -- -- -- -- -- --
gnum_rst <= gnum_rst_synch(1);
gnum_rst_o <= gnum_rst_synch(1);
---------------------------------------------------------------------------------------------------
-- Synchronous process pll_status_synchronizer: Synchronization of the pll_status_i input to the
-- spec_clk, using a set of 2 registers.
pll_status_synchronizer: process (spec_clk)
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' then
pll_status_synch <= (others => '0');
else
pll_status_synch <= pll_status_synch(0) & pll_status_i;
end if;
end if;
end process;
-- -- -- -- -- -- -- --
pll_status_o <= pll_status_synch(1);
---------------------------------------------------------------------------------------------------
-- Synchronous process Internal_rst_generation: Generation of a reset signal for as long as the PLL
-- is not locked. As soon as the pll_status is received the internal reset is released.
-- Note that the level of the pll_status signal rather than its rising edge is used, as in the case of
-- a gnum_rst during operation with the pll already locked the pll_status will remain active and no
-- edge will appear.
Internal_rst_generator: process (spec_clk)
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' then
rst <= '1';
else
if pll_status_synch(1) = '1' then
rst <= '0';
else
rst <= '1';
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Synchronous process internal_rst_synchronizer: Synchronization of the internal_rst signal to the
-- tdc_clk, using a set of 2 registers.
Internal_rst_synchronizer: process (tdc_clk)
begin
if rising_edge (tdc_clk) then
internal_rst_synch <= internal_rst_synch(0) & rst;
end if;
end process;
-- -- -- -- -- -- -- --
internal_rst <= internal_rst_synch(1);
internal_rst_o <= internal_rst;
---------------------------------------------------------------------------------------------------
-- ACAM Reference Clock --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
acam_refclk31M25_ibuf : IBUFDS
generic map
(DIFF_TERM => true, -- Differential Termination
IBUF_LOW_PWR => false, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
IOSTANDARD => "DEFAULT")
port map
(O => acam_refclk,
I => acam_refclk_p_i, -- Diff_p buffer input (connect directly to top-level port)
IB => acam_refclk_n_i);-- Diff_n buffer input (connect directly to top-level port)
--acam_refclk31M25_gbuf : BUFG
--port map
--(O => acam_refclk,
--I => acam_refclk_buf);
---------------------------------------------------------------------------------------------------
acam_refclk_synchronizer: process (tdc_clk)
begin
if rising_edge (tdc_clk) then
if internal_rst_synch(1) = '1' then
acam_refclk_synch <= (others => '0');
else
acam_refclk_synch <= acam_refclk_synch(1 downto 0) & acam_refclk;
end if;
end if;
end process;
-- -- -- -- -- --
acam_refclk_r_edge_p_o <= (not acam_refclk_synch(2)) and acam_refclk_synch(1);
acam_refclk_o <= acam_refclk;
---------------------------------------------------------------------------------------------------
-- DAC configuration --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- Synchronous process send_dac_word_p_synchronizer: Synchronization of the send_dac_word_p_o
-- input to the spec_clk, using a set of 3 registers.
send_dac_word_p_synchronizer: process (spec_clk)
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' then
send_dac_word_p_synch <= (others => '0');
else
send_dac_word_p_synch <= send_dac_word_p_synch(1 downto 0) & send_dac_word_p_i;
end if;
end if;
end process;
-- -- -- -- -- -- -- --
send_dac_word_r_edge_p <= (not send_dac_word_p_synch(2)) and send_dac_word_p_synch(1);
---------------------------------------------------------------------------------------------------
-- Synchronous process pll_dac_word: selection of the word to be sent to the DAC.
-- Upon initialization the default word is being sent; otherwise a word received through the PCI-e
-- interface on the DAC_WORD register.
pll_dac_word: process (spec_clk)
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' then
dac_word <= c_DEFAULT_DAC_WORD;
elsif send_dac_word_r_edge_p = '1' then
dac_word <= dac_word_i;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Processes for configuration of the DAC and PLL --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
pll_dac_initialization_seq: process (spec_clk)
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' or send_dac_word_r_edge_p = '1' then
config_st <= config_start;
else
config_st <= nxt_config_st;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
pll_dac_initialization_comb: process (config_st, dac_bit_index, pll_byte_index, pll_bit_index, sclk)
begin
case config_st is
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when config_start =>
-----------------------------------
pll_cs_n <= '1';
dac_cs_n <= '1';
-----------------------------------
if sclk = '1' then
nxt_config_st <= sending_dac_word;
else
nxt_config_st <= config_start;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when sending_dac_word =>
-----------------------------------
pll_cs_n <= '1';
dac_cs_n <= '0';
-----------------------------------
if dac_bit_index = 0 and sclk = '1' then
nxt_config_st <= sending_pll_instruction;
else
nxt_config_st <= sending_dac_word;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when sending_pll_instruction =>
-----------------------------------
pll_cs_n <= '0';
dac_cs_n <= '1';
-----------------------------------
if pll_bit_index = 0 and sclk = '1' then
nxt_config_st <= sending_pll_data;
else
nxt_config_st <= sending_pll_instruction;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when sending_pll_data =>
-----------------------------------
pll_cs_n <= '0';
dac_cs_n <= '1';
-----------------------------------
if pll_bit_index = 0 and sclk = '1' then
nxt_config_st <= rest;
else
nxt_config_st <= sending_pll_data;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when rest =>
-----------------------------------
pll_cs_n <= '1';
dac_cs_n <= '1';
-----------------------------------
if sclk = '1' then
if pll_byte_index = 0 then
nxt_config_st <= done;
else
nxt_config_st <= sending_pll_instruction;
end if;
else
nxt_config_st <= rest;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when done =>
-----------------------------------
pll_cs_n <= '1';
dac_cs_n <= '1';
-----------------------------------
nxt_config_st <= done;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when others =>
-----------------------------------
pll_cs_n <= '1';
dac_cs_n <= '1';
-----------------------------------
nxt_config_st <= config_start;
end case;
end process;
---------------------------------------------------------------------------------------------------
pll_sclk_generator: process (spec_clk) -- transitions take place on the falling edge of sclk
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' then
sclk <= '0';
else
sclk <= not(sclk);
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
pll_index_control: process (spec_clk)
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' then
pll_bit_index <= 15;
elsif pll_cs_n = '1' then
pll_bit_index <= 15;
elsif sclk = '1' then
if pll_bit_index = 0 then
pll_bit_index <= 7;
else
pll_bit_index <= pll_bit_index -1;
end if;
end if;
if gnum_rst = '1' then
pll_byte_index <= nb_of_reg -1;
elsif config_st = rest and sclk = '1' then
if pll_byte_index = 0 then
pll_byte_index <= nb_of_reg-1;
else
pll_byte_index <= pll_byte_index -1;
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- --
pll_bit_being_sent <= pll_word_being_sent(pll_bit_index);
pll_word_being_sent <= addr(pll_byte_index) when config_st = sending_pll_instruction
else x"00" & config_reg(pll_byte_index);
---------------------------------------------------------------------------------------------------
dac_index_control: process (spec_clk)
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' then
dac_bit_index <= 23;
elsif dac_cs_n = '1' then
dac_bit_index <= 23;
elsif sclk = '1' then
if dac_bit_index = 0 then
dac_bit_index <= 23;
else
dac_bit_index <= dac_bit_index - 1;
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- --
dac_bit_being_sent <= dac_word(dac_bit_index);
bit_being_sent <= dac_bit_being_sent when dac_cs_n = '0' else pll_bit_being_sent;
---------------------------------------------------------------------------------------------------
Output_regs: process (spec_clk)
begin
if rising_edge (spec_clk) then
if gnum_rst = '1' then
pll_cs_o <= '1';
pll_dac_sync_o <= '1';
pll_sdi_o <= '0';
else
if sclk = '1' then
pll_sdi_o <= bit_being_sent;
pll_dac_sync_o <= dac_cs_n;
pll_cs_o <= pll_cs_n;
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- --
pll_sclk_o <= sclk;
---------------------------------------------------------------------------------------------------
-- Assignement of the values to be sent for the configurations of the PLL --
---------------------------------------------------------------------------------------------------
-- According to the datasheet the register 232 should be written last to validate the transfer
-- from the buffer to the valid registers. The 16-bit instruction word indicates always a write
-- cycle of byte.
-- -- -- -- -- -- -- -- -- -- -- -- -- --
addr(0) <= x"0232";
addr(1) <= x"0000";
addr(2) <= x"0001";
addr(3) <= x"0002";
addr(4) <= x"0003";
addr(5) <= x"0004";
--------------------------
addr(6) <= x"0010";
addr(7) <= x"0011";
addr(8) <= x"0012";
addr(9) <= x"0013";
addr(10) <= x"0014";
addr(11) <= x"0015";
addr(12) <= x"0016";
addr(13) <= x"0017";
addr(14) <= x"0018";
addr(15) <= x"0019";
addr(16) <= x"001A";
addr(17) <= x"001B";
addr(18) <= x"001C";
addr(19) <= x"001D";
addr(20) <= x"001E";
addr(21) <= x"001F";
--------------------------
addr(22) <= x"00A0";
addr(23) <= x"00A1";
addr(24) <= x"00A2";
addr(25) <= x"00A3";
addr(26) <= x"00A4";
addr(27) <= x"00A5";
addr(28) <= x"00A6";
addr(29) <= x"00A7";
addr(30) <= x"00A8";
addr(31) <= x"00A9";
addr(32) <= x"00AA";
addr(33) <= x"00AB";
--------------------------
addr(34) <= x"00F0";
addr(35) <= x"00F1";
addr(36) <= x"00F2";
addr(37) <= x"00F3";
addr(38) <= x"00F4";
addr(39) <= x"00F5";
--------------------------
addr(40) <= x"0140";
addr(41) <= x"0141";
addr(42) <= x"0142";
addr(43) <= x"0143";
--------------------------
addr(44) <= x"0190";
addr(45) <= x"0191";
addr(46) <= x"0192";
addr(47) <= x"0193";
addr(48) <= x"0194";
addr(49) <= x"0195";
addr(50) <= x"0196";
addr(51) <= x"0197";
addr(52) <= x"0198";
--------------------------
addr(53) <= x"0199";
addr(54) <= x"019A";
addr(55) <= x"019B";
addr(56) <= x"019C";
addr(57) <= x"019D";
addr(58) <= x"019E";
addr(59) <= x"019F";
--------------------------
addr(60) <= x"01A0";
addr(61) <= x"01A1";
addr(62) <= x"01A2";
addr(63) <= x"01A3";
--------------------------
addr(64) <= x"01E0";
addr(65) <= x"01E1";
--------------------------
addr(66) <= x"0230";
addr(67) <= x"0231";
-- -- -- -- -- -- -- -- -- -- -- -- -- --
config_reg(0) <= REG_232;
config_reg(1) <= REG_000;
config_reg(2) <= REG_001;
config_reg(3) <= REG_002;
config_reg(4) <= REG_003;
config_reg(5) <= REG_004;
--------------------------
config_reg(6) <= REG_010;
config_reg(7) <= REG_011;
config_reg(8) <= REG_012;
config_reg(9) <= REG_013;
config_reg(10) <= REG_014;
config_reg(11) <= REG_015;
config_reg(12) <= REG_016;
config_reg(13) <= REG_017;
config_reg(14) <= REG_018;
config_reg(15) <= REG_019;
config_reg(16) <= REG_01A;
config_reg(17) <= REG_01B;
config_reg(18) <= REG_01C;
config_reg(19) <= REG_01D;
config_reg(20) <= REG_01E;
config_reg(21) <= REG_01F;
--------------------------
config_reg(22) <= REG_0A0;
config_reg(23) <= REG_0A1;
config_reg(24) <= REG_0A2;
config_reg(25) <= REG_0A3;
config_reg(26) <= REG_0A4;
config_reg(27) <= REG_0A5;
config_reg(28) <= REG_0A6;
config_reg(29) <= REG_0A7;
config_reg(30) <= REG_0A8;
config_reg(31) <= REG_0A9;
config_reg(32) <= REG_0AA;
config_reg(33) <= REG_0AB;
--------------------------
config_reg(34) <= REG_0F0;
config_reg(35) <= REG_0F1;
config_reg(36) <= REG_0F2;
config_reg(37) <= REG_0F3;
config_reg(38) <= REG_0F4;
config_reg(39) <= REG_0F5;
--------------------------
config_reg(40) <= REG_140;
config_reg(41) <= REG_141;
config_reg(42) <= REG_142;
config_reg(43) <= REG_143;
--------------------------
config_reg(44) <= REG_190;
config_reg(45) <= REG_191;
config_reg(46) <= REG_192;
config_reg(47) <= REG_193;
config_reg(48) <= REG_194;
config_reg(49) <= REG_195;
config_reg(50) <= REG_196;
config_reg(51) <= REG_197;
config_reg(52) <= REG_198;
--------------------------
config_reg(53) <= REG_199;
config_reg(54) <= REG_19A;
config_reg(55) <= REG_19B;
config_reg(56) <= REG_19C;
config_reg(57) <= REG_19D;
config_reg(58) <= REG_19E;
config_reg(59) <= REG_19F;
--------------------------
config_reg(60) <= REG_1A0;
config_reg(61) <= REG_1A1;
config_reg(62) <= REG_1A2;
config_reg(63) <= REG_1A3;
--------------------------
config_reg(64) <= REG_1E0;
config_reg(65) <= REG_1E1;
--------------------------
config_reg(66) <= REG_230;
config_reg(67) <= REG_231;
-- -- -- -- -- -- -- -- -- -- -- -- -- --
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- data_engine |
-- |
---------------------------------------------------------------------------------------------------
-- File data_engine.vhd |
-- |
-- Description The unit is managing: |
-- o the timestamps' acquisition from the ACAM, |
-- o the writing of the ACAM configuration, |
-- o the reading back of the ACAM configuration. |
-- |
-- The signals: activate_acq, deactivate_acq, |
-- acam_wr_config, acam_rst |
-- acam_rdbk_config, acam_rdbk_status, acam_rdbk_ififo1, |
-- acam_rdbk_ififo2, acam_rdbk_start01 |
-- coming from the reg_ctrl unit determine the actions of this unit. |
-- |
-- o In acquisition mode (activate_acq = 1) the unit monitors permanently the empty |
-- flags (ef1, ef2) of the ACAM iFIFOs, reads timestamps accordingly and then |
-- sends them to the data_formatting unit for them to endup in the circular_buffer|
-- o To configure the ACAM or read back its configuration registers, the unit should|
-- be in inactive mode (deactivate_acq = 1). |
-- |
-- For all types of interactions with the ACAM chip, the unit acts as a WISHBONE |
-- master fetching/ sending data from/ to the ACAM interface. |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 06/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.std_logic_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for data_engine
--=================================================================================================
entity data_engine is
port
-- INPUTS
-- Signals from the clk_rst_manager
(clk_i : in std_logic; -- 125 MHz
rst_i : in std_logic; -- global reset
-- Signals from the reg_ctrl unit
activate_acq_p_i : in std_logic; -- activates tstamps aquisition
deactivate_acq_p_i : in std_logic; -- activates configuration readings/ writings
acam_wr_config_p_i : in std_logic; -- enables writing acam_config_i values to ACAM regs 0-7, 11, 12, 14
acam_rst_p_i : in std_logic; -- enables writing c_RESET_WORD to ACAM reg 4
acam_rdbk_config_p_i : in std_logic; -- enables reading of ACAM regs 0-7, 11, 12, 14
acam_rdbk_status_p_i : in std_logic; -- enables reading of ACAM reg 12
acam_rdbk_ififo1_p_i : in std_logic; -- enables reading of ACAM reg 8
acam_rdbk_ififo2_p_i : in std_logic; -- enables reading of ACAM reg 9
acam_rdbk_start01_p_i: in std_logic; -- enables reading of ACAM reg 10
acam_config_i : in config_vector; -- array keeping values for ACAM regs 0-7, 11, 12, 14
-- as received from the PCIe interface
-- Signals from the acam_databus_interface unit: empty FIFO flags
acam_ef1_i : in std_logic; -- emply fifo 1 (fully synched signal; ef1 after 2 DFFs)
acam_ef1_synch1_i : in std_logic; -- emply fifo 1 (possibly metestable; ef1 after 1 DFF)
acam_ef2_i : in std_logic; -- emply fifo 2 (fully synched signal; ef2 after 2 DFFs)
acam_ef2_synch1_i : in std_logic; -- emply fifo 2 (possibly metestable; ef2 after 1 DFF)
-- Signals from the acam_databus_interface unit: WISHBONE master
acam_ack_i : in std_logic; -- WISHBONE ack
acam_dat_i : in std_logic_vector(31 downto 0); -- tstamps or rdbk regs
-- includes ef1 & ef2 & 0 & 0 & 28 bits acam data_bus_io
-- OUTPUTS
-- Signals to the acam_databus_interface unit: WISHBONE master
acam_adr_o : out std_logic_vector(7 downto 0); -- address of reg/ FIFO to write/ read
acam_cyc_o : out std_logic; -- WISHBONE cycle
acam_stb_o : out std_logic; -- WISHBONE strobe
acam_dat_o : out std_logic_vector(31 downto 0);-- values to write to ACAM regs
acam_we_o : out std_logic; -- WISHBONE write (enabled only for reg writings)
-- Signals to the reg_ctrl unit
acam_config_rdbk_o : out config_vector; -- array keeping values read from ACAM regs 0-7, 11, 12, 14
acam_status_o : out std_logic_vector(31 downto 0);-- keeps value read from ACAM reg 12
acam_ififo1_o : out std_logic_vector(31 downto 0);-- keeps value read from ACAM reg 8
acam_ififo2_o : out std_logic_vector(31 downto 0);-- keeps value read from ACAM reg 9
acam_start01_o : out std_logic_vector(31 downto 0);-- keeps value read from ACAM reg 10
-- Signals to the data_formatting unit:
acam_tstamp1_o : out std_logic_vector(31 downto 0);-- includes ef1 & ef2 & 0 & 0 & 28 bits tstamp from FIFO1
acam_tstamp2_o : out std_logic_vector(31 downto 0);-- includes ef1 & ef2 & 0 & 0 & 28 bits tstamp from FIFO2
acam_tstamp1_ok_p_o : out std_logic; -- indication of a valid tstamp1
acam_tstamp2_ok_p_o : out std_logic);-- indication of a valid tstamp2
end data_engine;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of data_engine is
type engine_state_ty is (ACTIVE, INACTIVE, GET_STAMP1, GET_STAMP2, WR_CONFIG, RDBK_CONFIG,
RD_STATUS, RD_IFIFO1, RD_IFIFO2, RD_START01, WR_RESET);
signal engine_st, nxt_engine_st : engine_state_ty;
signal acam_cyc, acam_stb, acam_we : std_logic;
signal acam_adr : std_logic_vector(7 downto 0);
signal config_adr_c : unsigned(7 downto 0);
signal acam_config_rdbk : config_vector;
signal reset_word : std_logic_vector(31 downto 0);
signal acam_config_reg4 : std_logic_vector(31 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- FSM --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- data_engine_fsm_seq FSM: the state machine is divided in three parts (a clocked process
-- to store the current state, a combinatorial process to manage state transitions and finally a
-- combinatorial process to manage the output signals), which are the three processes that follow.
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Synchronous process: storage of the current state of the FSM
data_engine_fsm_seq: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
engine_st <= INACTIVE;
else
engine_st <= nxt_engine_st;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Combinatorial process
data_engine_fsm_comb: process (engine_st, activate_acq_p_i, deactivate_acq_p_i, acam_ef1_i, acam_adr,
acam_ef2_i, acam_ef1_synch1_i, acam_ef2_synch1_i, acam_wr_config_p_i,
acam_rdbk_config_p_i, acam_rdbk_status_p_i, acam_ack_i, acam_rst_p_i,
acam_rdbk_ififo1_p_i, acam_rdbk_ififo2_p_i, acam_rdbk_start01_p_i)
begin
case engine_st is
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- from the INACTIVE state modifications/ readings of the ACAM configuration can be initiated
-- all interactions refer to transfers from the ACAM, locally and vice versa; the transfering
-- from/ to the PCIe needs....
when INACTIVE =>
-----------------------------------------------
acam_cyc <= '0';
acam_stb <= '0';
acam_we <= '0';
-----------------------------------------------
if activate_acq_p_i = '1' then -- activation of timestamps aquisition
nxt_engine_st <= ACTIVE;
elsif acam_wr_config_p_i = '1' then
nxt_engine_st <= WR_CONFIG; -- loading of ACAM config (local-> ACAM)
elsif acam_rdbk_config_p_i = '1' then
nxt_engine_st <= RDBK_CONFIG;-- readback of ACAM config (ACAM->local acam_config_rdbk( downto ))
elsif acam_rdbk_status_p_i = '1' then
nxt_engine_st <= RD_STATUS; -- reading of ACAM status reg (ACAM->local acam_config_rdbk(9))
elsif acam_rdbk_ififo1_p_i = '1' then
nxt_engine_st <= RD_IFIFO1; -- reading of ACAM last iFIFO1 timestamp (ACAM->local acam_ififo1)
-- this option is available for debugging purposes only
elsif acam_rdbk_ififo2_p_i = '1' then
nxt_engine_st <= RD_IFIFO2; -- reading of ACAM last iFIFO2 timestamp (ACAM->local acam_ififo2)
-- this option is available for debugging purposes only
elsif acam_rdbk_start01_p_i = '1' then
nxt_engine_st <= RD_START01; -- reading of ACAM Start01 reg (ACAM->local acam_start01)
-- this option is available for debugging purposes only
elsif acam_rst_p_i = '1' then
nxt_engine_st <= WR_RESET; -- loading of ACAM config reg 4 with rst word (local reset_word ->ACAM DAT_o)
else
nxt_engine_st <= INACTIVE;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- ACTIVE, GET_STAMP1, GET_STAMP2: intensive acquisition of timestamps from ACAM.
-- ACAM can receive and tag pulses with an overall rate up to 31.25 MHz;
-- therefore locally, running with a 125 MHz clk, in order to be able to receive timestamps
-- as fast as they arrive, it is needed to use up to 4 clk cycles to retreive each of them.
-- Timestamps are received as soon as the ef1, ef2 flags are at zero (indicating that the
-- iFIFOs are not empty!). In order to avoid metastabilities locally, the ef signals are
-- synchronized using a set of two registers.
-- _______ ___________________________________________________
-- | | ____ ____
-- |_____ef____|______| |___ef_synch1___| |_____ef_synch2
-- ACAM | | |DFF1| |DFF2|
-- | | |\ | |\ |
-- | | |/___| |/___|
-- _______| |___________________________________________________
--
-- In the beginning the output of the second synchronizer flip-flop (ef_synch2) is used,
-- as falling edges in the ef signals can arrive randomly at any moment and metastabilities
-- could occur in the first flip-flop. On the other hand, after this first falling edge, the
-- output ef_synch1 of the first flip-flop could be used since ef rising edges are not
-- random any more and depend on the rdn signal generated locally by the
-- acam_databus_interface unit. Following ACAM documentation (pg 7, Figure 2) 2 clk cycles
-- = 16 ns after an rdn falling edge the ef_synch1 should be stable.
--
-- Using the ef_synch1 signal instead of the ef_synch2 makes it possible to realise
-- timestamps' aquisitions from ACAM in just 4 clk cycles.
-- clk --|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__|--|__
-- ef ------|_______________________________________________________|--------------
-- ef_synch1 -----------|_____________________________________________________|-----------
-- ef_synch2 -----------------|_____________________________________________________|-----
-- stb _______________________|-----------------------------------------------|_____
-- adr _______________________| iFIFO adr set
-- rdn -----------------------------|_________________|-----|_______________________
-- data valid ^ ^
-- ack _________________________________________|-----|_________________|-----|_____
-- data retrieval ^ ^
-- ef check ^
-- It is first checked if iFIFO1 is not empty, and if so a timestamp is retreived from it.
-- Then iFIFO2 is checked and if it is not empty a timestamp is retreived from it.
-- The alternation between the two FIFOs takes place until they are both empty.
-- The retreival of a timestamp from any of the FIFOs takes place
when ACTIVE =>
-----------------------------------------------
acam_cyc <= '0';
acam_stb <= '0';
acam_we <= '0';
-----------------------------------------------
if deactivate_acq_p_i = '1' then
nxt_engine_st <= INACTIVE;
elsif acam_ef1_i = '0' then -- new tstamp in iFIFO1
nxt_engine_st <= GET_STAMP1;
elsif acam_ef2_i = '0' then -- new tstamp in iFIFO2
nxt_engine_st <= GET_STAMP2;
else
nxt_engine_st <= ACTIVE;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when GET_STAMP1 =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '0';
-----------------------------------------------
if acam_ack_i ='1' then
if acam_ef2_i = '0' then
nxt_engine_st <= GET_STAMP2;
elsif acam_ef1_synch1_i ='0' then
nxt_engine_st <= GET_STAMP1;
else
nxt_engine_st <= ACTIVE;
end if;
else
nxt_engine_st <= GET_STAMP1;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when GET_STAMP2 =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '0';
-----------------------------------------------
if acam_ack_i ='1' then -- idem.
if acam_ef1_i ='0' then
nxt_engine_st <= GET_STAMP1;
elsif acam_ef2_synch1_i ='0' then
nxt_engine_st <= GET_STAMP2;
else
nxt_engine_st <= ACTIVE;
end if;
else
nxt_engine_st <= GET_STAMP2;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when WR_CONFIG =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '1';
-----------------------------------------------
if acam_ack_i = '1' and acam_adr = x"0E" then -- last address
nxt_engine_st <= INACTIVE;
else
nxt_engine_st <= WR_CONFIG;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RDBK_CONFIG =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '0';
-----------------------------------------------
if acam_ack_i = '1' and acam_adr = x"0E" then -- last address
nxt_engine_st <= INACTIVE;
else
nxt_engine_st <= RDBK_CONFIG;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_STATUS =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '0';
-----------------------------------------------
if acam_ack_i ='1' then
nxt_engine_st <= INACTIVE;
else
nxt_engine_st <= RD_STATUS;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_IFIFO1 =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '0';
-----------------------------------------------
if acam_ack_i ='1' then
nxt_engine_st <= INACTIVE;
else
nxt_engine_st <= RD_IFIFO1;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_IFIFO2 =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '0';
-----------------------------------------------
if acam_ack_i ='1' then
nxt_engine_st <= INACTIVE;
else
nxt_engine_st <= RD_IFIFO2;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RD_START01 =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '0';
-----------------------------------------------
if acam_ack_i ='1' then
nxt_engine_st <= INACTIVE;
else
nxt_engine_st <= RD_START01;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when WR_RESET =>
-----------------------------------------------
acam_cyc <= '1';
acam_stb <= '1';
acam_we <= '1';
-----------------------------------------------
if acam_ack_i ='1' then
nxt_engine_st <= INACTIVE;
else
nxt_engine_st <= WR_RESET;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when others =>
-----------------------------------------------
acam_cyc <= '0';
acam_stb <= '0';
acam_we <= '0';
-----------------------------------------------
nxt_engine_st <= INACTIVE;
end case;
end process;
acam_cyc_o <= acam_cyc;
acam_stb_o <= acam_stb;
acam_we_o <= acam_we;
---------------------------------------------------------------------------------------------------
-- Address generation (acam_adr_o) for ACAM readings/ writings --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- adr_generation: according to the state of the FSM this process generates the acam_adr_o output
-- that specifies the ACAM register or FIFO to write to or to read from.
adr_generation: process (engine_st, config_adr_c)
begin
case engine_st is
when INACTIVE =>
acam_adr <= x"00";
when ACTIVE =>
acam_adr <= x"00";
when GET_STAMP1 =>
acam_adr <= std_logic_vector(c_ACAM_REG8_ADR); -- FIFO1: ACAM reg 8
when GET_STAMP2 =>
acam_adr <= std_logic_vector(c_ACAM_REG9_ADR); -- FIFO2: ACAM reg 9
when WR_CONFIG =>
acam_adr <= std_logic_vector(config_adr_c); -- sweeps through ACAM reg 0-7, 11, 12, 14
when RDBK_CONFIG=>
acam_adr <= std_logic_vector(config_adr_c); -- sweeps through ACAM reg 0-7, 11, 12, 14
when RD_STATUS =>
acam_adr <= std_logic_vector(c_ACAM_REG12_ADR); -- status: ACAM reg 12
when RD_IFIFO1 =>
acam_adr <= std_logic_vector(c_ACAM_REG8_ADR); -- FIFO1: ACAM reg 8
when RD_IFIFO2 =>
acam_adr <= std_logic_vector(c_ACAM_REG9_ADR); -- FIFO2: ACAM reg 9
when RD_START01 =>
acam_adr <= std_logic_vector(c_ACAM_REG10_ADR); -- START01: ACAM reg 10
when WR_RESET =>
acam_adr <= std_logic_vector(c_ACAM_REG4_ADR); -- reset: ACAM reg 4
when others =>
acam_adr <= x"00";
end case;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- --
acam_adr_o <= acam_adr; -- x"000000" & acam_adr; --reduce size!!
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- config_adr_c: counter used for the sweeping though the ACAM configuration addresses.
-- counter counting: 0-> 1-> 2-> 3-> 4-> 5-> 6-> 7-> 11-> 12-> 14
config_adr_counter: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' or acam_wr_config_p_i = '1' or acam_rdbk_config_p_i = '1' then
config_adr_c <= unsigned (c_ACAM_REG0_ADR);
elsif acam_ack_i ='1' then
if config_adr_c = unsigned (c_ACAM_REG14_ADR) then
config_adr_c <= unsigned (c_ACAM_REG14_ADR);
elsif config_adr_c = unsigned (c_ACAM_REG12_ADR) then
config_adr_c <= unsigned (c_ACAM_REG14_ADR);
elsif config_adr_c = unsigned (c_ACAM_REG7_ADR) then
config_adr_c <= unsigned (c_ACAM_REG11_ADR);
else
config_adr_c <= config_adr_c + 1;
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Values (acam_dat_o) for ACAM config writings --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- data_config_decoder: according to the acam_adr this process generates the acam_dat_o output
-- with the new value to be loaded to the corresponding ACAM reg. The values come from the
-- acam_config_i vector that keeps what has been loaded from the PCIe interface.
data_config_decoder: process(acam_adr, engine_st, acam_config_i, reset_word)
begin
case acam_adr is
when c_ACAM_REG0_ADR =>
acam_dat_o <= acam_config_i(0);
when c_ACAM_REG1_ADR =>
acam_dat_o <= acam_config_i(1);
when c_ACAM_REG2_ADR =>
acam_dat_o <= acam_config_i(2);
when c_ACAM_REG3_ADR =>
acam_dat_o <= acam_config_i(3);
when c_ACAM_REG4_ADR => -- in reg 4 there are bits (0-21, 24-27) defining normal config settings
-- and there are also bits (22&23) initiating ACAM resets
if engine_st = WR_RESET then
acam_dat_o <= reset_word;
else
acam_dat_o <= acam_config_i(4);
end if;
when c_ACAM_REG5_ADR =>
acam_dat_o <= acam_config_i(5);
when c_ACAM_REG6_ADR =>
acam_dat_o <= acam_config_i(6);
when c_ACAM_REG7_ADR =>
acam_dat_o <= acam_config_i(7);
when c_ACAM_REG11_ADR =>
acam_dat_o <= acam_config_i(8);
when c_ACAM_REG12_ADR =>
acam_dat_o <= acam_config_i(9);
when c_ACAM_REG14_ADR =>
acam_dat_o <= acam_config_i(10);
when others =>
acam_dat_o <= (others =>'0');
end case;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
acam_config_reg4 <= acam_config_i(4);
reset_word <= acam_config_reg4(31 downto 24) & "01" & acam_config_reg4(21 downto 0);
-- reg 4 bit 22: MasterReset :'1' = general reset excluding config regs
-- reg 4 bit 23: PartialReset: would initiate a general reset excluding
-- config regs&FIFOs, but this option is not used
---------------------------------------------------------------------------------------------------
-- Aquisition of ACAM Timestamps or Reedback Registers --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- data_readback_decoder: after reading accesses to the ACAM (acam_we=0), the process recuperates
-- the ACAM data and according to the acam_adr_o stores them to the corresponding registers.
-- In the case of timestamps aquisition, we generate the pulses acam_tstamp1_ok_p_o,
-- acam_tstamp2_ok_p_o that when active, indicate a valid timestamp. Note that for timing reasons
-- the signals acam_tstamp1_o, acam_tstamp2_o are not the outputs of flip-flops.
data_readback_decoder: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
acam_config_rdbk(0) <= (others => '0');
acam_config_rdbk(1) <= (others => '0');
acam_config_rdbk(2) <= (others => '0');
acam_config_rdbk(3) <= (others => '0');
acam_config_rdbk(4) <= (others => '0');
acam_config_rdbk(5) <= (others => '0');
acam_config_rdbk(6) <= (others => '0');
acam_config_rdbk(7) <= (others => '0');
acam_config_rdbk(8) <= (others => '0');
acam_config_rdbk(9) <= (others => '0');
acam_config_rdbk(10) <= (others => '0');
acam_ififo1_o <= (others => '0');
acam_ififo2_o <= (others => '0');
acam_start01_o <= (others => '0');
elsif acam_cyc = '1' and acam_stb = '1' and acam_ack_i = '1' and acam_we = '0' then
if acam_adr = c_ACAM_REG0_ADR then
acam_config_rdbk(0) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG1_ADR then
acam_config_rdbk(1) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG2_ADR then
acam_config_rdbk(2) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG3_ADR then
acam_config_rdbk(3) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG4_ADR then
acam_config_rdbk(4) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG5_ADR then
acam_config_rdbk(5) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG6_ADR then
acam_config_rdbk(6) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG7_ADR then
acam_config_rdbk(7) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG11_ADR then
acam_config_rdbk(8) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG12_ADR then
acam_config_rdbk(9) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG14_ADR then
acam_config_rdbk(10) <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG8_ADR then
acam_ififo1_o <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG9_ADR then
acam_ififo2_o <= acam_dat_i;
end if;
if acam_adr = c_ACAM_REG10_ADR then
acam_start01_o <= acam_dat_i;
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
acam_tstamp1_o <= acam_dat_i;
acam_tstamp1_ok_p_o <= '1' when (acam_ack_i ='1' and engine_st = GET_STAMP1) else '0';
acam_tstamp2_o <= acam_dat_i;
acam_tstamp2_ok_p_o <= '1' when (acam_ack_i ='1' and engine_st = GET_STAMP2) else '0';
acam_config_rdbk_o <= acam_config_rdbk;
acam_status_o <= acam_config_rdbk(9);
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- data_formatting |
-- |
---------------------------------------------------------------------------------------------------
-- File data_formatting.vhd |
-- |
-- Description timestamp data formatting. |
-- formats the timestamp coming from the acam plus the coarse timing |
-- plus the UTC time and writes it to the circular buffer |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 07/2013 |
-- Version v2 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- 04/2013 v1 EG Fixed bug when timestamop comes on the first retrigger after a new |
-- second; fixed bug on rollover that is a bit delayed wrt Acam IrFlag |
-- 07/2013 v2 EG Cleaner writing with adition of intermediate DFF on the acam_tstamp |
-- calculations |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for data_formatting
--=================================================================================================
entity data_formatting is
port
-- INPUTS
-- Signal from the clk_rst_manager
(clk_i : in std_logic; -- 125 MHz clk
rst_i : in std_logic; -- general reset
-- Signals from the circular_buffer unit: WISHBONE classic
tstamp_wr_wb_ack_i : in std_logic; -- tstamp writing WISHBONE acknowledge
tstamp_wr_dat_i : in std_logic_vector(127 downto 0); -- not used
-- Signals from the data_engine unit
acam_tstamp1_ok_p_i : in std_logic; -- tstamp1 valid indicator
acam_tstamp1_i : in std_logic_vector(31 downto 0); -- 32 bits tstamp to be treated and stored;
-- includes ef1 & ef2 & 0 & 0 & 28 bits tstamp from FIFO1
acam_tstamp2_ok_p_i : in std_logic; -- tstamp2 valid indicator
acam_tstamp2_i : in std_logic_vector(31 downto 0); -- 32 bits tstamp to be treated and stored;
-- includes ef1 & ef2 & 0 & 0 & 28 bits tstamp from FIFO2
-- Signals from the reg_ctrl unit
dacapo_c_rst_p_i : in std_logic; -- instruction from PCIe to clear dacapo flag
-- Signals from the one_hz_gen unit
local_utc_i : in std_logic_vector(31 downto 0); -- local UTC time
-- Signals from the start_retrig_ctrl unit
roll_over_incr_recent_i : in std_logic;
clk_i_cycles_offset_i : in std_logic_vector(31 downto 0);
roll_over_nb_i : in std_logic_vector(31 downto 0);
retrig_nb_offset_i : in std_logic_vector(31 downto 0);
-- Signal from the one_hz_generator unit
one_hz_p_i : in std_logic;
-- OUTPUTS
-- Signals to the circular_buffer unit: WISHBONE classic
tstamp_wr_wb_cyc_o : out std_logic; -- tstamp writing WISHBONE cycle
tstamp_wr_wb_stb_o : out std_logic; -- tstamp writing WISHBONE strobe
tstamp_wr_wb_we_o : out std_logic; -- tstamp writing WISHBONE write enable
tstamp_wr_wb_adr_o : out std_logic_vector(7 downto 0); -- WISHBONE adr to write to
tstamp_wr_dat_o : out std_logic_vector(127 downto 0); -- tstamp to write
-- Signal to the irq_generator unit
tstamp_wr_p_o : out std_logic; -- pulse upon storage of a new tstamp
-- Signal to the reg_ctrl unit
wr_index_o : out std_logic_vector(31 downto 0)); -- index of last byte written
-- note that the index is provided
-- #bytes, as the PCIe expects
-- (not in #128-bits-words)
end data_formatting;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of data_formatting is
constant c_MULTIPLY_BY_SIXTEEN : std_logic_vector(3 downto 0) := x"0";
-- ACAM timestamp fields
signal acam_channel : std_logic_vector(2 downto 0);
signal acam_slope, acam_fifo_ef : std_logic;
signal acam_fine_timestamp : std_logic_vector(16 downto 0);
signal acam_start_nb : std_logic_vector(7 downto 0);
-- timestamp manipulations
signal un_acam_start_nb, un_clk_i_cycles_offset : unsigned(31 downto 0);
signal un_roll_over, un_nb_of_retrig, un_retrig_nb_offset : unsigned(31 downto 0);
signal un_nb_of_cycles, un_retrig_from_roll_over : unsigned(31 downto 0);
signal acam_start_nb_32 : std_logic_vector(31 downto 0);
-- final timestamp fields
signal full_timestamp : std_logic_vector(127 downto 0);
signal metadata, local_utc, coarse_time, fine_time : std_logic_vector(31 downto 0);
-- circular buffer timestamp writings WISHBONE interface
signal tstamp_wr_cyc, tstamp_wr_stb, tstamp_wr_we : std_logic;
-- circular buffer counters
signal dacapo_counter : unsigned(19 downto 0);
signal wr_index : unsigned(7 downto 0);
-- coarse time calculations
signal belongs_to_previous_sec, tstamp_on_first_retrig_case1: std_logic;
signal tstamp_on_first_retrig_case2 : std_logic;
signal un_previous_clk_i_cycles_offset : unsigned(31 downto 0);
signal un_previous_retrig_nb_offset : unsigned(31 downto 0);
signal un_previous_roll_over_nb : unsigned(31 downto 0);
signal un_current_clk_i_cycles_offset : unsigned(31 downto 0);
signal un_current_retrig_nb_offset, un_current_roll_over_nb : unsigned(31 downto 0);
signal un_current_retrig_from_roll_over : unsigned(31 downto 0);
signal un_acam_fine_time :unsigned(31 downto 0);
signal previous_utc : std_logic_vector(31 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- WISHBONE STB, CYC, WE, ADR --
---------------------------------------------------------------------------------------------------
-- WISHBONE_master_signals: Generation of the WISHBONE classic signals STB, CYC, WE that initiate
-- writes to the circular_buffer memory. Upon acam_tstamp1_ok_p_i or acam_tstamp2_ok_p_i activation
-- the process activates the STB, CYC, WE signals and waits for an ACK; as soon as the ACK arrives
-- (and the tstamps are written in the memory) STB, CYC and WE are deactivated and a new
-- acam_tstamp1_ok_p_i or acam_tstamp2_ok_p_i pulse is awaited to initiate a new write cycle.
-- Reminder: timestamps (acam_tstamp1_ok_p_i or acam_tstamp2_ok_p_i pulses) can arrive at maximum
-- every 4 clk_i cycles (31.25 MHz).
-- clk_i : __|-|__|-|__|-|__|-|__|-|__|-|__|-|__|-|__|-|__|-|__|-|__ ...
-- acam_tstamp1_ok_p : ____________|----|______________|----|___________________ ...
-- tstamp_wr_wb_dat : _________________< one tstamp >< another tstamp > ...
-- tstamp_wr_wb_adr : address 0 >< address 1 >< address 2...
-- tstamp_wr_stb : _________________|--------|_________|---------|__________ ...
-- tstamp_wr_ack : ______________________|---|______________|----|__________ ...
WISHBONE_master_signals: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
tstamp_wr_stb <= '0';
tstamp_wr_cyc <= '0';
tstamp_wr_we <= '0';
elsif acam_tstamp1_ok_p_i ='1' or acam_tstamp2_ok_p_i ='1' then
tstamp_wr_stb <= '1';
tstamp_wr_cyc <= '1';
tstamp_wr_we <= '1';
elsif tstamp_wr_wb_ack_i = '1' then
tstamp_wr_stb <= '0';
tstamp_wr_cyc <= '0';
tstamp_wr_we <= '0';
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- tstamp_wr_wb_adr: the process keeps track of the place in the memory the next timestamp is to be
-- written; wr_index indicates which one is the next address to write to.
-- The index is also used by the PCIe host to configure the DMA coherently (DMALENR register)
tstamp_wr_wb_adr: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
wr_index <= (others => '0');
elsif tstamp_wr_cyc = '1' and tstamp_wr_stb = '1' and tstamp_wr_we = '1' and tstamp_wr_wb_ack_i = '1' then
if wr_index = c_CIRCULAR_BUFF_SIZE - 1 then
wr_index <= (others => '0'); -- when memory completed, restart from the beginning
else
wr_index <= wr_index + 1; -- otherwise write to the next one
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
tstamp_wr_p_o <= tstamp_wr_cyc and tstamp_wr_stb and tstamp_wr_we and tstamp_wr_wb_ack_i;
tstamp_wr_wb_adr_o <= std_logic_vector(wr_index);
wr_index_o <= std_logic_vector(dacapo_counter) & std_logic_vector(wr_index) & c_MULTIPLY_BY_SIXTEEN;
-- "& c_MULTIPLY_BY_SIXTEEN" for the convertion to the number of 8-bits-words
-- for the configuration of the DMA
---------------------------------------------------------------------------------------------------
-- Da Capo flag --
---------------------------------------------------------------------------------------------------
-- dacapo_counter_update: the Da Capo counter indicates the number of times the circular buffer
-- has been written completely; it can be cleared by the PCIe host.
dacapo_counter_update: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' or dacapo_c_rst_p_i = '1' then
dacapo_counter <= (others => '0');
elsif tstamp_wr_cyc = '1' and tstamp_wr_stb = '1' and tstamp_wr_we = '1' and
tstamp_wr_wb_ack_i = '1' and wr_index = c_CIRCULAR_BUFF_SIZE - 1 then
dacapo_counter <= dacapo_counter + 1;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Final Timestamp Formatting --
---------------------------------------------------------------------------------------------------
-- tstamp_formatting: slicing of the 32-bits word acam_tstamp1_i and acam_tstamp2_i as received
-- from the data_engine unit, to construct the final timestamps to be stored in the circular_buffer
-- acam_tstamp1_i, acam_tstamp2_i have the following structure:
-- [16:0] Stop-Start \
-- [17] Slope \ ACAM 28 bits word
-- [25:18] Start number /
-- [27:26] Channel Code /
-- [28] 0 \
-- [29] 0 \ empty and load flags (added by the acam_databus_interface unit)
-- [30] ef2 /
-- [31] ef1 /
-- The final timestamp written in the circular_buffer is a 128-bits word divided in four
-- 32-bits words with the following structure:
-- [31:0] Fine time to be added to the Coarse time: "00..00" & 16 bit Stop-Start;
-- each bit represents 81.03 ps
-- [63:32] Coarse time within the current second, caclulated from the: Start number,
-- clk_i_cycles_offset_i, retrig_nb_offset_i, roll_over_nb_i
-- each bit represents 8 ns
-- [95:64] Local UTC time coming from the one_hz_generator;
-- each bit represents 1s
-- [127:96] Metadata for each timestamp: "00..00" & 0 & ef & Slope & Channel
tstamp_formatting: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
acam_channel <= (others => '0');
acam_fifo_ef <= '0';
acam_fine_timestamp <= (others => '0');
acam_slope <= '0';
acam_start_nb <= (others => '0');
elsif acam_tstamp1_ok_p_i = '1' then
acam_channel <= "0" & acam_tstamp1_i(27 downto 26);
acam_fifo_ef <= acam_tstamp1_i(31);
acam_fine_timestamp <= acam_tstamp1_i(16 downto 0);
acam_slope <= acam_tstamp1_i(17);
acam_start_nb <= acam_tstamp1_i(25 downto 18);
elsif acam_tstamp2_ok_p_i ='1' then
acam_channel <= "1" & acam_tstamp2_i(27 downto 26);
acam_fifo_ef <= acam_tstamp2_i(30);
acam_fine_timestamp <= acam_tstamp2_i(16 downto 0);
acam_slope <= acam_tstamp2_i(17);
acam_start_nb <= acam_tstamp2_i(25 downto 18);
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
reg_info_of_previous_sec: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
un_previous_clk_i_cycles_offset <= (others => '0');
un_previous_retrig_nb_offset <= (others => '0');
un_previous_roll_over_nb <= (others => '0');
previous_utc <= (others => '0');
elsif one_hz_p_i = '1' then
un_previous_clk_i_cycles_offset <= unsigned(clk_i_cycles_offset_i);
un_previous_retrig_nb_offset <= unsigned(retrig_nb_offset_i);
un_previous_roll_over_nb <= unsigned(roll_over_nb_i);
previous_utc <= local_utc_i;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- all the values needed for the calculations have to be converted to unsigned
un_acam_fine_time <= unsigned(fine_time);
acam_start_nb_32 <= x"000000" & acam_start_nb;
un_acam_start_nb <= unsigned(acam_start_nb_32);
un_current_clk_i_cycles_offset <= unsigned(clk_i_cycles_offset_i);
un_current_retrig_nb_offset <= unsigned(retrig_nb_offset_i);
un_current_roll_over_nb <= unsigned(roll_over_nb_i);
un_current_retrig_from_roll_over <= shift_left(un_current_roll_over_nb-1, 8) when roll_over_incr_recent_i = '1' and un_acam_start_nb > 192
else shift_left(un_current_roll_over_nb, 8);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
full_timestamp(31 downto 0) <= fine_time;
full_timestamp(63 downto 32) <= coarse_time;
full_timestamp(95 downto 64) <= local_utc;
full_timestamp(127 downto 96) <= metadata;
tstamp_wr_dat_o <= full_timestamp;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- The following process makes essential calculations for the definition of the coarse time.
-- Regarding the signals: un_clk_i_cycles_offset, un_retrig_nb_offset, local_utc it has to be difined
-- if the values that characterize the current second or the one previous to it should be used.
-- In the case where: a timestamp came on the same retgigger after a new second
-- (un_current_retrig_from_roll_over is 0 and un_acam_start_nb = un_current_retrig_nb_offset)
-- the values of the previous second should be used.
-- Also, according to the ACAM documentation there is an indeterminacy to whether the fine time refers
-- to the previous retrigger or the current one. The equation described on line 386 describes
-- the case where: a timestamp came on the same retgigger after a new second but the ACAM assigned
-- it to the previous retrigger (the "un_current_retrig_from_roll_over = 0" describes that a new second
-- has arrived; the "un_acam_fine_time > 6318" desribes a fine time that is referred to the previous retrigger;
-- 6318 * 81ps = 512ns which is a complete ACAM retrigger).
-- Regarding the un_retrig_from_roll_over, i.e. number of roll-overs of the ACAM-internal-start-retrigger-counter,
-- it has to be converted to a number of internal start retriggers, multiplying by 256 i.e. shifting left!
-- Note that if a new tstamp has arrived from the ACAM when the roll_over has just been increased, there are chances
-- the tstamp belongs to the previous roll-over value. This is because the moment the IrFlag is taken into account
-- in the FPGA is different from the moment the tstamp has arrived to the ACAM (several clk_i cycles to empty ACAM FIFOs).
-- So if in a timestamp the start_nb from the ACAM is close to the upper end (close to 255) and on the moment the timestamp
-- is being treated in the FPGA the IrFlag has recently been tripped it means that for the formatting of the tstamp the
-- previous value of the roll_over_c should be considered (before the IrFlag tripping).
-- Eva: have to calculate better the amount of tstamps that could have been accumulated before the rollover changes;
-- the current value we put "192" is not well studied for all cases!!
coarse_time_intermed_calcul: process (clk_i) -- ACAM data handling DFF #3; at the next cycle (#4) the data is written in memory
begin
if rising_edge (clk_i) then
if rst_i ='1' then
un_clk_i_cycles_offset <= (others => '0');
un_retrig_nb_offset <= (others => '0');
un_retrig_from_roll_over <= (others => '0');
local_utc <= (others => '0');
else
-- ACAM tstamp arrived on the same retgigger after a new second
if (un_acam_start_nb+un_current_retrig_from_roll_over = un_current_retrig_nb_offset) or
(un_acam_start_nb = un_current_retrig_nb_offset-1 and un_acam_fine_time > 6318 and (un_current_retrig_from_roll_over = 0) ) then
un_clk_i_cycles_offset <= un_previous_clk_i_cycles_offset;
un_retrig_nb_offset <= un_previous_retrig_nb_offset;
local_utc <= previous_utc;
-- ACAM tstamp arrived when roll_over has just increased
if roll_over_incr_recent_i = '1' and un_acam_start_nb > 192 then
un_retrig_from_roll_over <= shift_left(un_previous_roll_over_nb-1, 8);
else
un_retrig_from_roll_over <= shift_left(un_previous_roll_over_nb, 8);
end if;
else
un_clk_i_cycles_offset <= unsigned(clk_i_cycles_offset_i);
un_retrig_nb_offset <= unsigned(retrig_nb_offset_i);
local_utc <= local_utc_i;
if roll_over_incr_recent_i = '1' and un_acam_start_nb > 192 then
un_retrig_from_roll_over <= shift_left(unsigned(roll_over_nb_i)-1, 8);
else
un_retrig_from_roll_over <= shift_left(unsigned(roll_over_nb_i), 8);
end if;
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- fine time: directly provided by ACAM as a number of BINs since the last internal retrigger
fine_time <= x"000" & "000" & acam_fine_timestamp;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- local UTC: updated every second by the one_hz_pulse unit
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- coarse time: expressed as the number of 125 MHz clock cycles since the last one_hz_pulse.
-- Since the clk_i and the pulse are derived from the same PLL, any offset between them is constant
-- and will cancel when substracting timestamps.
coarse_time <= std_logic_vector(un_nb_of_cycles);
-- the number of internal start retriggers actually occurred is calculated by subtracting the offset number
-- already present when the one_hz_pulse arrives, and adding the start nb provided by the ACAM.
un_nb_of_retrig <= un_retrig_from_roll_over - un_retrig_nb_offset + un_acam_start_nb;
-- finally, the coarse time is obtained by multiplying by the number of clk_i cycles in an internal
-- start retrigger period and adding the number of clk_i cycles still to be discounted when the
-- one_hz_pulse arrives.
un_nb_of_cycles <= shift_left(un_nb_of_retrig-1, c_ACAM_RETRIG_PERIOD_SHIFT) + un_clk_i_cycles_offset;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- metadata: information about the timestamp
metadata <= acam_start_nb & retrig_nb_offset_i(15 downto 0) & -- for debugging (24 MSbits)
belongs_to_previous_sec & roll_over_incr_recent_i & "0" & -- for debugging (3 bits)
acam_slope & "0" & acam_channel; -- 5 LSbits
---------------------------------------------------------------------------------------------------
-- Outputs --
---------------------------------------------------------------------------------------------------
-- wr_pointer_o <= dacapo_flag & std_logic_vector(wr_index(g_width-6 downto 0)) & x"0";
tstamp_wr_wb_cyc_o <= tstamp_wr_cyc;
tstamp_wr_wb_stb_o <= tstamp_wr_stb;
tstamp_wr_wb_we_o <= tstamp_wr_we;
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- decr_counter |
-- |
---------------------------------------------------------------------------------------------------
-- File decr_counter.vhd |
-- |
-- Description Stop counter. Configurable counter_top_i and width. |
-- Current count counter and done signal available. |
-- Done signal asserted simultaneous to counter=0. |
-- Countdown is launched each time counter_load_i is asserted for one clock tick. |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
--=================================================================================================
-- Entity declaration for decr_counter
--=================================================================================================
entity decr_counter is
generic
(width : integer := 32); -- default size
port
-- INPUTS
-- Signals from the clk_rst_manager
(clk_i : in std_logic;
rst_i : in std_logic;
-- Signals from any unit
counter_load_i : in std_logic; -- loads counter with counter_top_i value
counter_top_i : in std_logic_vector(width-1 downto 0); -- counter start value
-- OUTPUTS
-- Signals to any unit
counter_o : out std_logic_vector(width-1 downto 0);
counter_is_zero_o : out std_logic); -- counter empty indication
end decr_counter;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of decr_counter is
constant zeroes : unsigned(width-1 downto 0):=(others=>'0');
signal one : unsigned(width-1 downto 0);
signal counter : unsigned(width-1 downto 0) := (others=>'0'); -- init to avoid sim warnings
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
decr_counting: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
counter_is_zero_o <= '0';
counter <= zeroes;
elsif counter_load_i = '1' then
counter_is_zero_o <= '0';
counter <= unsigned(counter_top_i) - "1";
elsif counter = zeroes then
counter_is_zero_o <= '0';
counter <= zeroes;
elsif counter = one then
counter_is_zero_o <= '1';
counter <= counter - "1";
else
counter_is_zero_o <= '0';
counter <= counter - "1";
end if;
end if;
end process;
counter_o <= std_logic_vector(counter);
one <= zeroes + "1";
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- fmc_tdc_core |
-- |
---------------------------------------------------------------------------------------------------
-- File fmc_tdc_core.vhd |
-- |
-- Description TDC core top level |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2013 |
-- Version v4 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v1 GP First version |
-- 06/2012 v2 EG Revamping; Comments added, signals renamed |
-- removed LEDs from top level |
-- new gnum core integrated |
-- carrier 1 wire master added |
-- mezzanine I2C master added |
-- mezzanine 1 wire master added |
-- interrupts generator added |
-- changed generation of general_rst |
-- DAC reconfiguration+needed regs added |
-- 06/2012 v3 EG Changes for v2 of TDC mezzanine |
-- Several pinout changes, |
-- acam_ref_clk LVDS instead of CMOS, |
-- no PLL_LD only PLL_STATUS |
-- 04/2013 v4 EG created fmc_tdc_core module; before was all on fmc_tdc_core |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.tdc_core_pkg.all;
use work.gn4124_core_pkg.all;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
--=================================================================================================
-- Entity declaration for fmc_tdc_core
--=================================================================================================
entity fmc_tdc_core is
generic
(g_span : integer := 32; -- address span in bus interfaces
g_width : integer := 32; -- data width in bus interfaces
values_for_simul : boolean := FALSE); -- this generic is set to TRUE
-- when instantiated in a test-bench
port
(-- Clock and reset from the SPEC carrier
spec_clk_i : in std_logic ; -- 20 MHz clock from VCXO on SPEC
rst_n_a_i : in std_logic; -- reset signal from the GNUM interface
-- Xilinx PLL clock, generated in the clks_rsts_manager unit
tdc_clk_125m_o : out std_logic; -- 125 MHz clock
tdc_rst_n_o : out std_logic; -- reset
-- Signals for the interface with the PLL AD9516 and DAC AD5662 on TDC mezzanine
pll_sclk_o : out std_logic; -- SPI clock
pll_sdi_o : out std_logic; -- data line for PLL and DAC
pll_cs_o : out std_logic; -- PLL chip select
pll_dac_sync_o : out std_logic; -- DAC chip select
pll_sdo_i : in std_logic; -- not used for the moment
pll_status_i : in std_logic; -- PLL Digital Lock Detect, active high
tdc_clk_p_i : in std_logic; -- 125 MHz differential clock: system clock
tdc_clk_n_i : in std_logic; -- 125 MHz differential clock: system clock
acam_refclk_p_i : in std_logic; -- 31.25 MHz differential clock: ACAM ref clock
acam_refclk_n_i : in std_logic; -- 31.25 MHz differential clock: ACAM ref clock
-- Signals for the timing interface with the ACAM on TDC mezzanine
start_from_fpga_o : out std_logic; -- start signal
err_flag_i : in std_logic; -- error flag
int_flag_i : in std_logic; -- interrupt flag
start_dis_o : out std_logic; -- start disable, not used
stop_dis_o : out std_logic; -- stop disable, not used
-- Signals for the data interface with the ACAM on TDC mezzanine
data_bus_io : inout std_logic_vector(27 downto 0);
address_o : out std_logic_vector(3 downto 0);
cs_n_o : out std_logic; -- chip select for ACAM
oe_n_o : out std_logic; -- output enable for ACAM
rd_n_o : out std_logic; -- read signal for ACAM
wr_n_o : out std_logic; -- write signal for ACAM
ef1_i : in std_logic; -- empty flag iFIFO1
ef2_i : in std_logic; -- empty flag iFIFO2
-- Signals for the Input Logic on TDC mezzanine
tdc_in_fpga_1_i : in std_logic; -- Ch.1 for ACAM, also received by FPGA
tdc_in_fpga_2_i : in std_logic; -- Ch.2 for ACAM, also received by FPGA
tdc_in_fpga_3_i : in std_logic; -- Ch.3 for ACAM, also received by FPGA
tdc_in_fpga_4_i : in std_logic; -- Ch.4 for ACAM, also received by FPGA
tdc_in_fpga_5_i : in std_logic; -- Ch.5 for ACAM, also received by FPGA
-- Signals for the Input Logic on TDC mezzanine
enable_inputs_o : out std_logic; -- enables all 5 inputs
term_en_1_o : out std_logic; -- Ch.1 termination enable of 50 Ohm termination
term_en_2_o : out std_logic; -- Ch.2 termination enable of 50 Ohm termination
term_en_3_o : out std_logic; -- Ch.3 termination enable of 50 Ohm termination
term_en_4_o : out std_logic; -- Ch.4 termination enable of 50 Ohm termination
term_en_5_o : out std_logic; -- Ch.5 termination enable of 50 Ohm termination
-- LEDs on TDC mezzanine
tdc_led_status_o : out std_logic; -- amber led on front pannel, division of 125 MHz tdc_clk
tdc_led_trig1_o : out std_logic; -- amber led on front pannel, Ch.1 enable
tdc_led_trig2_o : out std_logic; -- amber led on front pannel, Ch.2 enable
tdc_led_trig3_o : out std_logic; -- amber led on front pannel, Ch.3 enable
tdc_led_trig4_o : out std_logic; -- amber led on front pannel, Ch.4 enable
tdc_led_trig5_o : out std_logic; -- amber led on front pannel, Ch.5 enable
-- Carrier other signals
spec_led_green_o : out std_logic; -- Green LED on SPEC front pannel, PLL status
spec_led_red_o : out std_logic; -- Red LED on SPEC front pannel
spec_aux0_i : in std_logic; -- Button on SPEC board
spec_aux1_i : in std_logic; -- Button on SPEC board
spec_aux2_o : out std_logic; -- Red LED on spec board
spec_aux3_o : out std_logic; -- Red LED on spec board
spec_aux4_o : out std_logic; -- Red LED on spec board
spec_aux5_o : out std_logic; -- Red LED on spec board
-- Interrupts
irq_tstamp_p_o : out std_logic; -- if amount of tstamps > tstamps_threshold
irq_time_p_o : out std_logic; -- if 0 < amount of tstamps < tstamps_threshold and time > time_threshold
irq_acam_err_p_o : out std_logic; -- if ACAM err_flag_i is activated
-- WISHBONE bus for the communication with GNUM core CSR
gnum_csr_adr_i : in std_logic_vector(g_span-1 downto 0); -- WISHBONE classic address
gnum_csr_dat_i : in std_logic_vector(g_width-1 downto 0); -- WISHBONE classic data in
gnum_csr_stb_i : in std_logic; -- WISHBONE classic strobe
gnum_csr_we_i : in std_logic; -- WISHBONE classic write enable
gnum_csr_cyc_i : in std_logic; -- WISHBONE classic cycle
gnum_csr_ack_o : out std_logic; -- WISHBONE classic acknowledge
gnum_csr_dat_o : out std_logic_vector(g_width-1 downto 0);-- WISHBONE classic data out
-- WISHBONE bus for the communication with GNUM core DMA
gnum_dma_adr_i : in std_logic_vector(31 downto 0); -- WISHBONE pipelined address
gnum_dma_dat_i : in std_logic_vector(31 downto 0); -- WISHBONE pipelined data in
gnum_dma_stb_i : in std_logic; -- WISHBONE pipelined strobe
gnum_dma_we_i : in std_logic; -- WISHBONE pipelined write enable
gnum_dma_cyc_i : in std_logic; -- WISHBONE pipelined cycle
gnum_dma_ack_o : out std_logic; -- WISHBONE pipelined acknowledge
gnum_dma_dat_o : out std_logic_vector(31 downto 0); -- WISHBONE classic data out
gnum_dma_stall_o : out std_logic); -- WISHBONE pipelined stall
end fmc_tdc_core;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of fmc_tdc_core is
-- clocks and resets
signal clk, acam_refclk, spec_clk, pll_status : std_logic;
signal general_rst, general_rst_n, gnum_rst : std_logic;
-- ACAM communication
signal acm_adr : std_logic_vector(7 downto 0);
signal acm_cyc, acm_stb, acm_we, acm_ack : std_logic;
signal acm_dat_r, acm_dat_w : std_logic_vector(g_width-1 downto 0);
signal acam_ef1, acam_ef2, acam_ef1_meta, acam_ef2_meta : std_logic;
signal acam_errflag_f_edge_p, acam_errflag_r_edge_p : std_logic;
signal acam_intflag_f_edge_p, acam_refclk_r_edge_p : std_logic;
signal acam_tstamp1, acam_tstamp2 : std_logic_vector(g_width-1 downto 0);
signal acam_tstamp1_ok_p, acam_tstamp2_ok_p : std_logic;
-- control unit
signal activate_acq_p, deactivate_acq_p, load_acam_config : std_logic;
signal read_acam_config, read_acam_status, read_ififo1 : std_logic;
signal read_ififo2, read_start01, reset_acam, load_utc : std_logic;
signal clear_dacapo_counter, roll_over_incr_recent : std_logic;
signal pulse_delay, window_delay, clk_period : std_logic_vector(g_width-1 downto 0);
signal starting_utc, acam_status, acam_inputs_en : std_logic_vector(g_width-1 downto 0);
signal acam_ififo1, acam_ififo2, acam_start01 : std_logic_vector(g_width-1 downto 0);
signal irq_tstamp_threshold, irq_time_threshold : std_logic_vector(g_width-1 downto 0);
signal local_utc, wr_index : std_logic_vector(g_width-1 downto 0);
signal pll_dac_word : std_logic_vector(23 downto 0);
signal acam_config, acam_config_rdbk : config_vector;
signal tstamp_wr_p, send_dac_word_p : std_logic;
-- retrigger control
signal clk_i_cycles_offset, roll_over_nb, retrig_nb_offset: std_logic_vector(g_width-1 downto 0);
signal one_hz_p : std_logic;
-- circular buffer
signal circ_buff_class_adr : std_logic_vector(7 downto 0);
signal circ_buff_class_stb, circ_buff_class_cyc : std_logic;
signal circ_buff_class_we, circ_buff_class_ack : std_logic;
signal circ_buff_class_data_wr, circ_buff_class_data_rd : std_logic_vector(4*g_width-1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- TDC REGISTERS CONTROLLER --
---------------------------------------------------------------------------------------------------
reg_control_block: reg_ctrl
generic map
(g_span => g_span,
g_width => g_width)
port map
(clk_i => clk,
rst_i => general_rst,
gnum_csr_adr_i => gnum_csr_adr_i,
gnum_csr_dat_i => gnum_csr_dat_i,
gnum_csr_stb_i => gnum_csr_stb_i,
gnum_csr_we_i => gnum_csr_we_i,
gnum_csr_cyc_i => gnum_csr_cyc_i,
gnum_csr_ack_o => gnum_csr_ack_o,
gnum_csr_dat_o => gnum_csr_dat_o,
activate_acq_p_o => activate_acq_p,
deactivate_acq_p_o => deactivate_acq_p,
acam_wr_config_p_o => load_acam_config,
acam_rdbk_config_p_o => read_acam_config,
acam_rdbk_status_p_o => read_acam_status,
acam_rdbk_ififo1_p_o => read_ififo1,
acam_rdbk_ififo2_p_o => read_ififo2,
acam_rdbk_start01_p_o => read_start01,
acam_rst_p_o => reset_acam,
load_utc_p_o => load_utc,
dacapo_c_rst_p_o => clear_dacapo_counter,
acam_config_rdbk_i => acam_config_rdbk,
acam_status_i => acam_status,
acam_ififo1_i => acam_ififo1,
acam_ififo2_i => acam_ififo2,
acam_start01_i => acam_start01,
local_utc_i => local_utc,
irq_code_i => open,
core_status_i => open,
wr_index_i => wr_index,
acam_config_o => acam_config,
starting_utc_o => starting_utc,
acam_inputs_en_o => acam_inputs_en,
start_phase_o => window_delay,
irq_tstamp_threshold_o=> irq_tstamp_threshold,
irq_time_threshold_o => irq_time_threshold,
send_dac_word_p_o => send_dac_word_p,
dac_word_o => pll_dac_word,
one_hz_phase_o => pulse_delay);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- termination enable registers
term_enable_regs: process (clk)
begin
if rising_edge (clk) then
if general_rst = '1' then
enable_inputs_o <= '0';
term_en_5_o <= '0';
term_en_4_o <= '0';
term_en_3_o <= '0';
term_en_2_o <= '0';
term_en_1_o <= '0';
else
enable_inputs_o <= acam_inputs_en(7);
term_en_5_o <= acam_inputs_en(4);
term_en_4_o <= acam_inputs_en(3);
term_en_3_o <= acam_inputs_en(2);
term_en_2_o <= acam_inputs_en(1);
term_en_1_o <= acam_inputs_en(0);
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- ONE HZ GENERATOR --
---------------------------------------------------------------------------------------------------
one_second_block: one_hz_gen
generic map
(g_width => g_width)
port map
(acam_refclk_r_edge_p_i => acam_refclk_r_edge_p,
clk_i => clk,
clk_period_i => clk_period,
load_utc_p_i => load_utc,
pulse_delay_i => pulse_delay,
rst_i => general_rst,
starting_utc_i => starting_utc,
local_utc_o => local_utc,
one_hz_p_o => one_hz_p);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
clk_period <= c_SIM_CLK_PERIOD when values_for_simul else c_SYN_CLK_PERIOD;
---------------------------------------------------------------------------------------------------
-- ACAM TIMECONTROL INTERFACE --
---------------------------------------------------------------------------------------------------
acam_timing_block: acam_timecontrol_interface
port map
(err_flag_i => err_flag_i,
int_flag_i => int_flag_i,
start_from_fpga_o => start_from_fpga_o,
acam_refclk_r_edge_p_i => acam_refclk_r_edge_p,
clk_i => clk,
activate_acq_p_i => activate_acq_p,
rst_i => general_rst,
window_delay_i => window_delay,
acam_errflag_f_edge_p_o => acam_errflag_f_edge_p,
acam_errflag_r_edge_p_o => acam_errflag_r_edge_p,
acam_intflag_f_edge_p_o => acam_intflag_f_edge_p);
---------------------------------------------------------------------------------------------------
-- ACAM DATABUS INTERFACE --
---------------------------------------------------------------------------------------------------
acam_data_block: acam_databus_interface
port map
(ef1_i => ef1_i,
ef2_i => ef2_i,
data_bus_io => data_bus_io,
adr_o => address_o,
cs_n_o => cs_n_o,
oe_n_o => oe_n_o,
rd_n_o => rd_n_o,
wr_n_o => wr_n_o,
ef1_o => acam_ef1,
ef1_synch1_o => acam_ef1_meta,
ef2_o => acam_ef2,
ef2_synch1_o => acam_ef2_meta,
clk_i => clk,
rst_i => general_rst,
adr_i => acm_adr,
cyc_i => acm_cyc,
dat_i => acm_dat_w,
stb_i => acm_stb,
we_i => acm_we,
ack_o => acm_ack,
dat_o => acm_dat_r);
---------------------------------------------------------------------------------------------------
-- ACAM START RETRIGGER CONTROLLER --
---------------------------------------------------------------------------------------------------
start_retrigger_block: start_retrig_ctrl
generic map
(g_width => g_width)
port map
(acam_intflag_f_edge_p_i => acam_intflag_f_edge_p,
clk_i => clk,
one_hz_p_i => one_hz_p,
rst_i => general_rst,
roll_over_incr_recent_o => roll_over_incr_recent,
clk_i_cycles_offset_o => clk_i_cycles_offset,
roll_over_nb_o => roll_over_nb,
retrig_nb_offset_o => retrig_nb_offset);
---------------------------------------------------------------------------------------------------
-- DATA ENGINE --
---------------------------------------------------------------------------------------------------
data_engine_block: data_engine
port map
(acam_ack_i => acm_ack,
acam_dat_i => acm_dat_r,
acam_adr_o => acm_adr,
acam_cyc_o => acm_cyc,
acam_dat_o => acm_dat_w,
acam_stb_o => acm_stb,
acam_we_o => acm_we,
clk_i => clk,
rst_i => general_rst,
acam_ef1_i => acam_ef1,
acam_ef1_synch1_i => acam_ef1_meta,
acam_ef2_i => acam_ef2,
acam_ef2_synch1_i => acam_ef2_meta,
activate_acq_p_i => activate_acq_p,
deactivate_acq_p_i => deactivate_acq_p,
acam_wr_config_p_i => load_acam_config,
acam_rdbk_config_p_i => read_acam_config,
acam_rdbk_status_p_i => read_acam_status,
acam_rdbk_ififo1_p_i => read_ififo1,
acam_rdbk_ififo2_p_i => read_ififo2,
acam_rdbk_start01_p_i => read_start01,
acam_rst_p_i => reset_acam,
acam_config_i => acam_config,
acam_config_rdbk_o => acam_config_rdbk,
acam_status_o => acam_status,
acam_ififo1_o => acam_ififo1,
acam_ififo2_o => acam_ififo2,
acam_start01_o => acam_start01,
acam_tstamp1_o => acam_tstamp1,
acam_tstamp1_ok_p_o => acam_tstamp1_ok_p,
acam_tstamp2_o => acam_tstamp2,
acam_tstamp2_ok_p_o => acam_tstamp2_ok_p);
---------------------------------------------------------------------------------------------------
-- DATA FORMATTING --
---------------------------------------------------------------------------------------------------
data_formatting_block: data_formatting
port map
(clk_i => clk,
rst_i => general_rst,
tstamp_wr_wb_ack_i => circ_buff_class_ack,
tstamp_wr_dat_i => circ_buff_class_data_rd,
tstamp_wr_wb_adr_o => circ_buff_class_adr,
tstamp_wr_wb_cyc_o => circ_buff_class_cyc,
tstamp_wr_dat_o => circ_buff_class_data_wr,
tstamp_wr_wb_stb_o => circ_buff_class_stb,
tstamp_wr_wb_we_o => circ_buff_class_we,
acam_tstamp1_i => acam_tstamp1,
acam_tstamp1_ok_p_i => acam_tstamp1_ok_p,
acam_tstamp2_i => acam_tstamp2,
acam_tstamp2_ok_p_i => acam_tstamp2_ok_p,
dacapo_c_rst_p_i => clear_dacapo_counter,
roll_over_incr_recent_i => roll_over_incr_recent,
clk_i_cycles_offset_i => clk_i_cycles_offset,
roll_over_nb_i => roll_over_nb,
retrig_nb_offset_i => retrig_nb_offset,
one_hz_p_i => one_hz_p,
local_utc_i => local_utc,
tstamp_wr_p_o => tstamp_wr_p,
wr_index_o => wr_index);
---------------------------------------------------------------------------------------------------
-- INTERRUPTS GENERATOR --
---------------------------------------------------------------------------------------------------
interrupts_generator: irq_generator
generic map
(g_width => 32)
port map
(clk_i => clk,
rst_i => general_rst,
irq_tstamp_threshold_i => irq_tstamp_threshold,
irq_time_threshold_i => irq_time_threshold,
activate_acq_p_i => activate_acq_p,
deactivate_acq_p_i => deactivate_acq_p,
tstamp_wr_p_i => tstamp_wr_p,
one_hz_p_i => one_hz_p,
irq_tstamp_p_o => irq_tstamp_p_o,
irq_time_p_o => irq_time_p_o);
---------------------------------------------------------------------------------------------------
-- CIRCULAR BUFFER --
---------------------------------------------------------------------------------------------------
circular_buffer_block: circular_buffer
port map
(clk_i => clk,
tstamp_wr_rst_i => general_rst,
tstamp_wr_adr_i => circ_buff_class_adr,
tstamp_wr_cyc_i => circ_buff_class_cyc,
tstamp_wr_dat_i => circ_buff_class_data_wr,
tstamp_wr_stb_i => circ_buff_class_stb,
tstamp_wr_we_i => circ_buff_class_we,
tstamp_wr_ack_p_o => circ_buff_class_ack,
tstamp_wr_dat_o => circ_buff_class_data_rd,
gnum_dma_rst_i => general_rst,
gnum_dma_adr_i => gnum_dma_adr_i,
gnum_dma_cyc_i => gnum_dma_cyc_i,
gnum_dma_dat_i => gnum_dma_dat_i,
gnum_dma_stb_i => gnum_dma_stb_i,
gnum_dma_we_i => gnum_dma_we_i,
gnum_dma_ack_o => gnum_dma_ack_o,
gnum_dma_dat_o => gnum_dma_dat_o,
gnum_dma_stall_o => gnum_dma_stall_o);
---------------------------------------------------------------------------------------------------
-- CLOCKS & RESETS MANAGER --
---------------------------------------------------------------------------------------------------
clks_rsts_mgment: clks_rsts_manager
generic map
(nb_of_reg => 68)
port map
(spec_clk_i => spec_clk_i,
acam_refclk_p_i => acam_refclk_p_i,
acam_refclk_n_i => acam_refclk_n_i,
tdc_clk_p_i => tdc_clk_p_i,
tdc_clk_n_i => tdc_clk_n_i,
rst_n_a_i => rst_n_a_i,
pll_sdo_i => pll_sdo_i,
pll_status_i => pll_status_i,
send_dac_word_p_i => send_dac_word_p,
dac_word_i => pll_dac_word,
acam_refclk_r_edge_p_o => acam_refclk_r_edge_p,
internal_rst_o => general_rst,
pll_cs_o => pll_cs_o,
pll_dac_sync_o => pll_dac_sync_o,
pll_sdi_o => pll_sdi_o,
pll_sclk_o => pll_sclk_o,
spec_clk_o => spec_clk,
tdc_clk_o => clk,
gnum_rst_o => gnum_rst,
pll_status_o => pll_status);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
general_rst_n <= not (general_rst);
tdc_rst_n_o <= general_rst_n;
tdc_clk_125m_o <= clk;
---------------------------------------------------------------------------------------------------
-- LEDs & BUTTONS --
---------------------------------------------------------------------------------------------------
leds_and_buttons: leds_manager
generic map
(g_width => 32,
values_for_simul => values_for_simul)
port map
(clk_20mhz_i => spec_clk,
clk_125mhz_i => clk,
gnum_rst_i => gnum_rst,
internal_rst_i => general_rst,
pll_status_i => pll_status,
spec_aux_butt_1_i => spec_aux0_i,
spec_aux_butt_2_i => spec_aux1_i,
one_hz_p_i => one_hz_p,
acam_inputs_en_i => acam_inputs_en,
tdc_led_status_o => tdc_led_status_o,
tdc_led_trig1_o => tdc_led_trig1_o,
tdc_led_trig2_o => tdc_led_trig2_o,
tdc_led_trig3_o => tdc_led_trig3_o,
tdc_led_trig4_o => tdc_led_trig4_o,
tdc_led_trig5_o => tdc_led_trig5_o,
spec_led_green_o => spec_led_green_o,
spec_led_red_o => spec_led_red_o,
spec_aux_led_1_o => spec_aux2_o,
spec_aux_led_2_o => spec_aux3_o,
spec_aux_led_3_o => spec_aux4_o,
spec_aux_led_4_o => spec_aux5_o);
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- free_counter |
-- |
---------------------------------------------------------------------------------------------------
-- File free_counter.vhd |
-- |
-- Description Free running counter. Configurable counter_top_i and width. |
-- Current count counter and done signal available. |
-- Done signal asserted simultaneous to counter=0. |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
--=================================================================================================
-- Entity declaration for free_counter
--=================================================================================================
entity free_counter is
generic
(width : integer := 32); -- default size
port
-- INPUTS
-- Signals from the clk_rst_manager
(clk_i : in std_logic;
rst_i : in std_logic;
-- Signals from any unit
counter_en_i : in std_logic; -- enables counting
counter_top_i : in std_logic_vector(width-1 downto 0); -- start value;
-- when zero is reached counter reloads
-- start value and restarts counting
-- OUTPUTS
-- Signals to any unit
counter_o : out std_logic_vector(width-1 downto 0);
counter_is_zero_o : out std_logic); -- empty counter indication
end free_counter;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of free_counter is
constant zeroes : unsigned(width-1 downto 0):=(others=>'0');
signal counter : unsigned(width-1 downto 0):=(others=>'0'); -- init to avoid sim warnings
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
decr_counting: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
counter_is_zero_o <= '0';
counter <= unsigned(counter_top_i) - "1";
elsif counter = zeroes then
counter_is_zero_o <= '0';
counter <= unsigned(counter_top_i) - "1";
elsif counter_en_i = '1' then
if counter = zeroes + "1" then
counter_is_zero_o <= '1';
counter <= counter - "1";
else
counter_is_zero_o <= '0';
counter <= counter - "1";
end if;
end if;
end if;
end process;
counter_o <= std_logic_vector(counter);
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- incr_counter |
-- |
---------------------------------------------------------------------------------------------------
-- File incr_counter.vhd |
-- |
-- Description Stop counter. Configurable counter_top_i and width. |
-- Current count value and done signal available. |
-- Done signal asserted simultaneous to value = counter_top_i. |
-- Needs a rst_i to restart. |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
--=================================================================================================
-- Entity declaration for incr_counter
--=================================================================================================
entity incr_counter is
generic
(width : integer := 32); -- default size
port
-- INPUTS
-- Signals from the clk_rst_manager
(clk_i : in std_logic;
rst_i : in std_logic;
-- Signals from any unit
counter_top_i : in std_logic_vector(width-1 downto 0); -- max value to be counted; when reached
-- counter stays at it, until a reset
counter_incr_en_i : in std_logic; -- enables counting
-- OUTPUTS
-- Signals to any unit
counter_o : out std_logic_vector(width-1 downto 0);
counter_is_full_o : out std_logic); -- counter reahed counter_top_i value
end incr_counter;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of incr_counter is
constant zeroes : unsigned(width-1 downto 0) := (others=>'0');
signal counter : unsigned(width-1 downto 0) := (others=>'0'); -- init to avoid sim warnings
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
incr_counting: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
counter_is_full_o <= '0';
counter <= zeroes;
elsif counter = unsigned (counter_top_i) then
counter_is_full_o <= '1';
counter <= unsigned (counter_top_i);
elsif counter_incr_en_i ='1' then
if counter = unsigned(counter_top_i) - "1" then
counter_is_full_o <= '1';
counter <= counter + "1";
else
counter_is_full_o <= '0';
counter <= counter + "1";
end if;
end if;
end if;
end process;
counter_o <= std_logic_vector(counter);
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- irq_generator |
-- |
---------------------------------------------------------------------------------------------------
-- File irq_generator.vhd |
-- |
-- Description Interrupts generator: the unit generates two interrups: |
-- o irq_tstamp_p_o is a 1 clk_i long pulse when the amount of timestamps written in |
-- the circular_buffer since the last interrupt or the aquisition start exceeds |
-- the PCIe settable threshold irq_tstamp_threshold_o |
-- o irq_time_p_o is a 1 clk_i long pulse when some timestamps have been written in |
-- the circular_buffer (>0) and the amount of time passed the last interrupt or |
-- the aquisition start exceeds the PCIe settable threshold irq_time_threshold_o |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 05/2012 |
-- Version v0.1 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2012 v0.1 EG First version |
-- 04/2013 v0.2 EG line 170 added "irq_time_threshold_i > 0"; if the user doesn t want the |
-- time interrupts he sets the irq_time_threshold reg to zero; same goes |
-- for number-of-tstamps interrupts, users sets to zero to disable them |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for irq_generator
--=================================================================================================
entity irq_generator is
generic
(g_width : integer := 32);
port
-- INPUTS
-- Signal from the clk_rst_manager
(clk_i : in std_logic; -- 125 MHz clk
rst_i : in std_logic; -- general reset
irq_tstamp_threshold_i : in std_logic_vector(g_width-1 downto 0);
irq_time_threshold_i : in std_logic_vector(g_width-1 downto 0);
-- Signal from the reg_ctrl unit
activate_acq_p_i : in std_logic; -- activates tstamps aquisition from ACAM
deactivate_acq_p_i : in std_logic; -- deactivates tstamps aquisition
-- Signals from the data_formatting unit
tstamp_wr_p_i : in std_logic; -- pulse upon storage of a new timestamp
-- Signal from the one_hz_gen unit
one_hz_p_i : in std_logic; -- pulse upon new second
-- OUTPUTS
-- Signals to the wb_irq_controller
irq_tstamp_p_o : out std_logic; -- amount of tstamps > tstamps_threshold
irq_time_p_o : out std_logic); -- amount of tstamps < tstamps_threshold but time > time_threshold
end irq_generator;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of irq_generator is
constant ZERO : std_logic_vector (8 downto 0):= "000000000";
type t_irq_st is (IDLE, TSTAMP_AND_TIME_COUNTING, RAISE_IRQ_TSTAMP, RAISE_IRQ_TIME);
signal irq_st, nxt_irq_st : t_irq_st;
signal tstamps_c_rst, time_c_rst, tstamps_c_en, time_c_en : std_logic;
signal tstamps_c_incr_en, time_c_incr_en : std_logic;
signal tstamps_c : std_logic_vector(8 downto 0);
signal time_c : std_logic_vector(g_width-1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
---------------------------------------------------------------------------------------------------
-- INTERRUPTS GENERATOR --
---------------------------------------------------------------------------------------------------
IRQ_generator_seq: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
irq_st <= IDLE;
else
irq_st <= nxt_irq_st;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
IRQ_generator_comb: process (irq_st, activate_acq_p_i, deactivate_acq_p_i, tstamps_c,
irq_tstamp_threshold_i, irq_time_threshold_i, time_c)
begin
case irq_st is
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when IDLE =>
-----------------------------------------------
irq_tstamp_p_o <= '0';
irq_time_p_o <= '0';
tstamps_c_rst <= '1';
time_c_rst <= '1';
tstamps_c_en <= '0';
time_c_en <= '0';
-----------------------------------------------
if activate_acq_p_i = '1' then
nxt_irq_st <= TSTAMP_AND_TIME_COUNTING;
else
nxt_irq_st <= IDLE;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when TSTAMP_AND_TIME_COUNTING =>
-----------------------------------------------
irq_tstamp_p_o <= '0';
irq_time_p_o <= '0';
tstamps_c_rst <= '0';
time_c_rst <= '0';
tstamps_c_en <= '1';
time_c_en <= '1';
-----------------------------------------------
if deactivate_acq_p_i = '1' then
nxt_irq_st <= IDLE;
elsif tstamps_c > ZERO and tstamps_c >= irq_tstamp_threshold_i(8 downto 0) then -- not >= ZERO!!
nxt_irq_st <= RAISE_IRQ_TSTAMP;
elsif unsigned(irq_time_threshold_i) > 0 and time_c >= irq_time_threshold_i and tstamps_c > ZERO then
nxt_irq_st <= RAISE_IRQ_TIME;
else
nxt_irq_st <= TSTAMP_AND_TIME_COUNTING;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RAISE_IRQ_TSTAMP =>
-----------------------------------------------
irq_tstamp_p_o <= '1';
irq_time_p_o <= '0';
tstamps_c_rst <= '1';
time_c_rst <= '1';
tstamps_c_en <= '0';
time_c_en <= '0';
-----------------------------------------------
if deactivate_acq_p_i = '1' then
nxt_irq_st <= IDLE;
else
nxt_irq_st <= TSTAMP_AND_TIME_COUNTING;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when RAISE_IRQ_TIME =>
-----------------------------------------------
irq_tstamp_p_o <= '0';
irq_time_p_o <= '1';
tstamps_c_rst <= '1';
time_c_rst <= '1';
tstamps_c_en <= '0';
time_c_en <= '0';
-----------------------------------------------
if deactivate_acq_p_i = '1' then
nxt_irq_st <= IDLE;
else
nxt_irq_st <= TSTAMP_AND_TIME_COUNTING;
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
when others =>
-----------------------------------------------
irq_tstamp_p_o <= '0';
irq_time_p_o <= '0';
tstamps_c_rst <= '1';
time_c_rst <= '1';
tstamps_c_en <= '0';
time_c_en <= '0';
-----------------------------------------------
nxt_irq_st <= IDLE;
end case;
end process;
---------------------------------------------------------------------------------------------------
-- TIMESTAMPS COUNTER --
---------------------------------------------------------------------------------------------------
-- Incremental counter counting the amount of timestamps written since the last interrupt or the
-- last reset. The counter counts up to 255 which is the circular buffer size.
tstamps_counter: incr_counter
generic map
(width => 9) -- counting up to 255
port map
(clk_i => clk_i,
rst_i => tstamps_c_rst,
counter_top_i => "100000000",
counter_incr_en_i => tstamps_c_incr_en,
counter_is_full_o => open,
-------------------------------------------
counter_o => tstamps_c);
-------------------------------------------
tstamps_c_incr_en <= tstamps_c_en and tstamp_wr_p_i;
---------------------------------------------------------------------------------------------------
-- TIME COUNTER --
---------------------------------------------------------------------------------------------------
-- Incremental counter counting the time in seconds since the last interrupt or the last reset.
time_counter: incr_counter
generic map
(width => g_width)
port map
(clk_i => clk_i,
rst_i => time_c_rst,
counter_top_i => x"FFFFFFFF",
counter_incr_en_i => time_c_incr_en,
counter_is_full_o => open,
-------------------------------------------
counter_o => time_c);
-------------------------------------------
time_c_incr_en <= time_c_en and one_hz_p_i;
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- leds_manager |
-- |
---------------------------------------------------------------------------------------------------
-- File leds_manager.vhd |
-- |
-- Description Generation of the signals that drive the LEDs on the TDC mezzanine and SPEC |
-- carrier boards. |
-- There are 6 LEDs on the front panel of the TDC mezzanine board: |
-- ______ |
-- | | |
-- | O O | 1, 2 |
-- | O O | 3, 4 |
-- | O O | 5, 6 |
-- |______| |
-- |
-- TDC LED 1 orange: division of the 125 MHz clock; one hz pulses |
-- TDC LED 2 orange: Channel 1 terminatio enable |
-- TDC LED 3 orange: Channel 2 terminatio enable |
-- TDC LED 4 orange: Channel 3 terminatio enable |
-- TDC LED 5 orange: Channel 4 terminatio enable |
-- TDC LED 6 orange: Channel 5 terminatio enable |
-- |
-- And further down 2 LEDs on the front panel of the SPEC carrier board: |
-- ______ |
-- | O O | 1, 2 |
-- |______| |
-- |
-- SPEC LED 1 green : PLL status (DLD) |
-- SPEC LED 2 red : division of the 20 MHz clock |
-- |
-- There are also 4 LEDs and 2 buttons on the PCB of the SPEC carrier: |
-- _______________ |
-- | O O O O | aux LEDs 1, 2, 3, 4 |
-- | __ __ | |
-- | |__| |__| | aux buttons 1, 2 |
-- |_______________| |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Date 05/2012 |
-- Version v0.3 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2012 v0.1 EG First version |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific libraries
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for leds_manager
--=================================================================================================
entity leds_manager is
generic
(g_width : integer := 32;
values_for_simulation : boolean := FALSE);
port
-- INPUTS
-- Signals from the clks_rsts_manager
(clk_20mhz_i : in std_logic; -- 20 MHz clock
clk_125mhz_i : in std_logic; -- 125 MHz clock
gnum_rst_i : in std_logic; -- reset from the PCI-e, synched with 20 MHz clk
internal_rst_i : in std_logic; -- core internal reset, synched with 125 MHz clk
-- Signal from the PLL
pll_status_i : in std_logic; -- PLL lock detect
-- Signals from the buttons on the SPEC PCB
spec_aux_butt_1_i : in std_logic; -- SPEC PCB button 1 (PB1)
spec_aux_butt_2_i : in std_logic; -- SPEC PCB button 2 (PB2)
-- Signal from the one_hz_generator unit
one_hz_p_i : in std_logic;
-- Signal from the reg_ctrl unit
acam_inputs_en_i : in std_logic_vector(g_width-1 downto 0); -- enable for the ACAM channels;
-- activation comes through dedicated reg c_ACAM_INPUTS_EN_ADR
-- OUTPUTS
-- Signals to the LEDs on the TDC front panel
tdc_led_status_o : out std_logic; -- TDC LED 1: division of 125 MHz
tdc_led_trig1_o : out std_logic; -- TDC LED 2: Channel 1 input enable
tdc_led_trig2_o : out std_logic; -- TDC LED 3: Channel 2 input enable
tdc_led_trig3_o : out std_logic; -- TDC LED 4: Channel 3 input enable
tdc_led_trig4_o : out std_logic; -- TDC LED 5: Channel 4 input enable
tdc_led_trig5_o : out std_logic; -- TDC LED 6: Channel 5 input enable
-- Signals to the LEDs on the SPEC front panel
spec_led_green_o : out std_logic; -- SPEC LED 1: PLL lock detect
spec_led_red_o : out std_logic; -- SPEC LED 2: division of 20 MHz
-- Signals to the LEDs on the SPEC PCB
spec_aux_led_1_o : out std_logic; -- SPEC PCB LED 1 (LD2)
spec_aux_led_2_o : out std_logic; -- SPEC PCB LED 2 (LD3)
spec_aux_led_3_o : out std_logic; -- SPEC PCB LED 3 (LD4)
spec_aux_led_4_o : out std_logic);-- SPEC PCB LED 4 (LD5)
end leds_manager;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of leds_manager is
signal spec_led_blink_done, spec_led_period_done, tdc_led_blink_done : std_logic;
signal spec_led_period, visible_blink_length : std_logic_vector(g_width-1 downto 0);
begin
---------------------------------------------------------------------------------------------------
-- TDC FRONT PANEL LED 1 --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
tdc_led_blink_counter: decr_counter
port map
(clk_i => clk_125mhz_i,
rst_i => internal_rst_i,
counter_load_i => one_hz_p_i,
counter_top_i => visible_blink_length,
counter_is_zero_o => tdc_led_blink_done,
counter_o => open);
---------------------------------------------------------------------------------------------------
tdc_led: process (clk_125mhz_i)
begin
if rising_edge (clk_125mhz_i) then
if internal_rst_i ='1' then
tdc_led_status_o <= '0';
elsif one_hz_p_i ='1' then
tdc_led_status_o <= '1';
elsif tdc_led_blink_done = '1' then
tdc_led_status_o <= '0';
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- TDC FRONT PANEL LEDs 2-6 --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
all_outputs: process (clk_125mhz_i)
begin
if rising_edge (clk_125mhz_i) then
tdc_led_trig5_o <= acam_inputs_en_i(4) and acam_inputs_en_i(7);
tdc_led_trig4_o <= acam_inputs_en_i(3) and acam_inputs_en_i(7);
tdc_led_trig3_o <= acam_inputs_en_i(2) and acam_inputs_en_i(7);
tdc_led_trig2_o <= acam_inputs_en_i(1) and acam_inputs_en_i(7);
tdc_led_trig1_o <= acam_inputs_en_i(0) and acam_inputs_en_i(7);
end if;
end process;
---------------------------------------------------------------------------------------------------
-- SPEC FRONT PANEL LED 1 --
---------------------------------------------------------------------------------------------------
spec_led_green_o <= pll_status_i;
---------------------------------------------------------------------------------------------------
-- SPEC FRONT PANEL LED 2 --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
spec_led_period_counter: free_counter
port map
(clk_i => clk_20mhz_i,
counter_en_i => '1',
rst_i => gnum_rst_i,
counter_top_i => spec_led_period,
counter_is_zero_o => spec_led_period_done,
counter_o => open);
-- -- -- -- -- -- -- --
spec_led_period <= c_SPEC_LED_PERIOD_SIM when values_for_simulation else c_SPEC_LED_PERIOD_SYN;
---------------------------------------------------------------------------------------------------
spec_led_blink_counter: decr_counter
port map
(clk_i => clk_20mhz_i,
rst_i => gnum_rst_i,
counter_load_i => spec_led_period_done,
counter_top_i => visible_blink_length,
counter_is_zero_o => spec_led_blink_done,
counter_o => open);
-- -- -- -- -- -- -- --
visible_blink_length <= c_BLINK_LGTH_SIM when values_for_simulation else c_BLINK_LGTH_SYN;
---------------------------------------------------------------------------------------------------
spec_led: process (clk_20mhz_i)
begin
if rising_edge (clk_20mhz_i) then
if gnum_rst_i ='1' then
spec_led_red_o <= '0';
elsif spec_led_period_done ='1' then
spec_led_red_o <= '1';
elsif spec_led_blink_done ='1' then
spec_led_red_o <= '0';
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- SPEC PCB LEDs and BUTTONs --
---------------------------------------------------------------------------------------------------
-- Note: all spec_aux signals are active low
---------------------------------------------------------------------------------------------------
button_with_20MHz_clk: process (clk_20mhz_i)
begin
if rising_edge (clk_20mhz_i) then
spec_aux_led_2_o <= spec_aux_butt_1_i;
spec_aux_led_1_o <= spec_aux_butt_1_i;
end if;
end process;
---------------------------------------------------------------------------------------------------
button_with_125MHz_clk: process (clk_125mhz_i)
begin
if rising_edge (clk_125mhz_i) then
spec_aux_led_3_o <= spec_aux_butt_2_i;
spec_aux_led_4_o <= spec_aux_butt_2_i;
end if;
end process;
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- one_hz_gen |
-- |
---------------------------------------------------------------------------------------------------
-- File one_hz_gen.vhd |
-- |
-- Description Generates one pulse every second synchronously with the acam reference clock. |
-- The phase with the reference clock can be adjusted. still don t know why?? |
-- It also keeps track of the UTC time based on the local clock. |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for one_hz_gen
--=================================================================================================
entity one_hz_gen is
generic
(g_width : integer := 32);
port
-- INPUTS
-- Signals from the clk_rst_manager unit
(clk_i : in std_logic;
rst_i : in std_logic;
acam_refclk_r_edge_p_i : in std_logic;
clk_period_i : in std_logic_vector(g_width-1 downto 0); -- nb of clock periods for 1s
-- Signals from the reg_ctrl unit
load_utc_p_i : in std_logic; -- enables loading of the local UTC time with starting_utc_i value
starting_utc_i : in std_logic_vector(g_width-1 downto 0); -- value coming from the PCIe
pulse_delay_i : in std_logic_vector(g_width-1 downto 0); -- nb of clock periods phase delay
-- with respect to reference clock
-- OUTPUTS
-- Signal to data_formatting and reg_ctrl units
local_utc_o : out std_logic_vector(g_width-1 downto 0); -- tstamp current second
-- Signal to start_retrig_ctrl unit
one_hz_p_o : out std_logic); -- pulse upon new second
end one_hz_gen;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of one_hz_gen is
constant constant_delay : unsigned(g_width-1 downto 0) := x"00000004"; --maybe put in package--maybe not needed
signal local_utc : unsigned(g_width-1 downto 0);
signal one_hz_p_pre : std_logic;
signal one_hz_p_post : std_logic;
signal onesec_counter_en : std_logic;
signal total_delay : std_logic_vector(g_width-1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- 1 sec counting --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- clk_periods_counter: generation of a 1 clk-long pulse every second.
-- The first pulse occurs one second after the startup of the acam_refclk
-- bits 27-31 not used.
clk_periods_counter: free_counter
generic map
(width => g_width)
port map
(clk_i => clk_i,
rst_i => rst_i,
counter_en_i => onesec_counter_en,
counter_top_i => clk_period_i,
-------------------------------------------
counter_is_zero_o => one_hz_p_pre,
counter_o => open);
-------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
clk_periods_counter_en_trigger: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
onesec_counter_en <= '0';
elsif acam_refclk_r_edge_p_i ='1' then
onesec_counter_en <= '1'; -- stays at 1 after the first acam_refclk pulse
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Load UTC time --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- utc_counter: generation of a 1 clk-long pulse every second
utc_counter: process (clk_i)--maybe use an already existing counter???
begin
if rising_edge (clk_i) then
if rst_i ='1' then
local_utc <= (others => '0');
elsif load_utc_p_i = '1' then
local_utc <= unsigned(starting_utc_i); -- loading of local_utc with incoming starting_utc_i
elsif one_hz_p_post = '1' then -- new second counted; local_utc updated
local_utc <= local_utc + 1;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
local_utc_o <= std_logic_vector(local_utc);
---------------------------------------------------------------------------------------------------
-- Delays?? --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
pulse_delayer_counter: decr_counter -- delays the one_hz_p_pre pulse for total_delay clk_i ticks
generic map
(width => g_width)
port map
(clk_i => clk_i,
rst_i => rst_i,
counter_load_i => one_hz_p_pre,
counter_top_i => total_delay,
-------------------------------------------
counter_is_zero_o => one_hz_p_post,
counter_o => open);
-------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
total_delay <= std_logic_vector(unsigned(pulse_delay_i)+constant_delay);
one_hz_p_o <= one_hz_p_post;
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- reg_ctrl |
-- |
---------------------------------------------------------------------------------------------------
-- File reg_ctrl.vhd |
-- |
-- Description Interfaces with the CSR WISHBONE bus of the GNUM core for data transfers between |
-- the PCIe interface and locally, the TDC core. The unit implements a WISHBONE |
-- pipeline slave. |
-- |
-- Through CSR WISHBONE writes, the unit receives: |
-- o the ACAM configuration registers which are then made available to the |
-- data_engine and acam_databus_interface units to be transfered to the ACAM chip|
-- o the local configuration registers that are then made available to the |
-- different units of this design |
-- o the control register that defines the action to be taken in the core; the |
-- register is decoded and the corresponding signals are made available to the |
-- different units in the design. |
-- |
-- Through CSR WISHBONE reads, the unit transmits: |
-- o the ACAM configuration registers read from the ACAM chip |
-- o status registers coming from different units of the TDC core |
-- o there is also the possilility of sending back the ACAM configuration |
-- registers that are received through CSR WISHBONE writes. |
-- |
-- All the registers are of size 32 bits, as the WISHBONE dat bus |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 10/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.std_logic_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for reg_ctrl
--=================================================================================================
entity reg_ctrl is
generic
(g_span : integer := 32;
g_width : integer := 32);
port
-- INPUTS
-- Signals from the clk_rst_manager unit
(clk_i : in std_logic; -- 125 MHz
rst_i : in std_logic; -- global reset
-- Signals from the GNUM_core unit: WISHBONE classic for TDC core and ACAM regs transfer
gnum_csr_adr_i : in std_logic_vector(g_span-1 downto 0); -- WISHBONE classic address
gnum_csr_cyc_i : in std_logic; -- WISHBONE classic cycle
gnum_csr_dat_i : in std_logic_vector(g_width-1 downto 0);-- WISHBONE classic data in
gnum_csr_stb_i : in std_logic; -- WISHBONE classic strobe
gnum_csr_we_i : in std_logic; -- WISHBONE classic write enable
-- Signals from the data_engine unit: config regs from the ACAM
acam_config_rdbk_i : in config_vector; -- array keeping values read from ACAM regs 0-7, 11, 12, 14
acam_status_i : in std_logic_vector(g_width-1 downto 0);-- keeps value read from ACAM reg 12
acam_ififo1_i : in std_logic_vector(g_width-1 downto 0);-- keeps value read from ACAM reg 8; for debug reasons only
acam_ififo2_i : in std_logic_vector(g_width-1 downto 0);-- keeps value read from ACAM reg 9; for debug reasons only
acam_start01_i : in std_logic_vector(g_width-1 downto 0);-- keeps value read from ACAM reg 10; for debug reasons only
-- Signals from the data_formatting unit
wr_index_i : in std_logic_vector(g_width-1 downto 0);-- index of the last circular_buffer adr written
-- Signals from the one_hz_gen unit
local_utc_i : in std_logic_vector(g_width-1 downto 0);-- local utc time
-- Signals not used so far
core_status_i : in std_logic_vector(g_width-1 downto 0);-- TDC core status word
irq_code_i : in std_logic_vector(g_width-1 downto 0);-- TDC core interrupt code word
-- OUTPUTS
-- Signals to the GNUM_core unit: WISHBONE classic for TDC core and ACAM regs transfer
gnum_csr_ack_o : out std_logic; -- WISHBONE classic acknowledge
gnum_csr_dat_o : out std_logic_vector(g_width-1 downto 0);-- WISHBONE classic data out
-- Signals to the data_engine unit: config regs for the ACAM
acam_config_o : out config_vector;
-- Signals to the data_engine unit: TDC core functionality
activate_acq_p_o : out std_logic; -- activates tstamps aquisition from ACAM
deactivate_acq_p_o : out std_logic; -- activates ACAM configuration readings/ writings
acam_wr_config_p_o : out std_logic; -- enables writing to ACAM regs 0-7, 11, 12, 14
acam_rdbk_config_p_o : out std_logic; -- enables reading of ACAM regs 0-7, 11, 12, 14
acam_rst_p_o : out std_logic; -- enables writing the c_RESET_WORD to ACAM reg 4
acam_rdbk_status_p_o : out std_logic; -- enables reading of ACAM reg 12
acam_rdbk_ififo1_p_o : out std_logic; -- enables reading of ACAM reg 8
acam_rdbk_ififo2_p_o : out std_logic; -- enables reading of ACAM reg 9
acam_rdbk_start01_p_o : out std_logic; -- enables reading of ACAM reg 10
-- Signal to the data_formatting unit
dacapo_c_rst_p_o : out std_logic; -- clears the dacapo counter
-- Signals to the clks_resets_manager ubit
send_dac_word_p_o : out std_logic; -- starts spi_dac_
dac_word_o : out std_logic_vector(23 downto 0);
-- Signal to the one_hz_gen unit
load_utc_p_o : out std_logic;
starting_utc_o : out std_logic_vector(g_width-1 downto 0);
irq_tstamp_threshold_o: out std_logic_vector(g_width-1 downto 0);
irq_time_threshold_o : out std_logic_vector(g_width-1 downto 0);
one_hz_phase_o : out std_logic_vector(g_width-1 downto 0); -- for debug only
-- Signal to the mezzanine board
acam_inputs_en_o : out std_logic_vector(g_width-1 downto 0); -- enables ACAM stop inputs
-- Signal to the acam_timecontrol_interface unit -- maybe not needed ???
start_phase_o : out std_logic_vector(g_width-1 downto 0));
end reg_ctrl;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of reg_ctrl is
signal acam_config : config_vector;
signal reg_adr : std_logic_vector(7 downto 0);
signal starting_utc, acam_inputs_en, start_phase : std_logic_vector(g_width-1 downto 0);
signal ctrl_reg, one_hz_phase, irq_tstamp_threshold : std_logic_vector(g_width-1 downto 0);
signal irq_time_threshold : std_logic_vector(g_width-1 downto 0);
signal clear_ctrl_reg, send_dac_word_p : std_logic;
signal dac_word : std_logic_vector(23 downto 0);
signal pulse_extender_en : std_logic;
signal pulse_extender_c : std_logic_vector(2 downto 0);
signal dat_out : std_logic_vector(g_span-1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
reg_adr <= gnum_csr_adr_i(7 downto 0); -- we are interested in addresses 0:20000 to 0:2000FC
---------------------------------------------------------------------------------------------------
-- WISHBONE ACK to GNUM core --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- gnum_csr_ack_generator: generation of the WISHBONE classic acknowledge signal for the
-- interactions with the GNUM core.
gnum_csr_ack_generator: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
gnum_csr_ack_o <= '0';
else
gnum_csr_ack_o <= gnum_csr_stb_i and gnum_csr_cyc_i;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Reception of ACAM Configuration Registers --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- acam_config_reg_reception: reception from the PCIe interface (through GNUM_core WISHBONE CSR) of
-- the configuration registers to be loaded to the ACAM chip. The received data is stored in the
-- acam_config vector which is input to the data_engine and the acam_databus_interface units for
-- the further transfer to the ACAM chip.
acam_config_reg_reception: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
acam_config(0) <= (others =>'0');
acam_config(1) <= (others =>'0');
acam_config(2) <= (others =>'0');
acam_config(3) <= (others =>'0');
acam_config(4) <= (others =>'0');
acam_config(5) <= (others =>'0');
acam_config(6) <= (others =>'0');
acam_config(7) <= (others =>'0');
acam_config(8) <= (others =>'0');
acam_config(9) <= (others =>'0');
acam_config(10) <= (others =>'0');
elsif gnum_csr_cyc_i = '1' and gnum_csr_stb_i = '1' and gnum_csr_we_i = '1' then -- WISHBONE writes
if reg_adr = c_ACAM_REG0_ADR then
acam_config(0) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG1_ADR then
acam_config(1) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG2_ADR then
acam_config(2) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG3_ADR then
acam_config(3) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG4_ADR then
acam_config(4) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG5_ADR then
acam_config(5) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG6_ADR then
acam_config(6) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG7_ADR then
acam_config(7) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG11_ADR then
acam_config(8) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG12_ADR then
acam_config(9) <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_REG14_ADR then
acam_config(10) <= gnum_csr_dat_i;
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- --
acam_config_o <= acam_config;
---------------------------------------------------------------------------------------------------
-- Reception of TDC core Configuration Registers --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- TDCcore_config_reg_reception: reception from the PCIe interface of the configuration registers
-- to be loaded locally.
-- The following information is received:
-- o acam_inputs_en : for the activation of the TDC input signals
-- o irq_tstamp_threshold : for the activation of PCIe interrupts based on the number of timestamps
-- o irq_time_threshold : for the activation of PCIe interrupts based on the time elapsed
-- o starting_utc : definition of the current UTC time
-- o one_hz_phase : eva: think not used
-- o start_phase : eva: think not used
TDCcore_config_reg_reception: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
acam_inputs_en <= (others =>'0');
starting_utc <= (others =>'0');
start_phase <= (others =>'0');
one_hz_phase <= (others =>'0');
irq_tstamp_threshold <= x"00000100"; -- default 256 timestamps: full memory
irq_time_threshold <= x"00000078"; -- default 2 minutes
dac_word <= c_DEFAULT_DAC_WORD; -- for DAC Vout = 1.65
elsif gnum_csr_cyc_i = '1' and gnum_csr_stb_i = '1' and gnum_csr_we_i = '1' then -- WISHBONE writes
if reg_adr = c_STARTING_UTC_ADR then
starting_utc <= gnum_csr_dat_i;
end if;
if reg_adr = c_ACAM_INPUTS_EN_ADR then
acam_inputs_en <= gnum_csr_dat_i;
end if;
if reg_adr = c_START_PHASE_ADR then
start_phase <= gnum_csr_dat_i;
end if;
if reg_adr = c_ONE_HZ_PHASE_ADR then
one_hz_phase <= gnum_csr_dat_i;
end if;
if reg_adr = c_IRQ_TSTAMP_THRESH_ADR then
irq_tstamp_threshold <= gnum_csr_dat_i;
end if;
if reg_adr = c_IRQ_TIME_THRESH_ADR then
irq_time_threshold <= gnum_csr_dat_i;
end if;
if reg_adr = c_DAC_WORD_ADR then
dac_word <= gnum_csr_dat_i(23 downto 0);
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- --
starting_utc_o <= starting_utc;
acam_inputs_en_o <= acam_inputs_en;
start_phase_o <= start_phase;
one_hz_phase_o <= one_hz_phase;
irq_tstamp_threshold_o <= irq_tstamp_threshold;
irq_time_threshold_o <= irq_time_threshold;
dac_word_o <= dac_word;
---------------------------------------------------------------------------------------------------
-- Reception of TDC core Control Register --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- TDCcore_ctrl_reg_reception: reception from the PCIe interface of the control register that
-- defines the action to be taken by the TDC core.
-- Note that only one bit of the register should be written at a time. The process receives
-- the register, defines the action to be taken and after 1 clk cycle clears the register.
TDCcore_ctrl_reg_reception: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
ctrl_reg <= (others =>'0');
clear_ctrl_reg <= '0';
elsif clear_ctrl_reg = '1' then
ctrl_reg <= (others =>'0');
clear_ctrl_reg <= '0';
elsif gnum_csr_cyc_i = '1' and gnum_csr_stb_i = '1' and gnum_csr_we_i = '1' then -- WISHBONE writes
if reg_adr = c_CTRL_REG_ADR then
ctrl_reg <= gnum_csr_dat_i;
clear_ctrl_reg <= '1';
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- --
activate_acq_p_o <= ctrl_reg(0);
deactivate_acq_p_o <= ctrl_reg(1);
acam_wr_config_p_o <= ctrl_reg(2);
acam_rdbk_config_p_o <= ctrl_reg(3);
acam_rdbk_status_p_o <= ctrl_reg(4);
acam_rdbk_ififo1_p_o <= ctrl_reg(5);
acam_rdbk_ififo2_p_o <= ctrl_reg(6);
acam_rdbk_start01_p_o <= ctrl_reg(7);
acam_rst_p_o <= ctrl_reg(8);
load_utc_p_o <= ctrl_reg(9);
dacapo_c_rst_p_o <= ctrl_reg(10);
send_dac_word_p <= ctrl_reg(11);
-- ctrl_reg bits 12 to 31 not used for the moment!
-- -- -- -- -- -- -- -- -- -- -- --
-- Pulse_stretcher: Increases the width of the send_dac_word_p pulse so that it can be sampled
-- by the 20 MHz clock of the clks_rsts_manager that is communicating with the DAC.
Pulse_stretcher: incr_counter
generic map
(width => 3)
port map
(clk_i => clk_i,
rst_i => send_dac_word_p,
counter_top_i => "111",
counter_incr_en_i => pulse_extender_en,
counter_is_full_o => open,
counter_o => pulse_extender_c);
pulse_extender_en <= '1' when pulse_extender_c < "111" else '0';
send_dac_word_p_o <= pulse_extender_en;
---------------------------------------------------------------------------------------------------
-- Delivery of ACAM and TDC core Readback Registers --
---------------------------------------------------------------------------------------------------
-- TDCcore_ctrl_reg_reception: Delivery to the PCIe interface of all the readable registers,
-- including those of the ACAM and the TDC core.
WISHBONEreads: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i = '1' then
gnum_csr_dat_o <= (others =>'0');
elsif gnum_csr_cyc_i = '1' and gnum_csr_stb_i = '1' and gnum_csr_we_i = '0' then -- WISHBONE reads
gnum_csr_dat_o <= dat_out;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
with reg_adr select dat_out <=
-- regs written by the PCIe
acam_config(0) when c_ACAM_REG0_ADR,
acam_config(1) when c_ACAM_REG1_ADR,
acam_config(2) when c_ACAM_REG2_ADR,
acam_config(3) when c_ACAM_REG3_ADR,
acam_config(4) when c_ACAM_REG4_ADR,
acam_config(5) when c_ACAM_REG5_ADR,
acam_config(6) when c_ACAM_REG6_ADR,
acam_config(7) when c_ACAM_REG7_ADR,
acam_config(8) when c_ACAM_REG11_ADR,
acam_config(9) when c_ACAM_REG12_ADR,
acam_config(10) when c_ACAM_REG14_ADR,
-- regs read from the ACAM
acam_config_rdbk_i(0) when c_ACAM_REG0_RDBK_ADR,
acam_config_rdbk_i(1) when c_ACAM_REG1_RDBK_ADR,
acam_config_rdbk_i(2) when c_ACAM_REG2_RDBK_ADR,
acam_config_rdbk_i(3) when c_ACAM_REG3_RDBK_ADR,
acam_config_rdbk_i(4) when c_ACAM_REG4_RDBK_ADR,
acam_config_rdbk_i(5) when c_ACAM_REG5_RDBK_ADR,
acam_config_rdbk_i(6) when c_ACAM_REG6_RDBK_ADR,
acam_config_rdbk_i(7) when c_ACAM_REG7_RDBK_ADR,
acam_ififo1_i when c_ACAM_REG8_RDBK_ADR,
acam_ififo2_i when c_ACAM_REG9_RDBK_ADR,
acam_start01_i when c_ACAM_REG10_RDBK_ADR,
acam_config_rdbk_i(8) when c_ACAM_REG11_RDBK_ADR,
acam_config_rdbk_i(9) when c_ACAM_REG12_RDBK_ADR,
acam_config_rdbk_i(10) when c_ACAM_REG14_RDBK_ADR,
-- regs written by the PCIe
starting_utc when c_STARTING_UTC_ADR,
acam_inputs_en when c_ACAM_INPUTS_EN_ADR,
start_phase when c_START_PHASE_ADR,
one_hz_phase when c_ONE_HZ_PHASE_ADR,
irq_tstamp_threshold when c_IRQ_TSTAMP_THRESH_ADR,
irq_time_threshold when c_IRQ_TIME_THRESH_ADR,
x"00" & dac_word when c_DAC_WORD_ADR,
-- regs written locally by the TDC core units
local_utc_i when c_LOCAL_UTC_ADR,
irq_code_i when c_IRQ_CODE_ADR,
wr_index_i when c_WR_INDEX_ADR,
core_status_i when c_CORE_STATUS_ADR,
-- others
x"C0FFEEEE" when others;
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- start_retrig_ctrl |
-- |
---------------------------------------------------------------------------------------------------
-- File start_retrig_ctrl.vhd |
-- |
-- Description The unit provides the main components for the calculation of the "Coarse time" of |
-- the final timestamps. These components are sent to the data_formatting unit where |
-- the actual Coarse time calculation takes place. |
-- |
-- As a reminder, the final timestamp is a 128-bits word divided in four 32-bits |
-- words with the following structure: |
-- |
-- [127:96] Timestamp Metadata (ex. Channel, Slope) |
-- |
-- [95:64] Local UTC time from the one_hz_generator; each bit represents 1 s |
-- |
-- [63:32] Coarse time within the current second; each bit represents 8 ns |
-- |
-- [31:0] Fine time to be added to the Coarse time: provided directly by Acam; |
-- each bit represents 81.03 ps |
-- |
-- In I-Mode the Acam chip provides unlimited measuring range with internal start |
-- retriggers. Acam is programmed to retrigger every (16*acam_clk_period) = |
-- (64*clk_i_period) = 512 ns; the StartTimer in Acam Reg 4 is set to 15. It counts |
-- the number of retriggers after a Start pulse and upon the arrival of a Stop pulse |
-- and it sends this number in the "Start#" field of the timestamp. |
-- Unfortunately Acam's counter of the retriggers has only 8 bits and can count up |
-- to 256 retriggers. Within one second (our UTC time) there can be up to |
-- 1,953,125 retriggers, which is >> 256 and actually corresponds to 7629 overflows |
-- of the Acam counter. Therefore there is the need to follow Acam and keep track of |
-- the overflows. The Acam Interrupt flag (IrFlag pin 59) has been set to follow the |
-- highest bit of the Start# (through the Acam Reg 12 bit 26) and like this we |
-- manage to count retriggers synchronously to Acam itself. |
-- For simplification, in the following figure we assume that two Stop signals arrive|
-- after less than 256 Acam internal retriggers. Therefore in the timestamps that |
-- Acam will give the Start# field will represent the exact amount of retriggers |
-- after the Start pulse. |
-- Note that the interval between this external Start pulse and the first internal |
-- retrigger may vary; it is measured by the Acam chip and stored as Start01 in Acam |
-- Reg 10. Moreover, there is the StartOff1 offset added to each Hit time by Acam |
-- (this does not appear in this figure) made available in Acam Reg 5. |
-- However, in this TDC core application we are only interested in time differences |
-- between Stop pulses (ex. Stop2 - Stop1) and not in the precise arrival time of a |
-- Stop pulse. Since now both Start01 and StartOff1 are stable numbers affecting |
-- equally all the Stop pulses, they would disappear during the subtraction (which |
-- takes place at the software side) and therefore thay are used in our calculations.|
-- |
-- Start ____|-|__________________________________________________________________________ |
-- Retriggers ________________|-|________________|-|________________|-|________________|-|_____ |
-- Stop1 _________________________________________________|-|_____________________________ |
-- Hit1 <------------->
-- Stop2 _____________________________________________________________________________|-|_ |
-- Hit2 <--> |
-- Start01 <----------> |
-- |
-- Coming back now to our timestamp format {UTC second, Coarse time, Fine time}, we |
-- have to somehow assosiate ACAM retriggers to the UTC time. Actually, Acam has no |
-- knowledge of the UTC time and the arrival of a new second happens completely |
-- independently. As the following figure shows the final timestamp of a Stop pulse |
-- is defined by the current UTC time plus the amount of time between that UTC and |
-- the Stop pulse: (2)+(3). Part (3) is provided exclusively by the Acam chip in the |
-- Start# and Hit time fields of the timestamp. The sum of (1)+(2) is multiples of |
-- 256 Acam retriggers and can be defined by following the Acam output IrFlag. |
-- Now Part (1), is the one that associates the arrival of a UTC second with the Acam|
-- time counting and is defined in this unit by following the Acam retriggers. |
-- |
-- IrFlag ______________|--------------|______________|-------------|... _____________|--- |
-- ___________________________ ___________________________ _____________ |
-- new UTC sec| _|-|_ || | | |
-- Stop1 | || | ... | _|-|_ |
-- |___________________________||___________________________| |______________ |
-- (1) |
-- |----------------| |
-- (2) |
-- |---------------------------------------------| |
-- (3) |
-- |-------| |
-- |
-- To conclude, the final Coarse time is: (Part(2) + Part(3)_Start#)*Retrigger period|
-- and the Fine time is : Part(3)_Hit |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.11 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 07/2011 v0.1 GP First version |
-- 04/2012 v0.11 EG Revamping; Comments added, signals renamed |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions-- Specific library
-- Specific library
library work;
use work.tdc_core_pkg.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for start_retrig_ctrl
--=================================================================================================
entity start_retrig_ctrl is
generic
(g_width : integer := 32);
port
-- INPUTS
-- Signal from the clk_rst_manager
(clk_i : in std_logic;
rst_i : in std_logic;
-- Signal from the acam_timecontrol_interface
acam_intflag_f_edge_p_i : in std_logic;
-- Signal from the one_hz_generator unit
one_hz_p_i : in std_logic;
-- OUTPUTS
-- Signals to the data_formatting unit
roll_over_incr_recent_o : out std_logic;
clk_i_cycles_offset_o : out std_logic_vector(g_width-1 downto 0);
roll_over_nb_o : out std_logic_vector(g_width-1 downto 0);
retrig_nb_offset_o : out std_logic_vector(g_width-1 downto 0));
end start_retrig_ctrl;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of start_retrig_ctrl is
signal clk_i_cycles_offset : std_logic_vector(g_width-1 downto 0);
signal current_cycles : std_logic_vector(g_width-1 downto 0);
signal current_retrig_nb : std_logic_vector(g_width-1 downto 0);
signal retrig_nb_offset : std_logic_vector(g_width-1 downto 0);
signal retrig_p : std_logic;
signal roll_over_c : std_logic_vector(g_width-1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
-- retrigger # : 0 1 127 128 255 256 257 383 384 385 511 512 513
-- retriggers : _|____|____...____|____|____...____|____|____|____...___|____|____|____...____|____|____|___
-- IrFlag : __________________|---------------------|____________________|---------------------|________
-- IrFlag_f_edge_p : ______________________________________|-|________________________________________|-|________
-- retrig_p : |-|__|-|__ ... __|-|__|-|__ ... __|-|__|-|__|-|__ ...__|-|__|-|__|-|___ ...__|-|__|-|__|-|___
-- current_retrig_nb: 0 1 127 128 255 0 1 127 128 129 255 0 1
-- one_hz_p_i : _____________________|-|_______________________________________________________________
-- roll_over_c : 0 1 2
-- retrig_nb_offset : 127
-- clk_i_cycles_offs: |..| (counts clk_i cycles from the pulse to the end of this retrigger)
--
-- At the moment that a new second arrives through the one_hz_p_i, we:
-- o keep note of the current_retrig_nb, 127 in this case (stored in retrig_nb_offset)
-- o keep note of the current_cycles, that is the number of clk_i cycles between the one_hz_p_i
-- and the next (128th) retrigger (stored in clk_i_cycles_offset)
-- o reinitialize the roll_over_c counter which starts counting rollovers of the current_retrig_nb
--
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- In this more macroscopic example we have included a Stop pulse arriving to the ACAM chip.
-- Each one of the n boxes represents 256 ACAM internal retriggers, which through the IrFlag are
-- synchronous with the counters in this unit. The coarse time is the amount of clk_i cycles
-- between the one_hz_p_i pulse and the ACAM Stop pulse. To the coarse time we then have to add the
-- fine time, which is the very precise 81ps resolution time measured by the ACAM. Note that the
-- ACAM can only provide timing information within the last box: the Start# (bits 25:18) indicates
-- the amount of internal retriggers and the Hit (bits 16:0) indicates the fine timing. The time
-- difference between the one_hz_p_i pulse and the last box is calculated through the counters of
-- this unit: roll_over_c, retrig_nb_offset, clk_i_cycles_offset.
-- Note that since the counting in the roll_over_c starts from 0, we do not need to subtract 1
-- so as not to consider the last, n-th, box. Similarly, for the retrig_nb_offset and ACAM Start#,
-- to calculate the amount of complete retriggers that have preceded the arrival of the
-- one_hz_p_i and the Stop pulse respectively, we would have to subtract 1, but since counting
-- starts from zero, we don't.
-- Finally, note that the the current_cycles counter is a decreasing counter giving the amount of
-- clk_i cycles between the resing edge of the one_hz_pulse_i and the next retrigger.
-- Note that in this project we are only interested in time differences between
-- _______________________________________ _________________________________________ ____________________
-- one_hz_p_i | _|-|_ || | |
-- ACAM Stop pulse | || | | _|-|_
-- | || | ... |
-- roll_over_c | 0 ||1 | |n-1
-- |_______________________________________||_________________________________________| |____________________
-- (1)
-- |----------------------------|
-- (2)
-- |-----------------------------------------------------------|
-- (3)
-- |--------|
-- (1): ((retrig_nb_offset + 1) * retrig_period) - (clk_i_cycles_offset)
-- (2): (roll_over_c * 256 * retrig_period) - (the amount that (1) represents)
-- (3): from ACAM tstamps: (Start# * retrig_period) + (Fine time: Hit)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- These two counters keep a track of the current internal start retrigger
-- of the Acam in parallel with the Acam itself. Counting up to c_ACAM_RETRIG_PERIOD = 64
retrig_period_counter: free_counter -- retrigger periods
generic map
(width => g_width)
port map
(clk_i => clk_i,
rst_i => acam_intflag_f_edge_p_i,
counter_en_i => '1',
counter_top_i => c_ACAM_RETRIG_PERIOD,
-------------------------------------------
counter_is_zero_o => retrig_p,
counter_o => current_cycles);
-------------------------------------------
retrig_nb_counter: incr_counter -- number of retriggers counting from 0 to 255 and restarting
generic map -- through the acam_intflag_f_edge_p_i
(width => g_width)
port map
(clk_i => clk_i,
rst_i => acam_intflag_f_edge_p_i,
counter_top_i => x"00000100",
counter_incr_en_i => retrig_p,
counter_is_full_o => open,
-------------------------------------------
counter_o => current_retrig_nb);
-------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- This counter keeps track of the number of overflows of the Acam counter within one second
roll_over_counter: incr_counter
generic map
(width => g_width)
port map
(clk_i => clk_i,
rst_i => one_hz_p_i,
counter_top_i => x"FFFFFFFF",
counter_incr_en_i => acam_intflag_f_edge_p_i,
counter_is_full_o => open,
counter_o => roll_over_c);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- When a new second starts, all values are captured and stored as offsets.
-- when a timestamps arrives, these offset will be subrstracted in order
-- to base the final timestamp with respect to the current second.
capture_offset: process (clk_i)
begin
if rising_edge (clk_i) then
if rst_i ='1' then
clk_i_cycles_offset <= (others=>'0');
retrig_nb_offset <= (others=>'0');
elsif one_hz_p_i = '1' then
clk_i_cycles_offset <= current_cycles;
retrig_nb_offset <= current_retrig_nb;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- outputs
roll_over_incr_recent_o <= '1' when unsigned(current_retrig_nb) < 64 else '0';
clk_i_cycles_offset_o <= clk_i_cycles_offset;
retrig_nb_offset_o <= retrig_nb_offset;
roll_over_nb_o <= roll_over_c;
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- tdc_core_pkg |
-- |
---------------------------------------------------------------------------------------------------
-- File tdc_core_pkg.vhd |
-- |
-- Description Package containing core wide constants and components |
-- |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 04/2012 |
-- Version v0.2 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 07/2011 v0.1 GP First version |
-- 04/2012 v0.2 EG Revamping; Gathering of all the constants, declarations of all the |
-- units; Comments added, signals renamed |
-- |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
use work.wishbone_pkg.all;
use work.sdb_meta_pkg.all;
--=================================================================================================
-- Package declaration for tdc_core_pkg
--=================================================================================================
package tdc_core_pkg is
---------------------------------------------------------------------------------------------------
-- Constant regarding the Mezzanine DAC configuration --
---------------------------------------------------------------------------------------------------
-- Vout = Vref (DAC_WORD/ 65536); for Vout = 1.65V, with Vref = 2.5V the DAC_WORD = xA8F5
constant c_DEFAULT_DAC_WORD : std_logic_vector(23 downto 0) := x"00A8F5";
---------------------------------------------------------------------------------------------------
-- Constants regarding the SDB crossbar --
---------------------------------------------------------------------------------------------------
-- Note: All address in sdb and crossbar are BYTE addresses!
-- Master ports on the wishbone crossbar
constant c_NUM_WB_MASTERS : integer := 7;
constant c_SLAVE_DMA : integer := 0; -- DMA controller in the Gennum core
constant c_SLAVE_SPEC_ONEWIRE: integer := 1; -- Carrier onewire interface
constant c_SLAVE_SPEC_CSR : integer := 2; -- Info on SPEC control and status registers
constant c_SLAVE_TDC_CORE : integer := 3; -- TDC core
constant c_SLAVE_INT : integer := 4; -- Interrupt controller
constant c_SLAVE_FMC_SYS_I2C : integer := 5; -- Mezzanine system I2C interface (EEPROM)
constant c_SLAVE_FMC_ONEWIRE : integer := 6; -- Mezzanine onewire interface
-- Slave port on the wishbone crossbar
constant c_NUM_WB_SLAVES : integer := 1;
constant c_MASTER_GENNUM : integer := 0;
-- SDB header address
constant c_SDB_ADDRESS : t_wishbone_address := x"00000000";
-- Devices sdb description
constant c_DMA_SDB_DEVICE : t_sdb_device :=
(abi_class => x"0000", -- undocumented device
abi_ver_major => x"01",
abi_ver_minor => x"01",
wbd_endian => c_sdb_endian_big,
wbd_width => x"4", -- 32-bit port granularity
sdb_component =>
(addr_first => x"0000000000000000",
addr_last => x"000000000000003F",
product =>
(vendor_id => x"000000000000CE42", -- CERN
device_id => x"00000601",
version => x"00000001",
date => x"20121116",
name => "WB-DMA.Control ")));
constant c_ONEWIRE_SDB_DEVICE : t_sdb_device :=
(abi_class => x"0000", -- undocumented device
abi_ver_major => x"01",
abi_ver_minor => x"01",
wbd_endian => c_sdb_endian_big,
wbd_width => x"4", -- 32-bit port granularity
sdb_component =>
(addr_first => x"0000000000000000",
addr_last => x"0000000000000007",
product =>
(vendor_id => x"000000000000CE42", -- CERN
device_id => x"00000602",
version => x"00000001",
date => x"20121116",
name => "WB-Onewire.Control ")));
constant c_SPEC_CSR_SDB_DEVICE : t_sdb_device :=
(abi_class => x"0000", -- undocumented device
abi_ver_major => x"01",
abi_ver_minor => x"01",
wbd_endian => c_sdb_endian_big,
wbd_width => x"4", -- 32-bit port granularity
sdb_component =>
(addr_first => x"0000000000000000",
addr_last => x"000000000000001F",
product =>
(vendor_id => x"000000000000CE42", -- CERN
device_id => x"00000603",
version => x"00000001",
date => x"20121116",
name => "WB-SPEC-CSR ")));
constant c_TDC_SDB_DEVICE : t_sdb_device :=
(abi_class => x"0000", -- undocumented device
abi_ver_major => x"01",
abi_ver_minor => x"01",
wbd_endian => c_sdb_endian_big,
wbd_width => x"4", -- 32-bit port granularity
sdb_component =>
(addr_first => x"0000000000000000",
addr_last => x"00000000000000FF",
product =>
(vendor_id => x"000000000000CE42", -- CERN
device_id => x"00000604",
version => x"00000001",
date => x"20130429",
name => "WB-TDC-Core ")));
constant c_INT_SDB_DEVICE : t_sdb_device :=
(abi_class => x"0000", -- undocumented device
abi_ver_major => x"01",
abi_ver_minor => x"01",
wbd_endian => c_sdb_endian_big,
wbd_width => x"4", -- 32-bit port granularity
sdb_component =>
(addr_first => x"0000000000000000",
addr_last => x"000000000000000F",
product =>
(vendor_id => x"000000000000CE42", -- CERN
device_id => x"00000605",
version => x"00000001",
date => x"20121116",
name => "WB-Int.Control ")));
constant c_I2C_SDB_DEVICE : t_sdb_device :=
(abi_class => x"0000", -- undocumented device
abi_ver_major => x"01",
abi_ver_minor => x"01",
wbd_endian => c_sdb_endian_big,
wbd_width => x"4", -- 32-bit port granularity
sdb_component =>
(addr_first => x"0000000000000000",
addr_last => x"000000000000001F",
product =>
(vendor_id => x"000000000000CE42", -- CERN
device_id => x"00000606",
version => x"00000001",
date => x"20121116",
name => "WB-I2C.Control ")));
-- Wishbone crossbar layout
constant c_INTERCONNECT_LAYOUT : t_sdb_record_array(9 downto 0) :=
(0 => f_sdb_embed_device(c_DMA_SDB_DEVICE, x"00004000"),
1 => f_sdb_embed_device(c_ONEWIRE_SDB_DEVICE, x"00004800"),
2 => f_sdb_embed_device(c_SPEC_CSR_SDB_DEVICE, x"00004C00"),
3 => f_sdb_embed_device(c_TDC_SDB_DEVICE, x"00005000"),
4 => f_sdb_embed_device(c_INT_SDB_DEVICE, x"00005400"),
5 => f_sdb_embed_device(c_I2C_SDB_DEVICE, x"00005800"),
6 => f_sdb_embed_device(c_ONEWIRE_SDB_DEVICE, x"00005C00"),
7 => f_sdb_embed_repo_url(c_SDB_REPO_URL),
8 => f_sdb_embed_synthesis(c_SDB_SYNTHESIS),
9 => f_sdb_embed_integration(c_SDB_INTEGRATION));
---------------------------------------------------------------------------------------------------
-- Constants regarding 1 Hz pulse generation --
---------------------------------------------------------------------------------------------------
-- for synthesis: 1 sec = x"07735940" clk_i cycles (1 clk_i cycle = 8ns)
constant c_SYN_CLK_PERIOD : std_logic_vector(31 downto 0) := x"07735940";
-- for simulation: 1 msec = x"0001E848" clk_i cycles (1 clk_i cycle = 8ns)
constant c_SIM_CLK_PERIOD : std_logic_vector(31 downto 0) := x"0001E848";
---------------------------------------------------------------------------------------------------
-- Vector with the 11 ACAM Configuration Registers --
---------------------------------------------------------------------------------------------------
subtype config_register is std_logic_vector(31 downto 0);
type config_vector is array (10 downto 0) of config_register;
---------------------------------------------------------------------------------------------------
-- Constants regarding addressing of the ACAM registers --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- Addresses of ACAM configuration registers to be written by the PCIe host
-- corresponds to:
constant c_ACAM_REG0_ADR : std_logic_vector(7 downto 0) := x"00"; -- address 5000 of gnum BAR 0
constant c_ACAM_REG1_ADR : std_logic_vector(7 downto 0) := x"01"; -- address 5004 of gnum BAR 0
constant c_ACAM_REG2_ADR : std_logic_vector(7 downto 0) := x"02"; -- address 5008 of gnum BAR 0
constant c_ACAM_REG3_ADR : std_logic_vector(7 downto 0) := x"03"; -- address 500C of gnum BAR 0
constant c_ACAM_REG4_ADR : std_logic_vector(7 downto 0) := x"04"; -- address 5010 of gnum BAR 0
constant c_ACAM_REG5_ADR : std_logic_vector(7 downto 0) := x"05"; -- address 5014 of gnum BAR 0
constant c_ACAM_REG6_ADR : std_logic_vector(7 downto 0) := x"06"; -- address 5018 of gnum BAR 0
constant c_ACAM_REG7_ADR : std_logic_vector(7 downto 0) := x"07"; -- address 501C of gnum BAR 0
constant c_ACAM_REG11_ADR : std_logic_vector(7 downto 0) := x"0B"; -- address 502C of gnum BAR 0
constant c_ACAM_REG12_ADR : std_logic_vector(7 downto 0) := x"0C"; -- address 5030 of gnum BAR 0
constant c_ACAM_REG14_ADR : std_logic_vector(7 downto 0) := x"0E"; -- address 5038 of gnum BAR 0
---------------------------------------------------------------------------------------------------
-- Addresses of ACAM read-only registers, to be written by the ACAM and used within the core to access ACAM timestamps
constant c_ACAM_REG8_ADR : std_logic_vector(7 downto 0) := x"08"; -- not accessible for writing from PCI-e
constant c_ACAM_REG9_ADR : std_logic_vector(7 downto 0) := x"09"; -- not accessible for writing from PCI-e
constant c_ACAM_REG10_ADR : std_logic_vector(7 downto 0) := x"0A"; -- not accessible for writing from PCI-e
---------------------------------------------------------------------------------------------------
-- Addresses of ACAM configuration readback registers, to be written by the ACAM
-- corresponds to:
constant c_ACAM_REG0_RDBK_ADR : std_logic_vector(7 downto 0) := x"10"; -- address 5040 of the gnum BAR 0
constant c_ACAM_REG1_RDBK_ADR : std_logic_vector(7 downto 0) := x"11"; -- address 5044 of the gnum BAR 0
constant c_ACAM_REG2_RDBK_ADR : std_logic_vector(7 downto 0) := x"12"; -- address 5048 of the gnum BAR 0
constant c_ACAM_REG3_RDBK_ADR : std_logic_vector(7 downto 0) := x"13"; -- address 504C of the gnum BAR 0
constant c_ACAM_REG4_RDBK_ADR : std_logic_vector(7 downto 0) := x"14"; -- address 5050 of the gnum BAR 0
constant c_ACAM_REG5_RDBK_ADR : std_logic_vector(7 downto 0) := x"15"; -- address 5054 of the gnum BAR 0
constant c_ACAM_REG6_RDBK_ADR : std_logic_vector(7 downto 0) := x"16"; -- address 5058 of the gnum BAR 0
constant c_ACAM_REG7_RDBK_ADR : std_logic_vector(7 downto 0) := x"17"; -- address 505C of the gnum BAR 0
constant c_ACAM_REG8_RDBK_ADR : std_logic_vector(7 downto 0) := x"18"; -- address 5060 of the gnum BAR 0
constant c_ACAM_REG9_RDBK_ADR : std_logic_vector(7 downto 0) := x"19"; -- address 5064 of the gnum BAR 0
constant c_ACAM_REG10_RDBK_ADR : std_logic_vector(7 downto 0) := x"1A"; -- address 5068 of the gnum BAR 0
constant c_ACAM_REG11_RDBK_ADR : std_logic_vector(7 downto 0) := x"1B"; -- address 506C of the gnum BAR 0
constant c_ACAM_REG12_RDBK_ADR : std_logic_vector(7 downto 0) := x"1C"; -- address 5070 of the gnum BAR 0
constant c_ACAM_REG14_RDBK_ADR : std_logic_vector(7 downto 0) := x"1E"; -- address 5078 of the gnum BAR 0
---------------------------------------------------------------------------------------------------
-- Constants regarding addressing of the TDC core registers --
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- Addresses of TDC core Configuration registers to be written by the PCIe host
-- corresponds to:
constant c_STARTING_UTC_ADR : std_logic_vector(7 downto 0) := x"20"; -- address 5080 of gnum BAR 0
constant c_ACAM_INPUTS_EN_ADR : std_logic_vector(7 downto 0) := x"21"; -- address 5084 of gnum BAR 0
constant c_START_PHASE_ADR : std_logic_vector(7 downto 0) := x"22"; -- address 5088 of gnum BAR 0
constant c_ONE_HZ_PHASE_ADR : std_logic_vector(7 downto 0) := x"23"; -- address 508C of gnum BAR 0
constant c_IRQ_TSTAMP_THRESH_ADR: std_logic_vector(7 downto 0) := x"24"; -- address 5090 of gnum BAR 0
constant c_IRQ_TIME_THRESH_ADR : std_logic_vector(7 downto 0) := x"25"; -- address 5094 of gnum BAR 0
constant c_DAC_WORD_ADR : std_logic_vector(7 downto 0) := x"26"; -- address 5098 of gnum BAR 0
-- constant c_RESERVED1 : std_logic_vector(7 downto 0) := x"27"; -- address 509C of gnum BAR 0
---------------------------------------------------------------------------------------------------
-- Addresses of TDC core Status registers to be written by the different core units
-- corresponds to:
constant c_LOCAL_UTC_ADR : std_logic_vector(7 downto 0) := x"28"; -- address 50A0 of gnum BAR 0
constant c_IRQ_CODE_ADR : std_logic_vector(7 downto 0) := x"29"; -- address 50A4 of gnum BAR 0
constant c_WR_INDEX_ADR : std_logic_vector(7 downto 0) := x"2A"; -- address 50A8 of gnum BAR 0
constant c_CORE_STATUS_ADR : std_logic_vector(7 downto 0) := x"2B"; -- address 50AC of gnum BAR 0
---------------------------------------------------------------------------------------------------
-- Address of TDC core Control register
-- corresponds to:
constant c_CTRL_REG_ADR : std_logic_vector(7 downto 0) := x"3F"; -- address 50FC of gnum BAR 0
---------------------------------------------------------------------------------------------------
-- Constants regarding ACAM retriggers --
---------------------------------------------------------------------------------------------------
-- Number of clk_i cycles corresponding to the Acam retrigger period;
-- through Acam Reg 4 StartTimer the chip is programmed to retrigger every:
-- (15+1) * acam_ref_clk = (15+1) * 32 ns
-- x"00000040" * clk_i = 64 * 8 ns
-- 512 ns
constant c_ACAM_RETRIG_PERIOD : std_logic_vector(31 downto 0) := x"00000040";
-- Used to multiply by 64, which is the retrigger period in clk_i cycles
constant c_ACAM_RETRIG_PERIOD_SHIFT : integer := 6;
---------------------------------------------------------------------------------------------------
-- Constants regarding TDC & SPEC LEDs --
---------------------------------------------------------------------------------------------------
constant c_SPEC_LED_PERIOD_SIM : std_logic_vector(31 downto 0) := x"00004E20"; -- 1 ms at 20 MHz
constant c_SPEC_LED_PERIOD_SYN : std_logic_vector(31 downto 0) := x"01312D00"; -- 1 s at 20 MHz
constant c_BLINK_LGTH_SYN : std_logic_vector(31 downto 0) := x"00BEBC20"; -- 100 ms at 125 MHz
constant c_BLINK_LGTH_SIM : std_logic_vector(31 downto 0) := x"000004E2"; -- 10 us at 125 MHz
--c_RESET_WORD
---------------------------------------------------------------------------------------------------
-- Constants regarding the Circular Buffer --
---------------------------------------------------------------------------------------------------
constant c_CIRCULAR_BUFF_SIZE : unsigned(31 downto 0) := x"00000100";
---------------------------------------------------------------------------------------------------
-- Constants regarding the One-Wire interface --
---------------------------------------------------------------------------------------------------
constant c_FMC_ONE_WIRE_NB : integer := 1;
---------------------------------------------------------------------------------------------------
-- Constants regarding the Carrier CSR info --
---------------------------------------------------------------------------------------------------
constant c_CARRIER_TYPE : std_logic_vector(15 downto 0) := X"0001";
---------------------------------------------------------------------------------------------------
-- Components Declarations: --
---------------------------------------------------------------------------------------------------
component fmc_tdc_core
generic
(g_span : integer := 32;
g_width : integer := 32;
values_for_simul : boolean := FALSE);
port
(spec_clk_i : in std_logic;
rst_n_a_i : in std_logic;
tdc_clk_125m_o : out std_logic;
tdc_rst_n_o : out std_logic;
pll_sclk_o : out std_logic;
pll_sdi_o : out std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdo_i : in std_logic;
pll_status_i : in std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
acam_refclk_p_i : in std_logic;
acam_refclk_n_i : in std_logic;
start_from_fpga_o : out std_logic;
err_flag_i : in std_logic;
int_flag_i : in std_logic;
start_dis_o : out std_logic;
stop_dis_o : out std_logic;
data_bus_io : inout std_logic_vector(27 downto 0);
address_o : out std_logic_vector(3 downto 0);
cs_n_o : out std_logic;
oe_n_o : out std_logic;
rd_n_o : out std_logic;
wr_n_o : out std_logic;
ef1_i : in std_logic;
ef2_i : in std_logic;
tdc_in_fpga_1_i : in std_logic;
tdc_in_fpga_2_i : in std_logic;
tdc_in_fpga_3_i : in std_logic;
tdc_in_fpga_4_i : in std_logic;
tdc_in_fpga_5_i : in std_logic;
enable_inputs_o : out std_logic;
term_en_1_o : out std_logic;
term_en_2_o : out std_logic;
term_en_3_o : out std_logic;
term_en_4_o : out std_logic;
term_en_5_o : out std_logic;
tdc_led_status_o : out std_logic;
tdc_led_trig1_o : out std_logic;
tdc_led_trig2_o : out std_logic;
tdc_led_trig3_o : out std_logic;
tdc_led_trig4_o : out std_logic;
tdc_led_trig5_o : out std_logic;
spec_led_green_o : out std_logic;
spec_led_red_o : out std_logic;
spec_aux0_i : in std_logic;
spec_aux1_i : in std_logic;
spec_aux2_o : out std_logic;
spec_aux3_o : out std_logic;
spec_aux4_o : out std_logic;
spec_aux5_o : out std_logic;
irq_tstamp_p_o : out std_logic;
irq_time_p_o : out std_logic;
irq_acam_err_p_o : out std_logic;
gnum_csr_adr_i : in std_logic_vector(g_span-1 downto 0);
gnum_csr_dat_i : in std_logic_vector(g_width-1 downto 0);
gnum_csr_stb_i : in std_logic;
gnum_csr_we_i : in std_logic;
gnum_csr_cyc_i : in std_logic;
gnum_csr_dat_o : out std_logic_vector(g_width-1 downto 0);
gnum_csr_ack_o : out std_logic;
gnum_dma_adr_i : in std_logic_vector(31 downto 0);
gnum_dma_dat_i : in std_logic_vector(31 downto 0);
gnum_dma_stb_i : in std_logic;
gnum_dma_we_i : in std_logic;
gnum_dma_cyc_i : in std_logic;
gnum_dma_ack_o : out std_logic;
gnum_dma_dat_o : out std_logic_vector(31 downto 0);
gnum_dma_stall_o : out std_logic);
end component;
---------------------------------------------------------------------------------------------------
component decr_counter
generic
(width : integer := 32);
port
(clk_i : in std_logic;
rst_i : in std_logic;
counter_load_i : in std_logic;
counter_top_i : in std_logic_vector(width-1 downto 0);
-------------------------------------------------------------
counter_is_zero_o : out std_logic;
counter_o : out std_logic_vector(width-1 downto 0));
-------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component free_counter is
generic
(width : integer := 32);
port
(clk_i : in std_logic;
counter_en_i : in std_logic;
rst_i : in std_logic;
counter_top_i : in std_logic_vector(width-1 downto 0);
-------------------------------------------------------------
counter_is_zero_o : out std_logic;
counter_o : out std_logic_vector(width-1 downto 0));
-------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component incr_counter
generic
(width : integer := 32);
port
(clk_i : in std_logic;
counter_top_i : in std_logic_vector(width-1 downto 0);
counter_incr_en_i : in std_logic;
rst_i : in std_logic;
-------------------------------------------------------------
counter_is_full_o : out std_logic;
counter_o : out std_logic_vector(width-1 downto 0));
-------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
component start_retrig_ctrl
generic
(g_width : integer := 32);
port
(clk_i : in std_logic;
rst_i : in std_logic;
acam_intflag_f_edge_p_i : in std_logic;
one_hz_p_i : in std_logic;
----------------------------------------------------------------------
roll_over_incr_recent_o : out std_logic;
clk_i_cycles_offset_o : out std_logic_vector(g_width-1 downto 0);
roll_over_nb_o : out std_logic_vector(g_width-1 downto 0);
retrig_nb_offset_o : out std_logic_vector(g_width-1 downto 0));
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component one_hz_gen
generic
(g_width : integer := 32);
port
(acam_refclk_r_edge_p_i : in std_logic;
clk_i : in std_logic;
clk_period_i : in std_logic_vector(g_width-1 downto 0);
load_utc_p_i : in std_logic;
pulse_delay_i : in std_logic_vector(g_width-1 downto 0);
rst_i : in std_logic;
starting_utc_i : in std_logic_vector(g_width-1 downto 0);
----------------------------------------------------------------------
local_utc_o : out std_logic_vector(g_width-1 downto 0);
one_hz_p_o : out std_logic);
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component data_engine
port
(acam_ack_i : in std_logic;
acam_dat_i : in std_logic_vector(31 downto 0);
clk_i : in std_logic;
rst_i : in std_logic;
acam_ef1_i : in std_logic;
acam_ef1_synch1_i : in std_logic;
acam_ef2_i : in std_logic;
acam_ef2_synch1_i : in std_logic;
activate_acq_p_i : in std_logic;
deactivate_acq_p_i : in std_logic;
acam_wr_config_p_i : in std_logic;
acam_rdbk_config_p_i : in std_logic;
acam_rdbk_status_p_i : in std_logic;
acam_rdbk_ififo1_p_i : in std_logic;
acam_rdbk_ififo2_p_i : in std_logic;
acam_rdbk_start01_p_i : in std_logic;
acam_rst_p_i : in std_logic;
acam_config_i : in config_vector;
----------------------------------------------------------------------
acam_adr_o : out std_logic_vector(7 downto 0);
acam_cyc_o : out std_logic;
acam_dat_o : out std_logic_vector(31 downto 0);
acam_stb_o : out std_logic;
acam_we_o : out std_logic;
acam_config_rdbk_o : out config_vector;
acam_status_o : out std_logic_vector(31 downto 0);
acam_ififo1_o : out std_logic_vector(31 downto 0);
acam_ififo2_o : out std_logic_vector(31 downto 0);
acam_start01_o : out std_logic_vector(31 downto 0);
acam_tstamp1_o : out std_logic_vector(31 downto 0);
acam_tstamp1_ok_p_o : out std_logic;
acam_tstamp2_o : out std_logic_vector(31 downto 0);
acam_tstamp2_ok_p_o : out std_logic);
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component reg_ctrl
generic
(g_span : integer := 32;
g_width : integer := 32);
port
(clk_i : in std_logic;
rst_i : in std_logic;
gnum_csr_adr_i : in std_logic_vector(g_span-1 downto 0);
gnum_csr_cyc_i : in std_logic;
gnum_csr_dat_i : in std_logic_vector(g_width-1 downto 0);
gnum_csr_stb_i : in std_logic;
gnum_csr_we_i : in std_logic;
acam_config_rdbk_i : in config_vector;
acam_status_i : in std_logic_vector(g_width-1 downto 0);
acam_ififo1_i : in std_logic_vector(g_width-1 downto 0);
acam_ififo2_i : in std_logic_vector(g_width-1 downto 0);
acam_start01_i : in std_logic_vector(g_width-1 downto 0);
local_utc_i : in std_logic_vector(g_width-1 downto 0);
irq_code_i : in std_logic_vector(g_width-1 downto 0);
wr_index_i : in std_logic_vector(g_width-1 downto 0);
core_status_i : in std_logic_vector(g_width-1 downto 0);
----------------------------------------------------------------------
gnum_csr_ack_o : out std_logic;
gnum_csr_dat_o : out std_logic_vector(g_width-1 downto 0);
activate_acq_p_o : out std_logic;
deactivate_acq_p_o : out std_logic;
acam_wr_config_p_o : out std_logic;
acam_rdbk_config_p_o : out std_logic;
acam_rdbk_status_p_o : out std_logic;
acam_rdbk_ififo1_p_o : out std_logic;
acam_rdbk_ififo2_p_o : out std_logic;
acam_rdbk_start01_p_o : out std_logic;
acam_rst_p_o : out std_logic;
load_utc_p_o : out std_logic;
irq_tstamp_threshold_o : out std_logic_vector(g_width-1 downto 0);
irq_time_threshold_o : out std_logic_vector(g_width-1 downto 0);
send_dac_word_p_o : out std_logic;
dac_word_o : out std_logic_vector(23 downto 0);
dacapo_c_rst_p_o : out std_logic;
acam_config_o : out config_vector;
starting_utc_o : out std_logic_vector(g_width-1 downto 0);
acam_inputs_en_o : out std_logic_vector(g_width-1 downto 0);
start_phase_o : out std_logic_vector(g_width-1 downto 0);
one_hz_phase_o : out std_logic_vector(g_width-1 downto 0));
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component acam_timecontrol_interface
port
(err_flag_i : in std_logic;
int_flag_i : in std_logic;
acam_refclk_r_edge_p_i : in std_logic;
clk_i : in std_logic;
activate_acq_p_i : in std_logic;
rst_i : in std_logic;
window_delay_i : in std_logic_vector(31 downto 0);
----------------------------------------------------------------------
start_from_fpga_o : out std_logic;
acam_errflag_r_edge_p_o : out std_logic;
acam_errflag_f_edge_p_o : out std_logic;
acam_intflag_f_edge_p_o : out std_logic);
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component data_formatting
port
(tstamp_wr_wb_ack_i : in std_logic;
tstamp_wr_dat_i : in std_logic_vector(127 downto 0);
acam_tstamp1_i : in std_logic_vector(31 downto 0);
acam_tstamp1_ok_p_i : in std_logic;
acam_tstamp2_i : in std_logic_vector(31 downto 0);
acam_tstamp2_ok_p_i : in std_logic;
clk_i : in std_logic;
dacapo_c_rst_p_i : in std_logic;
rst_i : in std_logic;
roll_over_incr_recent_i : in std_logic;
clk_i_cycles_offset_i : in std_logic_vector(31 downto 0);
roll_over_nb_i : in std_logic_vector(31 downto 0);
local_utc_i : in std_logic_vector(31 downto 0);
retrig_nb_offset_i : in std_logic_vector(31 downto 0);
one_hz_p_i : in std_logic;
----------------------------------------------------------------------
tstamp_wr_wb_adr_o : out std_logic_vector(7 downto 0);
tstamp_wr_wb_cyc_o : out std_logic;
tstamp_wr_dat_o : out std_logic_vector(127 downto 0);
tstamp_wr_wb_stb_o : out std_logic;
tstamp_wr_wb_we_o : out std_logic;
tstamp_wr_p_o : out std_logic;
wr_index_o : out std_logic_vector(31 downto 0));
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component irq_generator is
generic
(g_width : integer := 32);
port
(clk_i : in std_logic;
rst_i : in std_logic;
irq_tstamp_threshold_i : in std_logic_vector(g_width-1 downto 0);
irq_time_threshold_i : in std_logic_vector(g_width-1 downto 0);
activate_acq_p_i : in std_logic;
deactivate_acq_p_i : in std_logic;
tstamp_wr_p_i : in std_logic;
one_hz_p_i : in std_logic;
----------------------------------------------------------------------
irq_tstamp_p_o : out std_logic;
irq_time_p_o : out std_logic);
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component irq_controller
port
(clk_i : in std_logic;
rst_n_i : in std_logic;
irq_src_p_i : in std_logic_vector(31 downto 0);
wb_adr_i : in std_logic_vector(1 downto 0);
wb_dat_i : in 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_dat_o : out std_logic_vector(31 downto 0);
wb_ack_o : out std_logic;
irq_p_o : out std_logic);
end component irq_controller;
---------------------------------------------------------------------------------------------------
component clks_rsts_manager
generic
(nb_of_reg : integer := 68);
port
(spec_clk_i : in std_logic;
acam_refclk_p_i : in std_logic;
acam_refclk_n_i : in std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
rst_n_a_i : in std_logic;
pll_status_i : in std_logic;
pll_sdo_i : in std_logic;
send_dac_word_p_i : in std_logic;
dac_word_i : in std_logic_vector(23 downto 0);
----------------------------------------------------------------------
tdc_clk_o : out std_logic;
internal_rst_o : out std_logic;
spec_clk_o : out std_logic;
gnum_rst_o : out std_logic;
acam_refclk_r_edge_p_o : out std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdi_o : out std_logic;
pll_sclk_o : out std_logic;
pll_status_o : out std_logic);
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component carrier_csr
port
(rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(1 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_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;
carrier_csr_carrier_pcb_rev_i : in std_logic_vector(3 downto 0);
carrier_csr_carrier_reserved_i : in std_logic_vector(11 downto 0);
carrier_csr_carrier_type_i : in std_logic_vector(15 downto 0);
carrier_csr_stat_fmc_pres_i : in std_logic;
carrier_csr_stat_p2l_pll_lck_i : in std_logic;
carrier_csr_stat_sys_pll_lck_i : in std_logic;
carrier_csr_stat_ddr3_cal_done_i : in std_logic;
carrier_csr_stat_reserved_i : in std_logic_vector(27 downto 0);
carrier_csr_ctrl_led_green_o : out std_logic;
carrier_csr_ctrl_led_red_o : out std_logic;
carrier_csr_ctrl_dac_clr_n_o : out std_logic;
carrier_csr_ctrl_reserved_o : out std_logic_vector(28 downto 0));
end component carrier_csr;
---------------------------------------------------------------------------------------------------
component leds_manager is
generic
(g_width : integer := 32;
values_for_simul : boolean := FALSE);
port
(clk_20mhz_i : in std_logic;
clk_125mhz_i : in std_logic;
gnum_rst_i : in std_logic;
internal_rst_i : in std_logic;
pll_status_i : in std_logic;
spec_aux_butt_1_i : in std_logic;
spec_aux_butt_2_i : in std_logic;
one_hz_p_i : in std_logic;
acam_inputs_en_i : in std_logic_vector(g_width-1 downto 0);
----------------------------------------------------------------------
tdc_led_status_o : out std_logic;
tdc_led_trig1_o : out std_logic;
tdc_led_trig2_o : out std_logic;
tdc_led_trig3_o : out std_logic;
tdc_led_trig4_o : out std_logic;
tdc_led_trig5_o : out std_logic;
spec_led_green_o : out std_logic;
spec_led_red_o : out std_logic;
spec_aux_led_1_o : out std_logic;
spec_aux_led_2_o : out std_logic;
spec_aux_led_3_o : out std_logic;
spec_aux_led_4_o : out std_logic);
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component acam_databus_interface
port
(ef1_i : in std_logic;
ef2_i : in std_logic;
data_bus_io : inout std_logic_vector(27 downto 0);
clk_i : in std_logic;
rst_i : in std_logic;
adr_i : in std_logic_vector(7 downto 0);
cyc_i : in std_logic;
dat_i : in std_logic_vector(31 downto 0);
stb_i : in std_logic;
we_i : in std_logic;
----------------------------------------------------------------------
adr_o : out std_logic_vector(3 downto 0);
cs_n_o : out std_logic;
oe_n_o : out std_logic;
rd_n_o : out std_logic;
wr_n_o : out std_logic;
ack_o : out std_logic;
ef1_o : out std_logic;
ef1_synch1_o : out std_logic;
ef2_o : out std_logic;
ef2_synch1_o : out std_logic;
dat_o : out std_logic_vector(31 downto 0));
----------------------------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component circular_buffer
port
(clk_i : in std_logic;
tstamp_wr_rst_i : in std_logic;
tstamp_wr_stb_i : in std_logic;
tstamp_wr_cyc_i : in std_logic;
tstamp_wr_we_i : in std_logic;
tstamp_wr_adr_i : in std_logic_vector(7 downto 0);
tstamp_wr_dat_i : in std_logic_vector(127 downto 0);
gnum_dma_rst_i : in std_logic;
gnum_dma_stb_i : in std_logic;
gnum_dma_cyc_i : in std_logic;
gnum_dma_we_i : in std_logic;
gnum_dma_adr_i : in std_logic_vector(31 downto 0);
gnum_dma_dat_i : in std_logic_vector(31 downto 0);
--------------------------------------------------
tstamp_wr_ack_p_o : out std_logic;
tstamp_wr_dat_o : out std_logic_vector(127 downto 0);
gnum_dma_ack_o : out std_logic;
gnum_dma_dat_o : out std_logic_vector(31 downto 0);
gnum_dma_stall_o : out std_logic);
--------------------------------------------------
end component;
---------------------------------------------------------------------------------------------------
component blk_mem_circ_buff_v6_4
port
(clka : in std_logic;
addra : in std_logic_vector(7 downto 0);
dina : in std_logic_vector(127 downto 0);
ena : in std_logic;
wea : in std_logic_vector(0 downto 0);
clkb : in std_logic;
addrb : in std_logic_vector(9 downto 0);
dinb : in std_logic_vector(31 downto 0);
enb : in std_logic;
web : in std_logic_vector(0 downto 0);
--------------------------------------------------
douta : out std_logic_vector(127 downto 0);
doutb : out std_logic_vector(31 downto 0));
--------------------------------------------------
end component;
end tdc_core_pkg;
--=================================================================================================
-- package body
--=================================================================================================
package body tdc_core_pkg is
end tdc_core_pkg;
--=================================================================================================
-- package end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
"AD9516 Setup File"
"Rev.","1.1.0"
""
"Addr(Hex)","Value(Bin)","Value(Hex)"
"0000","00011000","18"
"0001","00000000","00"
"0002","00010000","10"
"0003","11000011","C3"
"0004","00000000","00"
"0010","01111100","7C"
"0011","00000001","01"
"0012","00000000","00"
"0013","00000011","03"
"0014","00001001","09"
"0015","00000000","00"
"0016","00000100","04"
"0017","00000000","00"
"0018","00000111","07"
"0019","00000000","00"
"001A","00000000","00"
"001B","00000000","00"
"001C","00000010","02"
"001D","00000000","00"
"001E","00000000","00"
"001F","00001110","0E"
"00A0","00000001","01"
"00A1","00000000","00"
"00A2","00000000","00"
"00A3","00000001","01"
"00A4","00000000","00"
"00A5","00000000","00"
"00A6","00000001","01"
"00A7","00000000","00"
"00A8","00000000","00"
"00A9","00000001","01"
"00AA","00000000","00"
"00AB","00000000","00"
"00F0","00001010","0A"
"00F1","00001010","0A"
"00F2","00001010","0A"
"00F3","00001010","0A"
"00F4","00001010","0A"
"00F5","00001010","0A"
"0140","01001010","4A"
"0141","01011010","5A"
"0142","01000011","43"
"0143","01000010","42"
"0190","00000000","00"
"0191","10000000","80"
"0192","00000000","00"
"0193","10111011","BB"
"0194","00000000","00"
"0195","00000000","00"
"0196","00000000","00"
"0197","00000000","00"
"0198","00000000","00"
"0199","00100010","22"
"019A","00000000","00"
"019B","00010001","11"
"019C","00000000","00"
"019D","00000000","00"
"019E","00100010","22"
"019F","00000000","00"
"01A0","00010001","11"
"01A1","00100000","20"
"01A2","00000000","00"
"01A3","00000000","00"
"01E0","00000000","00"
"01E1","00000010","02"
"0230","00000000","00"
"0231","00000000","00"
"0232","00000000","00"
"","",""
"Other Settings..."
"REF 1:",20
"REF 2:",30.72
"VCO:",1500
"CLK:",1200
"CPRSet:",5100
"Auto Update:",1
"Load All Regs:",1
----------------------------------------------------------------------------------------------------
-- CERN-BE-CO-HT
----------------------------------------------------------------------------------------------------
--
-- unit name : Clock and reset management unit (clk_rst_managr.vhd)
-- author : G. Penacoba
-- date : May 2011
-- version : Revision 1
-- description : independent block that uses the spec clk to parameterize
-- the TDC mezzanine PLL that will be used by all the other
-- blocks. Includes input clk buffers for Xilinx Spartan6.
-- dependencies:
-- references :
-- modified by :
--
----------------------------------------------------------------------------------------------------
-- last changes:
----------------------------------------------------------------------------------------------------
-- to do:
----------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library UNISIM;
use UNISIM.vcomponents.all;
----------------------------------------------------------------------------------------------------
-- entity declaration for clk_rst_managr
----------------------------------------------------------------------------------------------------
entity clk_rst_managr is
generic(
nb_of_reg : integer:=68
);
port(
acam_refclk_i : in std_logic;
pll_ld_i : in std_logic;
pll_refmon_i : in std_logic;
pll_sdo_i : in std_logic;
pll_status_i : in std_logic;
gnum_reset_i : in std_logic;
spec_clk_i : in std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
acam_refclk_o : out std_logic;
general_reset_o : out std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdi_o : out std_logic;
pll_sclk_o : out std_logic;
spec_clk_o : out std_logic;
tdc_clk_o : out std_logic
);
end clk_rst_managr;
----------------------------------------------------------------------------------------------------
-- architecture declaration for clk_rst_managr
----------------------------------------------------------------------------------------------------
architecture rtl of clk_rst_managr is
component incr_counter
generic(
width : integer :=32
);
port(
clk : in std_logic;
end_value : in std_logic_vector(width-1 downto 0);
incr : in std_logic;
reset : in std_logic;
count_done : out std_logic;
current_value : out std_logic_vector(width-1 downto 0)
);
end component;
subtype t_wd is std_logic_vector(15 downto 0);
subtype t_byte is std_logic_vector(7 downto 0);
type t_instr is array (nb_of_reg-1 downto 0) of t_wd;
type t_stream is array (nb_of_reg-1 downto 0) of t_byte;
type t_pll_init_st is (start, sending_instruction, sending_data, rest, done);
-- the PLL circuit AD9516-4 needs to be configured through 68 registers
-- the values and addresses are obtained from a dedicated Analog Devices
-- software and from the datasheet.
constant reg_000 : t_byte:=x"18";
constant reg_001 : t_byte:=x"00";
constant reg_002 : t_byte:=x"10";
constant reg_003 : t_byte:=x"C3";
constant reg_004 : t_byte:=x"00";
constant reg_010 : t_byte:=x"7C";
constant reg_011 : t_byte:=x"01";
constant reg_012 : t_byte:=x"00";
constant reg_013 : t_byte:=x"03";
constant reg_014 : t_byte:=x"09";
constant reg_015 : t_byte:=x"00";
constant reg_016 : t_byte:=x"04";
constant reg_017 : t_byte:=x"00";
constant reg_018 : t_byte:=x"07";
constant reg_019 : t_byte:=x"00";
constant reg_01A : t_byte:=x"00";
constant reg_01B : t_byte:=x"00";
constant reg_01C : t_byte:=x"02";
constant reg_01D : t_byte:=x"00";
constant reg_01E : t_byte:=x"00";
constant reg_01F : t_byte:=x"0E";
constant reg_0A0 : t_byte:=x"01";
constant reg_0A1 : t_byte:=x"00";
constant reg_0A2 : t_byte:=x"00";
constant reg_0A3 : t_byte:=x"01";
constant reg_0A4 : t_byte:=x"00";
constant reg_0A5 : t_byte:=x"00";
constant reg_0A6 : t_byte:=x"01";
constant reg_0A7 : t_byte:=x"00";
constant reg_0A8 : t_byte:=x"00";
constant reg_0A9 : t_byte:=x"01";
constant reg_0AA : t_byte:=x"00";
constant reg_0AB : t_byte:=x"00";
constant reg_0F0 : t_byte:=x"0A";
constant reg_0F1 : t_byte:=x"0A";
constant reg_0F2 : t_byte:=x"0A";
constant reg_0F3 : t_byte:=x"0A";
constant reg_0F4 : t_byte:=x"0A";
constant reg_0F5 : t_byte:=x"0A";
constant reg_140 : t_byte:=x"4A";
constant reg_141 : t_byte:=x"5A";
constant reg_142 : t_byte:=x"43";
constant reg_143 : t_byte:=x"42";
constant reg_190 : t_byte:=x"00";
constant reg_191 : t_byte:=x"80";
constant reg_192 : t_byte:=x"00";
constant reg_193 : t_byte:=x"00";
constant reg_194 : t_byte:=x"80";
constant reg_195 : t_byte:=x"00";
constant reg_196 : t_byte:=x"00";
constant reg_197 : t_byte:=x"80";
constant reg_198 : t_byte:=x"00";
constant reg_199 : t_byte:=x"22";
constant reg_19A : t_byte:=x"00";
constant reg_19B : t_byte:=x"11";
constant reg_19C : t_byte:=x"00";
constant reg_19D : t_byte:=x"00";
constant reg_19E : t_byte:=x"22";
constant reg_19F : t_byte:=x"00";
constant reg_1A0 : t_byte:=x"11";
constant reg_1A1 : t_byte:=x"20";
constant reg_1A2 : t_byte:=x"00";
constant reg_1A3 : t_byte:=x"00";
constant reg_1E0 : t_byte:=x"00";
constant reg_1E1 : t_byte:=x"02";
constant reg_230 : t_byte:=x"00";
constant reg_231 : t_byte:=x"00";
constant reg_232 : t_byte:=x"01";
signal pll_init_st : t_pll_init_st;
signal nxt_pll_init_st : t_pll_init_st;
signal config_reg : t_stream;
signal address : t_instr;
signal acam_refclk_buf : std_logic;
signal spec_clk_buf : std_logic;
signal tdc_clk_buf : std_logic;
signal acam_refclk : std_logic;
signal pll_sclk : std_logic;
signal spec_clk : std_logic;
signal tdc_clk : std_logic;
signal bit_being_sent : std_logic;
signal word_being_sent : t_wd;
signal bit_index : integer range 15 downto 0;
signal byte_index : integer range nb_of_reg-1 downto 0;
signal silly_altern : std_logic;
signal gnum_reset : std_logic;
signal gral_incr : std_logic;
signal inv_reset : std_logic;
signal cs : std_logic;
----------------------------------------------------------------------------------------------------
-- architecture begins
----------------------------------------------------------------------------------------------------
begin
--Clock input buffer instantiations
-----------------------------------
tdc_clk125_ibuf : IBUFDS
generic map (
DIFF_TERM => false, -- Differential Termination
IBUF_LOW_PWR => true, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
IOSTANDARD => "DEFAULT"
)
port map (
O => tdc_clk_buf, -- Buffer output
I => tdc_clk_p_i, -- Diff_p buffer input (connect directly to top-level port)
IB => tdc_clk_n_i -- Diff_n buffer input (connect directly to top-level port)
);
tdc_clk125_gbuf : BUFG
port map (
O => tdc_clk,
I => tdc_clk_buf
);
spec_clk_ibuf : IBUFG
port map (
I => spec_clk_i,
O => spec_clk_buf
);
spec_clk_gbuf : BUFG
port map (
O => spec_clk,
I => spec_clk_buf
);
-- acam_refclk_ibuf : IBUFG
-- port map (
-- I => acam_refclk_i,
-- O => acam_refclk_buf
-- );
--
-- acam_refclk_gbuf : BUFG
-- port map (
-- O => acam_refclk,
-- I => acam_refclk_buf
-- );
acam_refclk <= acam_refclk_i;
general_poreset: incr_counter
port map(
clk => spec_clk,
end_value => x"0000007D", -- 125 clk ticks
incr => gral_incr,
reset => gnum_reset,
count_done => inv_reset,
current_value => open
);
silly: process
begin
if gnum_reset ='1' then
silly_altern <= '0';
else
silly_altern <= not(silly_altern);
end if;
wait until spec_clk ='1';
end process;
gral_reset_incr: process(silly_altern, tdc_clk)
begin
if silly_altern ='0' then
gral_incr <= '0';
elsif rising_edge(tdc_clk) then
gral_incr <= '1';
end if;
end process;
-- Processes for initialization of the PLL
------------------------------------------
pll_initialization_seq: process
begin
if gnum_reset ='1' then
pll_init_st <= start;
else
pll_init_st <= nxt_pll_init_st;
end if;
wait until spec_clk ='1';
end process;
pll_initialization_comb: process(pll_init_st, byte_index, bit_index, pll_sclk)
begin
case pll_init_st is
when start =>
cs <= '1';
if pll_sclk ='1' then
nxt_pll_init_st <= sending_instruction;
else
nxt_pll_init_st <= start;
end if;
when sending_instruction =>
cs <= '0';
if bit_index = 0
and pll_sclk = '1' then
nxt_pll_init_st <= sending_data;
else
nxt_pll_init_st <= sending_instruction;
end if;
when sending_data =>
cs <= '0';
if bit_index = 0
and pll_sclk = '1' then
nxt_pll_init_st <= rest;
else
nxt_pll_init_st <= sending_data;
end if;
when rest =>
cs <= '1';
if pll_sclk = '1' then
if byte_index = 0 then
nxt_pll_init_st <= done;
else
nxt_pll_init_st <= sending_instruction;
end if;
else
nxt_pll_init_st <= rest;
end if;
when done =>
cs <= '1';
nxt_pll_init_st <= done;
when others =>
cs <= '1';
nxt_pll_init_st <= start;
end case;
end process;
index_control: process
begin
if gnum_reset ='1' then
bit_index <= 15;
elsif cs ='1' then
bit_index <= 15;
elsif pll_sclk ='1' then
if bit_index = 0 then
bit_index <= 7;
else
bit_index <= bit_index -1;
end if;
end if;
if gnum_reset ='1' then
byte_index <= nb_of_reg -1;
elsif pll_init_st = rest and pll_sclk ='1' then
if byte_index = 0 then
byte_index <= nb_of_reg-1;
else
byte_index <= byte_index -1;
end if;
end if;
wait until spec_clk ='1';
end process;
pll_sclk_generator: process
begin
if gnum_reset ='1' then
pll_sclk <= '0';
else
pll_sclk <= not(pll_sclk);
end if;
wait until spec_clk ='1';
end process;
bit_being_sent <= word_being_sent(bit_index);
word_being_sent <= address(byte_index) when pll_init_st = sending_instruction
else x"00" & config_reg(byte_index);
-- Assignement of the values to be sent for the configurations of the PLL
-------------------------------------------------------------------------
-- according to the datasheet the register 232 should be written last
-- to validate the transfer from the buffer to the valid registers
-- the 16-bit instruction word indicates always a write cycle of byte
address(0) <= x"0232";
address(1) <= x"0000";
address(2) <= x"0001";
address(3) <= x"0002";
address(4) <= x"0003";
address(5) <= x"0004";
address(6) <= x"0010";
address(7) <= x"0011";
address(8) <= x"0012";
address(9) <= x"0013";
address(10) <= x"0014";
address(11) <= x"0015";
address(12) <= x"0016";
address(13) <= x"0017";
address(14) <= x"0018";
address(15) <= x"0019";
address(16) <= x"001A";
address(17) <= x"001B";
address(18) <= x"001C";
address(19) <= x"001D";
address(20) <= x"001E";
address(21) <= x"001F";
address(22) <= x"00A0";
address(23) <= x"00A1";
address(24) <= x"00A2";
address(25) <= x"00A3";
address(26) <= x"00A4";
address(27) <= x"00A5";
address(28) <= x"00A6";
address(29) <= x"00A7";
address(30) <= x"00A8";
address(31) <= x"00A9";
address(32) <= x"00AA";
address(33) <= x"00AB";
address(34) <= x"00F0";
address(35) <= x"00F1";
address(36) <= x"00F2";
address(37) <= x"00F3";
address(38) <= x"00F4";
address(39) <= x"00F5";
address(40) <= x"0140";
address(41) <= x"0141";
address(42) <= x"0142";
address(43) <= x"0143";
address(44) <= x"0190";
address(45) <= x"0191";
address(46) <= x"0192";
address(47) <= x"0193";
address(48) <= x"0194";
address(49) <= x"0195";
address(50) <= x"0196";
address(51) <= x"0197";
address(52) <= x"0198";
address(53) <= x"0199";
address(54) <= x"019A";
address(55) <= x"019B";
address(56) <= x"019C";
address(57) <= x"019D";
address(58) <= x"019E";
address(59) <= x"019F";
address(60) <= x"01A0";
address(61) <= x"01A1";
address(62) <= x"01A2";
address(63) <= x"01A3";
address(64) <= x"01E0";
address(65) <= x"01E1";
address(66) <= x"0230";
address(67) <= x"0231";
config_reg(0) <= reg_232;
config_reg(1) <= reg_000;
config_reg(2) <= reg_001;
config_reg(3) <= reg_002;
config_reg(4) <= reg_003;
config_reg(5) <= reg_004;
config_reg(6) <= reg_010;
config_reg(7) <= reg_011;
config_reg(8) <= reg_012;
config_reg(9) <= reg_013;
config_reg(10) <= reg_014;
config_reg(11) <= reg_015;
config_reg(12) <= reg_016;
config_reg(13) <= reg_017;
config_reg(14) <= reg_018;
config_reg(15) <= reg_019;
config_reg(16) <= reg_01A;
config_reg(17) <= reg_01B;
config_reg(18) <= reg_01C;
config_reg(19) <= reg_01D;
config_reg(20) <= reg_01E;
config_reg(21) <= reg_01F;
config_reg(22) <= reg_0A0;
config_reg(23) <= reg_0A1;
config_reg(24) <= reg_0A2;
config_reg(25) <= reg_0A3;
config_reg(26) <= reg_0A4;
config_reg(27) <= reg_0A5;
config_reg(28) <= reg_0A6;
config_reg(29) <= reg_0A7;
config_reg(30) <= reg_0A8;
config_reg(31) <= reg_0A9;
config_reg(32) <= reg_0AA;
config_reg(33) <= reg_0AB;
config_reg(34) <= reg_0F0;
config_reg(35) <= reg_0F1;
config_reg(36) <= reg_0F2;
config_reg(37) <= reg_0F3;
config_reg(38) <= reg_0F4;
config_reg(39) <= reg_0F5;
config_reg(40) <= reg_140;
config_reg(41) <= reg_141;
config_reg(42) <= reg_142;
config_reg(43) <= reg_143;
config_reg(44) <= reg_190;
config_reg(45) <= reg_191;
config_reg(46) <= reg_192;
config_reg(47) <= reg_193;
config_reg(48) <= reg_194;
config_reg(49) <= reg_195;
config_reg(50) <= reg_196;
config_reg(51) <= reg_197;
config_reg(52) <= reg_198;
config_reg(53) <= reg_199;
config_reg(54) <= reg_19A;
config_reg(55) <= reg_19B;
config_reg(56) <= reg_19C;
config_reg(57) <= reg_19D;
config_reg(58) <= reg_19E;
config_reg(59) <= reg_19F;
config_reg(60) <= reg_1A0;
config_reg(61) <= reg_1A1;
config_reg(62) <= reg_1A2;
config_reg(63) <= reg_1A3;
config_reg(64) <= reg_1E0;
config_reg(65) <= reg_1E1;
config_reg(66) <= reg_230;
config_reg(67) <= reg_231;
-- Input and Output signals
---------------------------
gnum_reset <= gnum_reset_i;
acam_refclk_o <= acam_refclk;
general_reset_o <= not(inv_reset);
pll_cs_o <= cs;
pll_sdi_o <= bit_being_sent;
pll_sclk_o <= pll_sclk;
spec_clk_o <= spec_clk;
tdc_clk_o <= tdc_clk;
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- CERN-BE-CO-HT
----------------------------------------------------------------------------------------------------
--
-- unit name : Clock and reset management unit (clk_rst_managr.vhd)
-- author : G. Penacoba
-- date : May 2011
-- version : Revision 1
-- description : independent block that uses the spec clk to parameterize
-- the TDC mezzanine PLL that will be used by all the other
-- blocks. Includes input clk buffers for Xilinx Spartan6.
-- dependencies:
-- references :
-- modified by :
--
----------------------------------------------------------------------------------------------------
-- last changes:
----------------------------------------------------------------------------------------------------
-- to do:
----------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library UNISIM;
use UNISIM.vcomponents.all;
----------------------------------------------------------------------------------------------------
-- entity declaration for clk_rst_managr
----------------------------------------------------------------------------------------------------
entity clk_rst_managr is
generic(
nb_of_reg : integer:=563
);
port(
acam_refclk_i : in std_logic;
pll_ld_i : in std_logic;
pll_refmon_i : in std_logic;
pll_sdo_i : in std_logic;
pll_status_i : in std_logic;
gnum_reset_i : in std_logic;
spec_clk_i : in std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
acam_refclk_o : out std_logic;
general_reset_o : out std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdi_o : out std_logic;
pll_sclk_o : out std_logic;
spec_clk_o : out std_logic;
tdc_clk_o : out std_logic
);
end clk_rst_managr;
----------------------------------------------------------------------------------------------------
-- architecture declaration for clk_rst_managr
----------------------------------------------------------------------------------------------------
architecture rtl of clk_rst_managr is
component incr_counter
generic(
width : integer :=32
);
port(
clk : in std_logic;
end_value : in std_logic_vector(width-1 downto 0);
incr : in std_logic;
reset : in std_logic;
count_done : out std_logic;
current_value : out std_logic_vector(width-1 downto 0)
);
end component;
subtype t_byte is std_logic_vector(7 downto 0);
type t_instr is array (1 downto 0) of t_byte;
type t_stream is array (nb_of_reg-1 downto 0) of t_byte;
type t_pll_init_st is (start, sending_instruction, sending_data, done);
-- the PLL circuit AD9516-4 needs to be configured through 68 registers
-- the values and addresses are obtained from a dedicated Analog Devices
-- software and from the datasheet.
constant reg_000 : t_byte:=x"18";
constant reg_001 : t_byte:=x"00";
constant reg_002 : t_byte:=x"10";
constant reg_003 : t_byte:=x"C3";
constant reg_004 : t_byte:=x"00";
constant reg_010 : t_byte:=x"7C";
constant reg_011 : t_byte:=x"01";
constant reg_012 : t_byte:=x"00";
constant reg_013 : t_byte:=x"03";
constant reg_014 : t_byte:=x"09";
constant reg_015 : t_byte:=x"00";
constant reg_016 : t_byte:=x"04";
constant reg_017 : t_byte:=x"00";
constant reg_018 : t_byte:=x"06";
constant reg_019 : t_byte:=x"00";
constant reg_01A : t_byte:=x"00";
constant reg_01B : t_byte:=x"00";
constant reg_01C : t_byte:=x"02";
constant reg_01D : t_byte:=x"00";
constant reg_01E : t_byte:=x"00";
constant reg_01F : t_byte:=x"0E";
constant reg_0A0 : t_byte:=x"01";
constant reg_0A1 : t_byte:=x"00";
constant reg_0A2 : t_byte:=x"00";
constant reg_0A3 : t_byte:=x"01";
constant reg_0A4 : t_byte:=x"00";
constant reg_0A5 : t_byte:=x"00";
constant reg_0A6 : t_byte:=x"01";
constant reg_0A7 : t_byte:=x"00";
constant reg_0A8 : t_byte:=x"00";
constant reg_0A9 : t_byte:=x"01";
constant reg_0AA : t_byte:=x"00";
constant reg_0AB : t_byte:=x"00";
constant reg_0F0 : t_byte:=x"0A";
constant reg_0F1 : t_byte:=x"0A";
constant reg_0F2 : t_byte:=x"0A";
constant reg_0F3 : t_byte:=x"0A";
constant reg_0F4 : t_byte:=x"0A";
constant reg_0F5 : t_byte:=x"0A";
constant reg_140 : t_byte:=x"4A";
constant reg_141 : t_byte:=x"5A";
constant reg_142 : t_byte:=x"43";
constant reg_143 : t_byte:=x"42";
constant reg_190 : t_byte:=x"00";
constant reg_191 : t_byte:=x"80";
constant reg_192 : t_byte:=x"00";
constant reg_193 : t_byte:=x"00";
constant reg_194 : t_byte:=x"80";
constant reg_195 : t_byte:=x"00";
constant reg_196 : t_byte:=x"00";
constant reg_197 : t_byte:=x"80";
constant reg_198 : t_byte:=x"00";
constant reg_199 : t_byte:=x"22";
constant reg_19A : t_byte:=x"00";
constant reg_19B : t_byte:=x"11";
constant reg_19C : t_byte:=x"00";
constant reg_19D : t_byte:=x"00";
constant reg_19E : t_byte:=x"22";
constant reg_19F : t_byte:=x"00";
constant reg_1A0 : t_byte:=x"11";
constant reg_1A1 : t_byte:=x"20";
constant reg_1A2 : t_byte:=x"00";
constant reg_1A3 : t_byte:=x"00";
constant reg_1E0 : t_byte:=x"00";
constant reg_1E1 : t_byte:=x"02";
constant reg_230 : t_byte:=x"00";
constant reg_231 : t_byte:=x"00";
constant reg_232 : t_byte:=x"01";
-- the 16-bit instruction word indicates a write cycle
-- in streaming mode starting in address 231
constant instr_wd_msb : t_byte:=x"62";
constant instr_wd_lsb : t_byte:=x"31";
constant blank : t_byte:=x"00";
signal blank_registers : boolean;
signal pll_init_st : t_pll_init_st;
signal nxt_pll_init_st : t_pll_init_st;
signal stream : t_stream:=(others => blank);
signal instruction : t_instr;
signal acam_refclk_buf : std_logic;
signal spec_clk_buf : std_logic;
signal tdc_clk_buf : std_logic;
signal acam_refclk : std_logic;
signal pll_sclk : std_logic;
signal spec_clk : std_logic;
signal tdc_clk : std_logic;
signal bit_being_sent : std_logic;
signal byte_being_sent : t_byte;
signal bit_index : integer range 7 downto 0;
signal byte_index : integer range nb_of_reg-1 downto 0;
signal silly_altern : std_logic;
signal gnum_reset : std_logic;
signal gral_incr : std_logic;
signal inv_reset : std_logic;
signal cs : std_logic;
----------------------------------------------------------------------------------------------------
-- architecture begins
----------------------------------------------------------------------------------------------------
begin
--Clock input buffer instantiations
-----------------------------------
tdc_clk125_ibuf : IBUFDS
generic map (
DIFF_TERM => false, -- Differential Termination
IBUF_LOW_PWR => true, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
IOSTANDARD => "DEFAULT"
)
port map (
I => tdc_clk_p_i, -- Diff_p buffer input (connect directly to top-level port)
IB => tdc_clk_n_i, -- Diff_n buffer input (connect directly to top-level port)
O => tdc_clk_buf -- Buffer output
);
tdc_clk125_gbuf : BUFG
port map (
I => tdc_clk_buf,
O => tdc_clk
);
spec_clk_ibuf : IBUFG
port map (
I => spec_clk_i,
O => spec_clk_buf
);
spec_clk_gbuf : BUFG
port map (
I => spec_clk_buf,
O => spec_clk
);
-- acam_refclk_ibuf : IBUFG
-- port map (
-- I => acam_refclk_i,
-- O => acam_refclk_buf
-- );
--
-- acam_refclk_gbuf : BUFG
-- port map (
-- O => acam_refclk,
-- I => acam_refclk_buf
-- );
acam_refclk <= acam_refclk_i;
general_poreset: incr_counter
port map(
clk => spec_clk,
end_value => x"0000007D", -- 125 clk ticks
incr => gral_incr,
reset => gnum_reset,
count_done => inv_reset,
current_value => open
);
silly: process
begin
if gnum_reset ='1' then
silly_altern <= '0';
else
silly_altern <= not(silly_altern);
end if;
wait until spec_clk ='1';
end process;
gral_reset_incr: process(silly_altern, tdc_clk)
begin
if silly_altern ='0' then
gral_incr <= '0';
elsif rising_edge(tdc_clk) then
gral_incr <= '1';
end if;
end process;
-- Processes for initialization of the PLL
------------------------------------------
pll_initialization_seq: process
begin
if gnum_reset ='1' then
pll_init_st <= start;
else
pll_init_st <= nxt_pll_init_st;
end if;
wait until spec_clk ='1';
end process;
pll_initialization_comb: process(pll_init_st, byte_index, bit_index, pll_sclk)
begin
case pll_init_st is
when start =>
cs <= '1';
if pll_sclk ='1' then
nxt_pll_init_st <= sending_instruction;
else
nxt_pll_init_st <= start;
end if;
when sending_instruction =>
cs <= '0';
if byte_index = 0
and bit_index = 0
and pll_sclk = '1' then
nxt_pll_init_st <= sending_data;
else
nxt_pll_init_st <= sending_instruction;
end if;
when sending_data =>
cs <= '0';
if byte_index = 0
and bit_index = 0
and pll_sclk = '1' then
nxt_pll_init_st <= done;
else
nxt_pll_init_st <= sending_data;
end if;
when done =>
cs <= '1';
nxt_pll_init_st <= done;
when others =>
cs <= '1';
nxt_pll_init_st <= start;
end case;
end process;
index_control: process
begin
if gnum_reset ='1' then
bit_index <= 7;
elsif pll_sclk ='1'
and cs ='0' then
if bit_index = 0 then
bit_index <= 7;
else
bit_index <= bit_index -1;
end if;
end if;
if gnum_reset ='1' then
byte_index <= 1;
elsif pll_sclk ='1'
and cs ='0'
and bit_index = 0 then
if byte_index = 0 then
byte_index <= nb_of_reg-1;
else
byte_index <= byte_index -1;
end if;
end if;
wait until spec_clk ='1';
end process;
pll_sclk_generator: process
begin
if gnum_reset ='1' then
pll_sclk <= '0';
else
pll_sclk <= not(pll_sclk);
end if;
wait until spec_clk ='1';
end process;
bit_being_sent <= byte_being_sent(bit_index);
byte_being_sent <= instruction(byte_index) when pll_init_st = sending_instruction
-- else blank when blank_registers
else stream(byte_index);
-- blank_registers <= TRUE when (5 < byte_index and byte_index < 17)
-- or (32 < byte_index and byte_index < 161)
-- or (172 < byte_index and byte_index < 241)
-- or (246 < byte_index and byte_index < 321)
-- or (324 < byte_index and byte_index < 401)
-- or (420 < byte_index and byte_index < 481)
-- or (482 < byte_index and byte_index < 561)
-- else FALSE;
-- Assignement of the values to be sent for the configurations of the PLL
-------------------------------------------------------------------------
instruction(1) <= instr_wd_msb;
instruction(0) <= instr_wd_lsb;
-- according to the datasheet the register 232 should be written last
-- to validate the transfer from the buffer to the valid registers
stream(0) <= reg_232;
stream(1) <= reg_000;
stream(2) <= reg_001;
stream(3) <= reg_002;
stream(4) <= reg_003;
stream(5) <= reg_004;
stream(17) <= reg_010;
stream(18) <= reg_011;
stream(19) <= reg_012;
stream(20) <= reg_013;
stream(21) <= reg_014;
stream(22) <= reg_015;
stream(23) <= reg_016;
stream(24) <= reg_017;
stream(25) <= reg_018;
stream(26) <= reg_019;
stream(27) <= reg_01A;
stream(28) <= reg_01B;
stream(29) <= reg_01C;
stream(30) <= reg_01D;
stream(31) <= reg_01E;
stream(32) <= reg_01F;
stream(161) <= reg_0A0;
stream(162) <= reg_0A1;
stream(163) <= reg_0A2;
stream(164) <= reg_0A3;
stream(165) <= reg_0A4;
stream(166) <= reg_0A5;
stream(167) <= reg_0A6;
stream(168) <= reg_0A7;
stream(169) <= reg_0A8;
stream(170) <= reg_0A9;
stream(171) <= reg_0AA;
stream(172) <= reg_0AB;
stream(241) <= reg_0F0;
stream(242) <= reg_0F1;
stream(243) <= reg_0F2;
stream(244) <= reg_0F3;
stream(245) <= reg_0F4;
stream(246) <= reg_0F5;
stream(321) <= reg_140;
stream(322) <= reg_141;
stream(323) <= reg_142;
stream(324) <= reg_143;
stream(401) <= reg_190;
stream(402) <= reg_191;
stream(403) <= reg_192;
stream(404) <= reg_193;
stream(405) <= reg_194;
stream(406) <= reg_195;
stream(407) <= reg_196;
stream(408) <= reg_197;
stream(409) <= reg_198;
stream(410) <= reg_199;
stream(411) <= reg_19A;
stream(412) <= reg_19B;
stream(413) <= reg_19C;
stream(414) <= reg_19D;
stream(415) <= reg_19E;
stream(416) <= reg_19F;
stream(417) <= reg_1A0;
stream(418) <= reg_1A1;
stream(419) <= reg_1A2;
stream(420) <= reg_1A3;
stream(481) <= reg_1E0;
stream(482) <= reg_1E1;
stream(561) <= reg_230;
stream(562) <= reg_231;
-- Input and Output signals
---------------------------
gnum_reset <= gnum_reset_i;
acam_refclk_o <= acam_refclk;
general_reset_o <= not(inv_reset);
pll_cs_o <= cs;
pll_sdi_o <= bit_being_sent;
pll_sclk_o <= pll_sclk;
spec_clk_o <= spec_clk;
tdc_clk_o <= tdc_clk;
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- CERN-BE-CO-HT
----------------------------------------------------------------------------------------------------
--
-- unit name : TDC top level (top_tdc.vhd)
-- author : G. Penacoba
-- date : May 2011
-- version : Revision 1
-- description : top level for preliminary testing of the acam chip on the TDC card
-- dependencies:
-- references :
-- modified by :
--
----------------------------------------------------------------------------------------------------
-- last changes:
----------------------------------------------------------------------------------------------------
-- to do:
----------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.tdc_core_pkg.all;
use work.gn4124_core_pkg.all;
----------------------------------------------------------------------------------------------------
-- entity declaration for top_tdc
----------------------------------------------------------------------------------------------------
entity top_tdc is
generic(
g_width : integer :=32;
values_for_simulation : boolean :=FALSE
);
port(
-- interface with GNUM
rst_n_a_i : in std_logic;
-- P2L Direction
p2l_clk_p_i : in std_logic; -- Receiver Source Synchronous Clock+
p2l_clk_n_i : in std_logic; -- Receiver Source Synchronous Clock-
p2l_data_i : in std_logic_vector(15 downto 0); -- Parallel receive data
p2l_dframe_i: in std_logic; -- Receive Frame
p2l_valid_i : in std_logic; -- Receive Data Valid
p2l_rdy_o : out std_logic; -- Rx Buffer Full Flag
p_wr_req_i : in std_logic_vector(1 downto 0); -- PCIe Write Request
p_wr_rdy_o : out std_logic_vector(1 downto 0); -- PCIe Write Ready
rx_error_o : out std_logic; -- Receive Error
vc_rdy_i : in std_logic_vector(1 downto 0); -- Virtual channel ready
-- L2P Direction
l2p_clk_p_o : out std_logic; -- Transmitter Source Synchronous Clock+
l2p_clk_n_o : out std_logic; -- Transmitter Source Synchronous Clock-
l2p_data_o : out std_logic_vector(15 downto 0); -- Parallel transmit data
l2p_dframe_o: out std_logic; -- Transmit Data Frame
l2p_valid_o : out std_logic; -- Transmit Data Valid
l2p_edb_o : out std_logic; -- Packet termination and discard
l2p_rdy_i : in std_logic; -- Tx Buffer Full Flag
l_wr_rdy_i : in std_logic_vector(1 downto 0); -- Local-to-PCIe Write
p_rd_d_rdy_i: in std_logic_vector(1 downto 0); -- PCIe-to-Local Read Response Data Ready
tx_error_i : in std_logic; -- Transmit Error
irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO
spare_o : out std_logic;
-- interface signals with PLL circuit on TDC mezzanine
acam_refclk_i : in std_logic;
pll_ld_i : in std_logic;
pll_refmon_i : in std_logic;
pll_sdo_i : in std_logic;
pll_status_i : in std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdi_o : out std_logic;
pll_sclk_o : out std_logic;
-- interface signals with acam (timing) on TDC mezzanine
err_flag_i : in std_logic;
int_flag_i : in std_logic;
start_dis_o : out std_logic;
start_from_fpga_o : out std_logic;
stop_dis_o : out std_logic;
-- interface signals with acam (data) on TDC mezzanine
data_bus_io : inout std_logic_vector(27 downto 0);
ef1_i : in std_logic;
ef2_i : in std_logic;
lf1_i : in std_logic;
lf2_i : in std_logic;
address_o : out std_logic_vector(3 downto 0);
cs_n_o : out std_logic;
oe_n_o : out std_logic;
rd_n_o : out std_logic;
wr_n_o : out std_logic;
-- other signals on the TDC mezzanine
mute_inputs_o : out std_logic;
tdc_led_status_o : out std_logic;
tdc_led_trig1_o : out std_logic;
tdc_led_trig2_o : out std_logic;
tdc_led_trig3_o : out std_logic;
tdc_led_trig4_o : out std_logic;
tdc_led_trig5_o : out std_logic;
term_en_1_o : out std_logic;
term_en_2_o : out std_logic;
term_en_3_o : out std_logic;
term_en_4_o : out std_logic;
term_en_5_o : out std_logic;
-- other signals on the SPEC carrier
spec_aux0_i : in std_logic;
spec_aux1_i : in std_logic;
spec_aux2_o : out std_logic;
spec_aux3_o : out std_logic;
spec_aux4_o : out std_logic;
spec_aux5_o : out std_logic;
spec_led_green_o : out std_logic;
spec_led_red_o : out std_logic;
spec_clk_i : in std_logic
);
end top_tdc;
----------------------------------------------------------------------------------------------------
-- architecture declaration for top_tdc
----------------------------------------------------------------------------------------------------
architecture rtl of top_tdc is
component one_hz_gen
generic(
g_width : integer :=32
);
port(
acam_refclk_i : in std_logic;
clk_i : in std_logic;
clock_period_i : in std_logic_vector(g_width-1 downto 0);
pulse_delay_i : in std_logic_vector(g_width-1 downto 0);
reset_i : in std_logic;
one_hz_p_o : out std_logic
);
end component;
-- component start_nb_offset_gen is
-- generic(
-- g_width : integer :=32
-- );
-- port(
-- acam_intflag_p_i : in std_logic;
-- clk_i : in std_logic;
-- one_hz_p_i : in std_logic;
-- reset_i : in std_logic;
--
-- start_nb_offset_o : out std_logic_vector(g_width-1 downto 0)
-- );
-- end component;
--
-- component data_formatting
-- generic(
-- g_width : integer :=32
-- );
-- port(
-- acam_start01_i : in std_logic_vector(16 downto 0);
-- acam_timestamp_i : in std_logic_vector(28 downto 0);
-- acam_timestamp_valid_i : in std_logic;
-- clk_i : in std_logic;
-- reset_i : in std_logic;
-- start_nb_offset_i : in std_logic_vector(g_width-1 downto 0);
-- utc_current_time_i : in std_logic_vector(g_width-1 downto 0);
--
-- full_timestamp_o : out std_logic_vector(3*g_width-1 downto 0);
-- full_timestamp_valid_o : out std_logic
-- );
-- end component;
component acam_timecontrol_interface
generic(
g_width : integer :=32
);
port(
err_flag_i : in std_logic;
int_flag_i : in std_logic;
start_dis_o : out std_logic;
stop_dis_o : out std_logic;
clk_i : in std_logic;
one_hz_p_i : in std_logic;
reset_i : in std_logic;
acam_errflag_p_o : out std_logic;
acam_intflag_p_o : out std_logic
);
end component;
component acam_databus_interface
generic(
g_width : integer :=32
);
port(
ef1_i : in std_logic;
ef2_i : in std_logic;
lf1_i : in std_logic;
lf2_i : in std_logic;
data_bus_io : inout std_logic_vector(27 downto 0);
address_o : out std_logic_vector(3 downto 0);
cs_n_o : out std_logic;
oe_n_o : out std_logic;
rd_n_o : out std_logic;
wr_n_o : out std_logic;
clk_i : in std_logic;
reset_i : in std_logic;
adr_i : in std_logic_vector(19 downto 0);
cyc_i : in std_logic;
dat_i : in std_logic_vector(31 downto 0);
stb_i : in std_logic;
we_i : in std_logic;
ack_o : out std_logic;
dat_o : out std_logic_vector(31 downto 0)
);
end component;
component clk_rst_managr
generic(
nb_of_reg : integer:=68;
values_for_simulation : boolean:=FALSE
);
port(
acam_refclk_i : in std_logic;
pll_ld_i : in std_logic;
pll_refmon_i : in std_logic;
pll_sdo_i : in std_logic;
pll_status_i : in std_logic;
gnum_reset_i : in std_logic;
spec_clk_i : in std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
acam_refclk_o : out std_logic;
general_reset_o : out std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdi_o : out std_logic;
pll_sclk_o : out std_logic;
spec_clk_o : out std_logic;
tdc_clk_o : out std_logic
);
end component;
component gn4124_core
generic(
g_BAR0_APERTURE : integer := 20; -- BAR0 aperture, defined in GN4124 PCI_BAR_CONFIG register (0x80C)
-- => number of bits to address periph on the board
g_CSR_WB_SLAVES_NB : integer := 1; -- Number of CSR wishbone slaves
g_DMA_WB_SLAVES_NB : integer := 1; -- Number of DMA wishbone slaves
g_DMA_WB_ADDR_WIDTH : integer := 26 -- DMA wishbone address bus width
);
port
(
---------------------------------------------------------
-- Control and status
--
-- Asynchronous reset from GN4124
rst_n_a_i : in std_logic;
-- P2L clock PLL locked
p2l_pll_locked : out std_logic;
-- Debug ouputs
debug_o : out std_logic_vector(7 downto 0);
---------------------------------------------------------
-- P2L Direction
--
-- Source Sync DDR related signals
p2l_clk_p_i : in std_logic; -- Receiver Source Synchronous Clock+
p2l_clk_n_i : in std_logic; -- Receiver Source Synchronous Clock-
p2l_data_i : in std_logic_vector(15 downto 0); -- Parallel receive data
p2l_dframe_i : in std_logic; -- Receive Frame
p2l_valid_i : in std_logic; -- Receive Data Valid
-- P2L Control
p2l_rdy_o : out std_logic; -- Rx Buffer Full Flag
p_wr_req_i : in std_logic_vector(1 downto 0); -- PCIe Write Request
p_wr_rdy_o : out std_logic_vector(1 downto 0); -- PCIe Write Ready
rx_error_o : out std_logic; -- Receive Error
vc_rdy_i : in std_logic_vector(1 downto 0); -- Virtual channel ready
---------------------------------------------------------
-- L2P Direction
--
-- Source Sync DDR related signals
l2p_clk_p_o : out std_logic; -- Transmitter Source Synchronous Clock+
l2p_clk_n_o : out std_logic; -- Transmitter Source Synchronous Clock-
l2p_data_o : out std_logic_vector(15 downto 0); -- Parallel transmit data
l2p_dframe_o : out std_logic; -- Transmit Data Frame
l2p_valid_o : out std_logic; -- Transmit Data Valid
l2p_edb_o : out std_logic; -- Packet termination and discard
-- L2P Control
l2p_rdy_i : in std_logic; -- Tx Buffer Full Flag
l_wr_rdy_i : in std_logic_vector(1 downto 0); -- Local-to-PCIe Write
p_rd_d_rdy_i : in std_logic_vector(1 downto 0); -- PCIe-to-Local Read Response Data Ready
tx_error_i : in std_logic; -- Transmit Error
---------------------------------------------------------
-- Interrupt interface
dma_irq_o : out std_logic_vector(1 downto 0); -- Interrupts sources to IRQ manager
irq_p_i : in std_logic; -- Interrupt request pulse from IRQ manager
irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO
---------------------------------------------------------
-- Target interface (CSR wishbone master)
wb_clk_i : in std_logic;
wb_adr_o : out std_logic_vector(g_BAR0_APERTURE-log2_ceil(g_CSR_WB_SLAVES_NB+1)-1 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0); -- Data out
wb_sel_o : out std_logic_vector(3 downto 0); -- Byte select
wb_stb_o : out std_logic;
wb_we_o : out std_logic;
wb_cyc_o : out std_logic_vector(g_CSR_WB_SLAVES_NB-1 downto 0);
wb_dat_i : in std_logic_vector((32*g_CSR_WB_SLAVES_NB)-1 downto 0); -- Data in
wb_ack_i : in std_logic_vector(g_CSR_WB_SLAVES_NB-1 downto 0);
---------------------------------------------------------
-- DMA interface (Pipelined wishbone master)
dma_clk_i : in std_logic;
dma_adr_o : out std_logic_vector(31 downto 0);
dma_dat_o : out std_logic_vector(31 downto 0); -- Data out
dma_sel_o : out std_logic_vector(3 downto 0); -- Byte select
dma_stb_o : out std_logic;
dma_we_o : out std_logic;
dma_cyc_o : out std_logic; --_vector(g_DMA_WB_SLAVES_NB-1 downto 0);
dma_dat_i : in std_logic_vector((32*g_DMA_WB_SLAVES_NB)-1 downto 0); -- Data in
dma_ack_i : in std_logic; --_vector(g_DMA_WB_SLAVES_NB-1 downto 0);
dma_stall_i : in std_logic--_vector(g_DMA_WB_SLAVES_NB-1 downto 0) -- for pipelined Wishbone
);
end component;
--used to generate the one_hz_p pulse
constant sim_clock_period : std_logic_vector(g_width-1 downto 0):=x"0001E848"; -- 1 ms at 125 MHz (tdc board clock)
constant syn_clock_period : std_logic_vector(g_width-1 downto 0):=x"07735940"; -- 1 s at 125 MHz (tdc board clock)
signal spec_led_period : std_logic_vector(g_width-1 downto 0);
signal tdc_led_period : std_logic_vector(g_width-1 downto 0);
signal visible_blink_length : std_logic_vector(g_width-1 downto 0);
signal tdc_led_count_done : std_logic;
signal spec_led_count_done : std_logic;
-- will be registers of the core
signal pulse_delay : std_logic_vector(g_width-1 downto 0);
signal clock_period : std_logic_vector(g_width-1 downto 0);
signal gnum_reset : std_logic;
signal pll_cs : std_logic;
signal spec_led_green : std_logic;
signal spec_led_red : std_logic;
signal tdc_led_status : std_logic;
signal tdc_led_trig1 : std_logic:='0';
signal tdc_led_trig2 : std_logic:='0';
signal tdc_led_trig3 : std_logic:='0';
signal tdc_led_trig4 : std_logic:='0';
signal tdc_led_trig5 : std_logic:='0';
signal acam_errflag_p : std_logic;
signal acam_intflag_p : std_logic;
signal acam_start01 : std_logic_vector(16 downto 0);
signal acam_timestamp : std_logic_vector(28 downto 0);
signal acam_timestamp_valid : std_logic;
signal full_timestamp : std_logic_vector(3*g_width-1 downto 0);
signal full_timestamp_valid : std_logic;
signal general_reset : std_logic;
signal one_hz_p : std_logic;
signal start_nb_offset : std_logic_vector(g_width-1 downto 0);
signal start_timer_reg : std_logic_vector(7 downto 0);
signal utc_current_time : std_logic_vector(g_width-1 downto 0);
signal acm_adr : std_logic_vector(19 downto 0);
signal acm_cyc : std_logic;
signal acm_stb : std_logic;
signal acm_we : std_logic;
signal acm_ack : std_logic;
signal acm_dat_r : std_logic_vector(g_width-1 downto 0);
signal acm_dat_w : std_logic_vector(g_width-1 downto 0);
signal dma_irq : std_logic_vector(1 downto 0);
signal irq_p : std_logic;
signal csr_adr : std_logic_vector(18 downto 0);
signal csr_dat_r : std_logic_vector(31 downto 0);
signal csr_sel : std_logic_vector(3 downto 0);
signal csr_stb : std_logic;
signal csr_we : std_logic;
signal csr_cyc : std_logic_vector(0 downto 0);
signal csr_dat_w : std_logic_vector(31 downto 0);
signal csr_ack : std_logic_vector(0 downto 0);
signal dma_adr : std_logic_vector(31 downto 0);
signal dma_dat_i : std_logic_vector(31 downto 0);
signal dma_sel : std_logic_vector(3 downto 0);
signal dma_stb : std_logic;
signal dma_we : std_logic;
signal dma_cyc : std_logic;
signal dma_dat_o : std_logic_vector(31 downto 0);
signal dma_ack : std_logic;
signal dma_stall : std_logic;
signal acam_refclk : std_logic;
signal clk : std_logic;
signal spec_clk : std_logic;
----------------------------------------------------------------------------------------------------
-- architecture begins
----------------------------------------------------------------------------------------------------
begin
one_second_block: one_hz_gen
generic map(
g_width => g_width
)
port map(
acam_refclk_i => acam_refclk,
clk_i => clk,
clock_period_i => clock_period,
pulse_delay_i => pulse_delay,
reset_i => general_reset,
one_hz_p_o => one_hz_p
);
-- start_nb_block: start_nb_offset_gen
-- generic map(
-- g_width => g_width
-- )
-- port map(
-- acam_intflag_p_i => acam_intflag_p,
-- clk_i => clk,
-- one_hz_p_i => one_hz_p,
-- reset_i => general_reset,
--
-- start_nb_offset_o => start_nb_offset
-- );
-- data_formatting_block: data_formatting
-- generic map(
-- g_width => g_width
-- )
-- port map(
-- acam_start01_i => acam_start01,
-- acam_timestamp_i => acam_timestamp,
-- acam_timestamp_valid_i => acam_timestamp_valid,
-- clk_i => clk_i,
-- reset_i => general_reset,
-- start_nb_offset_i => start_nb_offset,
-- utc_current_time_i => utc_current_time,
--
-- full_timestamp_o => full_timestamp,
-- full_timestamp_valid_o => full_timestamp_valid
-- );
acam_timing_block: acam_timecontrol_interface
generic map(
g_width => g_width
)
port map(
-- signals external to the chip: interface with acam
err_flag_i => err_flag_i,
int_flag_i => int_flag_i,
-- this is the config for acam test, in normal application connect the outputs
start_dis_o => open,
stop_dis_o => open,
-- start_dis_o => start_dis_o,
-- stop_dis_o => stop_dis_o,
-- signals internal to the chip: interface with other modules
clk_i => clk,
one_hz_p_i => one_hz_p,
reset_i => general_reset,
acam_errflag_p_o => acam_errflag_p,
acam_intflag_p_o => acam_intflag_p
);
acam_data_block: acam_databus_interface
generic map(
g_width => g_width
)
port map(
-- signals external to the chip: interface with acam
ef1_i => ef1_i,
ef2_i => ef2_i,
lf1_i => lf1_i,
lf2_i => lf2_i,
data_bus_io => data_bus_io,
address_o => address_o,
cs_n_o => cs_n_o,
oe_n_o => oe_n_o,
rd_n_o => rd_n_o,
wr_n_o => wr_n_o,
-- signals internal to the chip: interface with other modules
clk_i => clk,
reset_i => general_reset,
adr_i => acm_adr,
cyc_i => acm_cyc,
dat_i => acm_dat_w,
stb_i => acm_stb,
we_i => acm_we,
ack_o => acm_ack,
dat_o => acm_dat_r
);
gnum_interface_block: gn4124_core
generic map(
g_CSR_WB_SLAVES_NB => 1
)
port map(
rst_n_a_i => rst_n_a_i,
p2l_pll_locked => open,
debug_o => open,
p2l_clk_p_i => p2l_clk_p_i,
p2l_clk_n_i => p2l_clk_n_i,
p2l_data_i => p2l_data_i,
p2l_dframe_i => p2l_dframe_i,
p2l_valid_i => p2l_valid_i,
p2l_rdy_o => p2l_rdy_o,
p_wr_req_i => p_wr_req_i,
p_wr_rdy_o => p_wr_rdy_o,
rx_error_o => rx_error_o,
vc_rdy_i => vc_rdy_i,
l2p_clk_p_o => l2p_clk_p_o,
l2p_clk_n_o => l2p_clk_n_o,
l2p_data_o => l2p_data_o ,
l2p_dframe_o => l2p_dframe_o,
l2p_valid_o => l2p_valid_o,
l2p_edb_o => l2p_edb_o,
l2p_rdy_i => l2p_rdy_i,
l_wr_rdy_i => l_wr_rdy_i,
p_rd_d_rdy_i => p_rd_d_rdy_i,
tx_error_i => tx_error_i,
irq_p_o => irq_p_o,
dma_irq_o => dma_irq,
irq_p_i => irq_p,
wb_clk_i => clk,
wb_adr_o => csr_adr,
wb_dat_o => csr_dat_w,
wb_sel_o => csr_sel,
wb_stb_o => csr_stb,
wb_we_o => csr_we,
wb_cyc_o => csr_cyc,
wb_dat_i => csr_dat_r,
wb_ack_i => csr_ack,
dma_clk_i => clk,
dma_adr_o => dma_adr,
dma_dat_o => dma_dat_i,
dma_sel_o => dma_sel,
dma_stb_o => dma_stb,
dma_we_o => dma_we,
dma_cyc_o => dma_cyc,
dma_dat_i => dma_dat_O,
dma_ack_i => dma_ack,
dma_stall_i => dma_stall
);
clks_rsts_mgment: clk_rst_managr
generic map(
nb_of_reg => 68,
values_for_simulation => values_for_simulation
)
port map(
acam_refclk_i => acam_refclk_i,
pll_ld_i => pll_ld_i,
pll_refmon_i => pll_refmon_i,
pll_sdo_i => pll_sdo_i,
pll_status_i => pll_status_i,
gnum_reset_i => gnum_reset,
spec_clk_i => spec_clk_i,
tdc_clk_p_i => tdc_clk_p_i,
tdc_clk_n_i => tdc_clk_n_i,
acam_refclk_o => acam_refclk,
general_reset_o => general_reset,
pll_cs_o => pll_cs_o,
pll_dac_sync_o => pll_dac_sync_o,
pll_sdi_o => pll_sdi_o,
pll_sclk_o => pll_sclk_o,
spec_clk_o => spec_clk,
tdc_clk_o => clk
);
tdc_led_counter: countdown_counter
port map(
clk => clk,
reset => general_reset,
start => one_hz_p,
start_value => visible_blink_length,
count_done => tdc_led_count_done,
current_value => open
);
blink: process
begin
if one_hz_p ='1' then
tdc_led_status <= '1';
elsif tdc_led_count_done = '1' then
tdc_led_status <= '0';
end if;
wait until clk ='1';
end process;
two_seconds: process
begin
if one_hz_p ='1' then
tdc_led_trig5 <= not(tdc_led_trig5);
end if;
wait until clk ='1';
end process;
spec_led_counter: free_counter
port map(
clk => spec_clk,
enable => '1',
reset => gnum_reset,
start_value => spec_led_period,
count_done => spec_led_count_done,
current_value => open
);
spec_led: process
begin
if gnum_reset ='1' then
spec_led_red <= '0';
elsif spec_led_count_done ='1' then
spec_led_red <= not(spec_led_red);
end if;
wait until spec_clk ='1';
end process;
spec_led_period <= spec_led_period_sim when values_for_simulation
else spec_led_period_syn;
tdc_led_period <= tdc_led_period_sim when values_for_simulation
else tdc_led_period_syn;
visible_blink_length <= blink_length_sim when values_for_simulation
else blink_length_syn;
spec_led_green <= pll_ld_i;
-- inputs
gnum_reset <= not(rst_n_a_i) or not(spec_aux1_i);
-- internal signals
acm_adr(19) <= '0';
acm_adr(18 downto 0) <= csr_adr;
acm_cyc <= csr_cyc(0);
acm_stb <= csr_stb;
acm_we <= csr_we;
acm_dat_w <= csr_dat_w;
csr_ack(0) <= acm_ack;
csr_dat_r <= acm_dat_r;
-- csr_dat_r <= x"0B0AB0BA";
-- outputs
mute_inputs_o <= '1';
term_en_1_o <= '1';
term_en_2_o <= '1';
term_en_3_o <= '1';
term_en_4_o <= '1';
term_en_5_o <= '1';
spec_aux5_o <= spec_aux0_i;
spec_aux4_o <= spec_aux1_i;
button_with_spec_clk: process
begin
spec_aux3_o <= spec_aux0_i;
wait until spec_clk ='1';
end process;
button_with_tdc_clk: process
begin
spec_aux2_o <= spec_aux0_i;
wait until clk ='1';
end process;
spec_led_green_o <= spec_led_green;
spec_led_red_o <= spec_led_red;
tdc_led_status_o <= tdc_led_status;
tdc_led_trig1_o <= tdc_led_trig1;
tdc_led_trig2_o <= tdc_led_trig2;
tdc_led_trig3_o <= tdc_led_trig3;
tdc_led_trig4_o <= tdc_led_trig4;
tdc_led_trig5_o <= tdc_led_trig5;
-- this is the config for acam test...
clock_period <= sim_clock_period when values_for_simulation
else syn_clock_period;
pulse_delay <= x"00000000";
start_dis_o <= '0';
stop_dis_o <= '0';
-- when button 1 is pressed --> start every second. Otherwise start with button 0
start_from_fpga_o <= one_hz_p;-- when spec_aux1_i ='0' else not(spec_aux0_i);
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- CERN-BE-CO-HT
----------------------------------------------------------------------------------------------------
--
-- unit name : PLL test top level (top_tdc.vhd)
-- author : G. Penacoba
-- date : June 2011
-- version : Revision 1
-- description : top level for preliminary testing of the PLL on the TDC card
-- dependencies:
-- references :
-- modified by :
--
----------------------------------------------------------------------------------------------------
-- last changes:
----------------------------------------------------------------------------------------------------
-- to do:
----------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
--use work.tdc_core_pkg.all;
--use work.gn4124_core_pkg.all;
----------------------------------------------------------------------------------------------------
-- entity declaration for top_tdc
----------------------------------------------------------------------------------------------------
entity top_tdc is
generic(
g_width : integer :=32;
values_for_simulation : boolean :=FALSE
);
port(
-- interface with GNUM on SPEC carrier
rst_n_a_i : in std_logic;
-- P2L Direction
p2l_clk_p_i : in std_logic; -- Receiver Source Synchronous Clock+
p2l_clk_n_i : in std_logic; -- Receiver Source Synchronous Clock-
p2l_data_i : in std_logic_vector(15 downto 0); -- Parallel receive data
p2l_dframe_i: in std_logic; -- Receive Frame
p2l_valid_i : in std_logic; -- Receive Data Valid
p2l_rdy_o : out std_logic; -- Rx Buffer Full Flag
p_wr_req_i : in std_logic_vector(1 downto 0); -- PCIe Write Request
p_wr_rdy_o : out std_logic_vector(1 downto 0); -- PCIe Write Ready
rx_error_o : out std_logic; -- Receive Error
vc_rdy_i : in std_logic_vector(1 downto 0); -- Virtual channel ready
-- L2P Direction
l2p_clk_p_o : out std_logic; -- Transmitter Source Synchronous Clock+
l2p_clk_n_o : out std_logic; -- Transmitter Source Synchronous Clock-
l2p_data_o : out std_logic_vector(15 downto 0); -- Parallel transmit data
l2p_dframe_o: out std_logic; -- Transmit Data Frame
l2p_valid_o : out std_logic; -- Transmit Data Valid
l2p_edb_o : out std_logic; -- Packet termination and discard
l2p_rdy_i : in std_logic; -- Tx Buffer Full Flag
l_wr_rdy_i : in std_logic_vector(1 downto 0); -- Local-to-PCIe Write
p_rd_d_rdy_i: in std_logic_vector(1 downto 0); -- PCIe-to-Local Read Response Data Ready
tx_error_i : in std_logic; -- Transmit Error
irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO
spare_o : out std_logic;
-- interface signals with PLL circuit on TDC mezzanine
acam_refclk_i : in std_logic;
pll_ld_i : in std_logic;
pll_refmon_i : in std_logic;
pll_sdo_i : in std_logic;
pll_status_i : in std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdi_o : out std_logic;
pll_sclk_o : out std_logic;
-- interface signals with acam (timing) on TDC mezzanine
err_flag_i : in std_logic;
int_flag_i : in std_logic;
start_dis_o : out std_logic;
start_from_fpga_o : out std_logic;
stop_dis_o : out std_logic;
-- interface signals with acam (data) on TDC mezzanine
data_bus_io : inout std_logic_vector(27 downto 0);
ef1_i : in std_logic;
ef2_i : in std_logic;
lf1_i : in std_logic;
lf2_i : in std_logic;
address_o : out std_logic_vector(3 downto 0);
cs_n_o : out std_logic;
oe_n_o : out std_logic;
rd_n_o : out std_logic;
wr_n_o : out std_logic;
-- other signals on the TDC mezzanine
mute_inputs_o : out std_logic;
tdc_led_status_o : out std_logic;
tdc_led_trig1_o : out std_logic;
tdc_led_trig2_o : out std_logic;
tdc_led_trig3_o : out std_logic;
tdc_led_trig4_o : out std_logic;
tdc_led_trig5_o : out std_logic;
term_en_1_o : out std_logic;
term_en_2_o : out std_logic;
term_en_3_o : out std_logic;
term_en_4_o : out std_logic;
term_en_5_o : out std_logic;
-- other signals on the SPEC carrier
spec_aux0_i : in std_logic;
spec_aux1_i : in std_logic;
spec_aux2_o : out std_logic;
spec_aux3_o : out std_logic;
spec_aux4_o : out std_logic;
spec_aux5_o : out std_logic;
spec_led_green_o : out std_logic;
spec_led_red_o : out std_logic;
spec_clk_i : in std_logic
);
end top_tdc;
----------------------------------------------------------------------------------------------------
-- architecture declaration for top_tdc
----------------------------------------------------------------------------------------------------
architecture rtl of top_tdc is
component clk_rst_managr
port(
acam_refclk_i : in std_logic;
pll_ld_i : in std_logic;
pll_refmon_i : in std_logic;
pll_sdo_i : in std_logic;
pll_status_i : in std_logic;
gnum_reset_i : in std_logic;
spec_clk_i : in std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
acam_refclk_o : out std_logic;
general_reset_o : out std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdi_o : out std_logic;
pll_sclk_o : out std_logic;
spec_clk_o : out std_logic;
tdc_clk_o : out std_logic
);
end component;
component free_counter is
generic(
width : integer :=32
);
port(
clk : in std_logic;
enable : in std_logic;
reset : in std_logic;
start_value : in std_logic_vector(width-1 downto 0);
count_done : out std_logic;
current_value : out std_logic_vector(width-1 downto 0)
);
end component;
constant tdc_led_period_sim : std_logic_vector(g_width-1 downto 0):=x"0000F424"; -- 0.5 ms at 125 MHz (tdc board clock)
constant tdc_led_period_syn : std_logic_vector(g_width-1 downto 0):=x"03B9ACA0"; -- 0.5 ms at 125 MHz (tdc board clock)
constant spec_led_period_sim : std_logic_vector(g_width-1 downto 0):=x"00004E20"; -- 1 ms at 20 MHz (spec board clock)
constant spec_led_period_syn : std_logic_vector(g_width-1 downto 0):=x"01312D00"; -- 1 s at 20 MHz (spec board clock)
signal tdc_led_period : std_logic_vector(g_width-1 downto 0);
signal spec_led_period : std_logic_vector(g_width-1 downto 0);
signal tdc_led_count_done : std_logic;
signal spec_led_count_done : std_logic;
-- will be registers of the core
signal pulse_delay : std_logic_vector(g_width-1 downto 0):=x"00000000";
signal clock_period : std_logic_vector(g_width-1 downto 0):=x"000030D4";
signal gnum_reset : std_logic;
signal pll_cs : std_logic;
signal pll_sclk : std_logic;
signal pll_sdi : std_logic;
signal spec_led_green : std_logic;
signal spec_led_red : std_logic;
signal tdc_led_status : std_logic;
signal tdc_led_trig1 : std_logic:='0';
signal tdc_led_trig2 : std_logic:='0';
signal tdc_led_trig3 : std_logic:='0';
signal tdc_led_trig4 : std_logic:='0';
signal tdc_led_trig5 : std_logic:='0';
signal acam_errflag_p : std_logic;
signal acam_intflag_p : std_logic;
signal acam_start01 : std_logic_vector(16 downto 0);
signal acam_timestamp : std_logic_vector(28 downto 0);
signal acam_timestamp_valid : std_logic;
signal full_timestamp : std_logic_vector(3*g_width-1 downto 0);
signal full_timestamp_valid : std_logic;
signal one_hz_p : std_logic;
signal general_reset : std_logic;
signal start_nb_offset : std_logic_vector(g_width-1 downto 0);
signal start_timer_reg : std_logic_vector(7 downto 0);
signal utc_current_time : std_logic_vector(g_width-1 downto 0);
signal acm_adr : std_logic_vector(19 downto 0);
signal acm_cyc : std_logic;
signal acm_stb : std_logic;
signal acm_we : std_logic;
signal acm_ack : std_logic;
signal acm_dat_r : std_logic_vector(g_width-1 downto 0);
signal acm_dat_w : std_logic_vector(g_width-1 downto 0);
signal dma_irq : std_logic_vector(1 downto 0);
signal irq_p : std_logic;
signal csr_clk : std_logic;
signal csr_adr : std_logic_vector(18 downto 0);
signal csr_dat_r : std_logic_vector(31 downto 0);
signal csr_sel : std_logic_vector(3 downto 0);
signal csr_stb : std_logic;
signal csr_we : std_logic;
signal csr_cyc : std_logic_vector(0 downto 0);
signal csr_dat_w : std_logic_vector(31 downto 0);
signal csr_ack : std_logic_vector(0 downto 0);
signal dma_clk : std_logic;
signal dma_adr : std_logic_vector(31 downto 0);
signal dma_dat_i : std_logic_vector(31 downto 0);
signal dma_sel : std_logic_vector(3 downto 0);
signal dma_stb : std_logic;
signal dma_we : std_logic;
signal dma_cyc : std_logic;
signal dma_dat_o : std_logic_vector(31 downto 0);
signal dma_ack : std_logic;
signal dma_stall : std_logic;
signal acam_refclk : std_logic;
signal clk : std_logic;
signal spec_clk : std_logic;
----------------------------------------------------------------------------------------------------
-- architecture begins
----------------------------------------------------------------------------------------------------
begin
clks_rsts_mgment: clk_rst_managr
port map(
acam_refclk_i => acam_refclk_i,
pll_ld_i => pll_ld_i,
pll_refmon_i => pll_refmon_i,
pll_sdo_i => pll_sdo_i,
pll_status_i => pll_status_i,
gnum_reset_i => gnum_reset,
spec_clk_i => spec_clk_i,
tdc_clk_p_i => tdc_clk_p_i,
tdc_clk_n_i => tdc_clk_n_i,
acam_refclk_o => acam_refclk,
general_reset_o => general_reset,
pll_cs_o => pll_cs,
pll_dac_sync_o => pll_dac_sync_o,
pll_sdi_o => pll_sdi,
pll_sclk_o => pll_sclk,
spec_clk_o => spec_clk,
tdc_clk_o => clk
);
tdc_led_counter: free_counter
port map(
clk => clk,
enable => '1',
reset => general_reset,
start_value => tdc_led_period,
count_done => tdc_led_count_done,
current_value => open
);
tdc_led_period <= tdc_led_period_sim when values_for_simulation
else tdc_led_period_syn;
spec_led_red_counter: free_counter
port map(
clk => spec_clk,
enable => '1',
reset => gnum_reset,
start_value => spec_led_period,
count_done => spec_led_count_done,
current_value => open
);
spec_led_period <= spec_led_period_sim when values_for_simulation
else spec_led_period_syn;
tdc_led: process
begin
if general_reset ='1' then
tdc_led_status <= '0';
elsif tdc_led_count_done ='1' then
tdc_led_status <= not(tdc_led_status);
end if;
wait until clk='1';
end process;
spec_led: process
begin
if gnum_reset ='1' then
spec_led_red <= '0';
elsif spec_led_count_done ='1' then
spec_led_red <= not(spec_led_red);
end if;
wait until spec_clk ='1';
end process;
spec_led_green <= pll_ld_i;
-- inputs
gnum_reset <= not(rst_n_a_i) or not(spec_aux1_i);
-- outputs
pll_cs_o <= pll_cs;
pll_sclk_o <= pll_sclk;
pll_sdi_o <= pll_sdi;
mute_inputs_o <= '0';
term_en_1_o <= '1';
term_en_2_o <= '1';
term_en_3_o <= '1';
term_en_4_o <= '1';
term_en_5_o <= '1';
tdc_led_status_o <= tdc_led_status;
spec_led_green_o <= spec_led_green;
spec_led_red_o <= spec_led_red;
-- tdc_led_trig1_o <= not(spec_aux0_i);
-- tdc_led_trig2_o <= not(spec_aux0_i);
tdc_led_trig3_o <= not(spec_aux0_i);
tdc_led_trig4_o <= not(spec_aux0_i);
tdc_led_trig5_o <= not(spec_aux0_i);
button_with_spec_clk: process
begin
tdc_led_trig1_o <= spec_aux0_i;
wait until spec_clk ='1';
end process;
button_with_tdc_clk: process
begin
tdc_led_trig2_o <= spec_aux0_i;
wait until clk ='1';
end process;
spec_aux2_o <= pll_sdi;
spec_aux3_o <= pll_cs;
spec_aux4_o <= general_reset;
spec_aux5_o <= gnum_reset;
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
--_________________________________________________________________________________________________
-- |
-- |TDC core| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- top_tdc |
-- |
---------------------------------------------------------------------------------------------------
-- File top_tdc.vhd |
-- |
-- Description TDC top level |
-- |
-- Authors Gonzalo Penacoba (Gonzalo.Penacoba@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 06/2012 |
-- Version v3 |
-- Depends on |
-- |
---------------- |
-- Last changes |
-- 05/2011 v1 GP First version |
-- 06/2012 v2 EG Revamping; Comments added, signals renamed |
-- removed LEDs from top level |
-- new gnum core integrated |
-- carrier 1 wire master added |
-- mezzanine I2C master added |
-- mezzanine 1 wire master added |
-- interrupts generator added |
-- changed generation of general_rst |
-- DAC reconfiguration+needed regs added |
-- 06/2012 v3 EG Changes for v2 of TDC mezzanine |
-- Several pinout changes, |
-- acam_ref_clk LVDS instead of CMOS, |
-- no PLL_LD only PLL_STATUS |
-- 04/2013 v4 EG added SDB; fixed bugs in data_formatting; added carrier CSR information |
-- |
----------------------------------------------/!\-------------------------------------------------|
-- Note for eva: Remember the design is synthesised with Synplify Premier with DP (tdc_syn.prj) |
-- For PAR use the tdc_par_script.tcl commands in Xilinx ISE! |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
-- See the GNU Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.tdc_core_pkg.all;
use work.gn4124_core_pkg.all;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.sdb_meta_pkg.all;
--=================================================================================================
-- Entity declaration for top_tdc
--=================================================================================================
entity top_tdc is
generic
(g_span : integer :=32; -- address span in bus interfaces
g_width : integer :=32; -- data width in bus interfaces
values_for_simul : boolean :=FALSE); -- this generic is set to TRUE
-- when instantiated in a test-bench
port
(-- Signals for the GNUM interface
rst_n_a_i : in std_logic;
-- P2L Direction
p2l_clk_p_i : in std_logic; -- Receiver Source Synchronous Clock+
p2l_clk_n_i : in std_logic; -- Receiver Source Synchronous Clock-
p2l_data_i : in std_logic_vector(15 downto 0);-- Parallel receive data
p2l_dframe_i : in std_logic; -- Receive Frame
p2l_valid_i : in std_logic; -- Receive Data Valid
p2l_rdy_o : out std_logic; -- Rx Buffer Full Flag
p_wr_req_i : in std_logic_vector(1 downto 0); -- PCIe Write Request
p_wr_rdy_o : out std_logic_vector(1 downto 0); -- PCIe Write Ready
rx_error_o : out std_logic; -- Receive Error
vc_rdy_i : in std_logic_vector(1 downto 0); -- Virtual channel ready
-- L2P Direction
l2p_clk_p_o : out std_logic; -- Transmitter Source Synchronous Clock+ (freq set in GN4124 config registers)
l2p_clk_n_o : out std_logic; -- Transmitter Source Synchronous Clock- (freq set in GN4124 config registers)
l2p_data_o : out std_logic_vector(15 downto 0);-- Parallel transmit data
l2p_dframe_o : out std_logic; -- Transmit Data Frame
l2p_valid_o : out std_logic; -- Transmit Data Valid
l2p_edb_o : out std_logic; -- Packet termination and discard
l2p_rdy_i : in std_logic; -- Tx Buffer Full Flag
l_wr_rdy_i : in std_logic_vector(1 downto 0); -- Local-to-PCIe Write
p_rd_d_rdy_i : in std_logic_vector(1 downto 0); -- PCIe-to-Local Read Response Data Ready
tx_error_i : in std_logic; -- Transmit Error
irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO 8
irq_aux_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO 9, aux signal
-- Signals for the interface with the PLL AD9516 and DAC AD5662 on TDC mezzanine
pll_sclk_o : out std_logic; -- SPI clock
pll_sdi_o : out std_logic; -- data line for PLL and DAC
pll_cs_o : out std_logic; -- PLL chip select
pll_dac_sync_o : out std_logic; -- DAC chip select
pll_sdo_i : in std_logic; -- not used for the moment
pll_status_i : in std_logic; -- PLL Digital Lock Detect, active high
tdc_clk_p_i : in std_logic; -- 125 MHz differential clock: system clock
tdc_clk_n_i : in std_logic; -- 125 MHz differential clock: system clock
acam_refclk_p_i : in std_logic; -- 31.25 MHz differential clock: ACAM ref clock
acam_refclk_n_i : in std_logic; -- 31.25 MHz differential clock: ACAM ref clock
-- Signals for the timing interface with the ACAM on TDC mezzanine
start_from_fpga_o : out std_logic; -- start signal
err_flag_i : in std_logic; -- error flag
int_flag_i : in std_logic; -- interrupt flag
start_dis_o : out std_logic; -- start disable, not used
stop_dis_o : out std_logic; -- stop disable, not used
-- Signals for the data interface with the ACAM on TDC mezzanine
data_bus_io : inout std_logic_vector(27 downto 0);
address_o : out std_logic_vector(3 downto 0);
cs_n_o : out std_logic; -- chip select for ACAM
oe_n_o : out std_logic; -- output enable for ACAM
rd_n_o : out std_logic; -- read signal for ACAM
wr_n_o : out std_logic; -- write signal for ACAM
ef1_i : in std_logic; -- empty flag iFIFO1
ef2_i : in std_logic; -- empty flag iFIFO2
-- Signals for the Input Logic on TDC mezzanine
tdc_in_fpga_1_i : in std_logic; -- Ch.1 for ACAM, also received by FPGA
tdc_in_fpga_2_i : in std_logic; -- Ch.2 for ACAM, also received by FPGA
tdc_in_fpga_3_i : in std_logic; -- Ch.3 for ACAM, also received by FPGA
tdc_in_fpga_4_i : in std_logic; -- Ch.4 for ACAM, also received by FPGA
tdc_in_fpga_5_i : in std_logic; -- Ch.5 for ACAM, also received by FPGA
-- Signals for the Input Logic on TDC mezzanine
enable_inputs_o : out std_logic; -- enables all 5 inputs
term_en_1_o : out std_logic; -- Ch.1 termination enable of 50 Ohm termination
term_en_2_o : out std_logic; -- Ch.2 termination enable of 50 Ohm termination
term_en_3_o : out std_logic; -- Ch.3 termination enable of 50 Ohm termination
term_en_4_o : out std_logic; -- Ch.4 termination enable of 50 Ohm termination
term_en_5_o : out std_logic; -- Ch.5 termination enable of 50 Ohm termination
-- LEDs on TDC mezzanine
tdc_led_status_o : out std_logic; -- amber led on front pannel, division of 125 MHz tdc_clk
tdc_led_trig1_o : out std_logic; -- amber led on front pannel, Ch.1 enable
tdc_led_trig2_o : out std_logic; -- amber led on front pannel, Ch.2 enable
tdc_led_trig3_o : out std_logic; -- amber led on front pannel, Ch.3 enable
tdc_led_trig4_o : out std_logic; -- amber led on front pannel, Ch.4 enable
tdc_led_trig5_o : out std_logic; -- amber led on front pannel, Ch.5 enable
-- Clock from the SPEC carrier
spec_clk_i : in std_logic ; -- 20 MHz clock from VCXO on SPEC
-- Signal for the 1-wire interface (DS18B20 thermometer + unique ID) on SPEC carrier
carrier_one_wire_b : inout std_logic;
-- Signals for the I2C EEPROM interface on TDC mezzanine
sys_scl_b : inout std_logic; -- Mezzanine system I2C clock (EEPROM)
sys_sda_b : inout std_logic; -- Mezzanine system I2C data (EEPROM)
-- Signal for the 1-wire interface (DS18B20 thermometer + unique ID) on TDC mezzanine
mezz_one_wire_b : inout std_logic;
-- Carrier other signals
pcb_ver_i : in std_logic_vector(3 downto 0); -- PCB version
prsnt_m2c_n_i : in std_logic; -- Mezzanine presence (active low)
spec_led_green_o : out std_logic; -- Green LED on SPEC front pannel, PLL status
spec_led_red_o : out std_logic; -- Red LED on SPEC front pannel
spec_aux0_i : in std_logic; -- Button on SPEC board
spec_aux1_i : in std_logic; -- Button on SPEC board
spec_aux2_o : out std_logic; -- Red LED on spec board
spec_aux3_o : out std_logic; -- Red LED on spec board
spec_aux4_o : out std_logic; -- Red LED on spec board
spec_aux5_o : out std_logic); -- Red LED on spec board
end top_tdc;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of top_tdc is
-- clocks and resets
signal clk, general_rst_n : std_logic;
-- WISHBONE GNUM DMA
signal dma_stb, dma_cyc, dma_we, dma_ack, dma_stall : std_logic;
signal dma_sel : std_logic_vector(3 downto 0);
signal dma_adr, dma_dat_rd, dma_dat_wr : std_logic_vector(31 downto 0);
-- WISHBONE from crossbar master port
signal cnx_master_out : t_wishbone_master_out_array(c_NUM_WB_MASTERS-1 downto 0);
signal cnx_master_in : t_wishbone_master_in_array(c_NUM_WB_MASTERS-1 downto 0);
-- WISHBONE to crossbar slave port
signal cnx_slave_out : t_wishbone_slave_out_array(c_NUM_WB_SLAVES-1 downto 0);
signal cnx_slave_in : t_wishbone_slave_in_array(c_NUM_WB_SLAVES-1 downto 0);
-- WISHBONE addresses
signal dma_ctrl_wb_adr, tdc_core_wb_adr, gn_wb_adr : std_logic_vector(31 downto 0);
-- Interrupts
signal irq_to_gn4124 : std_logic;
signal irq_acam_err_p, irq_tstamp_p, irq_time_p : std_logic;
signal dma_irq : std_logic_vector(1 downto 0);
signal irq_sources : std_logic_vector(g_width-1 downto 0);
-- Carrier CSR info
signal gn4124_status : std_logic_vector(31 downto 0);
signal mezz_pll_status : std_logic_vector(11 downto 0);
-- Mezzanine 1-wire
signal mezz_owr_pwren, mezz_owr_en, mezz_owr_i : std_logic_vector(c_FMC_ONE_WIRE_NB - 1 downto 0);
-- Carrier 1-wire
signal carrier_owr_en, carrier_owr_i : std_logic_vector(c_FMC_ONE_WIRE_NB - 1 downto 0);
-- Mezzanine system I2C for EEPROM
signal sys_scl_in, sys_scl_out, sys_scl_oe_n : std_logic;
signal sys_sda_in, sys_sda_out, sys_sda_oe_n : std_logic;
-- <acam_status_i<31:0>> is never used.
-- <adr_i<7:4>> is never used.
-- <dat_i<31:28>> is never used.
-- <tstamp_wr_dat_i<127:0>> is never used.
-- <acam_tstamp1_i<30:30>> is never used.
-- <acam_tstamp1_i<28:28>> is never used.
-- <acam_tstamp2_i<31:31>> is never used.
-- <acam_tstamp2_i<29:29>> is never used.
-- <gnum_dma_adr_i<31:10>> is never used.
-- <wbm_adr_i<31:18> never used
-- gnum_csr_adr_i<31:8> is never used
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- CSR WISHBONE CROSSBAR --
---------------------------------------------------------------------------------------------------
-- CSR wishbone address decoder
-- 0x04000 -> DMA configuration
-- 0x04800 -> Carrier 1-wire master (Unidue ID & Thermometer)
-- 0x04C00 -> Carrier CSR information
-- 0x05000 -> TDC core & ACAM
-- 0x05400 -> Interrupt controller
-- 0x05800 -> Mezzanine I2C master (EEPROM)
-- 0x05C00 -> Mezzanine 1-wire master (Unidue ID & Thermometer)
cmp_sdb_crossbar : xwb_sdb_crossbar
generic map
(g_num_masters => c_NUM_WB_SLAVES,
g_num_slaves => c_NUM_WB_MASTERS,
g_registered => true,
g_wraparound => true,
g_layout => c_INTERCONNECT_LAYOUT,
g_sdb_addr => c_SDB_ADDRESS)
port map
(clk_sys_i => clk,
rst_n_i => rst_n_a_i,
slave_i => cnx_slave_in,
slave_o => cnx_slave_out,
master_i => cnx_master_in,
master_o => cnx_master_out);
---------------------------------------------------------------------------------------------------
-- GNUM CORE --
---------------------------------------------------------------------------------------------------
gnum_interface_block: gn4124_core
port map
(rst_n_a_i => rst_n_a_i,
status_o => gn4124_status,
-- P2L Direction Source Sync DDR related signals
p2l_clk_p_i => p2l_clk_p_i,
p2l_clk_n_i => p2l_clk_n_i,
p2l_data_i => p2l_data_i,
p2l_dframe_i => p2l_dframe_i,
p2l_valid_i => p2l_valid_i,
-- P2L Control
p2l_rdy_o => p2l_rdy_o,
p_wr_req_i => p_wr_req_i,
p_wr_rdy_o => p_wr_rdy_o,
rx_error_o => rx_error_o,
-- L2P Direction Source Sync DDR related signals
l2p_clk_p_o => l2p_clk_p_o,
l2p_clk_n_o => l2p_clk_n_o,
l2p_data_o => l2p_data_o ,
l2p_dframe_o => l2p_dframe_o,
l2p_valid_o => l2p_valid_o,
l2p_edb_o => l2p_edb_o,
-- L2P Control
l2p_rdy_i => l2p_rdy_i,
l_wr_rdy_i => l_wr_rdy_i,
p_rd_d_rdy_i => p_rd_d_rdy_i,
tx_error_i => tx_error_i,
vc_rdy_i => vc_rdy_i,
-- Interrupt interface
dma_irq_o => dma_irq,
irq_p_i => irq_to_gn4124,
irq_p_o => irq_p_o,
-- CSR WISHBONE interface (master pipelined)
csr_clk_i => clk,
csr_adr_o => gn_wb_adr,
csr_dat_o => cnx_slave_in(c_MASTER_GENNUM).dat,
csr_sel_o => cnx_slave_in(c_MASTER_GENNUM).sel,
csr_stb_o => cnx_slave_in(c_MASTER_GENNUM).stb,
csr_we_o => cnx_slave_in(c_MASTER_GENNUM).we,
csr_cyc_o => cnx_slave_in(c_MASTER_GENNUM).cyc,
csr_dat_i => cnx_slave_out(c_MASTER_GENNUM).dat,
csr_ack_i => cnx_slave_out(c_MASTER_GENNUM).ack,
csr_stall_i => cnx_slave_out(c_MASTER_GENNUM).stall,
-- DMA WISHBONE interface (pipelined)
dma_clk_i => clk,
dma_adr_o => dma_adr,
dma_cyc_o => dma_cyc,
dma_dat_o => dma_dat_wr,
dma_sel_o => dma_sel,
dma_stb_o => dma_stb,
dma_we_o => dma_we,
dma_ack_i => dma_ack,
dma_dat_i => dma_dat_rd,
dma_stall_i => dma_stall,
-- DMA registers WISHBONE interface (slave classic)
dma_reg_clk_i => clk,
dma_reg_adr_i => dma_ctrl_wb_adr,
dma_reg_dat_i => cnx_master_out(c_SLAVE_DMA).dat,
dma_reg_sel_i => cnx_master_out(c_SLAVE_DMA).sel,
dma_reg_stb_i => cnx_master_out(c_SLAVE_DMA).stb,
dma_reg_we_i => cnx_master_out(c_SLAVE_DMA).we,
dma_reg_cyc_i => cnx_master_out(c_SLAVE_DMA).cyc,
dma_reg_dat_o => cnx_master_in(c_SLAVE_DMA).dat,
dma_reg_ack_o => cnx_master_in(c_SLAVE_DMA).ack,
dma_reg_stall_o => cnx_master_in(c_SLAVE_DMA).stall);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Convert 32-bit word address into byte address for crossbar
cnx_slave_in(c_MASTER_GENNUM).adr <= gn_wb_adr(29 downto 0) & "00";
-- Convert 32-bit byte address into word address for DMA controller
dma_ctrl_wb_adr <= "00" & cnx_master_out(c_SLAVE_DMA).adr(31 downto 2);
-- Unused wishbone signals
cnx_master_in(c_SLAVE_DMA).err <= '0';
cnx_master_in(c_SLAVE_DMA).rty <= '0';
cnx_master_in(c_SLAVE_DMA).int <= '0';
---------------------------------------------------------------------------------------------------
-- TDC CORE --
---------------------------------------------------------------------------------------------------
tdc_core: fmc_tdc_core
generic map
(g_span => g_span,
g_width => g_width,
values_for_simul => FALSE)
port map
(-- SPEC clocks, resets
spec_clk_i => spec_clk_i,
rst_n_a_i => rst_n_a_i,
tdc_clk_125m_o => clk,
tdc_rst_n_o => general_rst_n,
-- PLL on TDC mezz
pll_sclk_o => pll_sclk_o,
pll_sdi_o => pll_sdi_o,
pll_cs_o => pll_cs_o,
pll_dac_sync_o => pll_dac_sync_o,
pll_sdo_i => pll_sdo_i,
pll_status_i => pll_status_i,
tdc_clk_p_i => tdc_clk_p_i,
tdc_clk_n_i => tdc_clk_n_i,
acam_refclk_p_i => acam_refclk_p_i,
acam_refclk_n_i => acam_refclk_n_i,
-- ACAM
start_from_fpga_o => start_from_fpga_o,
err_flag_i => err_flag_i,
int_flag_i => int_flag_i,
start_dis_o => start_dis_o,
stop_dis_o => stop_dis_o,
data_bus_io => data_bus_io,
address_o => address_o,
cs_n_o => cs_n_o,
oe_n_o => oe_n_o,
rd_n_o => rd_n_o,
wr_n_o => wr_n_o,
ef1_i => ef1_i,
ef2_i => ef2_i,
-- Input channels enable
enable_inputs_o => enable_inputs_o,
term_en_1_o => term_en_1_o,
term_en_2_o => term_en_2_o,
term_en_3_o => term_en_3_o,
term_en_4_o => term_en_4_o,
term_en_5_o => term_en_5_o,
-- Input channels to FPGA (not used)
tdc_in_fpga_1_i => tdc_in_fpga_1_i,
tdc_in_fpga_2_i => tdc_in_fpga_2_i,
tdc_in_fpga_3_i => tdc_in_fpga_3_i,
tdc_in_fpga_4_i => tdc_in_fpga_4_i,
tdc_in_fpga_5_i => tdc_in_fpga_5_i,
-- LEDs and buttons on TDC and SPEC
tdc_led_status_o => tdc_led_status_o,
tdc_led_trig1_o => tdc_led_trig1_o,
tdc_led_trig2_o => tdc_led_trig2_o,
tdc_led_trig3_o => tdc_led_trig3_o,
tdc_led_trig4_o => tdc_led_trig4_o,
tdc_led_trig5_o => tdc_led_trig5_o,
spec_led_green_o => spec_led_green_o,
spec_led_red_o => spec_led_red_o,
spec_aux0_i => spec_aux0_i,
spec_aux1_i => spec_aux1_i,
spec_aux2_o => spec_aux2_o,
spec_aux3_o => spec_aux3_o,
spec_aux4_o => spec_aux4_o,
spec_aux5_o => spec_aux5_o,
-- Interrupts
irq_tstamp_p_o => irq_tstamp_p,
irq_time_p_o => irq_time_p,
irq_acam_err_p_o => irq_acam_err_p,
-- WISHBONE CSR for TDC core and ACAM configuration
gnum_csr_adr_i => tdc_core_wb_adr,
gnum_csr_dat_i => cnx_master_out(c_SLAVE_TDC_CORE).dat,
gnum_csr_stb_i => cnx_master_out(c_SLAVE_TDC_CORE).stb,
gnum_csr_we_i => cnx_master_out(c_SLAVE_TDC_CORE).we,
gnum_csr_cyc_i => cnx_master_out(c_SLAVE_TDC_CORE).cyc,
gnum_csr_dat_o => cnx_master_in(c_SLAVE_TDC_CORE).dat,
gnum_csr_ack_o => cnx_master_in(c_SLAVE_TDC_CORE).ack,
-- WISHBONE DMA for timestamps transfer
gnum_dma_adr_i => dma_adr,
gnum_dma_dat_i => dma_dat_wr,
gnum_dma_stb_i => dma_stb,
gnum_dma_we_i => dma_we,
gnum_dma_cyc_i => dma_cyc,
gnum_dma_ack_o => dma_ack,
gnum_dma_dat_o => dma_dat_rd,
gnum_dma_stall_o => dma_stall);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Convert byte address into word address
tdc_core_wb_adr <= "00" & cnx_master_out(c_SLAVE_TDC_CORE).adr(31 downto 2);
-- Unused wishbone signals
cnx_master_in(c_SLAVE_TDC_CORE).err <= '0';
cnx_master_in(c_SLAVE_TDC_CORE).rty <= '0';
cnx_master_in(c_SLAVE_TDC_CORE).stall <= '0';
cnx_master_in(c_SLAVE_TDC_CORE).int <= '0';
---------------------------------------------------------------------------------------------------
-- INTERRUPTS CONTROLLER --
---------------------------------------------------------------------------------------------------
-- IRQ sources
-- 0 -> end of DMA transfer
-- 1 -> DMA transfer error
-- 2 -> number of timestamps reached threshold
-- 3 -> number of seconds passed reached threshold
-- 4 -> ACAM error
-- 5-31 -> unused
cmp_irq_controller : irq_controller
port map
(clk_i => clk,
rst_n_i => general_rst_n,
irq_src_p_i => irq_sources,
irq_p_o => irq_to_gn4124,
wb_adr_i => cnx_master_out(c_SLAVE_INT).adr(3 downto 2),
wb_dat_i => cnx_master_out(c_SLAVE_INT).dat,
wb_dat_o => cnx_master_in(c_SLAVE_INT).dat,
wb_cyc_i => cnx_master_out(c_SLAVE_INT).cyc,
wb_sel_i => cnx_master_out(c_SLAVE_INT).sel,
wb_stb_i => cnx_master_out(c_SLAVE_INT).stb,
wb_we_i => cnx_master_out(c_SLAVE_INT).we,
wb_ack_o => cnx_master_in(c_SLAVE_INT).ack);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
irq_sources(1 downto 0) <= dma_irq;
irq_sources(2) <= irq_tstamp_p;
irq_sources(3) <= irq_time_p;
irq_sources(4) <= irq_acam_err_p;
irq_sources(31 downto 5) <= (others => '0');
irq_aux_p_o <= irq_to_gn4124;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Unused wishbone signals
cnx_master_in(c_SLAVE_INT).err <= '0';
cnx_master_in(c_SLAVE_INT).rty <= '0';
cnx_master_in(c_SLAVE_INT).stall <= '0';
cnx_master_in(c_SLAVE_INT).int <= '0';
---------------------------------------------------------------------------------------------------
-- Carrier 1-wire MASTER DS18B20 (thermometer + unique ID) --
---------------------------------------------------------------------------------------------------
cmp_carrier_onewire : xwb_onewire_master
generic map
(g_interface_mode => CLASSIC,
g_address_granularity => BYTE,
g_num_ports => 1,
g_ow_btp_normal => "5.0",
g_ow_btp_overdrive => "1.0")
port map
(clk_sys_i => clk,
rst_n_i => general_rst_n,
slave_i => cnx_master_out(c_SLAVE_SPEC_ONEWIRE),
slave_o => cnx_master_in(c_SLAVE_SPEC_ONEWIRE),
desc_o => open,
owr_pwren_o => open,
owr_en_o => carrier_owr_en,
owr_i => carrier_owr_i);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
carrier_one_wire_b <= '0' when carrier_owr_en(0) = '1' else 'Z';
carrier_owr_i(0) <= carrier_one_wire_b;
---------------------------------------------------------------------------------------------------
-- Mezzanine I2C Master EEPROM --
---------------------------------------------------------------------------------------------------
mezzanine_I2C_master_EEPROM : xwb_i2c_master
generic map
(g_interface_mode => CLASSIC,
g_address_granularity => BYTE)
port map
(clk_sys_i => clk,
rst_n_i => general_rst_n,
slave_i => cnx_master_out(c_SLAVE_FMC_SYS_I2C),
slave_o => cnx_master_in(c_SLAVE_FMC_SYS_I2C),
desc_o => open,
scl_pad_i => sys_scl_in,
scl_pad_o => sys_scl_out,
scl_padoen_o => sys_scl_oe_n,
sda_pad_i => sys_sda_in,
sda_pad_o => sys_sda_out,
sda_padoen_o => sys_sda_oe_n);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Tri-state buffer for SDA and SCL
sys_scl_b <= sys_scl_out when sys_scl_oe_n = '0' else 'Z';
sys_scl_in <= sys_scl_b;
sys_sda_b <= sys_sda_out when sys_sda_oe_n = '0' else 'Z';
sys_sda_in <= sys_sda_b;
---------------------------------------------------------------------------------------------------
-- Mezzanine 1-wire MASTER DS18B20 (thermometer + unique ID) --
---------------------------------------------------------------------------------------------------
cmp_fmc_onewire : xwb_onewire_master
generic map
(g_interface_mode => CLASSIC,
g_address_granularity => BYTE,
g_num_ports => 1,
g_ow_btp_normal => "5.0",
g_ow_btp_overdrive => "1.0")
port map
(clk_sys_i => clk,
rst_n_i => general_rst_n,
slave_i => cnx_master_out(c_SLAVE_FMC_ONEWIRE),
slave_o => cnx_master_in(c_SLAVE_FMC_ONEWIRE),
desc_o => open,
owr_pwren_o => mezz_owr_pwren,
owr_en_o => mezz_owr_en,
owr_i => mezz_owr_i);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
mezz_one_wire_b <= '0' when mezz_owr_en(0) = '1' else 'Z';
mezz_owr_i(0) <= mezz_one_wire_b;
---------------------------------------------------------------------------------------------------
-- Carrier CSR information --
---------------------------------------------------------------------------------------------------
-- Information on carrier type, mezzanine presence, pcb version
cmp_carrier_csr : carrier_csr
port map
(rst_n_i => general_rst_n,
wb_clk_i => clk,
wb_addr_i => cnx_master_out(c_SLAVE_SPEC_CSR).adr(3 downto 2),
wb_data_i => cnx_master_out(c_SLAVE_SPEC_CSR).dat,
wb_data_o => cnx_master_in(c_SLAVE_SPEC_CSR).dat,
wb_cyc_i => cnx_master_out(c_SLAVE_SPEC_CSR).cyc,
wb_sel_i => cnx_master_out(c_SLAVE_SPEC_CSR).sel,
wb_stb_i => cnx_master_out(c_SLAVE_SPEC_CSR).stb,
wb_we_i => cnx_master_out(c_SLAVE_SPEC_CSR).we,
wb_ack_o => cnx_master_in(c_SLAVE_SPEC_CSR).ack,
carrier_csr_carrier_pcb_rev_i => pcb_ver_i,
carrier_csr_carrier_reserved_i => mezz_pll_status,
carrier_csr_carrier_type_i => c_CARRIER_TYPE,
carrier_csr_stat_fmc_pres_i => prsnt_m2c_n_i,
carrier_csr_stat_p2l_pll_lck_i => gn4124_status(0),
carrier_csr_stat_sys_pll_lck_i => open,
carrier_csr_stat_ddr3_cal_done_i => open,
carrier_csr_stat_reserved_i => (others => '0'),
carrier_csr_ctrl_led_green_o => open,
carrier_csr_ctrl_led_red_o => open,
carrier_csr_ctrl_dac_clr_n_o => open,
carrier_csr_ctrl_reserved_o => open);
mezz_pll_status <= "00000000000" & pll_status_i;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Unused wishbone signals
cnx_master_in(c_SLAVE_SPEC_CSR).err <= '0';
cnx_master_in(c_SLAVE_SPEC_CSR).rty <= '0';
cnx_master_in(c_SLAVE_SPEC_CSR).stall <= '0';
cnx_master_in(c_SLAVE_SPEC_CSR).int <= '0';
end rtl;
----------------------------------------------------------------------------------------------------
-- architecture ends
----------------------------------------------------------------------------------------------------
\ No newline at end of file
-- Created by : G. Penacoba
-- Creation Date: June 2011
-- Description: reproduced roughly the functionality of the acam:
-- handles the FIFO and the data communication handshake
-- Modified by:
-- Modification Date:
-- Modification consisted on:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity acam_data_model is
port(
start01_i : in std_logic_vector(16 downto 0);
timestamp_for_fifo1 : in std_logic_vector(27 downto 0);
timestamp_for_fifo2 : in std_logic_vector(27 downto 0);
address_i : in std_logic_vector(3 downto 0);
cs_n_i : in std_logic;
oe_n_i : in std_logic;
rd_n_i : in std_logic;
wr_n_i : in std_logic;
data_bus_o : out std_logic_vector(27 downto 0);
ef1_o : out std_logic;
ef2_o : out std_logic;
lf1_o : out std_logic;
lf2_o : out std_logic
);
end acam_data_model;
architecture behavioral of acam_data_model is
component acam_fifo_model
generic(
size : integer;
full_threshold : integer;
empty_threshold : integer
);
port(
data_input : in std_logic_vector(27 downto 0);
rd_fifo : in std_logic;
data_output : out std_logic_vector(27 downto 0);
empty : out std_logic;
full : out std_logic
);
end component;
constant ts_ad : time:= 2000 ps; -- minimum address setup time
constant th_ad : time:= 0 ps; -- minimum address hold time
constant tpw_rl : time:= 6000 ps; -- minimum read low time
constant tpw_rh : time:= 6000 ps; -- minimum read high time
constant tpw_wl : time:= 6000 ps; -- minimum write low time
constant tpw_wh : time:= 6000 ps; -- minimum write high time
constant tv_dr : time:= 11800 ps; -- maximum read data valid time
constant th_dr : time:= 4000 ps; -- minimum read data hold time
constant ts_dw : time:= 5000 ps; -- minimum write data setup time
constant th_dw : time:= 4000 ps; -- minimum write data hold time
constant ts_csn : time:= 0 ps; -- minimum chip select setup time
constant th_csn : time:= 0 ps; -- minimum chip select hold time
constant ts_ef : time:= 11800 ps; -- maximum empty flag set time
signal address : std_logic_vector(3 downto 0);
signal cs_n : std_logic;
signal oe_n : std_logic;
signal rd_n : std_logic;
signal wr_n : std_logic;
signal data_bus : std_logic_vector(27 downto 0):= (others =>'Z');
signal ef1 : std_logic;
signal ef2 : std_logic;
signal lf1 : std_logic;
signal lf2 : std_logic;
signal address_change_time : time:= 0 ps;
signal data_change_time : time:= 0 ps;
signal cs_falling_time : time:= 0 ps;
signal cs_rising_time : time:= 0 ps;
signal rd_falling_time : time:= 0 ps;
signal rd_rising_time : time:= 0 ps;
signal wr_falling_time : time:= 0 ps;
signal wr_rising_time : time:= 0 ps;
signal start01 : std_logic_vector(16 downto 0);
signal data_for_bus : std_logic_vector(27 downto 0);
signal data_from_fifo1 : std_logic_vector(27 downto 0);
signal data_from_fifo2 : std_logic_vector(27 downto 0);
signal rd_fifo1 : std_logic;
signal rd_fifo2 : std_logic;
begin
read: process
begin
wait until rd_n ='0';
if cs_n ='0' then
wait for tv_dr;
data_bus <= data_for_bus;
end if;
wait until rd_n ='1';
if cs_n ='0' then
wait for th_dr;
data_bus <= (others =>'Z');
end if;
end process;
data_mux: process(address, data_from_fifo1, data_from_fifo2, start01, rd_n, cs_n)
begin
case address is
when x"8" =>
data_for_bus <= data_from_fifo1;
if rd_n ='0' and cs_n ='0' then
rd_fifo1 <= '1';
rd_fifo2 <= '0';
else
rd_fifo1 <= '0';
rd_fifo2 <= '0';
end if;
when x"9" =>
data_for_bus <= data_from_fifo2;
if rd_n ='0' and cs_n ='0' then
rd_fifo1 <= '0';
rd_fifo2 <= '1';
else
rd_fifo1 <= '0';
rd_fifo2 <= '0';
end if;
when x"A" =>
data_for_bus <= "00000000000" & start01;
rd_fifo1 <= '0';
rd_fifo2 <= '0';
when others =>
data_for_bus <= (others => 'Z');
rd_fifo1 <= '0';
rd_fifo2 <= '0';
end case;
end process;
interface_fifo1: acam_fifo_model
generic map(
size => 256,
full_threshold => 10,
empty_threshold => 1
)
port map(
data_input => timestamp_for_fifo1,
rd_fifo => rd_fifo1,
data_output => data_from_fifo1,
empty => ef1,
full => lf1
);
interface_fifo2: acam_fifo_model
generic map(
size => 256,
full_threshold => 10,
empty_threshold => 1
)
port map(
data_input => timestamp_for_fifo2,
rd_fifo => rd_fifo2,
data_output => data_from_fifo2,
empty => ef2,
full => lf2
);
start01 <= start01_i;
address <= address_i;
cs_n <= cs_n_i;
oe_n <= oe_n_i;
rd_n <= rd_n_i;
wr_n <= wr_n_i;
data_bus_o <= data_bus;
ef1_o <= ef1;
ef2_o <= ef2;
lf1_o <= lf1;
lf2_o <= lf2;
address_timing: process(address)
begin
address_change_time <= now;
end process;
data_timing: process(address)
begin
data_change_time <= now;
end process;
read_timing: process(rd_n)
begin
if falling_edge(rd_n) then
rd_falling_time <= now;
end if;
if rising_edge(rd_n) then
rd_rising_time <= now;
end if;
end process;
write_timing: process(wr_n)
begin
if falling_edge(wr_n) then
wr_falling_time <= now;
end if;
if rising_edge(wr_n) then
wr_rising_time <= now;
end if;
end process;
chip_select_timing: process(cs_n)
begin
if falling_edge(cs_n) then
cs_falling_time <= now;
end if;
if rising_edge(cs_n) then
cs_rising_time <= now;
end if;
end process;
reporting_read_times: process(rd_falling_time, rd_rising_time)
begin
if rd_rising_time - rd_falling_time < tpw_rl
and rd_rising_time - rd_falling_time > 0 ps
and now /= 0 ps then
report LF & " #### Timing error in read signal when reading: minimum low time not respected" & LF
severity warning;
end if;
if rd_falling_time - rd_rising_time < tpw_rh
and rd_falling_time - rd_rising_time > 0 ps
and now /= 0 ps then
report LF & " #### Timing error in read signal when reading: minimum high time not respected" & LF
severity warning;
end if;
end process;
reporting_write_times: process(wr_falling_time, wr_rising_time)
begin
if wr_rising_time - wr_falling_time < tpw_wl
and wr_rising_time - wr_falling_time > 0 ps
and now /= 0 ps then
report LF & " #### Timing error in read signal when writing: minimum low time not respected" & LF
severity warning;
end if;
if wr_falling_time - wr_rising_time < tpw_wh
and wr_falling_time - wr_rising_time > 0 ps
and now /= 0 ps then
report " #### Timing error in read signal when writing: minimum high time not respected" & LF
severity warning;
end if;
end process;
reporting_setup_rd: process(rd_falling_time)
begin
if rd_falling_time - address_change_time < ts_ad and now /= 0 ps then
report LF & " #### Timing error in address bus when reading: minimum setup time not respected" & LF
severity warning;
end if;
if rd_falling_time - cs_falling_time < ts_csn and now /= 0 ps then
report LF & " #### Timing error in chip select signal when reading: minimum setup time not respected" & LF
severity warning;
end if;
end process;
reporting_setup_wr: process(wr_falling_time)
begin
if wr_falling_time - address_change_time < ts_ad and now /= 0 ps then
report LF & " #### Timing error in address bus when writing: minimum setup time not respected" & LF
severity warning;
end if;
if wr_falling_time - cs_falling_time < ts_csn then
report LF & " #### Timing error in chip select signal when writing: minimum setup time not respected" & LF
severity warning;
end if;
end process;
reporting_hold_ad: process(address_change_time)
begin
if address_change_time - rd_rising_time < th_ad and now /= 0 ps then
report LF & " #### Timing error in address bus when reading: minimum hold time not respected" & LF
severity warning;
end if;
if address_change_time - wr_rising_time < th_ad and now /= 0 ps then
report LF & " #### Timing error in address bus when writing: minimum hold time not respected" & LF
severity warning;
end if;
end process;
reporting_hold_cs: process(cs_rising_time)
begin
if cs_rising_time - rd_rising_time < th_csn and now /= 0 ps then
report LF & " #### Timing error in chip select signal when reading: minimum hold time not respected" & LF
severity warning;
end if;
if cs_rising_time - wr_rising_time < th_csn and now /= 0 ps then
report LF & " #### Timing error in chip select signal when writing: minimum hold time not respected" & LF
severity warning;
end if;
end process;
reporting_data_setup_wr: process(wr_rising_time)
begin
if wr_rising_time - data_change_time < ts_dw and now /= 0 ps then
report LF & " #### Timing error in data bus when writing: minimum setup time not respected" & LF
severity warning;
end if;
end process;
reporting_data_hold_wr: process(data_change_time)
begin
if data_change_time - wr_rising_time < th_dw and now /= 0 ps then
report LF & " #### Timing error in data bus when writing: minimum hold time not respected" & LF
severity warning;
end if;
end process;
end behavioral;
-- Created by : G. Penacoba
-- Creation Date: June 2011
-- Description: reproduces roughly the functionality of the acam:
-- handles the FIFO and the data communication handshake
-- Modified by:
-- Modification Date:
-- Modification consisted on:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity acam_fifo_model is
generic(
size : integer;
full_threshold : integer;
empty_threshold : integer
);
port(
data_input : in std_logic_vector(27 downto 0);
rd_fifo : in std_logic;
data_output : out std_logic_vector(27 downto 0);
empty : out std_logic;
full : out std_logic
);
end acam_fifo_model;
architecture behavioral of acam_fifo_model is
constant ts_ef : time:= 11800 ps; -- maximum empty flag set time
subtype index is natural range size-1 downto 0;
subtype memory_cell is std_logic_vector(27 downto 0);
type memory_block is array (natural range size-1 downto 0) of memory_cell;
signal fifo : memory_block;
signal wr_pointer : index:= 0;
signal rd_pointer : index:= 0;
signal level : index:= 0;
begin
writing: process(data_input)
begin
if now /= 0 ps then
fifo(wr_pointer) <= data_input;
if wr_pointer = size-1 then
wr_pointer <= 0;
else
wr_pointer <= wr_pointer + 1;
end if;
end if;
end process;
reading: process(rd_fifo)
begin
if rising_edge(rd_fifo) then
data_output <= fifo(rd_pointer);
if rd_pointer = size-1 then
rd_pointer <= 0 after ts_ef;
else
rd_pointer <= rd_pointer + 1 after ts_ef;
end if;
end if;
-- if falling_edge(rd_fifo) then
-- if rd_pointer = size-1 then
-- rd_pointer <= 0;
-- else
-- rd_pointer <= rd_pointer + 1;
-- end if;
-- end if;
end process;
flags: process(level)
begin
if level > full_threshold then
full <= '1';
else
full <= '0';
end if;
if level < empty_threshold then
empty <= '1';
else
empty <= '0';
end if;
end process;
filling_level: process(rd_pointer, wr_pointer)
begin
if wr_pointer >= rd_pointer then
level <= wr_pointer - rd_pointer;
else
level <= wr_pointer + 256 - rd_pointer;
end if;
end process;
-- process(level)
-- begin
-- report " filling level " & integer'image(level) & LF &
-- " rd_pointer " & integer'image(rd_pointer) & LF &
-- " wr_pointer " & integer'image(wr_pointer) & LF;
-- end process;
corruption_reporting_reading: process(rd_pointer)
begin
if now /= 0 ps then
if rd_pointer = wr_pointer then
report LF & " #### Interface FIFO is empty: no further reading should be performed" & LF
severity warning;
end if;
end if;
end process;
corruption_reporting_writing: process(wr_pointer)
begin
if now /= 0 ps then
if rd_pointer = wr_pointer then
report LF & " #### Interface FIFO is full: no further writing should be performed" & LF
severity warning;
end if;
end if;
end process;
end behavioral;
-- Creation Date: May 2011
-- Description: reproduced roughly the functionality of the acam:
-- Modified by:
-- Modification Date:
-- Modification consisted on:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity acam_model is
generic(
start_retrig_period : time:= 3200 ns;
refclk_period : time:= 32 ns
);
port(
tstart_i : in std_logic;
tstop1_i : in std_logic;
tstop2_i : in std_logic;
tstop3_i : in std_logic;
tstop4_i : in std_logic;
tstop5_i : in std_logic;
startdis_i : in std_logic;
stopdis_i : in std_logic;
int_flag_o : out std_logic;
err_flag_o : out std_logic;
address_i : in std_logic_vector(3 downto 0);
cs_n_i : in std_logic;
oe_n_i : in std_logic;
rd_n_i : in std_logic;
wr_n_i : in std_logic;
data_bus_io : inout std_logic_vector(27 downto 0);
ef1_o : out std_logic;
ef2_o : out std_logic;
lf1_o : out std_logic;
lf2_o : out std_logic
);
end acam_model;
architecture behavioral of acam_model is
component acam_timing_model
generic(
refclk_period : time:= 32 ns;
start_retrig_period : time:= 3200 ns
);
port(
tstart_i : in std_logic;
tstop1_i : in std_logic;
tstop2_i : in std_logic;
tstop3_i : in std_logic;
tstop4_i : in std_logic;
tstop5_i : in std_logic;
startdis_i : in std_logic;
stopdis_i : in std_logic;
err_flag_o : out std_logic;
int_flag_o : out std_logic;
start01_o : out std_logic_vector(16 downto 0);
timestamp_for_fifo1 : out std_logic_vector(27 downto 0);
timestamp_for_fifo2 : out std_logic_vector(27 downto 0)
);
end component;
component acam_data_model
port(
start01_i : in std_logic_vector(16 downto 0);
timestamp_for_fifo1 : in std_logic_vector(27 downto 0);
timestamp_for_fifo2 : in std_logic_vector(27 downto 0);
address_i : in std_logic_vector(3 downto 0);
cs_n_i : in std_logic;
oe_n_i : in std_logic;
rd_n_i : in std_logic;
wr_n_i : in std_logic;
data_bus_o : out std_logic_vector(27 downto 0);
ef1_o : out std_logic;
ef2_o : out std_logic;
lf1_o : out std_logic;
lf2_o : out std_logic
);
end component;
signal timestamp_for_fifo1 : std_logic_vector(27 downto 0);
signal timestamp_for_fifo2 : std_logic_vector(27 downto 0);
signal start01 : std_logic_vector(16 downto 0);
begin
timing_block: acam_timing_model
generic map(
refclk_period => refclk_period,
start_retrig_period => start_retrig_period
)
port map(
tstart_i => tstart_i,
tstop1_i => tstop1_i,
tstop2_i => tstop2_i,
tstop3_i => tstop3_i,
tstop4_i => tstop4_i,
tstop5_i => tstop5_i,
startdis_i => startdis_i,
stopdis_i => stopdis_i,
err_flag_o => err_flag_o,
int_flag_o => int_flag_o,
start01_o => start01,
timestamp_for_fifo1 => timestamp_for_fifo1,
timestamp_for_fifo2 => timestamp_for_fifo2
);
data_block: acam_data_model
port map(
start01_i => start01,
timestamp_for_fifo1 => timestamp_for_fifo1,
timestamp_for_fifo2 => timestamp_for_fifo2,
address_i => address_i,
cs_n_i => cs_n_i,
oe_n_i => oe_n_i,
rd_n_i => rd_n_i,
wr_n_i => wr_n_i,
data_bus_o => data_bus_io,
ef1_o => ef1_o,
ef2_o => ef2_o,
lf1_o => lf1_o,
lf2_o => lf2_o
);
end behavioral;
-- Created by : G. Penacoba
-- Creation Date: May 2011
-- Description: reproduced roughly the functionality of the acam:
-- measures the time between input pulses.
-- Modified by:
-- Modification Date:
-- Modification consisted on:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity acam_timing_model is
generic(
refclk_period : time:= 32 ns;
start_retrig_period : time:= 3200 ns
);
port(
tstart_i : in std_logic;
tstop1_i : in std_logic;
tstop2_i : in std_logic;
tstop3_i : in std_logic;
tstop4_i : in std_logic;
tstop5_i : in std_logic;
startdis_i : in std_logic;
stopdis_i : in std_logic;
err_flag_o : out std_logic;
int_flag_o : out std_logic;
start01_o : out std_logic_vector(16 downto 0);
timestamp_for_fifo1 : out std_logic_vector(27 downto 0);
timestamp_for_fifo2 : out std_logic_vector(27 downto 0)
);
end acam_timing_model;
architecture behavioral of acam_timing_model is
constant resolution : time:= 81 ps;
signal tstart : std_logic;
signal tstop1 : std_logic;
signal tstop2 : std_logic;
signal tstop3 : std_logic;
signal tstop4 : std_logic;
signal tstop5 : std_logic;
signal startdis : std_logic;
signal stopdis : std_logic;
signal intflag : std_logic;
signal start01_reg : std_logic_vector(16 downto 0);
signal start01 : time:= 0 ps;
signal start_trig : time:= 0 ps;
signal stop1_trig : time:= 0 ps;
signal stop2_trig : time:= 0 ps;
signal stop3_trig : time:= 0 ps;
signal stop4_trig : time:= 0 ps;
signal stop5_trig : time:= 0 ps;
signal stop1 : time:= 0 ps;
signal stop2 : time:= 0 ps;
signal stop3 : time:= 0 ps;
signal stop4 : time:= 0 ps;
signal stop5 : time:= 0 ps;
signal start_nb1 : integer:=0;
signal start_nb2 : integer:=0;
signal start_nb3 : integer:=0;
signal start_nb4 : integer:=0;
signal start_nb5 : integer:=0;
signal start_retrig_nb : integer:=0;
signal start_retrig_p : std_logic;
begin
listening: process (tstart, tstop1, tstop2, tstop3, tstop4, tstop5)
begin
if rising_edge(tstart) then
if startdis ='0' then
start_trig <= now;
end if;
end if;
if rising_edge(tstop1) then
if stopdis ='0' then
stop1_trig <= now;
end if;
end if;
if rising_edge(tstop2) then
if stopdis ='0' then
stop2_trig <= now;
end if;
end if;
if rising_edge(tstop3) then
if stopdis ='0' then
stop3_trig <= now;
end if;
end if;
if rising_edge(tstop4) then
if stopdis ='0' then
stop4_trig <= now;
end if;
end if;
if rising_edge(tstop5) then
if stopdis ='0' then
stop5_trig <= now;
end if;
end if;
end process;
measuring1: process(stop1_trig)
begin
if start_retrig_nb > 1 then
stop1 <= (stop1_trig-start_trig-start01)-((start_retrig_nb-1)*start_retrig_period);
elsif start_retrig_nb = 1 then
stop1 <= (stop1_trig-start_trig-start01);
else
stop1 <= (stop1_trig-start_trig);
end if;
start_nb1 <= start_retrig_nb mod 256;
end process;
measuring2: process(stop2_trig)
begin
if start_retrig_nb > 1 then
stop2 <= (stop2_trig-start_trig-start01)-((start_retrig_nb-1)*start_retrig_period);
elsif start_retrig_nb = 1 then
stop2 <= (stop2_trig-start_trig-start01);
else
stop2 <= (stop2_trig-start_trig);
end if;
start_nb2 <= start_retrig_nb mod 256;
end process;
measuring3: process(stop3_trig)
begin
if start_retrig_nb > 1 then
stop3 <= (stop3_trig-start_trig-start01)-((start_retrig_nb-1)*start_retrig_period);
elsif start_retrig_nb = 1 then
stop3 <= (stop3_trig-start_trig-start01);
else
stop3 <= (stop3_trig-start_trig);
end if;
start_nb3 <= start_retrig_nb mod 256;
end process;
measuring4: process(stop4_trig)
begin
if start_retrig_nb > 1 then
stop4 <= (stop4_trig-start_trig-start01)-((start_retrig_nb-1)*start_retrig_period);
elsif start_retrig_nb = 1 then
stop4 <= (stop4_trig-start_trig-start01);
else
stop4 <= (stop4_trig-start_trig);
end if;
start_nb4 <= start_retrig_nb mod 256;
end process;
measuring5: process(stop5_trig)
begin
if start_retrig_nb > 1 then
stop5 <= (stop5_trig-start_trig-start01)-((start_retrig_nb-1)*start_retrig_period);
elsif start_retrig_nb = 1 then
stop5 <= (stop5_trig-start_trig-start01);
else
stop5 <= (stop5_trig-start_trig);
end if;
start_nb5 <= start_retrig_nb mod 256;
end process;
measuring_start01: process(start_retrig_p)
begin
if rising_edge(start_retrig_p) then
if start_retrig_nb = 0 then
start01 <= now - start_trig;
end if;
end if;
end process;
writing_fifo1: process (tstop1, tstop2, tstop3, tstop4)
begin
if falling_edge(tstop1) then
timestamp_for_fifo1(27 downto 26) <= "00";
timestamp_for_fifo1(25 downto 18) <= std_logic_vector(to_unsigned(start_nb1,8));
timestamp_for_fifo1(17) <= '1';
timestamp_for_fifo1(16 downto 0) <= std_logic_vector(to_unsigned(stop1/resolution,17));
start01_reg <= std_logic_vector(to_unsigned(start01/resolution,17));
report " Timestamp for interface FIFO 1:" & LF &
"===============================" & LF &
"Channel 1" & LF &
"Start number: " & integer'image(start_nb1) & LF &
"Time Interval: " & integer'image(stop1/resolution) & LF &
"Start01: " & integer'image(start01/resolution) & LF;
end if;
if falling_edge(tstop2) then
timestamp_for_fifo1(27 downto 26) <= "01";
timestamp_for_fifo1(25 downto 18) <= std_logic_vector(to_unsigned(start_nb2,8));
timestamp_for_fifo1(17) <= '1';
timestamp_for_fifo1(16 downto 0) <= std_logic_vector(to_unsigned(stop2/resolution,17));
start01_reg <= std_logic_vector(to_unsigned(start01/resolution,17));
report " Timestamp for interface FIFO 1:" & LF &
"===============================" & LF &
"Channel 2" & LF &
"Start number: " & integer'image(start_nb2) & LF &
"Time Interval: " & integer'image(stop2/resolution) & LF &
"Start01: " & integer'image(start01/resolution) & LF;
end if;
if falling_edge(tstop3) then
timestamp_for_fifo1(27 downto 26) <= "10";
timestamp_for_fifo1(25 downto 18) <= std_logic_vector(to_unsigned(start_nb3,8));
timestamp_for_fifo1(17) <= '1';
timestamp_for_fifo1(16 downto 0) <= std_logic_vector(to_unsigned(stop3/resolution,17));
start01_reg <= std_logic_vector(to_unsigned(start01/resolution,17));
report " Timestamp for interface FIFO 1:" & LF &
"===============================" & LF &
"Channel 3" & LF &
"Start number: " & integer'image(start_nb3) & LF &
"Time Interval: " & integer'image(stop3/resolution) & LF &
"Start01: " & integer'image(start01/resolution) & LF;
end if;
if falling_edge(tstop4) then
timestamp_for_fifo1(27 downto 26) <= "11";
timestamp_for_fifo1(25 downto 18) <= std_logic_vector(to_unsigned(start_nb4,8));
timestamp_for_fifo1(17) <= '1';
timestamp_for_fifo1(16 downto 0) <= std_logic_vector(to_unsigned(stop4/resolution,17));
start01_reg <= std_logic_vector(to_unsigned(start01/resolution,17));
report " Timestamp for interface FIFO 1:" & LF &
"===============================" & LF &
"Channel 4" & LF &
"Start number: " & integer'image(start_nb4) & LF &
"Time Interval: " & integer'image(stop4/resolution) & LF &
"Start01: " & integer'image(start01/resolution) & LF;
end if;
end process;
writing_fifo2: process (tstop5)
begin
if falling_edge(tstop5) then
timestamp_for_fifo2(27 downto 26) <= "00";
timestamp_for_fifo2(25 downto 18) <= std_logic_vector(to_unsigned(start_nb5,8));
timestamp_for_fifo2(17) <= '1';
timestamp_for_fifo2(16 downto 0) <= std_logic_vector(to_unsigned(stop5/resolution,17));
start01_reg <= std_logic_vector(to_unsigned(start01/resolution,17));
report " Timestamp for interface FIFO 2:" & LF &
"===============================" & LF &
"Channel 5" & LF &
"Start number: " & integer'image(start_nb5) & LF &
"Time Interval: " & integer'image(stop5/resolution) & LF &
"Start01: " & integer'image(start01/resolution) & LF;
end if;
end process;
start_retrigger_pulses: process
begin
start_retrig_p <= '0' after 333 ps;
wait for start_retrig_period/4;
start_retrig_p <= '1' after 333 ps;
wait for start_retrig_period/4;
start_retrig_p <= '0' after 333 ps;
wait for start_retrig_period/2;
end process;
start_nb_counter: process(tstart, start_retrig_p)
begin
if rising_edge(tstart) then
start_retrig_nb <= 0;
elsif rising_edge(start_retrig_p) then
start_retrig_nb <= start_retrig_nb + 1;
end if;
end process;
interrupt_flag: process(start_retrig_nb)
begin
if (start_retrig_nb mod 256) > 127 then
intflag <= '1';
else
intflag <= '0';
end if;
end process;
tstart <= tstart_i;
tstop1 <= tstop1_i;
tstop2 <= tstop2_i;
tstop3 <= tstop3_i;
tstop4 <= tstop4_i;
tstop5 <= tstop5_i;
startdis <= startdis_i;
stopdis <= stopdis_i;
int_flag_o <= intflag;
start01_o <= start01_reg;
end behavioral;
library IEEE;
use IEEE.std_logic_1164.all;
use std.textio.all;
--library std_developerskit;
--use std_developerskit.std_iopak.all;
use work.util.all;
use work.textutil.all;
--==========================================================================--
--
-- *MODULE << cmd_router >>
--
-- *Description : This module routes commands to all command driven modules
-- in the simulation. It instanciates N_FILES instances of
-- cmd_router1 and agregates the outputs to control N_BFM BFMs.
--
-- *History: M. Alford (originaly created 1993 with subsequent updates)
--
--==========================================================================--
--==========================================================================--
-- Operation
--
-- This module opens a text file and passes commands to individual vhdl models.
--
--==========================================================================--
entity cmd_router is
generic( N_BFM : integer := 8;
N_FILES : integer := 3;
FIFO_DEPTH : integer := 16;
STRING_MAX : integer := 256
);
port( CMD : out string(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean
);
end cmd_router;
architecture MODEL of cmd_router is
component cmd_router1
generic( N_BFM : integer := 8;
FIFO_DEPTH : integer := 8;
STRING_MAX : integer := 256;
FILENAME : string :="cmdfile.vec"
);
port( CMD : out STRING(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean;
CMD_DONE_IN : in boolean;
CMD_DONE_OUT : out boolean
);
end component; -- cmd_router1
type FILE_ARRAY is array (natural range <>) of string(1 to 31);
type CMD_ARRAY is array (natural range <>) of string(CMD'range);
type CMD_REQ_ARRAY is array (natural range <>) of bit_vector(N_BFM-1 downto 0);
type integer_vector is array (natural range <>) of integer;
type boolean_vector is array (natural range <>) of boolean;
constant MAX_FILES : integer := 10;
constant FILENAMES : FILE_ARRAY(0 to MAX_FILES-1) := (others=>"data_vectors/atdc_test_cmd0.vec");
-- , "data_vectors/acam_test_cmd1.vec");
-- "data_vectors/acam_test_cmd2.vec", "data_vectors/acam_test_cmd3.vec",
-- "data_vectors/acam_test_cmd4.vec", "data_vectors/acam_test_cmd5.vec",
-- "data_vectors/acam_test_cmd6.vec", "data_vectors/acam_test_cmd7.vec",
-- "data_vectors/acam_test_cmd8.vec", "data_vectors/acam_test_cmd9.vec" );
signal CMDo : CMD_ARRAY(N_FILES-1 downto 0);
signal REQ : bit_vector(CMD_REQ'range);
signal CMD_REQo : CMD_REQ_ARRAY(N_FILES-1 downto 0);
signal CMD_ACKi : CMD_REQ_ARRAY(N_FILES-1 downto 0);
signal CMD_ACK_MASK : CMD_REQ_ARRAY(N_FILES-1 downto 0); -- 1 bit_vector per file to mask CMD_ACK
signal CMD_CLOCK_ENo : boolean_vector(N_FILES-1 downto 0);
signal CMD_ALL_DONE : boolean;
signal CMD_DONE_OUT : boolean_vector(N_FILES-1 downto 0);
function or_reduce(ARG: bit_vector) return bit is
variable result: bit;
begin
result := '0';
for i in ARG'range loop
result := result or ARG(i);
end loop;
return result;
end;
function or_reduce(ARG: boolean_vector) return boolean is
variable result: boolean;
begin
result := FALSE;
for i in ARG'range loop
result := result or ARG(i);
end loop;
return result;
end;
function and_reduce(ARG: boolean_vector) return boolean is
variable result: boolean;
begin
result := TRUE;
for i in ARG'range loop
result := result and ARG(i);
end loop;
return result;
end;
begin
-----------------------------------------------------------------------------
-- Instanciate 1 cmd_router1 per file to be processed
-----------------------------------------------------------------------------
G1 : for i in 0 to N_FILES-1 generate
U1 : cmd_router1
generic map
( N_BFM => N_BFM,
FIFO_DEPTH => FIFO_DEPTH,
STRING_MAX => STRING_MAX,
FILENAME => FILENAMES(i)
)
port map
( CMD => CMDo(i),
CMD_REQ => CMD_REQo(i),
CMD_ACK => CMD_ACKi(i),
CMD_ERR => CMD_ERR,
CMD_CLOCK_EN => CMD_CLOCK_ENo(i),
CMD_DONE_IN => CMD_ALL_DONE,
CMD_DONE_OUT => CMD_DONE_OUT(i)
);
end generate;
-----------------------------------------------------------------------------
-- Multiplex the commands from the cmd_router1 modules
-----------------------------------------------------------------------------
process
variable vDONE : boolean;
begin
CMD <= (others => '0');
wait on CMD_REQo;
vDONE := FALSE;
while(not vDONE) loop
vDONE := TRUE;
for i in 0 to N_FILES-1 loop -- Loop on each file
if(or_reduce(CMD_REQo(i)) = '1') then -- this file wants to do a command
vDONE := FALSE;
--
-- if the ACK is already on from another cmd_router1
--
while(or_reduce(CMD_REQo(i) and CMD_ACK) = '1') loop
wait on CMD_ACK;
end loop;
--
-- Do the request
--
CMD <= CMDo(i);
REQ <= CMD_REQo(i);
--
-- Wait for the ACK
--
wait until(CMD_ACK'event and (or_reduce(CMD_ACK and REQ) = '1'));
--
-- send the ack to the proper file
--
for j in 0 to N_FILES-1 loop
if(i = j) then -- enable this one
CMD_ACK_MASK(j) <= CMD_ACK_MASK(j) or REQ;
else
CMD_ACK_MASK(j) <= CMD_ACK_MASK(j) and not REQ;
end if;
end loop;
--
-- Wait for the request to de-assert
--
while(or_reduce(CMD_REQo(i) and REQ) = '1') loop
wait on CMD_REQo;
end loop;
REQ <= (others => '0');
end if;
end loop;
end loop;
end process;
process(CMD_ACK, CMD_ACK_MASK)
begin
for i in 0 to N_FILES-1 loop -- Loop on each file
CMD_ACKi(i) <= CMD_ACK and CMD_ACK_MASK(i);
end loop;
end process;
CMD_REQ <= REQ;
CMD_ALL_DONE <= and_reduce(CMD_DONE_OUT);
CMD_CLOCK_EN <= CMD_CLOCK_ENo(0);
end MODEL;
library IEEE;
use IEEE.std_logic_1164.all;
use std.textio.all;
--library std_developerskit;
--use std_developerskit.std_iopak.all;
use work.util.all;
use work.textutil.all;
--==========================================================================--
--
-- *MODULE << model1 >>
--
-- *Description : This module routes commands to all command driven modules
-- in the simulation.
--
-- *History: M. Alford (originaly created 1993 with subsequent updates)
--
--==========================================================================--
--==========================================================================--
-- Operation
--
-- This module opens a text file and passes commands to individual vhdl models.
--
--==========================================================================--
entity cmd_router1 is
generic( N_BFM : integer := 8;
FIFO_DEPTH : integer := 8;
STRING_MAX : integer := 256;
FILENAME : string :="cmdfile.vec"
);
port( CMD : out STRING(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean;
CMD_DONE_IN : in boolean;
CMD_DONE_OUT : out boolean
);
end cmd_router1;
architecture MODEL of cmd_router1 is
type STRING_ARRAY is array (FIFO_DEPTH-1 downto 0) of STRING(1 to STRING_MAX);
type FD_ARRAY is array (N_BFM-1 downto 0) of STRING_ARRAY;
type integer_vector is array (natural range <>) of integer;
signal FD : FD_ARRAY;
signal ERR_CNT : integer;
signal PUSH_PTR : integer_vector(N_BFM-1 downto 0);
signal POP_PTR : integer_vector(N_BFM-1 downto 0);
signal SET_CHAN : std_ulogic;
signal POP_INIT : std_ulogic;
signal CMD_REQo : bit_vector(CMD_REQ'range);
signal LINE_NUM : integer;
begin
PUSH_PROCESS : process
file FOUT : text open write_mode is "usc.lst";
file stim_file : text open read_mode is FILENAME;
file out_file : text open write_mode is "STD_OUTPUT";
-------- For VHDL-87
-- file stim_file : text is in FILENAME;
-- file out_file : text is out "STD_OUTPUT";
variable input_line : line;
variable output_line : line;
variable tmp_lout : line;
variable command : string(1 to 8);
variable tmp_str : string(1 to STRING_MAX);
variable input_str : string(1 to STRING_MAX);
variable i : integer;
variable CHANNEL : integer;
variable S_PTR : integer;
variable vLINE_NUM : integer;
variable vPUSH_PTR : integer_vector(N_BFM-1 downto 0);
variable DONE : boolean;
variable EOS : integer;
variable ERR : integer;
begin
-----------------------------------------------------------------------------
-- Main Loop
-----------------------------------------------------------------------------
vLINE_NUM := 0;
PUSH_PTR <= (others => 0);
vPUSH_PTR := (others => 0);
CHANNEL := 0;
CMD_CLOCK_EN <= TRUE;
SET_CHAN <= '0';
CMD_DONE_OUT <= FALSE;
if(POP_INIT /= '1') then
wait until(POP_INIT'event and (POP_INIT = '1'));
end if;
ST_LOOP: while not endfile(stim_file) loop
readline(stim_file, input_line);
S_PTR := 1;
vLINE_NUM := vLINE_NUM + 1;
LINE_NUM <= vLINE_NUM;
-- Copy the line
input_str := (others => ' ');
input_str(1 to 6) := To_Strn(vLINE_NUM, 6);
input_str(7 to 8) := string'(": ");
input_str(9 to input_line'length+8) := string'(input_line.all);
while(input_str(S_PTR) /= ':') loop
S_PTR := S_PTR + 1;
end loop;
S_PTR := S_PTR + 1;
sget_token(input_str, S_PTR, command);
SET_CHAN <= '1';
for j in STRING_MAX downto 1 loop
if(input_str(j) /= ' ') then
EOS := j;
exit;
end if;
end loop;
---------------------------
-- "model" command ?
---------------------------
if(command(1 to 5) = "model") then
sget_int(input_str, S_PTR, i);
write(tmp_lout, FILENAME);
write(tmp_lout, input_str(1 to EOS));
writeline(out_file, tmp_lout);
if((i >= N_BFM) or (i < 0)) then
CHANNEL := N_BFM-1;
write(tmp_lout, string'("ERROR: Invalid Channel "));
write(tmp_lout, i);
writeline(out_file, tmp_lout);
else
CHANNEL := i;
end if;
---------------------------
-- "sync" command ?
---------------------------
elsif(command(1 to 4) = "sync") then
loop
DONE := TRUE;
for i in PUSH_PTR'reverse_range loop
if((vPUSH_PTR(i) /= POP_PTR(i)) or (CMD_ACK(i) /= '0')) then
DONE := FALSE;
end if;
end loop;
if(DONE) then
exit;
end if;
wait on POP_PTR, CMD_ACK;
end loop;
write(tmp_lout, FILENAME);
write(tmp_lout, input_str(1 to EOS));
writeline(out_file, tmp_lout);
---------------------------
-- "gsync" and "ckoff" command ?
---------------------------
elsif((command(1 to 5) = "gsync") or (command(1 to 5) = "ckoff")) then
write(tmp_lout, FILENAME);
write(tmp_lout, string'(": entering the gsync command"));
writeline(out_file, tmp_lout);
loop
DONE := TRUE;
for i in PUSH_PTR'reverse_range loop
if((vPUSH_PTR(i) /= POP_PTR(i)) or (CMD_ACK(i) /= '0')) then
DONE := FALSE;
end if;
end loop;
if(DONE) then
exit;
end if;
wait on POP_PTR, CMD_ACK;
end loop;
CMD_DONE_OUT <= TRUE;
-- wait for the external CMD_DONE_IN to be done
while (not CMD_DONE_IN) loop
wait on CMD_DONE_IN;
end loop;
CMD_DONE_OUT <= FALSE;
write(tmp_lout, FILENAME);
write(tmp_lout, input_str(1 to EOS));
writeline(out_file, tmp_lout);
if (command(1 to 5) = "ckoff") then
CMD_CLOCK_EN <= FALSE;
end if;
write(tmp_lout, FILENAME);
write(tmp_lout, string'(": gsync command is DONE"));
writeline(out_file, tmp_lout);
--------------------
-- ckon
--------------------
elsif (command(1 to 4) = "ckon") then
CMD_CLOCK_EN <= TRUE;
write(tmp_lout, FILENAME);
write(tmp_lout, input_str(1 to EOS));
writeline(out_file, tmp_lout);
---------------------------
-- put the line in the FIFO
---------------------------
else
FD(CHANNEL)(vPUSH_PTR(CHANNEL)) <= input_str;
vPUSH_PTR(CHANNEL) := vPUSH_PTR(CHANNEL) + 1;
if(vPUSH_PTR(CHANNEL) >= FIFO_DEPTH) then
vPUSH_PTR(CHANNEL) := 0;
end if;
if(vPUSH_PTR(CHANNEL) = POP_PTR(CHANNEL)) then -- The FIFO is full
wait until(POP_PTR'event and (vPUSH_PTR(CHANNEL) /= POP_PTR(CHANNEL)));
end if;
PUSH_PTR(CHANNEL) <= vPUSH_PTR(CHANNEL);
end if;
end loop;
loop
DONE := TRUE;
for i in POP_PTR'reverse_range loop
if((POP_PTR(i) /= vPUSH_PTR(i)) or (CMD_ACK(i) = '1')) then -- FIFO channel not empty
DONE := FALSE;
end if;
end loop;
if(DONE) then
exit;
end if;
wait on CMD_ACK, POP_PTR;
end loop;
CMD_DONE_OUT <= TRUE;
write(output_line, string'("******************************* Test Finished *******************************"));
writeline(out_file, output_line);
write(output_line, string'("* Total Errors for "));
write(output_line, FILENAME);
write(output_line, string'(": "));
write(output_line, err_cnt);
writeline(out_file, output_line);
write(output_line, string'("*****************************************************************************"));
writeline(out_file, output_line);
file_close(stim_file); -- Close File
loop
wait for 100000 us;
end loop;
end process;
-----------------------------------------------------------------------------
-- POP Process
-----------------------------------------------------------------------------
POP_PROCESS : process
variable vPOP_PTR : integer_vector(POP_PTR'range);
variable DONE : boolean;
file out_file : text open write_mode is "STD_OUTPUT";
-------- For VHDL-87
-- file out_file : text is out "STD_OUTPUT";
variable tmp_lout : line;
variable CHAR_PTR : integer;
variable EOS : integer;
begin
CHAR_PTR := 1;
ERR_CNT <= 0;
POP_PTR <= (others => 0);
vPOP_PTR := (others => 0);
CMD_REQo <= (others => '0');
POP_INIT <= '1';
if(SET_CHAN /= '1') then
wait until(SET_CHAN'event and (SET_CHAN = '1'));
end if;
loop
DONE := FALSE;
loop
DONE := TRUE;
for i in POP_PTR'reverse_range loop
if((vPOP_PTR(i) /= PUSH_PTR(i)) and (CMD_ACK(i) = '0')) then -- FIFO channel not empty
CMD <= FD(i)(vPOP_PTR(i));
CMD_REQo(i) <= '1';
for j in STRING_MAX downto 1 loop
if(FD(i)(vPOP_PTR(i))(j) /= ' ') then
EOS := j;
exit;
end if;
end loop;
write(tmp_lout, FILENAME);
write(tmp_lout, FD(i)(vPOP_PTR(i))(1 to EOS));
writeline(out_file, tmp_lout);
if(CMD_ACK(i) /= '1') then
wait until(CMD_ACK'event and (CMD_ACK(i) = '1'));
end if;
CMD_REQo(i) <= '0';
DONE := FALSE;
vPOP_PTR(i) := vPOP_PTR(i) + 1;
if(vPOP_PTR(i) >= FIFO_DEPTH) then
vPOP_PTR(i) := 0;
end if;
POP_PTR(i) <= vPOP_PTR(i);
end if;
end loop;
if(DONE) then
exit;
end if;
end loop;
wait on PUSH_PTR, CMD_ACK;
end loop;
end process;
CMD_REQ <= CMD_REQo;
end MODEL;
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
library IEEE;
use IEEE.std_logic_1164.all;
use std.textio.all;
use work.util.all;
-----------------------------------------------------------------------------
-- *Module : textutil
--
-- *Description : Improved Free-format string and line manipulation
--
-- *History: M. Alford (originaly created 1993 with subsequent updates)
-----------------------------------------------------------------------------
package textutil is
procedure read_token(L : inout line; X : out STRING);
procedure sget_token(S : in string; P : inout integer; X : out STRING);
procedure sget_vector(S : in string; P : inout integer; VEC : out STD_ULOGIC_VECTOR);
procedure sget_vector_64(S : in string; P : inout integer; VEC : out STD_ULOGIC_VECTOR);
procedure sget_int(S : in string; P : inout integer; X : out integer);
function hex_char_to_vector(C : in character) return STD_ULOGIC_VECTOR;
function vector_to_hex_char(V : in STD_ULOGIC_VECTOR) return character;
function is_hex(C : in character) return BOOLEAN;
function hex_char_to_int(C : in character) return integer;
procedure read_vector(L : inout line; VEC : out STD_ULOGIC_VECTOR);
procedure read_int(L : inout line; I : out integer);
procedure write_hex_vector(L : inout line; V : in STD_ULOGIC_VECTOR);
function to_str(constant V: in STD_ULOGIC_VECTOR) return STRING;
function to_str(constant V: in STD_ULOGIC) return STRING;
function to_str(constant val : in INTEGER) return STRING;
function to_strn(constant val : in INTEGER; constant n : in INTEGER) return STRING;
end textutil;
package body textutil is
-----------------------------------------------------------------------------
-- *Module : read_token
--
-- *Description : Skip over spaces then load a token string from a line
-- until either the string is full or the token is finished
-- (i.e. another space). The output string is padded out
-- with blanks at the end if the token length is less then
-- the full string length.
-----------------------------------------------------------------------------
procedure read_token(L : inout line; X : out STRING) is
variable char : character;
begin
if(L'length > 0) then
char := ' ';
while((char = ' ') and (L'length > 0)) loop -- Skip spaces
read(L, char);
end loop;
for i in X'low to X'high loop
X(i) := char;
if(char /= ' ') then
if(L'length > 0) then
read(L, char);
else
char := ' ';
end if;
end if;
end loop;
else
assert false report "Couldn't read a token from file"
severity error;
end if;
end read_token;
-----------------------------------------------------------------------------
-- *Module : sget_token
--
-- *Description : Same as read_token except for strings.
-----------------------------------------------------------------------------
procedure sget_token(S : in string; P : inout integer; X : out STRING) is
variable char : character;
begin
if(S'length > P) then
char := ' ';
while((char = ' ') and (S'length >= P)) loop -- Skip spaces
char := S(P);
P := P + 1;
end loop;
for i in X'low to X'high loop
X(i) := char;
if(char /= ' ') then
if(S'length > P) then
char := S(P);
P := P + 1;
else
char := ' ';
end if;
end if;
end loop;
else
assert false report "Couldn't read a token from a string"
severity error;
end if;
end sget_token;
-----------------------------------------------------------------------------
-- *Module : hex_char_to_vector
--
-- *Description : Convert a hex character to a vector
-----------------------------------------------------------------------------
function hex_char_to_vector(C : in character) return STD_ULOGIC_VECTOR is
variable X : STD_ULOGIC_VECTOR( 3 downto 0);
begin
case C is
when '0' => X := "0000";
when '1' => X := "0001";
when '2' => X := "0010";
when '3' => X := "0011";
when '4' => X := "0100";
when '5' => X := "0101";
when '6' => X := "0110";
when '7' => X := "0111";
when '8' => X := "1000";
when '9' => X := "1001";
when 'A' => X := "1010";
when 'B' => X := "1011";
when 'C' => X := "1100";
when 'D' => X := "1101";
when 'E' => X := "1110";
when 'F' => X := "1111";
when 'a' => X := "1010";
when 'b' => X := "1011";
when 'c' => X := "1100";
when 'd' => X := "1101";
when 'e' => X := "1110";
when 'f' => X := "1111";
when others =>
X := "0000";
assert false report "Invalid Hex Character"
severity error;
end case;
return(X);
end hex_char_to_vector;
-----------------------------------------------------------------------------
-- *Module : vector_to_hex_char
--
-- *Description : Convert a vector to a hex character. Only uses low 4 bits.
-----------------------------------------------------------------------------
function vector_to_hex_char(V : in STD_ULOGIC_VECTOR) return character is
variable C : character;
variable VV : STD_ULOGIC_VECTOR(3 downto 0);
begin
if(V'length < 4) then
VV := To_X01(V(V'low + 3 downto V'low));
else
VV := To_X01(V(V'low + V'length - 1 downto V'low));
end if;
case VV is
when "0000" => C := '0';
when "0001" => C := '1';
when "0010" => C := '2';
when "0011" => C := '3';
when "0100" => C := '4';
when "0101" => C := '5';
when "0110" => C := '6';
when "0111" => C := '7';
when "1000" => C := '8';
when "1001" => C := '9';
when "1010" => C := 'A';
when "1011" => C := 'B';
when "1100" => C := 'C';
when "1101" => C := 'D';
when "1110" => C := 'E';
when "1111" => C := 'F';
when others => C := 'X';
end case;
return(C);
end vector_to_hex_char;
-----------------------------------------------------------------------------
-- *Module : is_hex
--
-- *Description : report if a char is ASCII hex
-----------------------------------------------------------------------------
function is_hex(C : in character) return BOOLEAN is
variable X : boolean;
begin
case C is
when '0' => X := TRUE;
when '1' => X := TRUE;
when '2' => X := TRUE;
when '3' => X := TRUE;
when '4' => X := TRUE;
when '5' => X := TRUE;
when '6' => X := TRUE;
when '7' => X := TRUE;
when '8' => X := TRUE;
when '9' => X := TRUE;
when 'A' => X := TRUE;
when 'B' => X := TRUE;
when 'C' => X := TRUE;
when 'D' => X := TRUE;
when 'E' => X := TRUE;
when 'F' => X := TRUE;
when 'a' => X := TRUE;
when 'b' => X := TRUE;
when 'c' => X := TRUE;
when 'd' => X := TRUE;
when 'e' => X := TRUE;
when 'f' => X := TRUE;
when others =>
X := FALSE;
end case;
return(X);
end is_hex;
-----------------------------------------------------------------------------
-- *Module : hex_char_to_int
--
-- *Description : Convert a hex character to an integer
-----------------------------------------------------------------------------
function hex_char_to_int(C : in character) return integer is
variable X : integer;
begin
case C is
when '0' => X := 0;
when '1' => X := 1;
when '2' => X := 2;
when '3' => X := 3;
when '4' => X := 4;
when '5' => X := 5;
when '6' => X := 6;
when '7' => X := 7;
when '8' => X := 8;
when '9' => X := 9;
when 'A' => X := 10;
when 'B' => X := 11;
when 'C' => X := 12;
when 'D' => X := 13;
when 'E' => X := 14;
when 'F' => X := 15;
when 'a' => X := 10;
when 'b' => X := 11;
when 'c' => X := 12;
when 'd' => X := 13;
when 'e' => X := 14;
when 'f' => X := 15;
when others =>
X := 0;
assert false report "Invalid Hex Character"
severity error;
end case;
return(X);
end hex_char_to_int;
-----------------------------------------------------------------------------
-- *Module : read_vector
--
-- *Description : load a vector from the input line in a free floating format
-----------------------------------------------------------------------------
procedure read_vector(L : inout line; VEC : out STD_ULOGIC_VECTOR) is
variable char : character;
variable base : integer;
variable q : integer;
variable v : STD_ULOGIC_VECTOR(31 downto 0);
begin
if(L'length > 0) then
char := ' ';
while(char = ' ') loop -- Skip spaces
read(L, char);
end loop;
base := 16; -- Hex is the default
if(char = '%') then -- determine base
read(L, char);
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
elsif(char = 'd' or char = 'D') then
base := 10;
else
assert false report "Unsupported Base detected when reading a Vector"
severity error;
end if;
read(L, char);
end if;
q := 0;
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
while(is_hex(char) and not (L'length = 0)) loop
read(L, char);
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
end if;
end loop;
end if;
if(q < 0) then
q := q-2147483648;
V(30 downto 0) := to_vector(q, 31);
V(31) := '1';
else
V(30 downto 0) := to_vector(q, 31);
V(31) := '0';
end if;
VEC := V((VEC'high - VEC'low) downto 0);
else
assert false report "Couldn't read a vector"
severity error;
end if;
end read_vector;
-----------------------------------------------------------------------------
-- *Module : sget_vector
--
-- *Description : Same as sget_vector except for strings
-----------------------------------------------------------------------------
procedure sget_vector(S : in string; P : inout integer; VEC : out STD_ULOGIC_VECTOR) is
variable char : character;
variable base : integer;
variable q : integer;
variable v : STD_ULOGIC_VECTOR(31 downto 0);
begin
while(S(P) = ' ') loop -- Skip spaces
if(P >= S'length) then
P := S'length;
exit;
end if;
P := P + 1;
end loop;
if(S'length > P) then
char := S(P);
if(char = '"') then -- read in as a literal
q := v'high;
v := (others => 'U');
VEC := v(VEC'range);
char := ' ';
P := P + 1;
while((char /= '"') and not (S'length = P)) loop
char := S(P);
P := P + 1;
case char is
when '0' =>
v(q) := '0';
when '1' =>
v(q) := '1';
when 'L' | 'l' =>
v(q) := 'L';
when 'H' | 'h' =>
v(q) := 'H';
when 'Z' | 'z' =>
v(q) := 'Z';
when 'X' | 'x' =>
v(q) := 'X';
when 'U' | 'u' =>
v(q) := 'U';
when others =>
-- char := '"';
exit;
end case;
q := q - 1;
end loop;
if(v'high-q < 2) then -- only a single bit was read
VEC(VEC'low) := v(v'high);
elsif((v'high - q) > VEC'length) then -- too many bits
VEC := v(q+VEC'length downto q+1);
else -- the number of bits read is same or less than required
VEC(v'high-q-1+VEC'low downto VEC'low) := v(v'high downto q+1);
end if;
else
base := 16; -- Hex is the default
if(char = '%') then -- determine base
P := P + 1;
char := S(P);
P := P + 1;
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
elsif(char = 'd' or char = 'D') then
base := 10;
else
assert false report "Unsupported Base detected when reading a Vector"
severity error;
end if;
elsif((char = '0') and ((S(P+1) = 'x') or (S(P+1) = 'X'))) then
P := P + 2;
end if;
q := 0;
char := S(P);
if(is_hex(char)) then
while(is_hex(char) and not (S'length = P)) loop
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
end if;
P := P + 1;
char := S(P);
end loop;
end if;
if(q < 0) then
q := q-2147483648;
V(30 downto 0) := to_vector(q, 31);
V(31) := '1';
else
V(30 downto 0) := to_vector(q, 31);
V(31) := '0';
end if;
VEC := V((VEC'high - VEC'low) downto 0);
end if;
else
assert false report "Couldn't read a vector"
severity error;
V := (others => '0');
VEC := V((VEC'high - VEC'low) downto 0);
end if;
end sget_vector;
-----------------------------------------------------------------------------
-- *Module : sget_vector_64
--
-- *Description : Same as sget_vector except can handle 64 bit quantities and hex or binary base (no base 10)
-----------------------------------------------------------------------------
procedure sget_vector_64(S : in string; P : inout integer; VEC : out STD_ULOGIC_VECTOR) is
variable char : character;
variable base : integer;
variable q : integer;
variable v : STD_ULOGIC_VECTOR(63 downto 0);
begin
while(S(P) = ' ') loop -- Skip spaces
if(P >= S'length) then
P := S'length;
exit;
end if;
P := P + 1;
end loop;
if(S'length > P) then
char := S(P);
if(char = '"') then -- read in as a literal
q := v'high;
v := (others => 'U');
VEC := v(VEC'range);
char := ' ';
P := P + 1;
while((char /= '"') and not (S'length = P)) loop
char := S(P);
P := P + 1;
case char is
when '0' =>
v(q) := '0';
when '1' =>
v(q) := '1';
when 'L' | 'l' =>
v(q) := 'L';
when 'H' | 'h' =>
v(q) := 'H';
when 'Z' | 'z' =>
v(q) := 'Z';
when 'X' | 'x' =>
v(q) := 'X';
when 'U' | 'u' =>
v(q) := 'U';
when others =>
-- char := '"';
exit;
end case;
q := q - 1;
end loop;
if(v'high-q < 2) then -- only a single bit was read
VEC(VEC'low) := v(v'high);
elsif((v'high - q) > VEC'length) then -- too many bits
VEC := v(q+VEC'length downto q+1);
else -- the number of bits read is same or less than required
VEC(v'high-q-1+VEC'low downto VEC'low) := v(v'high downto q+1);
end if;
else
base := 16; -- Hex is the default
if(char = '%') then -- determine base
P := P + 1;
char := S(P);
P := P + 1;
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
else
assert false report "Unsupported Base detected when reading a Vector"
severity error;
end if;
char := S(P);
-- P := P + 1;
elsif((char = '0') and ((S(P+1) = 'x') or (S(P+1) = 'X'))) then
P := P + 2;
end if;
v := (others => '0');
char := S(P);
if(base = 2) then
while(((char = '0') or (char = '1')) and not (P > S'length)) loop
if(char = '0') then
v := v(v'high-1 downto 0) & '0';
else
v := v(v'high-1 downto 0) & '1';
end if;
P := P + 1;
char := S(P);
end loop;
else
while(is_hex(char) and not (P > S'length)) loop
if(is_hex(char)) then
v := v(v'high-4 downto 0) & hex_char_to_vector(char);
end if;
P := P + 1;
char := S(P);
end loop;
end if;
VEC := V((VEC'high - VEC'low) downto 0);
end if;
else
assert false report "Couldn't read a vector"
severity error;
V := (others => '0');
VEC := V((VEC'high - VEC'low) downto 0);
end if;
end sget_vector_64;
-----------------------------------------------------------------------------
-- *Module : read_int
--
-- *Description : load an integer from the input line in a free floating format
-----------------------------------------------------------------------------
procedure read_int(L : inout line; I : out integer) is
variable char : character;
variable base : integer;
variable q : integer;
begin
if(L'length > 0) then
char := ' ';
while(char = ' ') loop -- Skip spaces
read(L, char);
end loop;
base := 16; -- Hex is the default
if(char = '%') then -- determine base
read(L, char);
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
elsif(char = 'd' or char = 'D') then
base := 10;
else
assert false report "Unsupported Base detected when reading an integer"
severity error;
end if;
read(L, char);
end if;
q := 0;
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
while(is_hex(char) and not (L'length = 0)) loop
read(L, char);
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
end if;
end loop;
end if;
I := q;
else
assert false report "Couldn't read an integer"
severity error;
end if;
end read_int;
-----------------------------------------------------------------------------
-- *Module : sget_int
--
-- *Description : Same as read_int except for strings
-----------------------------------------------------------------------------
procedure sget_int(S : in string; P : inout integer; X : out integer) is
variable char : character;
variable base : integer;
variable q : integer;
begin
if(S'length > P) then
char := ' ';
while(char = ' ') loop -- Skip spaces
char := S(P);
P := P + 1;
end loop;
base := 16; -- Hex is the default
if(char = '%') then -- determine base
char := S(P);
P := P + 1;
if(char = 'b' or char = 'B') then
base := 2;
elsif(char = 'x' or char = 'X') then
base := 16;
elsif(char = 'd' or char = 'D') then
base := 10;
else
assert false report "Unsupported Base detected when reading an integer"
severity error;
end if;
char := S(P);
P := P + 1;
end if;
q := 0;
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
while(is_hex(char) and not (S'length = P)) loop
char := S(P);
P := P + 1;
if(is_hex(char)) then
q := q * base + hex_char_to_int(char);
end if;
end loop;
end if;
X := q;
else
assert false report "Couldn't read an integer"
severity error;
end if;
end sget_int;
-----------------------------------------------------------------------------
-- *Module : write_hex_vector
--
-- *Description : writes out a vector as hex
-----------------------------------------------------------------------------
procedure write_hex_vector(L : inout line; V : in STD_ULOGIC_VECTOR) is
variable C : character;
variable VV : STD_ULOGIC_VECTOR(((V'length + 3)/4) * 4 - 1 downto 0);
begin
VV := (others => '0');
VV(V'length -1 downto 0) := V;
for i in VV'length/4 - 1 downto 0 loop
C := vector_to_hex_char(VV(i*4+3 downto i*4));
write(L, C);
end loop;
end write_hex_vector;
-----------------------------------------------------------------------------
-- *Module : to_str
--
-- *Description : Converts a STD_ULOGIC_VECTOR to a string of the same length
-----------------------------------------------------------------------------
function to_str(constant V: in STD_ULOGIC_VECTOR) return STRING is
variable S : STRING(1 to V'length);
variable sp : integer;
begin
sp := 1;
for i in V'range loop
case V(i) is
when '1' | 'H' =>
S(sp) := '1';
when '0' | 'L' =>
S(sp) := '0';
when others =>
S(sp) := 'X';
end case;
sp := sp + 1;
end loop;
return(S);
end to_str;
-----------------------------------------------------------------------------
-- *Module : to_str
--
-- *Description : Converts a STD_ULOGIC to a string
-----------------------------------------------------------------------------
function to_str(constant V: in STD_ULOGIC) return STRING is
-- variable S : STRING(1);
begin
case V is
when '1' | 'H' =>
return("1");
when '0' | 'L' =>
return("0");
when others =>
return("X");
end case;
return("X");
end to_str;
-----------------------------------------------------------------------------
-- *Module : to_str
--
-- *Description : Converts a integer to a string
-----------------------------------------------------------------------------
function to_str(constant val : in INTEGER) return STRING is
variable result : STRING(11 downto 1) := "-2147483648"; -- smallest integer and longest string
variable tmp : INTEGER;
variable pos : NATURAL := 1;
variable digit : NATURAL;
begin
-- for the smallest integer MOD does not seem to work...
--if val = -2147483648 then : compilation error with Xilinx tools...
if val < -2147483647 then
pos := 12;
else
tmp := abs(val);
loop
digit := abs(tmp MOD 10);
tmp := tmp / 10;
result(pos) := character'val(character'pos('0') + digit);
pos := pos + 1;
exit when tmp = 0;
end loop;
if val < 0 then
result(pos) := '-';
pos := pos + 1;
end if;
end if;
return result((pos-1) downto 1);
end to_str;
-----------------------------------------------------------------------------
-- *Module : to_strn
--
-- *Description : Converts an integer to a string of length N
-----------------------------------------------------------------------------
function to_strn(constant val : in INTEGER; constant n : in INTEGER) return STRING is
variable result : STRING(11 downto 1) := "-2147483648"; -- smallest integer and longest string
variable tmp : INTEGER;
variable pos : NATURAL := 1;
variable digit : NATURAL;
begin
-- for the smallest integer MOD does not seem to work...
--if val = -2147483648 then : compilation error with Xilinx tools...
if val < -2147483647 then
pos := 12;
else
result := (others => ' ');
tmp := abs(val);
loop
digit := abs(tmp MOD 10);
tmp := tmp / 10;
result(pos) := character'val(character'pos('0') + digit);
pos := pos + 1;
exit when tmp = 0;
end loop;
if val < 0 then
result(pos) := '-';
pos := pos + 1;
end if;
end if;
return result(n downto 1);
end to_strn;
end textutil;
library ieee;
use ieee.std_logic_1164.all;
--library synopsys;
--use synopsys.arithmetic.all;
package UTIL is
function to_mvl ( b: in boolean ) return STD_ULOGIC;
function to_mvl ( i: in integer ) return STD_ULOGIC;
function to_vector(input,num_bits:integer) return STD_ULOGIC_VECTOR;
-- function to_signed( b: in std_ulogic_vector ) return signed;
-- function to_std_ulogic_vector( b: in signed ) return std_ulogic_vector;
-- function std_logic_to_std_ulogic( b: in std_logic ) return std_ulogic;
-- function std_ulogic_to_std_logic( b: in std_ulogic ) return std_logic;
function "and"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC) return STD_ULOGIC_VECTOR;
function "and"(l: STD_ULOGIC; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
function "and"(l: STD_ULOGIC_VECTOR; r: BOOLEAN) return STD_ULOGIC_VECTOR;
function "and"(l: BOOLEAN; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
function "and"(l: BOOLEAN; r: STD_ULOGIC) return STD_ULOGIC;
function "and"(l: STD_ULOGIC; r: BOOLEAN) return STD_ULOGIC;
function exp(input: STD_ULOGIC; num_bits: integer) return STD_ULOGIC_VECTOR;
function exp(input: STD_ULOGIC_VECTOR; num_bits: integer) return STD_ULOGIC_VECTOR;
function conv_integer ( ARG: in STD_ULOGIC_VECTOR ) return integer;
function "+"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC) return STD_ULOGIC_VECTOR;
-- function "+"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
-- function "-"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC) return STD_ULOGIC_VECTOR;
-- function "-"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR;
function to_int(l: std_ulogic_vector) return natural;
function to_int(l: std_ulogic) return natural;
function and_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function nand_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function or_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function nor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function xor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function xnor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC;
function ge ( l, r : STD_ULOGIC_VECTOR ) return BOOLEAN;
function gt ( l, r : STD_ULOGIC_VECTOR ) return BOOLEAN;
function lt ( l, r : STD_ULOGIC_VECTOR ) return BOOLEAN;
function eq ( l, r : STD_ULOGIC_VECTOR ) return BOOLEAN;
function maximum ( arg1, arg2 : INTEGER) return INTEGER;
function minimum ( arg1, arg2 : INTEGER) return INTEGER;
procedure keep(signal X: inout STD_LOGIC);
function log2(A: in integer) return integer;
-------------------------------------------------------------------
-- Declaration of Synthesis directive attributes
-------------------------------------------------------------------
ATTRIBUTE synthesis_return : string ;
end UTIL;
package body UTIL is
--------------------------------------------------------------------
-- function to_signed ( b: in std_ulogic_vector ) return signed is
-- variable result : signed(b'range);
-- begin
-- for i in b'range loop
-- result(i) := b(i);
-- end loop;
-- return result;
-- end to_signed;
--------------------------------------------------------------------
-- function to_std_ulogic_vector ( b: in signed ) return std_ulogic_vector is
-- variable result : std_ulogic_vector(b'range);
-- begin
-- for i in b'range loop
-- result(i) := b(i);
-- end loop;
-- return result;
-- end to_std_ulogic_vector;
--------------------------------------------------------------------
function to_mvl ( b: in boolean ) return STD_ULOGIC is
begin
if ( b = TRUE ) then
return( '1' );
else
return( '0' );
end if;
end to_mvl;
--------------------------------------------------------------------
function to_mvl ( i: in integer ) return STD_ULOGIC is
begin
if ( i = 1 ) then
return( '1' );
else
return( '0' );
end if;
end to_mvl;
--------------------------------------------------------------------
function "and"(l: STD_ULOGIC; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
variable rr: STD_ULOGIC_vector(r'range);
begin
if (l = '1') then
rr := r;
else
rr := (others => '0');
end if;
return(rr);
end;
--------------------------------------------------------------------
function "and"(l: STD_ULOGIC_VECTOR; r: STD_ULOGIC) return STD_ULOGIC_VECTOR is
variable ll: STD_ULOGIC_vector(l'range);
begin
if (r = '1') then
ll := l;
else
ll := (others => '0');
end if;
return(ll);
end;
--------------------------------------------------------------------
function "and"(l: BOOLEAN; r: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
variable rr: STD_ULOGIC_vector(r'range);
begin
if (l) then
rr := r;
else
rr := (others => '0');
end if;
return(rr);
end;
--------------------------------------------------------------------
function "and"(l: STD_ULOGIC_VECTOR; r: BOOLEAN) return STD_ULOGIC_VECTOR is
variable ll: STD_ULOGIC_vector(l'range);
begin
if (r) then
ll := l;
else
ll := (others => '0');
end if;
return(ll);
end;
--------------------------------------------------------------------
function "and"(l: BOOLEAN; r: STD_ULOGIC) return STD_ULOGIC is
variable ll: STD_ULOGIC;
begin
if (l) then
ll := r;
else
ll := '0';
end if;
return(ll);
end;
--------------------------------------------------------------------
function "and"(l: STD_ULOGIC; r: BOOLEAN) return STD_ULOGIC is
variable ll: STD_ULOGIC;
begin
if (r) then
ll := l;
else
ll := '0';
end if;
return(ll);
end;
--------------------------------------------------------------------
-- function std_ulogic_to_std_logic(b : std_ulogic) return std_logic is
-- variable result: std_logic;
-- begin
-- result := b;
-- return result;
-- end;
--------------------------------------------------------------------
-- function std_logic_to_std_ulogic(b : std_logic) return std_ulogic is
-- variable result: std_ulogic;
-- begin
-- result := b;
-- return result;
-- end;
--------------------------------------------------------------------
function to_vector(input,num_bits: integer) return std_ulogic_vector is
variable vec: std_ulogic_vector(num_bits-1 downto 0);
variable a: integer;
begin
a := input;
for i in 0 to num_bits-1 loop
if ((a mod 2) = 1) then
vec(i) := '1';
else
vec(i) := '0';
end if;
a := a / 2;
end loop;
return vec;
end to_vector;
-- FUNCTION to_vector(input,num_bits:integer) RETURN STD_ULOGIC_VECTOR IS
-- VARIABLE result:STD_ULOGIC_VECTOR(num_bits-1 DOWNTO 0);
-- VARIABLE weight:integer;
-- VARIABLE temp:integer;
-- BEGIN
-- weight := 2**(num_bits-1);
-- temp := input;
-- FOR i in result'HIGH DOWNTO result'LOW LOOP
-- IF temp >= weight THEN
-- result(i) := '1';
-- temp := temp - weight;
-- ELSE
-- result(i) := '0';
-- END IF;
-- weight := weight/2;
-- END LOOP;
-- RETURN result;
-- END to_vector;
--------------------------------------------------------------------
-- exp: Expand one bit into many
--------------------------------------------------------------------
FUNCTION exp(input:STD_ULOGIC; num_bits:integer) RETURN STD_ULOGIC_VECTOR IS
VARIABLE result:STD_ULOGIC_VECTOR(num_bits-1 DOWNTO 0);
BEGIN
FOR i in result'HIGH DOWNTO result'LOW LOOP
result(i) := input;
END LOOP;
RETURN result;
END exp;
--------------------------------------------------------------------
-- exp: Expand n bits into m bits
--------------------------------------------------------------------
FUNCTION exp(input:STD_ULOGIC_VECTOR; num_bits:integer) RETURN STD_ULOGIC_VECTOR IS
VARIABLE result:STD_ULOGIC_VECTOR(num_bits-1 DOWNTO 0);
BEGIN
result(input'high-input'low downto 0) := input;
result(num_bits-1 downto input'high-input'low+1) := (others => '0');
RETURN result;
END exp;
--------------------------------------------------------------------
-- conv_integer
--------------------------------------------------------------------
function conv_integer ( ARG: in STD_ULOGIC_VECTOR ) return integer is
variable result: INTEGER;
begin
assert ARG'length <= 31
report "ARG is too large in CONV_INTEGER"
severity FAILURE;
result := 0;
for i in ARG'range loop
result := result * 2;
if(ARG(i) = 'H' or ARG(i) = '1') then
result := result + 1;
end if;
end loop;
return result;
end;
--------------------------------------------------------------------
-- "+" Increment function
--------------------------------------------------------------------
function "+"(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC) return STD_ULOGIC_VECTOR is
variable Q: STD_ULOGIC_VECTOR(L'range);
variable A: STD_ULOGIC;
begin
A := R;
for i in L'low to L'high loop
Q(i) := L(i) xor A;
A := A and L(i);
end loop;
return Q;
end;
--------------------------------------------------------------------
-- "+" adder function
--------------------------------------------------------------------
-- function "+"(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
-- variable Q : SIGNED(L'range);
-- variable result: STD_ULOGIC_VECTOR(L'range);
-- begin
-- Q := to_signed(L) + to_signed(R);
-- result := to_std_ulogic_vector(Q);
-- return result;
-- end;
--------------------------------------------------------------------
-- "-" Decrement function
--------------------------------------------------------------------
-- function "-"(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC) return STD_ULOGIC_VECTOR is
-- variable Q: STD_ULOGIC_VECTOR(L'range);
-- variable A: STD_ULOGIC;
-- begin
-- A := R;
-- for i in L'low to L'high loop
-- Q(i) := L(i) xor A;
-- A := A and not L(i);
-- end loop;
-- return Q;
-- end;
--------------------------------------------------------------------
-- "-" subtractor function
--------------------------------------------------------------------
-- function "-"(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is
-- variable Q : SIGNED(L'range);
-- variable result: STD_ULOGIC_VECTOR(L'range);
-- begin
-- Q := to_signed(L) - to_signed(R);
-- result := to_std_ulogic_vector(Q);
-- return result;
-- end;
--------------------------------------------------------------------
-- to_int : Convert std_ulogic_vector to an integer
--------------------------------------------------------------------
function to_int(l: std_ulogic_vector) return natural is
variable result: natural := 0;
begin
for t1 in l'range loop
result := result * 2;
if (l(t1) = '1') or (l(t1) = 'H') then
result := result + 1;
end if;
end loop;
return result;
end to_int;
--------------------------------------------------------------------
-- to_int : Convert std_ulogic_vector to an integer
--------------------------------------------------------------------
function to_int(l: std_ulogic) return natural is
variable result: natural := 0;
begin
if (l = '1') or (l = 'H') then
result := 1;
else
result := 0;
end if;
return result;
end to_int;
--------------------------------------------------------------------
-- Reduce Functions
--------------------------------------------------------------------
function and_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
variable result: STD_ULOGIC;
begin
result := '1';
for i in ARG'range loop
result := result and ARG(i);
end loop;
return result;
end;
function nand_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
begin
return not and_reduce(ARG);
end;
function or_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
variable result: STD_ULOGIC;
begin
result := '0';
for i in ARG'range loop
result := result or ARG(i);
end loop;
return result;
end;
function nor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
begin
return not or_reduce(ARG);
end;
function xor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
variable result: STD_ULOGIC;
begin
result := '0';
for i in ARG'range loop
result := result xor ARG(i);
end loop;
return result;
end;
function xnor_reduce(ARG: STD_ULOGIC_VECTOR) return STD_ULOGIC is
begin
return not xor_reduce(ARG);
end;
--------------------------------------------------------------------
-- Some useful generic functions
--------------------------------------------------------------------
--//// Zero Extend ////
--
-- Function zxt
--
FUNCTION zxt( q : STD_ULOGIC_VECTOR; i : INTEGER ) RETURN STD_ULOGIC_VECTOR IS
VARIABLE qs : STD_ULOGIC_VECTOR (1 TO i);
VARIABLE qt : STD_ULOGIC_VECTOR (1 TO q'length);
-- Hidden function. Synthesis directives are present in its callers
BEGIN
qt := q;
IF i < q'length THEN
qs := qt( (q'length-i+1) TO qt'right);
ELSIF i > q'length THEN
qs := (OTHERS=>'0');
qs := qs(1 TO (i-q'length)) & qt;
ELSE
qs := qt;
END IF;
RETURN qs;
END;
FUNCTION maximum (arg1,arg2:INTEGER) RETURN INTEGER IS
BEGIN
IF(arg1 > arg2) THEN
RETURN(arg1) ;
ELSE
RETURN(arg2) ;
END IF;
END ;
FUNCTION minimum (arg1,arg2:INTEGER) RETURN INTEGER IS
BEGIN
IF(arg1 < arg2) THEN
RETURN(arg1) ;
ELSE
RETURN(arg2) ;
END IF;
END ;
--------------------------------------------------------------------
-- Comparision functions
--------------------------------------------------------------------
--
-- Equal functions.
--
TYPE stdlogic_boolean_table IS ARRAY(std_ulogic, std_ulogic) OF BOOLEAN;
CONSTANT eq_table : stdlogic_boolean_table := (
--
----------------------------------------------------------------------------
-- | U X 0 1 Z W L H D | |
--
----------------------------------------------------------------------------
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X |
( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 0 |
( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 1 |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W |
( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | L |
( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | H |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D |
);
FUNCTION eq ( l, r : STD_LOGIC ) RETURN BOOLEAN IS
-- Equal for two logic types
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "EQ" ;
BEGIN
result := eq_table( l, r );
RETURN result ;
END;
FUNCTION eq ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS
CONSTANT ml : INTEGER := maximum( l'length, r'length );
VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml );
VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml );
-- Arithmetic Equal for two Unsigned vectors
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "EQ" ;
BEGIN
lt := zxt( l, ml );
rt := zxt( r, ml );
FOR i IN lt'range LOOP
IF NOT eq( lt(i), rt(i) ) THEN
result := FALSE;
RETURN result ;
END IF;
END LOOP;
RETURN TRUE;
END;
TYPE std_ulogic_fuzzy_state IS ('U', 'X', 'T', 'F', 'N');
TYPE std_ulogic_fuzzy_state_table IS ARRAY ( std_ulogic, std_ulogic ) OF std_ulogic_fuzzy_state;
CONSTANT ge_fuzzy_table : std_ulogic_fuzzy_state_table := (
-- ----------------------------------------------------
-- | U X 0 1 Z W L H D | |
-- ----------------------------------------------------
( 'U', 'U', 'N', 'U', 'U', 'U', 'N', 'U', 'U' ), -- | U |
( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | X |
( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | 0 |
( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | 1 |
( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | Z |
( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ), -- | W |
( 'U', 'X', 'N', 'F', 'X', 'X', 'N', 'F', 'X' ), -- | L |
( 'N', 'N', 'T', 'N', 'N', 'N', 'T', 'N', 'N' ), -- | H |
( 'U', 'X', 'N', 'X', 'X', 'X', 'N', 'X', 'X' ) -- | D |
);
FUNCTION ge ( L,R : std_ulogic_vector ) RETURN boolean IS
CONSTANT ml : integer := maximum( L'LENGTH, R'LENGTH );
VARIABLE lt : std_ulogic_vector ( 1 to ml );
VARIABLE rt : std_ulogic_vector ( 1 to ml );
VARIABLE res : std_ulogic_fuzzy_state;
-- Greater-than-or-equal for two Unsigned vectors
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "GTE" ;
begin
lt := zxt( l, ml );
rt := zxt( r, ml );
FOR i IN lt'RANGE LOOP
res := ge_fuzzy_table( lt(i), rt(i) );
CASE res IS
WHEN 'U' => RETURN FALSE;
WHEN 'X' => RETURN FALSE;
WHEN 'T' => RETURN TRUE;
WHEN 'F' => RETURN FALSE;
WHEN OTHERS => null;
END CASE;
END LOOP;
result := TRUE ;
RETURN result;
end ;
--
-- Greater Than functions.
--
CONSTANT gtb_table : stdlogic_boolean_table := (
--
----------------------------------------------------------------------------
-- | U X 0 1 Z W L H D | |
--
----------------------------------------------------------------------------
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | 0 |
( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | 1 |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | L |
( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE ), -- | H |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D |
);
FUNCTION gt ( l, r : std_logic ) RETURN BOOLEAN IS
-- Greater-than for two logic types
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "GT" ;
BEGIN
result := gtb_table( l, r );
RETURN result ;
END ;
FUNCTION gt ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS
CONSTANT ml : INTEGER := maximum( l'length, r'length );
VARIABLE lt : STD_ULOGIC_VECTOR ( 1 TO ml );
VARIABLE rt : STD_ULOGIC_VECTOR ( 1 TO ml );
-- Greater-than for two logic unsigned vectors
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "GT" ;
BEGIN
lt := zxt( l, ml );
rt := zxt( r, ml );
FOR i IN lt'range LOOP
IF NOT eq( lt(i), rt(i) ) THEN
result := gt( lt(i), rt(i) );
RETURN result ;
END IF;
END LOOP;
RETURN FALSE;
END;
--
-- Less Than functions.
--
CONSTANT ltb_table : stdlogic_boolean_table := (
--
----------------------------------------------------------------------------
-- | U X 0 1 Z W L H D | |
--
----------------------------------------------------------------------------
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | U |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | X |
( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | 0 |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | 1 |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | Z |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | W |
( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE ), -- | L |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ), -- | H |
( FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE ) -- | D |
);
FUNCTION lt ( l, r : STD_LOGIC ) RETURN BOOLEAN IS
-- Less-than for two logic types
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "LT" ;
BEGIN
result := ltb_table( l, r );
RETURN result ;
END;
FUNCTION lt ( l,r : STD_ULOGIC_VECTOR ) RETURN BOOLEAN IS
CONSTANT ml : INTEGER := maximum( l'length, r'length );
VARIABLE ltt : STD_ULOGIC_VECTOR ( 1 TO ml );
VARIABLE rtt : STD_ULOGIC_VECTOR ( 1 TO ml );
-- Less-than for two Unsigned vectors
VARIABLE result : BOOLEAN ;
ATTRIBUTE synthesis_return OF result:VARIABLE IS "LT" ;
BEGIN
ltt := zxt( l, ml );
rtt := zxt( r, ml );
FOR i IN ltt'range LOOP
IF NOT eq( ltt(i), rtt(i) ) THEN
result := lt( ltt(i), rtt(i) );
RETURN result ;
END IF;
END LOOP;
RETURN FALSE;
END;
--------------------------------------------------------------------
-- "keep" Retain Last value when floated
--------------------------------------------------------------------
procedure keep(signal X: inout STD_LOGIC) is
begin
if(X = 'Z') then
if(X'last_value = '0') then
X <= 'L';
elsif(X'last_value = '1') then
X <= 'H';
else
X <= 'Z';
end if;
else
X <= 'Z';
end if;
end keep;
---------------------------------------------------------------------
-- log base 2 function
---------------------------------------------------------------------
function log2 ( A: in integer ) return integer is
variable B : integer;
begin
B := 1;
for i in 0 to 31 loop
if not ( A > B ) then
return ( i );
exit;
end if;
B := B * 2;
end loop;
end log2;
end UTIL;
-- Created by : G. Penacoba
-- Creation Date: May 2011
-- Description: generates start and stop pulses for test-bench
-- Modified by:
-- Modification Date:
-- Modification consisted on:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_textio.all;
use std.textio.all;
entity start_stop_gen is
port(
tstart_o : out std_logic;
tstop1_o : out std_logic;
tstop2_o : out std_logic;
tstop3_o : out std_logic;
tstop4_o : out std_logic;
tstop5_o : out std_logic
);
end start_stop_gen;
architecture behavioral of start_stop_gen is
signal tstart : std_logic:='0';
signal tstop1 : std_logic:='0';
signal tstop2 : std_logic:='0';
signal tstop3 : std_logic:='0';
signal tstop4 : std_logic:='0';
signal tstop5 : std_logic:='0';
signal pulse_channel : integer;
signal pulse_length : time;
begin
-- process reading the schedule of frame exchange from a text file
------------------------------------------------------------------
sequence: process
file sequence_file : text open read_mode is "data_vectors/pulses.txt";
variable sequence_line : line;
variable interval_time : time;
variable coma : string(1 to 1);
variable pulse_ch : integer;
variable pulse_lgth : time;
begin
readline (sequence_file, sequence_line);
read (sequence_line, interval_time);
read (sequence_line, coma);
read (sequence_line, pulse_ch);
read (sequence_line, coma);
read (sequence_line, pulse_lgth);
wait for interval_time;
pulse_channel <= pulse_ch;
pulse_length <= pulse_lgth;
if endfile(sequence_file) then
file_close(sequence_file);
wait;
end if;
end process;
start_extender: process
begin
wait until pulse_channel = 0;
tstart <= '1';
wait for pulse_length;
tstart <= '0';
end process;
stop1_extender: process
begin
wait until pulse_channel = 1;
tstop1 <= '1';
wait for pulse_length;
tstop1 <= '0';
end process;
stop2_extender: process
begin
wait until pulse_channel = 2;
tstop2 <= '1';
wait for pulse_length;
tstop2 <= '0';
end process;
stop3_extender: process
begin
wait until pulse_channel = 3;
tstop3 <= '1';
wait for pulse_length;
tstop3 <= '0';
end process;
stop4_extender: process
begin
wait until pulse_channel = 4;
tstop4 <= '1';
wait for pulse_length;
tstop4 <= '0';
end process;
stop5_extender: process
begin
wait until pulse_channel = 5;
tstop5 <= '1';
wait for pulse_length;
tstop5 <= '0';
end process;
tstart_o <= tstart;
tstop1_o <= tstop1;
tstop2_o <= tstop2;
tstop3_o <= tstop3;
tstop4_o <= tstop4;
tstop5_o <= tstop5;
end behavioral;
----------------------------------------------------------------------------------------------------
-- CERN-BE-CO-HT
----------------------------------------------------------------------------------------------------
--
-- unit name : TDC test-bench (tb_tdc)
-- author : G. Penacoba
-- date : May 2011
-- version : Revision 1
-- description : top module for test-bench
-- dependencies:
-- references :
-- modified by :
--
----------------------------------------------------------------------------------------------------
-- last changes:
----------------------------------------------------------------------------------------------------
-- to do:
----------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_tdc is
end tb_tdc;
architecture behavioral of tb_tdc is
component top_tdc
generic(
g_span : integer :=32;
g_width : integer :=32;
values_for_simulation : boolean :=FALSE
);
port(
-- interface with GNUM circuit
rst_n_a_i : in std_logic;
-- P2L Direction
p2l_clk_p_i : in std_logic; -- Receiver Source Synchronous Clock+
p2l_clk_n_i : in std_logic; -- Receiver Source Synchronous Clock-
p2l_data_i : in std_logic_vector(15 downto 0); -- Parallel receive data
p2l_dframe_i: in std_logic; -- Receive Frame
p2l_valid_i : in std_logic; -- Receive Data Valid
p2l_rdy_o : out std_logic; -- Rx Buffer Full Flag
p_wr_req_i : in std_logic_vector(1 downto 0); -- PCIe Write Request
p_wr_rdy_o : out std_logic_vector(1 downto 0); -- PCIe Write Ready
rx_error_o : out std_logic; -- Receive Error
vc_rdy_i : in std_logic_vector(1 downto 0); -- Virtual channel ready
-- L2P Direction
l2p_clk_p_o : out std_logic; -- Transmitter Source Synchronous Clock+
l2p_clk_n_o : out std_logic; -- Transmitter Source Synchronous Clock-
l2p_data_o : out std_logic_vector(15 downto 0); -- Parallel transmit data
l2p_dframe_o: out std_logic; -- Transmit Data Frame
l2p_valid_o : out std_logic; -- Transmit Data Valid
l2p_edb_o : out std_logic; -- Packet termination and discard
l2p_rdy_i : in std_logic; -- Tx Buffer Full Flag
l_wr_rdy_i : in std_logic_vector(1 downto 0); -- Local-to-PCIe Write
p_rd_d_rdy_i: in std_logic_vector(1 downto 0); -- PCIe-to-Local Read Response Data Ready
tx_error_i : in std_logic; -- Transmit Error
irq_p_o : out std_logic; -- Interrupt request pulse to GN4124 GPIO
spare_o : out std_logic;
-- interface signals with PLL circuit
acam_refclk_i : in std_logic;
pll_ld_i : in std_logic;
pll_refmon_i : in std_logic;
pll_sdo_i : in std_logic;
pll_status_i : in std_logic;
pll_cs_o : out std_logic;
pll_dac_sync_o : out std_logic;
pll_sdi_o : out std_logic;
pll_sclk_o : out std_logic;
tdc_clk_p_i : in std_logic;
tdc_clk_n_i : in std_logic;
-- interface signals with acam (timing)
err_flag_i : in std_logic;
int_flag_i : in std_logic;
start_dis_o : out std_logic;
start_from_fpga_o : out std_logic;
stop_dis_o : out std_logic;
-- interface signals with acam (data)
data_bus_io : inout std_logic_vector(27 downto 0);
ef1_i : in std_logic;
ef2_i : in std_logic;
lf1_i : in std_logic;
lf2_i : in std_logic;
address_o : out std_logic_vector(3 downto 0);
cs_n_o : out std_logic;
oe_n_o : out std_logic;
rd_n_o : out std_logic;
wr_n_o : out std_logic;
-- other signals on the tdc card
tdc_in_fpga_5_i : in std_logic;
mute_inputs_o : out std_logic;
tdc_led_status_o : out std_logic;
tdc_led_trig1_o : out std_logic;
tdc_led_trig2_o : out std_logic;
tdc_led_trig3_o : out std_logic;
tdc_led_trig4_o : out std_logic;
tdc_led_trig5_o : out std_logic;
-- other signals on the spec card
spec_aux0_i : in std_logic;
spec_aux1_i : in std_logic;
spec_aux2_o : out std_logic;
spec_aux3_o : out std_logic;
spec_aux4_o : out std_logic;
spec_aux5_o : out std_logic;
spec_led_green_o : out std_logic;
spec_led_red_o : out std_logic;
spec_clk_i : in std_logic
);
end component;
component acam_model
generic(
start_retrig_period : time:= 3200 ns;
refclk_period : time:= 32 ns
);
port(
tstart_i : in std_logic;
tstop1_i : in std_logic;
tstop2_i : in std_logic;
tstop3_i : in std_logic;
tstop4_i : in std_logic;
tstop5_i : in std_logic;
startdis_i : in std_logic;
stopdis_i : in std_logic;
int_flag_o : out std_logic;
err_flag_o : out std_logic;
address_i : in std_logic_vector(3 downto 0);
cs_n_i : in std_logic;
oe_n_i : in std_logic;
rd_n_i : in std_logic;
wr_n_i : in std_logic;
data_bus_io : inout std_logic_vector(27 downto 0);
ef1_o : out std_logic;
ef2_o : out std_logic;
lf1_o : out std_logic;
lf2_o : out std_logic
);
end component;
component start_stop_gen
port(
tstart_o : out std_logic;
tstop1_o : out std_logic;
tstop2_o : out std_logic;
tstop3_o : out std_logic;
tstop4_o : out std_logic;
tstop5_o : out std_logic
);
end component;
-----------------------------------------------------------------------------
-- GN4124 Local Bus Model
-----------------------------------------------------------------------------
component GN412X_BFM
generic
(
STRING_MAX : integer := 256; -- Command string maximum length
T_LCLK : time := 10 ns; -- Local Bus Clock Period
T_P2L_CLK_DLY : time := 2 ns; -- Delay from LCLK to P2L_CLK
INSTANCE_LABEL : string := "GN412X_BFM"; -- Label string to be used as a prefix for messages from the model
MODE_PRIMARY : boolean := true -- TRUE for BFM acting as GN412x, FALSE for BFM acting as the DUT
);
port
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD : in string(1 to STRING_MAX);
CMD_REQ : in bit;
CMD_ACK : out bit;
CMD_CLOCK_EN : in boolean;
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn : in std_logic;
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n : out std_logic;
RSTOUT33n : out std_logic;
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
------------------------------------------------------------- __ Direction for primary mode
-- / \
LCLK, LCLKn : inout std_logic; -- Out
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp, L2P_CLKn : inout std_logic; -- In
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA : inout std_logic_vector(15 downto 0); -- In -- Parallel Transmit Data.
L2P_DFRAME : inout std_logic; -- In -- Transmit Data Frame.
L2P_VALID : inout std_logic; -- In -- Transmit Data Valid.
L2P_EDB : inout std_logic; -- In -- End-of-Packet Bad Flag.
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY : inout std_logic_vector(1 downto 0); -- Out -- Local-to-PCIe Write.
P_RD_D_RDY : inout std_logic_vector(1 downto 0); -- Out -- PCIe-to-Local Read Response Data Ready.
L2P_RDY : inout std_logic; -- Out -- Tx Buffer Full Flag.
TX_ERROR : inout std_logic; -- Out -- Transmit Error.
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp, P2L_CLKn : inout std_logic; -- Out -- P2L Source Synchronous Clock.
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA : inout std_logic_vector(15 downto 0); -- Out -- Parallel Receive Data.
P2L_DFRAME : inout std_logic; -- Out -- Receive Frame.
P2L_VALID : inout std_logic; -- Out -- Receive Data Valid.
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY : inout std_logic; -- In -- Rx Buffer Full Flag.
P_WR_REQ : inout std_logic_vector(1 downto 0); -- Out -- PCIe Write Request.
P_WR_RDY : inout std_logic_vector(1 downto 0); -- In -- PCIe Write Ready.
RX_ERROR : inout std_logic; -- In -- Receive Error.
VC_RDY : inout std_logic_vector(1 downto 0); -- Out -- Virtual Channel Ready Status.
-------------------------------------------------------------
-- GPIO signals
--
GPIO : inout std_logic_vector(15 downto 0)
);
end component; --GN412X_BFM;
-----------------------------------------------------------------------------
-- CMD_ROUTER component
-----------------------------------------------------------------------------
component cmd_router
generic(N_BFM : integer := 8;
N_FILES : integer := 3;
FIFO_DEPTH : integer := 8;
STRING_MAX : integer := 256
);
port(CMD : out string(1 to STRING_MAX);
CMD_REQ : out bit_vector(N_BFM-1 downto 0);
CMD_ACK : in bit_vector(N_BFM-1 downto 0);
CMD_ERR : in bit_vector(N_BFM-1 downto 0);
CMD_CLOCK_EN : out boolean
);
end component; --cmd_router;
constant pll_clk_period : time:= 8 ns;
constant g_width : integer:= 32;
constant g_span : integer:= 32;
constant spec_clk_period : time:= 50 ns;
constant start_retrig_period : time:= 512 ns;
-- Number of Models receiving commands
constant N_BFM : integer := 1; -- 0 : GN412X_BFM in Model Mode
-- -- 1 : GN412X_BFM in DUT mode
-- Number of files to feed BFMs
constant N_FILES : integer := 1;
--
-- Depth of the command FIFO for each model
constant FIFO_DEPTH : integer := 16;
--
-- Maximum width of a command string
constant STRING_MAX : integer := 256;
signal acam_refclk_i : std_logic:='0';
signal tdc_clk_p_i : std_logic:='0';
signal tdc_clk_n_i : std_logic:='1';
signal spec_clk_i : std_logic:='0';
signal pll_ld_i : std_logic;
signal pll_refmon_i : std_logic;
signal pll_sdo_i : std_logic;
signal pll_status_i : std_logic;
signal pll_cs_o : std_logic;
signal pll_dac_sync_o : std_logic;
signal pll_sdi_o : std_logic;
signal pll_sclk_o : std_logic;
signal mute_inputs : std_logic;
signal address_o : std_logic_vector(3 downto 0);
signal cs_n_o : std_logic;
signal data_bus_io : std_logic_vector(27 downto 0);
signal ef1_i : std_logic;
signal ef2_i : std_logic;
signal err_flag_i : std_logic;
signal int_flag_i : std_logic;
signal lf1_i : std_logic;
signal lf2_i : std_logic;
signal oe_n_o : std_logic;
signal rd_n_o : std_logic;
signal start_dis_o : std_logic;
signal start_from_fpga_o : std_logic;
signal stop_dis_o : std_logic;
signal wr_n_o : std_logic;
--signal tstart : std_logic;
signal tstop1 : std_logic;
signal tstop2 : std_logic;
signal tstop3 : std_logic;
signal tstop4 : std_logic;
signal tstop5 : std_logic;
signal dummy_tstop5 : std_logic;
signal tdc_in_fpga_5 : std_logic;
signal tdc_led_status : std_logic;
signal tdc_led_trig1 : std_logic;
signal tdc_led_trig2 : std_logic;
signal tdc_led_trig3 : std_logic;
signal tdc_led_trig4 : std_logic;
signal tdc_led_trig5 : std_logic;
signal spec_aux0_i : std_logic;
signal spec_aux1_i : std_logic;
signal spec_aux2_o : std_logic;
signal spec_aux3_o : std_logic;
signal spec_aux4_o : std_logic;
signal spec_aux5_o : std_logic;
signal spec_led_green : std_logic;
signal spec_led_red : std_logic;
-- GN4124 interface
signal rst_n : std_logic;
signal irq_p : std_logic;
signal spare : std_logic;
signal RSTINn : std_logic;
signal RSTOUT18n : std_logic;
signal RSTOUT33n : std_logic;
signal LCLK, LCLKn : std_logic;
signal P2L_CLKp, P2L_CLKn : std_logic;
signal P2L_DATA : std_logic_vector(15 downto 0);
signal P2L_DATA_32 : std_logic_vector(31 downto 0); -- For monitoring use
signal P2L_DFRAME : std_logic;
signal P2L_VALID : std_logic;
signal P2L_RDY : std_logic;
signal P_WR_REQ : std_logic_vector(1 downto 0);
signal P_WR_RDY : std_logic_vector(1 downto 0);
signal RX_ERROR : std_logic;
signal VC_RDY : std_logic_vector(1 downto 0);
signal L2P_CLKp, L2P_CLKn : std_logic;
signal L2P_DATA : std_logic_vector(15 downto 0);
signal L2P_DATA_32 : std_logic_vector(31 downto 0); -- For monitoring use
signal L2P_DFRAME : std_logic;
signal L2P_VALID : std_logic;
signal L2P_EDB : std_logic;
signal L2P_RDY : std_logic;
signal L_WR_RDY : std_logic_vector(1 downto 0);
signal P_RD_D_RDY : std_logic_vector(1 downto 0);
signal TX_ERROR : std_logic;
signal GPIO : std_logic_vector(15 downto 0);
-----------------------------------------------------------------------------
-- Command Router Signals
-----------------------------------------------------------------------------
signal CMD : string(1 to STRING_MAX);
signal CMD_REQ : bit_vector(N_BFM-1 downto 0);
signal CMD_ACK : bit_vector(N_BFM-1 downto 0);
signal CMD_ERR : bit_vector(N_BFM-1 downto 0);
signal CMD_CLOCK_EN : boolean;
begin
dut: top_tdc
generic map(
g_span => 32,
g_width => 32,
values_for_simulation => TRUE
)
port map(
-- interface with GNUM circuit
rst_n_a_i => rst_n,
p2l_clk_p_i => p2l_clkp,
p2l_clk_n_i => p2l_clkn,
p2l_data_i => p2l_data,
p2l_dframe_i => p2l_dframe,
p2l_valid_i => p2l_valid,
p2l_rdy_o => p2l_rdy,
p_wr_req_i => p_wr_req,
p_wr_rdy_o => p_wr_rdy,
rx_error_o => rx_error,
vc_rdy_i => vc_rdy,
l2p_clk_p_o => l2p_clkp,
l2p_clk_n_o => l2p_clkn,
l2p_data_o => l2p_data,
l2p_dframe_o => l2p_dframe,
l2p_valid_o => l2p_valid,
l2p_edb_o => l2p_edb,
l2p_rdy_i => l2p_rdy,
l_wr_rdy_i => l_wr_rdy,
p_rd_d_rdy_i => p_rd_d_rdy,
tx_error_i => tx_error,
irq_p_o => irq_p,
spare_o => spare,
-- interface with PLL circuit
acam_refclk_i => acam_refclk_i,
pll_ld_i => pll_ld_i,
pll_refmon_i => pll_refmon_i,
pll_sdo_i => pll_sdo_i,
pll_status_i => pll_status_i,
pll_cs_o => pll_cs_o,
pll_dac_sync_o => pll_dac_sync_o,
pll_sdi_o => pll_sdi_o,
pll_sclk_o => pll_sclk_o,
tdc_clk_p_i => tdc_clk_p_i,
tdc_clk_n_i => tdc_clk_n_i,
-- interface signals with acam (timing)
int_flag_i => int_flag_i,
err_flag_i => err_flag_i,
start_dis_o => start_dis_o,
start_from_fpga_o => start_from_fpga_o,
stop_dis_o => stop_dis_o,
-- interface signals with acam (data)
data_bus_io => data_bus_io,
ef1_i => ef1_i,
ef2_i => ef2_i,
lf1_i => lf1_i,
lf2_i => lf2_i,
address_o => address_o,
cs_n_o => cs_n_o,
oe_n_o => oe_n_o,
rd_n_o => rd_n_o,
wr_n_o => wr_n_o,
-- other signals on the tdc card
tdc_in_fpga_5_i => tdc_in_fpga_5,
mute_inputs_o => mute_inputs,
tdc_led_status_o => tdc_led_status,
tdc_led_trig1_o => tdc_led_trig1,
tdc_led_trig2_o => tdc_led_trig2,
tdc_led_trig3_o => tdc_led_trig3,
tdc_led_trig4_o => tdc_led_trig4,
tdc_led_trig5_o => tdc_led_trig5,
-- other signals on the spec card
spec_aux0_i => spec_aux0_i,
spec_aux1_i => spec_aux1_i,
spec_aux2_o => spec_aux2_o,
spec_aux3_o => spec_aux3_o,
spec_aux4_o => spec_aux4_o,
spec_aux5_o => spec_aux5_o,
spec_led_green_o => spec_led_green,
spec_led_red_o => spec_led_red,
spec_clk_i => spec_clk_i
);
acam: acam_model
generic map(
start_retrig_period => start_retrig_period,
refclk_period => pll_clk_period/4
)
port map(
tstart_i => start_from_fpga_o,
tstop1_i => tstop1,
tstop2_i => tstop2,
tstop3_i => tstop3,
tstop4_i => tstop4,
tstop5_i => tstop5,
-- tstop5_i => dummy_tstop5,
startdis_i => start_dis_o,
stopdis_i => stop_dis_o,
int_flag_o => int_flag_i,
address_i => address_o,
cs_n_i => cs_n_o,
oe_n_i => oe_n_o,
rd_n_i => rd_n_o,
wr_n_i => wr_n_o,
data_bus_io => data_bus_io,
ef1_o => ef1_i,
ef2_o => ef2_i,
err_flag_o => err_flag_i,
lf1_o => lf1_i,
lf2_o => lf2_i
);
pulses_generator: start_stop_gen
port map(
tstart_o => open,
tstop1_o => tstop1,
tstop2_o => tstop2,
tstop3_o => tstop3,
tstop4_o => tstop4,
tstop5_o => tstop5
);
CMD_ERR <= (others => '0');
UC : cmd_router
generic map
(N_BFM => N_BFM,
N_FILES => N_FILES,
FIFO_DEPTH => FIFO_DEPTH,
STRING_MAX => STRING_MAX
)
port map
(CMD => CMD,
CMD_REQ => CMD_REQ,
CMD_ACK => CMD_ACK,
CMD_ERR => CMD_ERR,
CMD_CLOCK_EN => CMD_CLOCK_EN
);
-----------------------------------------------------------------------------
-- GN412x BFM - PRIMARY
-----------------------------------------------------------------------------
U0 : gn412x_bfm
generic map
(
STRING_MAX => STRING_MAX,
-- T_LCLK => 5 ns,
-- T_LCLK => 10 ns,
T_LCLK => 6.25 ns,
T_P2L_CLK_DLY => 2 ns,
INSTANCE_LABEL => "U0(Primary GN412x): ",
MODE_PRIMARY => true
)
port map
(
--=========================================================--
-------------------------------------------------------------
-- CMD_ROUTER Interface
--
CMD => CMD,
CMD_REQ => CMD_REQ(0),
CMD_ACK => CMD_ACK(0),
CMD_CLOCK_EN => CMD_CLOCK_EN,
--=========================================================--
-------------------------------------------------------------
-- GN412x Signal I/O
-------------------------------------------------------------
-- This is the reset input to the BFM
--
RSTINn => RSTINn,
-------------------------------------------------------------
-- Reset outputs to DUT
--
RSTOUT18n => RSTOUT18n,
RSTOUT33n => RSTOUT33n,
-------------------------------------------------------------
----------------- Local Bus Clock ---------------------------
-------------------------------------------------------------
--
LCLK => LCLK,
LCLKn => LCLKn,
-------------------------------------------------------------
----------------- Local-to-PCI Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
L2P_CLKp => L2P_CLKp,
L2P_CLKn => L2P_CLKn,
-------------------------------------------------------------
-- L2P DDR Link
--
L2P_DATA => L2P_DATA,
L2P_DFRAME => L2P_DFRAME,
L2P_VALID => L2P_VALID,
L2P_EDB => L2P_EDB,
-------------------------------------------------------------
-- L2P SDR Controls
--
L_WR_RDY => L_WR_RDY,
P_RD_D_RDY => P_RD_D_RDY,
L2P_RDY => L2P_RDY,
TX_ERROR => TX_ERROR,
-------------------------------------------------------------
----------------- PCIe-to-Local Dataflow ---------------------
-------------------------------------------------------------
-- Transmitter Source Synchronous Clock.
--
P2L_CLKp => P2L_CLKp,
P2L_CLKn => P2L_CLKn,
-------------------------------------------------------------
-- P2L DDR Link
--
P2L_DATA => P2L_DATA,
P2L_DFRAME => P2L_DFRAME,
P2L_VALID => P2L_VALID,
-------------------------------------------------------------
-- P2L SDR Controls
--
P2L_RDY => P2L_RDY,
P_WR_REQ => P_WR_REQ,
P_WR_RDY => P_WR_RDY,
RX_ERROR => RX_ERROR,
VC_RDY => VC_RDY,
GPIO => gpio
); -- GN412X_BFM;
tdc_pll_clock: process
begin
if pll_cs_o ='1' and rst_n ='1' then
tdc_clk_p_i <= not (tdc_clk_p_i) after 1 ns;
tdc_clk_n_i <= not (tdc_clk_n_i) after 1 ns;
end if;
wait for pll_clk_period/2;
end process;
tdc_ref_clock: process
begin
if pll_cs_o ='1' and rst_n ='1' then
acam_refclk_i <= not (acam_refclk_i) after 3 ns;
end if;
wait for pll_clk_period*2;
end process;
spec_clock: process
begin
spec_clk_i <= not (spec_clk_i) after 1 ns;
wait for spec_clk_period/2;
end process;
rst_n <= RSTOUT18n;
GPIO(0) <= irq_p;
GPIO(1) <= spare;
tdc_in_fpga_5 <= tstop5;
spec_aux0_i <= '1';
spec_aux1_i <= '1';
end behavioral;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment