Commit 1ed997b7 authored by David Cussans's avatar David Cussans

Merge branch 'dcussans/8bit_fine_ts' into 'master'

Dcussans/8bit fine ts

See merge request !2
parents d5da54ef 27f96930
......@@ -61,6 +61,7 @@ use work.ipbus_reg_types.all;
ENTITY eventFormatter IS
GENERIC(
g_EVENT_DATA_WIDTH : positive := 64;
g_COARSE_TIMESTAMP_WIDTH : positive := 48; -- ! Number of bits in 40MHz timestamp
g_IPBUS_WIDTH : positive := 32;
g_COUNTER_TRIG_WIDTH : positive := 32;
g_COUNTER_WIDTH : positive := 12;
......@@ -92,6 +93,7 @@ ENTITY eventFormatter IS
ipbus_o : OUT ipb_rbus;
data_strobe_o : OUT std_logic; --! goes high when data ready to load into event buffer
event_data_o : OUT std_logic_vector (g_EVENT_DATA_WIDTH-1 DOWNTO 0);
coarse_timestamp_o : OUT std_logic_vector (g_COARSE_TIMESTAMP_WIDTH-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
reset_timestamp_i : IN std_logic; --! Taking high causes timestamp to be reset. Combined with internal timestmap reset and written to reset_timestamp_o
reset_timestamp_o : OUT std_logic --! Goes high for one clock cycle of clk_4x_logic when timestamp reset
);
......@@ -134,8 +136,7 @@ ARCHITECTURE rtl OF eventFormatter IS
signal s_data_o : std_logic_vector(g_EVENT_DATA_WIDTH-1 DOWNTO 0); -- Multiplexed data from FIFOs
constant c_COARSE_TIMESTAMP_WIDTH : positive := 48; -- ! Number of bits in 40MHz timestamp
signal s_coarse_timestamp : std_logic_vector(c_COARSE_TIMESTAMP_WIDTH-1 downto 0) := (others => '0'); -- 40MHz timestamp.
signal s_coarse_timestamp : std_logic_vector(g_COARSE_TIMESTAMP_WIDTH-1 downto 0) := (others => '0'); -- 40MHz timestamp.
signal s_coarse_timestamp_ipbus : ipb_reg_v(1 downto 0) := ( others => (others => '0')); --! 40MHz timestamp on IPB clock domain.
-- signal s_event_number : unsigned(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- increment after each post-veto trigger.
......@@ -327,8 +328,8 @@ BEGIN
s_word0_p1 <= s_evttype & s_var & s_coarse_timestamp;
s_word1 <= "000" & trigger_times_d1(0) & "000" & trigger_times_d1(1) &
"000" & trigger_times_d1(2) & "000" & trigger_times_d1(3) &
s_word1 <= trigger_times_d1(0) & trigger_times_d1(1) &
trigger_times_d1(2) & trigger_times_d1(3) &
trigger_cnt_i;
......@@ -375,7 +376,8 @@ BEGIN
enable_i => logic_strobe_i,
result_o => s_coarse_timestamp);
coarse_timestamp_o <= s_coarse_timestamp;
-- Generate data in format decided at DESY. Put out two strobes for the
-- two 64 bit words.
-- get trigger inputs to also generate a global time-stamp ??
......
......@@ -13,11 +13,13 @@ LIBRARY ieee;
USE ieee.std_logic_1164.all;
PACKAGE fmcTLU IS
constant c_NUM_TIME_BITS : natural := 5;
constant c_NUM_TIME_BITS : natural := 8;
constant c_NUM_TRIG_INPUTS : natural := 4;
constant c_EVENT_DATA_WIDTH : natural := 32;
constant c_DATA_WIDTH : natural := 32;
constant c_COARSE_TIMESTAMP_WIDTH : natural := 48;
constant c_TRIGIN_NUM_COARSE_TS_BITS : natural := 3;
subtype t_triggerTime is std_logic_vector(c_NUM_TIME_BITS-1 downto 0);
--type t_triggerTimeArray is array(natural range <>) of t_triggerTime;
type t_triggerTimeArray is array(natural range <>) of std_logic_vector(c_NUM_TIME_BITS-1 downto 0) ;
......
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 17.02.2017 11:26:56
-- Design Name:
-- Module Name: testbench_clocks - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity testbench_clocks is
-- Port ( );
end testbench_clocks;
architecture Behavioral of testbench_clocks is
begin
end Behavioral;
......@@ -163,19 +163,10 @@ BEGIN
end process examine_lut;
--! Coarse time stamp. Phase w.r.t. strobe
-- c_coarse_ts : entity work.CounterUp
-- PORT MAP (
-- clk => clk_4x_logic_i,
-- ce => '1',
-- sinit => strobe_4x_logic_i, --'0',
-- q(31 downto 2) => open,
-- q(1 downto 0) => s_coarse_bits
-- );
--
c_coarse_ts : entity work.CounterWithReset
GENERIC MAP (
g_COUNTER_WIDTH => 2 )
g_COUNTER_WIDTH => 2,
g_OUTPUT_REGISTERS => 3)
PORT MAP (
clock_i => clk_4x_logic_i,
enable_i => '1',
......
......@@ -37,6 +37,7 @@ use unisim.vcomponents.all;
--!
--! @details
--! \li IPBus address 0 = control and status
--! \li write -->
--! \li bit0 = reset serdes
--! \li bit1 = reset counter
--! \li bit2 = calibrate IDELAYs
......@@ -71,6 +72,7 @@ use unisim.vcomponents.all;
--! \li IPBus address 3 = edge rising(2) counter
--! \li IPBus address 4 = edge rising(3) counter
--!
--! \li Address 1 = invert input bits 5..0. Set 1 to select for negative going pulses.
--!
--! <b>Modified by: Alvaro Dosil , alvaro.dosil@usc.es </b>\n
--! Author:
......@@ -82,7 +84,8 @@ use unisim.vcomponents.all;
ENTITY triggerInputs_newTLU IS
GENERIC(
g_NUM_INPUTS : natural := 1;--1
g_NUM_INPUTS : natural := 1;--1
g_NUM_COARSE_TS_BITS : natural := 3; --! Number of coarse ( clk_1x_logic normally 40MHz ) timestamp bits to add to MSB of trigger times.
g_IPBUS_WIDTH : positive := 32
);
PORT(
......@@ -94,6 +97,7 @@ ENTITY triggerInputs_newTLU IS
threshold_discr_p_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
threshold_discr_n_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
reset_i : IN std_logic;
coarse_timestamp_i : in std_logic_vector (g_NUM_COARSE_TS_BITS-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
trigger_times_o : OUT t_triggerTimeArray (g_NUM_INPUTS-1 DOWNTO 0); --! trigger arrival time ( w.r.t. logic_strobe)
trigger_o : OUT std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! Goes high on leading edge of trigger, in sync with clk_4x_logic_i
--trigger_debug_o : OUT std_logic_vector ( ((2*g_NUM_INPUTS)-1) DOWNTO 0); --! Copy of input trigger level. High bits CFD, Low threshold
......@@ -127,13 +131,13 @@ ARCHITECTURE rtl OF triggerInputs_newTLU IS
signal s_edge_falling_times: t_triggerTimeArray (g_NUM_INPUTS-1 DOWNTO 0); --! edge arrival time ( w.r.t. logic_strobe)
signal s_edge_rising: std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! High when rising edge
signal s_edge_falling: std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! High when falling edge
constant c_N_CTRL : positive := 1;
constant c_N_CTRL : positive := 2;
constant c_N_STAT : positive := g_NUM_INPUTS+1 ;
signal s_status_to_ipbus , s_sync_status_to_ipbus: ipb_reg_v(c_N_STAT-1 downto 0);
signal s_control_from_ipbus , s_sync_control_from_ipbus: ipb_reg_v(c_N_CTRL-1 downto 0);
-- signal s_reset_reg , s_status_reg: std_logic_vector(g_IPBUS_WIDTH-1 downto 0) := (others => '0');
signal s_counter_reset, s_calibrate_idelay: std_logic := '0';
signal s_select_input_invert : std_logic_vector(g_NUM_INPUTS-1 downto 0) := ( others => '1'); -- set bit high to invert input
BEGIN
-----------------------------------------------------------------------------
-- IPBus interface
......@@ -143,6 +147,7 @@ BEGIN
-- by synchronizer.
ipbus_registers: entity work.ipbus_ctrlreg_v
generic map (
N_CTRL => c_N_CTRL,
N_STAT => c_N_STAT )
port map(
clk=> ipbus_clk_i,
......@@ -179,7 +184,8 @@ BEGIN
s_rst_iserdes <= reset_i or s_sync_control_from_ipbus(0)(0);
s_counter_reset <= s_sync_control_from_ipbus(0)(1);
s_calibrate_idelay <= s_sync_control_from_ipbus(0)(2);
s_select_input_invert <= s_sync_control_from_ipbus(1)(g_NUM_INPUTS-1 downto 0);
s_status_to_ipbus(0)(0) <= s_rst_iserdes;
s_status_to_ipbus(0)(1) <= s_counter_reset;
s_status_to_ipbus(0)(2) <= s_calibrate_idelay;
......@@ -199,7 +205,11 @@ BEGIN
--BEGIN FOR LOOP
-- Instantiate one for each trigger input of the TLU
trigger_input_loop: for triggerInput in 0 to (g_NUM_INPUTS-1) generate
signal s_edge_rising_time_short : std_logic_vector( (c_NUM_TIME_BITS-c_TRIGIN_NUM_COARSE_TS_BITS)-1 downto 0);
signal s_edge_falling_time_short : std_logic_vector( (c_NUM_TIME_BITS-c_TRIGIN_NUM_COARSE_TS_BITS)-1 downto 0);
begin
-- Differential buffer. Receives differential trigger input and produces a buffered differential signal.
IBUFDS_DIFF_OUT_inst : IBUFDS_DIFF_OUT
generic map (
......@@ -238,25 +248,13 @@ BEGIN
clk_4x_logic_i => clk_4x_logic,
strobe_4x_logic_i => strobe_4x_logic_i,
deserialized_data_i => s_deserialized_threshold_data_l(triggerInput),
first_rising_edge_time_o => s_edge_rising_times(triggerInput),
last_falling_edge_time_o => s_edge_falling_times(triggerInput),
first_rising_edge_time_o => s_edge_rising_time_short,
last_falling_edge_time_o => s_edge_falling_time_short,
rising_edge_o => s_edge_rising(triggerInput),
falling_edge_o => s_edge_falling(triggerInput),
multiple_edges_o => open
);
-- The leading edge may be a high-->low or a low-->high transition (
-- depending on polarity of input signal. ). For now assume that leading
-- edge is low-->high and connect trigger times and trigger output accordingly.
-- In the future have this selectable.
edge_rising_times_o(triggerInput) <= s_edge_rising_times(triggerInput);
edge_falling_times_o(triggerInput) <= s_edge_falling_times(triggerInput);
edge_rising_o(triggerInput) <= s_edge_rising(triggerInput);
edge_falling_o(triggerInput) <= s_edge_falling(triggerInput);
trigger_times_o(triggerInput) <= s_edge_rising_times(triggerInput);
trigger_o(triggerInput) <= s_edge_rising(triggerInput);
p_register_delayed_bits : process ( clk_4x_logic )
begin
if rising_edge(clk_4x_logic) then
......@@ -269,7 +267,50 @@ BEGIN
--s_status_to_ipbus(0)(24+triggerInput) <= s_CFD_previous_late_bit(triggerInput);
end if ;
end process;
s_edge_rising_times(triggerInput) <= coarse_timestamp_i & s_edge_rising_time_short;
s_edge_falling_times(triggerInput) <= coarse_timestamp_i & s_edge_falling_time_short;
-- purpose: registers output of arrivalTimeLUT and performs optional
-- edge inversion
proc_registerLUT_output : process (clk_4x_logic) is
begin -- process proc_registerLUT_output
if rising_edge(clk_4x_logic) then
-- The leading edge may be a high-->low or a low-->high transition (
-- depending on polarity of input signal. ). For now assume that leading
-- edge is low-->high and connect trigger times and trigger output accordingly.
-- In the future have this selectable.
edge_rising_o(triggerInput) <= s_edge_rising(triggerInput);
if (s_edge_rising(triggerInput) = '1') then
edge_rising_times_o(triggerInput) <= s_edge_rising_times(triggerInput);
end if;
edge_falling_o(triggerInput) <= s_edge_falling(triggerInput);
if (s_edge_falling(triggerInput) = '1') then
edge_falling_times_o(triggerInput) <= s_edge_falling_times(triggerInput);
end if;
-- If s_select_input_invert(triggerInput) = 0 then connect up
-- rising edge. Otherwise falling edge.
if s_select_input_invert(triggerInput) = '0' then
trigger_o(triggerInput) <= s_edge_rising(triggerInput);
if (s_edge_rising(triggerInput) = '1') then
trigger_times_o(triggerInput) <= s_edge_rising_times(triggerInput);
end if;
else
trigger_o(triggerInput) <= s_edge_falling(triggerInput);
if (s_edge_falling(triggerInput) = '1') then
trigger_times_o(triggerInput) <= s_edge_falling_times(triggerInput);
end if;
end if;
end if;
end process proc_registerLUT_output;
--! Instantiate counter for output triggers.
--! Input I is connected to address I+1
cmp_inputTriggerCounter : entity work.counterWithReset
......
Simulation of trigger inputs
ipbb proj create sim triggerInputs_sim fmc-mtlu-gw:AIDA_tlu/components/tlu/sim -t ../../cfg/triggerInputs_newTLU_tb.dep
cd proj/triggerInputs_sim
ipbb sim setup-simlib ipcores fli
ipbb sim make-project
./vsim
Point to input and output files on command line:
vsim -voptargs=+acc work.triggerinputs_newtlu_tb(bench) -G g_BFMINPUT="/users/phdgc/tlu-tmp-2020-2-24/work/build/proj/triggerInputs_sim/BFM_INPUT_01.txt" -G g_BFMOUTPUT="/users/phdgc/tlu-tmp-2020-2-24/work/build/proj/triggerInputs_sim/BFM_OUTPUT_01.txt"
... or just
vsim work.triggerinputs_newtlu_tb -G g_BFMINPUT=BFM_INPUT_01.txt -G g_BFMOUTPUT=BFM_OUTPUT_01.txt
./vsim -c work.triggerinputs_newtlu_tb -G g_BFMINPUT=BFM_INPUT_02.txt -G g_BFMOUTPUT=BFM_OUTPUT_02.txt -do "run -all"
Reads from input file
cmd arg1 arg2 ....
cmd =
0 IPBUS
1 RESET
2 PAUSE
3 PULSE
pulse args...
3 delay0 width0 delay1 width1 delay2 width2 delay3 width3 delay4 width4 delay5 width5
IPBus args
0 w/r/rc addr data
w/r/rc = 0 : write , 1: read , 2: read with check
Pause args ...
2 nclock_cycles
@device_family = "artix7"
@device_name = "xc7a35t"
@device_package = "csg324"
@device_speed = "-2"
@boardname = "enclustra_ax3_pm3"
src --vhdl2008 -c AIDA_tlu/components/tlu ../../sim/hdl/triggerInputs_newTLU_tb.vhd
src --vhdl2008 -c AIDA_tlu/components/tlu ../../sim/hdl/transactionGenerator_behavioural.vhd
src --vhdl2008 -c AIDA_tlu/components/tlu ../../sim/hdl/ipbusTransactor_behavioural.vhd
src -c AIDA_tlu/components/tlu ../../sim/hdl/variablePulseTransactor_rtl.vhd
src -c AIDA_tlu/components/tlu ../../sim/hdl/BFMTypes.vhd
src -c AIDA_tlu/components/tlu trigger/triggerInputs_newTLU_rtl.vhd
src -c ipbus-firmware:components/ipbus_slaves ipbus_ctrlreg_v.vhd
src -c ipbus-firmware:components/ipbus_slaves ipbus_syncreg_v.vhd
src -c ipbus-firmware:components/ipbus_slaves syncreg_w.vhd
src -c ipbus-firmware:components/ipbus_slaves syncreg_r.vhd
src -c ipbus-firmware:components/ipbus_core ipbus_fabric_sel.vhd
src -c AIDA_tlu/components/tlu synchronizeRegisters_rtl.vhd
src -c AIDA_tlu/components/tlu trigger/arrivalTimeLUT_rtl.vhd
src --vhdl2008 -c AIDA_tlu/components/tlu trigger/dualSERDES_1to4_rtl.vhd
src -c AIDA_tlu/components/tlu trigger/IODELAYCal_FSM_rtl.vhd
src -c AIDA_tlu/components/tlu counterWithReset_rtl.vhd
src -c AIDA_tlu/components/tlu logic_clocks_rtl.vhd
src -c ipbus-firmware:components/ipbus_slaves ipbus_reg_types.vhd
src -c ipbus-firmware:components/ipbus_core ipbus_package.vhd
# Include type definitions for TLU
src -c AIDA_tlu/components/tlu fmcTLU_pkg_body.vhd
src -c AIDA_tlu/components/tlu fmcTLU_pkg.vhd
-- Package File Template
--
-- Purpose: This package defines supplemental types, subtypes,
-- constants, and functions
-- Defines types used for "Bus Functional Model" of pulse generation and
-- IPBus cycle generation
library IEEE;
use IEEE.STD_LOGIC_1164.all;
USE ieee.numeric_std.ALL;
package BFMTypes is
constant c_BUSWIDTH : natural := 32;
-- List transaction types
constant NTRANSACTION_TYPES : integer := 4;
constant IPBUS : integer := 0;
constant RESET : integer := 1;
constant PAUSE : integer := 2;
constant PULSE : integer := 3;
constant COMMENT : integer := 777; -- make it large and easy to remember
constant WRITE_TO_SLAVE : integer := 0;
constant READ_FROM_SLAVE : integer := 1;
constant READ_FROM_SLAVE_WITH_CHECK : integer := 2;
-- map each transaction onto a port with a transactor attached
constant NTRANSACTORS : integer := 2;
constant IPBUSPORT : integer := 0;
constant PULSEPORT : integer := 1;
type t_transactorMap is array (NTRANSACTION_TYPES - 1 downto 0) of integer;
constant c_transactorMap : t_transactorMap := (IPBUS => IPBUSPORT,
RESET => 999,
PAUSE => 999,
PULSE => PULSEPORT
);
type t_transactorReturnValues is array (NTRANSACTORS - 1 downto 0) of integer;
constant TIMEUNIT : time := 100 ps; --! Sets units for pulse and sync
subtype t_wbTransactionReturn is std_logic_vector(c_BUSWIDTH - 1 downto 0);
type t_wbTransaction is record
r_read_write : integer;
r_addr : t_wbTransactionReturn;
r_data : t_wbTransactionReturn;
end record;
constant c_wbNullTransactionReturn : t_wbTransactionReturn := (others => '0');
-- Define the number of channels with pulses on....
constant c_NPULSE_CHANNELS : integer := 6;
type t_PULSEDEF is record
r_delay : integer;
r_width : integer;
end record;
type t_pulseTransaction is array (c_NPULSE_CHANNELS - 1 downto 0) of t_PULSEDEF;
subtype t_pulseTransactionReturn is integer;
-- VHDL 2008 has no dynamically sizable strings :-(
constant c_MAX_COMMAND_LINE_LENGTH : integer := (25 * c_NPULSE_CHANNELS) + 200;
end BFMTypes;
--! @file
--
---------------------------------------------------------------------------------------------------
--! @brief Simulation of a IPBus master ( subset of Wishbone master ) --
---------------------------------------------------------------------------------------------------
--
-- unit name: testbench (main_tb.vhd)
--
-- @author David Cussans
--
--! @details
--! based on code by Miguel Mendez (mmendez@sevensols.com),
--! http://svn.ohwr.org/qdr2-v6-core/trunk/hdl/sim/main_tb.vhd
--
-- @date 29-2-2012
--
-- version: 0.1
--
-- dependencies:
--
---------------------------------------------------------------------------------------------------
-- last changes: see svn log.
---------------------------------------------------------------------------------------------------
-- TODO: - .
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- 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 STD.TEXTIO.all;
--! Declaration of transaction types for Bus Functional Model
use work.BFMTypes.all;
use work.ipbus.all; --! Declarations of IPBus records
entity ipbusTransactor is
port (
-- interface to transaction generator
Trans : in t_wbTransaction; --! Transaction from transaction generator
returnedData : out t_wbTransactionReturn; --! Signal end-of-cycle by making a transaction on this port
-- interface to "physical" ports
clk_i : in std_logic; --! System clock, active high
ipb_to_slave : out ipb_wbus; --! Signals from master to slave
ipb_from_slave : in ipb_rbus --! Signals from slave to master
);
end ipbusTransactor;
architecture behavioural of ipbusTransactor is
begin -- behavioural
p_commandloop: process
variable v_addr : integer;
variable v_addr_ack : integer;
variable outline : line;
variable v_data_from_slave : t_wbTransactionReturn := ( others => '0'); --! Temporary store for data
--read from slave.
variable v_receivedAck : boolean := false; -- set true when strobe goes high...
begin -- process p_commandloop
-- set the bus idle
ipb_to_slave.ipb_strobe <= '0';
ipb_to_slave.ipb_write <= '0';
ipb_to_slave.ipb_addr <= ( others => '1'); --! Set to a dummy value....
wait on Trans'TRANSACTION;
report "wishboneMasterBFM: Got transaction" severity note;
ipb_to_slave.ipb_strobe <= '1';
if( Trans.r_read_write = WRITE_TO_SLAVE ) then
-- Write data
ipb_to_slave.ipb_write <= '1';
ipb_to_slave.ipb_wdata <= Trans.r_data;
else
-- Read data
ipb_to_slave.ipb_write <= '0';
end if;
-- Addr for writing and reading
ipb_to_slave.ipb_addr <= Trans.r_addr;
v_receivedAck := false;
-- Loop until the slave raises ack.
while v_receivedAck = false loop
wait until rising_edge(clk_i); -- s_wb_clk'event and s_wb_clk = '1';
--got ack?
if(ipb_from_slave.ipb_ack = '1') then
v_receivedAck := true;
--read data
if(Trans.r_read_write=READ_FROM_SLAVE) or (Trans.r_read_write=READ_FROM_SLAVE_WITH_CHECK) then
-- the read data is stored
v_data_from_slave := ipb_from_slave.ipb_rdata;
report "Read from slave. Data = " & to_hstring(v_data_from_slave) severity note;
else -- if a write then ....
v_data_from_slave := Trans.r_data; -- just return what we were given
end if;
end if;
end loop;
-- terminate the cycle
ipb_to_slave.ipb_strobe <= '0';
ipb_to_slave.ipb_write <= '0';
report "returning data = " & to_hstring(v_data_from_slave) severity note;
returnedData <= v_data_from_slave; -- This event is what signals the end
-- of transaction.
end process p_commandloop;
end behavioural;
--=============================================================================
--! @file wishboneTransactionGenerator_behavioural.vhd
--=============================================================================
--! Standard library
library IEEE;
--! Standard packages
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
--! Package containg type definition and constants
use work.BFMTypes.all;
use std.TEXTIO.all;
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
-------------------------------------------------------------------------------
-- unit name: wishboneTransactionGenerator
--
--! @brief Loops Generating transactions to send to BFM
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 2\1\2012
--
--! @version v0.1
--
--! @details
--! Must be compiled with VHDL-2008 ( uses HREAD and HWRITE ).
--! \li Pause = 2 [delay]
--! \li Pulse (delay,width in 100ps ticks) = 3 [delay before pulse] [width]
--! \li IPBus transaction = 0 [ipbus params]
--! \li IPBus write = 0 0 [addr] [data]
--! \li IPBus read = 0 1 [addr] [dummy]
--! <b>Dependencies:</b>\n
--! None
--!
--! <b>References:</b>\n
--! referenced by ipbusMarocADC_tb \n
--!
--! <b>Modified by:</b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--! 9/March/2012 DGC - changing address and data to be STD_LOGIC_VECTOR. \n
--! using HWRITE / HREAD for Hexidecimal IO
--! 1/March/2020 DGC - repurposed for AIDA-2020 TLU work. Changed syntax
-------------------------------------------------------------------------------
--! @todo <next thing to do> \n
--! <another thing to do> \n
--
--------------------------------------------------------------------------------
entity wishboneTransactionGenerator is
generic (
g_BUSWIDTH : integer := c_BUSWIDTH; --! Number of bits in each word
BFMINPUT : string := "$BFMINPUT"; --! File containing list of commands
BFMOUTPUT : string := "$BFMOUTPUT" --! Output file
);
port (
wb_transaction_o : out t_wbTransaction; -- ! signal that carries transaction to
-- IPBus interface
wb_returned_data_i : in t_wbTransactionReturn; -- ! Carrys data back from BFM
pulse_transaction_o : out t_pulseTransaction;
pulse_returned_data_i : in t_pulseTransactionReturn;
--! Signal to clock generator
endOfSim_o : out boolean --! Take high to stop simulation.
);
end wishboneTransactionGenerator;
architecture behavioural of wishboneTransactionGenerator is
signal s_command_time : time; -- Store the time the commands are issued.
begin -- behavioural
p_commandLoop : process
file COMMANDS : text;
file DATA : text;
variable status : file_open_status;
variable Lin : line;
variable Lout : line;
-- variable debugL : line;
variable v_comment : string(1 to c_MAX_COMMAND_LINE_LENGTH);
variable v_wb_returned_data : t_wbTransactionReturn;
variable v_currentWbTransaction : t_wbTransaction;
variable v_pulse_returned_data : t_pulseTransactionReturn;
variable v_currentPulseTransaction : t_pulseTransaction;
variable textLine : line;
variable v_transactor_id : integer := 999; --! Halt with error if
--transactor ID not set...
variable v_transactionType : integer := 999;
variable v_pauseValue : integer;
--variable v_wb_returned_data : t_wbTransactionReturn ;
begin
-- open input and output files
FILE_OPEN(status, COMMANDS, BFMINPUT, read_mode);
FILE_OPEN(status, DATA, BFMOUTPUT, write_mode);
endOfSim_o <= false;
while not ENDFILE(COMMANDS) loop --! Loop over commands from BFMINPUT
s_command_time <= NOW;
READLINE(COMMANDS, Lin);
READ(Lin, v_transactionType); --! Read the transaction type as the first item on line
if (v_transactionType = PULSE) then
for pulseChan in 0 to c_NPULSE_CHANNELS-1 loop
READ(Lin, v_currentPulseTransaction(pulseChan).r_delay);
READ(Lin, v_currentPulseTransaction(pulseChan).r_width);
end loop; -- pulseChan
pulse_transaction_o <= v_currentPulseTransaction;
wait on pulse_returned_data_i'transaction; -- read the data returned by BFM
v_pulse_returned_data := pulse_returned_data_i;
-- bodge up a return printout
WRITE(Lout, v_pulse_returned_data, left, 20);
elsif (v_transactionType = COMMENT) then
-- read in comment string..
assert Lin'length < v_comment'length; -- make sure S is big enough
v_comment := (others => ' '); -- make sure that the previous line is overwritten
if Lin'length > 0 then
read(Lin, v_comment(1 to Lin'length));
end if;
-- we have a comment
WRITE(Lout, v_comment, left, v_comment'length);
elsif (v_transactionType = IPBUS) then
-- we have an IPBus transaction
-- Read line of form
-- r/w addr data
READ(Lin, v_currentWbTransaction.r_read_write);
HREAD(Lin, v_currentWbTransaction.r_addr);
HREAD(Lin, v_currentWbTransaction.r_data); -- Need to provide dummy data for reads.
-- Issue transaction to Wishbone (IPBus) port
wb_transaction_o <= v_currentWbTransaction;
wait on wb_returned_data_i'transaction; -- read the data returned by BFM
v_wb_returned_data := wb_returned_data_i;
write(LOut,
"transaction type, addr, data, returned data, current time: " &
to_hstring(to_unsigned(v_currentWbTransaction.r_read_write, 32)) & string'(" ") &
to_hstring(unsigned(v_currentWbTransaction.r_addr)) & string'(" ") &
to_hstring(unsigned(v_currentWbTransaction.r_data)) & string'(" ") &
to_hstring(unsigned(v_wb_returned_data)) & string'(" ") &
time'image(s_command_time)
);
elsif (v_transactionType = PAUSE) then
-- Read number of time ticks ( 100ps ) to pause for
READ(Lin, v_pauseValue);
report "BFM: Pausing for clock cycles = " & to_string(v_pauseValue) & " starting at " & time'image(s_command_time) severity note;
wait for v_pauseValue * TIMEUNIT;
else
report "BFM: Bad command type. Exiting" severity error;
end if;
WRITELINE(DATA, Lout);
--! Flush the buffers every time we write a line....
FLUSH(DATA);
end loop; -- idx
report "Ending simulation" severity note;
endOfSim_o <= true;
wait;
end process p_commandLoop;
end behavioural;
This diff is collapsed.
--! @file
--!
--! @brief Issues a pulse of variable width and delay. Based on pulseTransactor
--! @author David Cussans
--! @date 23\4\2013
--
--! Note - have to compile with VHDL-2008
--
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
use STD.TEXTIO.all;
--! Declaration of transaction types for Bus Functional Model
use work.BFMTypes.all;
use std.TEXTIO.all;
entity variablePulseTransactor is
generic(
g_BUSWIDTH : integer := 32); -- width for triggernumber and timestamp
port(
clk_i : in std_logic;
trans_i : in t_pulseTransaction;
returnedData_o : out t_pulseTransactionReturn;
signal_o : out std_logic_vector(c_NPULSE_CHANNELS - 1 downto 0); --! Signal pulses low-high-low
triggerNumber_o : out std_logic_vector(g_BUSWIDTH - 1 downto 0);
timeStamp_o : out std_logic_vector(g_BUSWIDTH - 1 downto 0)
);
end variablePulseTransactor;
architecture rtl of variablePulseTransactor is
signal s_timeStamp : unsigned(g_BUSWIDTH - 1 downto 0) := (others => '0');
constant c_timeGranularity : time := 1 ps;
signal s_pulseNum : integer := 0;
begin -- rtl
p_pulseGen : process is
variable v_pulseDelay : time := 0 ps;
variable v_pulseWidth : time := 0 ps;
variable v_lastEdge : time := 0 ps;
begin
report "variablePulseBFM: waiting for transaction" severity note;
signal_o <= (others => '0');
wait on trans_i'transaction;
report "variablePulseBFM: Got transaction" severity note;
wait until rising_edge(clk_i);
for chan in 0 to signal_o'length - 1 loop
v_pulseDelay := trans_i(chan).r_delay * TIMEUNIT;
v_pulseWidth := trans_i(chan).r_width * TIMEUNIT;
if (v_pulseDelay + v_pulseWidth) > v_lastEdge then
v_lastEdge := (v_pulseDelay + v_pulseWidth);
end if;
if trans_i(chan).r_delay >= 0 then
report "Queing pulse . chan , delay , width " & integer'image(chan) & " " & time'image(v_pulseDelay) & " " & time'image(v_pulseWidth);
signal_o(chan) <= '1' after v_pulseDelay, '0' after (v_pulseDelay + v_pulseWidth);
else
report "NO Pulse queued chr chan " & integer'image(chan);
end if;
end loop;
report "Waiting until last edge finished. Delay = " & time'image(v_lastEdge) severity note;
wait for v_lastEdge;
-- Update trigger number
s_pulseNum <= s_pulseNum + 1;
triggerNumber_o <= std_logic_vector(to_unsigned(s_pulseNum, g_BUSWIDTH));
-- output current time-stamp
timeStamp_o <= std_logic_vector(s_timeStamp);
returnedData_o <= s_pulseNum;
end process p_pulseGen;
-- purpose: keeps a timestamp in terms of clock cycles
-- type : sequential
-- inputs : clk_i, s_timeStamp
-- outputs: s_timeStamp
p_timeStamp : process(clk_i)
begin -- process p_timeStamp
if rising_edge(clk_i) then
s_timeStamp <= s_timeStamp + 1;
end if;
end process p_timeStamp;
end rtl;
777 Generate test pulses
2 8000
3 10 1000 100 2000 500 4000 0 200 200 6000 400 8000
2 6000
#!/usr/bin/python
#
# script to generate input for triggerinputs_newtlu_tb
#
print "777 Generate test pulses in 200ps steps"
# waiting for clocks to settle
print "2 8000"
# setting up trigger inputs to look for falling edges
print "0 0 00006001 FFFFFFFF"
#
# generate pulses
for i in range(1000):
print "3 " + str( i * 2) + " 3000 -10 0 -10 0 -10 0 -10 0 -10 0"
# pause between pulses
print "2 3000"
# pause before ending simulation
print "2 8000"
......@@ -50,7 +50,8 @@
</node>
<!-- This needs checking. The counters work, not sure about the reset -->
<node id="triggerInputs" address="0x6000" description="Inputs configuration" fwinfo="endpoint;width=4">
<node id="SerdesRstW" address="0x0" permission="w" description="" />
<node id="SerdesRstW" address="0x0" permission="w" description="" />
<node id="InvertEdgeW" address="0x1" permission="w" description="Set bit high to invert sense of leading edge" />
<node id="SerdesRstR" address="0x8" permission="r" description="" />
<node id="ThrCount0R" address="0x9" permission="r" description="" />
<node id="ThrCount1R" address="0xa" permission="r" description="" />
......
......@@ -51,7 +51,7 @@ use work.ipbus.ALL;
entity top is
generic(
constant FW_VERSION : unsigned(31 downto 0):= X"1e000024"; -- Firmware revision. Remember to change this as needed.
constant FW_VERSION : unsigned(31 downto 0):= X"1e000025"; -- Firmware revision. Remember to change this as needed.
g_NUM_DUTS : positive := 4; -- <- was 3
g_NUM_TRIG_INPUTS :positive := 6;-- <- was 4
g_NUM_EDGE_INPUTS :positive := 6;-- <-- was 4
......@@ -171,6 +171,7 @@ architecture rtl of top is
SIGNAL triggers : std_logic_vector(g_NUM_TRIG_INPUTS-1 DOWNTO 0); --! Rising edge of trigger inputs
SIGNAL s_veto : std_logic; --! goes high when one or more DUT are busy
signal s_shutter_veto : std_logic; --! Goes high when triggers should be vetoed by shutter
signal s_coarse_timestamp : std_logic_vector(c_COARSE_TIMESTAMP_WIDTH-1 downto 0) := (others => '0'); -- 40MHz timestamp.
signal ctrl, stat: ipb_reg_v(0 downto 0);
--My signals
--SIGNAL busy_toggle_o : std_logic_vector(g_NUM_DUTS-1 downto 0);
......@@ -257,6 +258,7 @@ architecture rtl of top is
COMPONENT eventFormatter
GENERIC (
g_EVENT_DATA_WIDTH : positive := 64;
g_COARSE_TIMESTAMP_WIDTH : positive := 48; -- ! Number of bits in 40MHz timestamp
g_IPBUS_WIDTH : positive := 32;
g_COUNTER_TRIG_WIDTH : positive := 32;
g_COUNTER_WIDTH : positive := 12;
......@@ -288,6 +290,7 @@ architecture rtl of top is
ipbus_o : OUT ipb_rbus ;
data_strobe_o : OUT std_logic ; --! goes high when data ready TO load into event buffer
event_data_o : OUT std_logic_vector (g_EVENT_DATA_WIDTH-1 DOWNTO 0);
coarse_timestamp_o : out std_logic_vector (g_COARSE_TIMESTAMP_WIDTH-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
reset_timestamp_i : IN std_logic ; --! Taking high causes timestamp TO be reset. Combined with internal timestmap reset and written to reset_timestamp_o
reset_timestamp_o : OUT std_logic --! Goes high for one clock cycle of clk_4x_logic when timestamp reset
);
......@@ -320,7 +323,8 @@ architecture rtl of top is
----------------------------------------------
COMPONENT triggerInputs_newTLU
GENERIC (
g_NUM_INPUTS : natural := 1;
g_NUM_INPUTS : natural := 1;
g_NUM_COARSE_TS_BITS : natural := 3; --! Number of coarse ( clk_1x_logic normally 40MHz ) timestamp bits to add to MSB of trigger times.
g_IPBUS_WIDTH : positive := 32
);
PORT (
......@@ -332,6 +336,7 @@ architecture rtl of top is
threshold_discr_p_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
threshold_discr_n_i : IN std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! inputs from threshold comparators
reset_i : IN std_logic ;
coarse_timestamp_i : in std_logic_vector (g_NUM_COARSE_TS_BITS-1 DOWNTO 0); --! Global timestamp. Clocked on clk_4x_logic, but only increments with logic_strobe
trigger_times_o : OUT t_triggerTimeArray (g_NUM_INPUTS-1 DOWNTO 0); --! trigger arrival time ( w.r.t. logic_strobe)
trigger_o : OUT std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0); --! Goes high on leading edge of trigger, in sync with clk_4x_logic_i
--trigger_debug_o : OUT std_logic_vector ( ((2*g_NUM_INPUTS)-1) DOWNTO 0); --! Copy of input trigger level. High bits CFD, Low threshold
......@@ -566,6 +571,7 @@ begin
threshold_discr_p_i => threshold_discr_p_i,
threshold_discr_n_i => threshold_discr_n_i,
reset_i => logic_reset,
coarse_timestamp_i => s_coarse_timestamp(c_TRIGIN_NUM_COARSE_TS_BITS-1 downto 0),
trigger_times_o => trigger_times,
trigger_o => triggers,
--trigger_debug_o => OPEN,
......@@ -616,6 +622,7 @@ begin
ipbus_o => ipbrr(N_SLV_EVENT_FORMATTER),
data_strobe_o => data_strobe,
event_data_o => event_data,
coarse_timestamp_o => s_coarse_timestamp,
reset_timestamp_i => s_T0,
reset_timestamp_o => OPEN
);
......
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