From f6178e9dbd405dbf6a8fbb2b13bfe363e957a974 Mon Sep 17 00:00:00 2001 From: stef_b Date: Fri, 14 Apr 2023 17:36:50 +0200 Subject: [PATCH] Refactoring and compliant with 3.0.0 release psi_common --- README.md | 4 +- hdl/psi_ms_daq_axi.vhd | 839 +++++++++++----------- hdl/psi_ms_daq_axi_if.vhd | 381 +++++----- hdl/psi_ms_daq_daq_dma.vhd | 714 ++++++++++--------- hdl/psi_ms_daq_daq_sm.vhd | 1343 ++++++++++++++++++------------------ hdl/psi_ms_daq_input.vhd | 1072 ++++++++++++++-------------- hdl/psi_ms_daq_pkg.vhd | 278 ++++---- hdl/psi_ms_daq_reg_axi.vhd | 1062 ++++++++++++++-------------- 8 files changed, 2812 insertions(+), 2881 deletions(-) diff --git a/README.md b/README.md index 68d126f..5ebaf77 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ Alternatively the repository [psi\_fpga\_all](https://github.com/paulscherrerins * TCL * [PsiSim](https://github.com/paulscherrerinstitute/PsiSim) (2.1.0 or higher, for development only) * VHDL - * [psi\_common](https://github.com/paulscherrerinstitute/psi_common) (2.5.0 or higher) - * [psi\_tb](https://github.com/paulscherrerinstitute/psi_tb) (2.2.2 or higher, for development only) + * [psi\_common](https://github.com/paulscherrerinstitute/psi_common) (3.0.0 or higher) + * [psi\_tb](https://github.com/paulscherrerinstitute/psi_tb) (3.0.0 or higher, for development only) * [**psi\_multi\_stream\_daq**](https://github.com/paulscherrerinstitute/psi_multi_stream_daq) diff --git a/hdl/psi_ms_daq_axi.vhd b/hdl/psi_ms_daq_axi.vhd index 8445945..78ef90f 100644 --- a/hdl/psi_ms_daq_axi.vhd +++ b/hdl/psi_ms_daq_axi.vhd @@ -8,448 +8,439 @@ -- Libraries ------------------------------------------------------------------------------ library ieee; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; - -library work; - use work.psi_common_math_pkg.all; - use work.psi_common_array_pkg.all; - use work.psi_ms_daq_pkg.all; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.psi_common_math_pkg.all; +use work.psi_common_array_pkg.all; +use work.psi_ms_daq_pkg.all; - ------------------------------------------------------------------------------ -- Entity Declaration ------------------------------------------------------------------------------ entity psi_ms_daq_axi is - generic ( - -- Streams - Streams_g : positive range 1 to 32 := 2; - StreamWidth_g : t_ainteger := (16, 16); - StreamPrio_g : t_ainteger := (1, 1); - StreamBuffer_g : t_ainteger := (1024, 1024); - StreamTimeout_g : t_areal := (1.0e-3, 1.0e-3); - StreamClkFreq_g : t_areal := (100.0e6, 100.0e6); - StreamTsFifoDepth_g : t_ainteger := (16, 16); - StreamUseTs_g : t_abool := (true, true); - -- Recording - MaxWindows_g : positive range 1 to 32 := 16; - MinBurstSize_g : integer range 1 to 512 := 512; - MaxBurstSize_g : integer range 1 to 512 := 512; - -- Axi - AxiDataWidth_g : natural range 64 to 1024 := 64; - AxiMaxBurstBeats_g : integer range 1 to 256 := 256; - AxiMaxOpenTrasactions_g : natural range 1 to 8 := 8; - AxiFifoDepth_g : natural := 1024; - -- Axi Slave - AxiSlaveIdWidth_g : integer := 0 - ); - port ( - -- Data Stream Input - Str_Clk : in std_logic_vector(Streams_g-1 downto 0); - Str_Data : in t_aslv64(Streams_g-1 downto 0); - Str_Ts : in t_aslv64(Streams_g-1 downto 0); - Str_Vld : in std_logic_vector(Streams_g-1 downto 0); - Str_Rdy : out std_logic_vector(Streams_g-1 downto 0); - Str_Trig : in std_logic_vector(Streams_g-1 downto 0); - - -- Miscellaneous - Irq : out std_logic; - - -- AXI Slave Interface for Register Access - S_Axi_Aclk : in std_logic; - S_Axi_Aresetn : in std_logic; - S_Axi_ArId : in std_logic_vector(AxiSlaveIdWidth_g-1 downto 0); - S_Axi_ArAddr : in std_logic_vector(15 downto 0); - S_Axi_Arlen : in std_logic_vector(7 downto 0); - S_Axi_ArSize : in std_logic_vector(2 downto 0); - S_Axi_ArBurst : in std_logic_vector(1 downto 0); - S_Axi_ArLock : in std_logic; - S_Axi_ArCache : in std_logic_vector(3 downto 0); - S_Axi_ArProt : in std_logic_vector(2 downto 0); - S_Axi_ArValid : in std_logic; - S_Axi_ArReady : out std_logic; - S_Axi_RId : out std_logic_vector(AxiSlaveIdWidth_g-1 downto 0); - S_Axi_RData : out std_logic_vector(31 downto 0); - S_Axi_RResp : out std_logic_vector(1 downto 0); - S_Axi_RLast : out std_logic; - S_Axi_RValid : out std_logic; - S_Axi_RReady : in std_logic; - S_Axi_AwId : in std_logic_vector(AxiSlaveIdWidth_g-1 downto 0); - S_Axi_AwAddr : in std_logic_vector(15 downto 0); - S_Axi_AwLen : in std_logic_vector(7 downto 0); - S_Axi_AwSize : in std_logic_vector(2 downto 0); - S_Axi_AwBurst : in std_logic_vector(1 downto 0); - S_Axi_AwLock : in std_logic; - S_Axi_AwCache : in std_logic_vector(3 downto 0); - S_Axi_AwProt : in std_logic_vector(2 downto 0); - S_Axi_AwValid : in std_logic; - S_Axi_AwReady : out std_logic; - S_Axi_WData : in std_logic_vector(31 downto 0); - S_Axi_WStrb : in std_logic_vector(3 downto 0); - S_Axi_WLast : in std_logic; - S_Axi_WValid : in std_logic; - S_Axi_WReady : out std_logic; - S_Axi_BId : out std_logic_vector(AxiSlaveIdWidth_g-1 downto 0); - S_Axi_BResp : out std_logic_vector(1 downto 0); - S_Axi_BValid : out std_logic; - S_Axi_BReady : in std_logic; - - -- AXI Master Interface for Memory Access - M_Axi_Aclk : in std_logic; - M_Axi_Aresetn : in std_logic; - M_Axi_AwAddr : out std_logic_vector(31 downto 0); - M_Axi_AwLen : out std_logic_vector(7 downto 0); - M_Axi_AwSize : out std_logic_vector(2 downto 0); - M_Axi_AwBurst : out std_logic_vector(1 downto 0); - M_Axi_AwLock : out std_logic; - M_Axi_AwCache : out std_logic_vector(3 downto 0); - M_Axi_AwProt : out std_logic_vector(2 downto 0); - M_Axi_AwValid : out std_logic; - M_Axi_AwReady : in std_logic := '0'; - M_Axi_WData : out std_logic_vector(AxiDataWidth_g-1 downto 0); - M_Axi_WStrb : out std_logic_vector(AxiDataWidth_g/8-1 downto 0); - M_Axi_WLast : out std_logic; - M_Axi_WValid : out std_logic; - M_Axi_WReady : in std_logic := '0'; - M_Axi_BResp : in std_logic_vector(1 downto 0) := (others => '0'); - M_Axi_BValid : in std_logic := '0'; - M_Axi_BReady : out std_logic; - M_Axi_ArAddr : out std_logic_vector(31 downto 0); - M_Axi_ArLen : out std_logic_vector(7 downto 0); - M_Axi_ArSize : out std_logic_vector(2 downto 0); - M_Axi_ArBurst : out std_logic_vector(1 downto 0); - M_Axi_ArLock : out std_logic; - M_Axi_ArCache : out std_logic_vector(3 downto 0); - M_Axi_ArProt : out std_logic_vector(2 downto 0); - M_Axi_ArValid : out std_logic; - M_Axi_ArReady : in std_logic := '0'; - M_Axi_RData : in std_logic_vector(AxiDataWidth_g-1 downto 0) := (others => '0'); - M_Axi_RResp : in std_logic_vector(1 downto 0) := (others => '0'); - M_Axi_RLast : in std_logic := '0'; - M_Axi_RValid : in std_logic := '0'; - M_Axi_RReady : out std_logic - ); + generic( + -- Streams + Streams_g : positive range 1 to 32 := 2; + StreamWidth_g : t_ainteger := (16, 16); + StreamPrio_g : t_ainteger := (1, 1); + StreamBuffer_g : t_ainteger := (1024, 1024); + StreamTimeout_g : t_areal := (1.0e-3, 1.0e-3); + StreamClkFreq_g : t_areal := (100.0e6, 100.0e6); + StreamTsFifoDepth_g : t_ainteger := (16, 16); + StreamUseTs_g : t_abool := (true, true); + -- Recording + MaxWindows_g : positive range 1 to 32 := 16; + MinBurstSize_g : integer range 1 to 512 := 512; + MaxBurstSize_g : integer range 1 to 512 := 512; + -- Axi + AxiDataWidth_g : natural range 64 to 1024 := 64; + AxiMaxBurstBeats_g : integer range 1 to 256 := 256; + AxiMaxOpenTrasactions_g : natural range 1 to 8 := 8; + AxiFifoDepth_g : natural := 1024; + -- Axi Slave + AxiSlaveIdWidth_g : integer := 0 + ); + port( + -- Data Stream Input + Str_Clk : in std_logic_vector(Streams_g - 1 downto 0); + Str_Data : in t_aslv64(Streams_g - 1 downto 0); + Str_Ts : in t_aslv64(Streams_g - 1 downto 0); + Str_Vld : in std_logic_vector(Streams_g - 1 downto 0); + Str_Rdy : out std_logic_vector(Streams_g - 1 downto 0); + Str_Trig : in std_logic_vector(Streams_g - 1 downto 0); + -- Miscellaneous + Irq : out std_logic; + -- AXI Slave Interface for Register Access + S_Axi_Aclk : in std_logic; + S_Axi_Aresetn : in std_logic; + S_Axi_ArId : in std_logic_vector(AxiSlaveIdWidth_g - 1 downto 0); + S_Axi_ArAddr : in std_logic_vector(15 downto 0); + S_Axi_Arlen : in std_logic_vector(7 downto 0); + S_Axi_ArSize : in std_logic_vector(2 downto 0); + S_Axi_ArBurst : in std_logic_vector(1 downto 0); + S_Axi_ArLock : in std_logic; + S_Axi_ArCache : in std_logic_vector(3 downto 0); + S_Axi_ArProt : in std_logic_vector(2 downto 0); + S_Axi_ArValid : in std_logic; + S_Axi_ArReady : out std_logic; + S_Axi_RId : out std_logic_vector(AxiSlaveIdWidth_g - 1 downto 0); + S_Axi_RData : out std_logic_vector(31 downto 0); + S_Axi_RResp : out std_logic_vector(1 downto 0); + S_Axi_RLast : out std_logic; + S_Axi_RValid : out std_logic; + S_Axi_RReady : in std_logic; + S_Axi_AwId : in std_logic_vector(AxiSlaveIdWidth_g - 1 downto 0); + S_Axi_AwAddr : in std_logic_vector(15 downto 0); + S_Axi_AwLen : in std_logic_vector(7 downto 0); + S_Axi_AwSize : in std_logic_vector(2 downto 0); + S_Axi_AwBurst : in std_logic_vector(1 downto 0); + S_Axi_AwLock : in std_logic; + S_Axi_AwCache : in std_logic_vector(3 downto 0); + S_Axi_AwProt : in std_logic_vector(2 downto 0); + S_Axi_AwValid : in std_logic; + S_Axi_AwReady : out std_logic; + S_Axi_WData : in std_logic_vector(31 downto 0); + S_Axi_WStrb : in std_logic_vector(3 downto 0); + S_Axi_WLast : in std_logic; + S_Axi_WValid : in std_logic; + S_Axi_WReady : out std_logic; + S_Axi_BId : out std_logic_vector(AxiSlaveIdWidth_g - 1 downto 0); + S_Axi_BResp : out std_logic_vector(1 downto 0); + S_Axi_BValid : out std_logic; + S_Axi_BReady : in std_logic; + -- AXI Master Interface for Memory Access + M_Axi_Aclk : in std_logic; + M_Axi_Aresetn : in std_logic; + M_Axi_AwAddr : out std_logic_vector(31 downto 0); + M_Axi_AwLen : out std_logic_vector(7 downto 0); + M_Axi_AwSize : out std_logic_vector(2 downto 0); + M_Axi_AwBurst : out std_logic_vector(1 downto 0); + M_Axi_AwLock : out std_logic; + M_Axi_AwCache : out std_logic_vector(3 downto 0); + M_Axi_AwProt : out std_logic_vector(2 downto 0); + M_Axi_AwValid : out std_logic; + M_Axi_AwReady : in std_logic := '0'; + M_Axi_WData : out std_logic_vector(AxiDataWidth_g - 1 downto 0); + M_Axi_WStrb : out std_logic_vector(AxiDataWidth_g / 8 - 1 downto 0); + M_Axi_WLast : out std_logic; + M_Axi_WValid : out std_logic; + M_Axi_WReady : in std_logic := '0'; + M_Axi_BResp : in std_logic_vector(1 downto 0) := (others => '0'); + M_Axi_BValid : in std_logic := '0'; + M_Axi_BReady : out std_logic; + M_Axi_ArAddr : out std_logic_vector(31 downto 0); + M_Axi_ArLen : out std_logic_vector(7 downto 0); + M_Axi_ArSize : out std_logic_vector(2 downto 0); + M_Axi_ArBurst : out std_logic_vector(1 downto 0); + M_Axi_ArLock : out std_logic; + M_Axi_ArCache : out std_logic_vector(3 downto 0); + M_Axi_ArProt : out std_logic_vector(2 downto 0); + M_Axi_ArValid : out std_logic; + M_Axi_ArReady : in std_logic := '0'; + M_Axi_RData : in std_logic_vector(AxiDataWidth_g - 1 downto 0) := (others => '0'); + M_Axi_RResp : in std_logic_vector(1 downto 0) := (others => '0'); + M_Axi_RLast : in std_logic := '0'; + M_Axi_RValid : in std_logic := '0'; + M_Axi_RReady : out std_logic + ); end entity; - + ------------------------------------------------------------------------------ -- Architecture Declaration ------------------------------------------------------------------------------ architecture rtl of psi_ms_daq_axi is - -- Config Arrays with correct size - constant StreamWidth_c : t_ainteger(0 to Streams_g-1) := StreamWidth_g(0 to Streams_g-1); - constant StreamPrio_c : t_ainteger(0 to Streams_g-1) := StreamPrio_g(0 to Streams_g-1); - constant StreamBuffer_c : t_ainteger(0 to Streams_g-1) := StreamBuffer_g(0 to Streams_g-1); - constant StreamTimeout_c : t_areal(0 to Streams_g-1) := StreamTimeout_g(0 to Streams_g-1); - constant StreamClkFreq_c : t_areal(0 to Streams_g-1) := StreamClkFreq_g(0 to Streams_g-1); - constant StreamTsFifoDepth_c : t_ainteger(0 to Streams_g-1) := StreamTsFifoDepth_g(0 to Streams_g-1); - constant StreamUseTs_c : t_abool(0 to Streams_g-1) := StreamUseTs_g(0 to Streams_g-1); + -- Config Arrays with correct size + constant StreamWidth_c : t_ainteger(0 to Streams_g - 1) := StreamWidth_g(0 to Streams_g - 1); + constant StreamPrio_c : t_ainteger(0 to Streams_g - 1) := StreamPrio_g(0 to Streams_g - 1); + constant StreamBuffer_c : t_ainteger(0 to Streams_g - 1) := StreamBuffer_g(0 to Streams_g - 1); + constant StreamTimeout_c : t_areal(0 to Streams_g - 1) := StreamTimeout_g(0 to Streams_g - 1); + constant StreamClkFreq_c : t_areal(0 to Streams_g - 1) := StreamClkFreq_g(0 to Streams_g - 1); + constant StreamTsFifoDepth_c : t_ainteger(0 to Streams_g - 1) := StreamTsFifoDepth_g(0 to Streams_g - 1); + constant StreamUseTs_c : t_abool(0 to Streams_g - 1) := StreamUseTs_g(0 to Streams_g - 1); + + -- Input/Statemachine Signals + signal InpSm_HasTlast : std_logic_vector(Streams_g - 1 downto 0); + signal InpSm_TsVld : std_logic_vector(Streams_g - 1 downto 0); + signal InpSm_TsRdy : std_logic_vector(Streams_g - 1 downto 0); + signal InpSm_Level : t_aslv16(Streams_g - 1 downto 0); + signal InpSm_TsData : t_aslv64(Streams_g - 1 downto 0); + + -- Statemachine/Dma + signal SmDma_Cmd : DaqSm2DaqDma_Cmd_t; + signal SmDma_CmdVld : std_logic; + signal DmaSm_Resp : DaqDma2DaqSm_Resp_t; + signal DmaSm_RespVld : std_logic; + signal DmaSm_RespRdy : std_logic; + signal DmaSm_HasLast : std_logic_vector(Streams_g - 1 downto 0); + + -- Input/Dma + signal InpDma_Vld : std_logic_vector(Streams_g - 1 downto 0); + signal InpDma_Rdy : std_logic_vector(Streams_g - 1 downto 0); + signal InpDma_Data : Input2Daq_Data_a(Streams_g - 1 downto 0); + + -- Dma/Mem + signal DmaMem_CmdAddr : std_logic_vector(31 downto 0); + signal DmaMem_CmdSize : std_logic_vector(31 downto 0); + signal DmaMem_CmdVld : std_logic; + signal DmaMem_CmdRdy : std_logic; + signal DmaMem_DatData : std_logic_vector(63 downto 0); + signal DmaMem_DatVld : std_logic; + signal DmaMem_DatRdy : std_logic; + + -- Mem/Statemachine + signal MemSm_Done : std_logic; + + -- Configuration + signal Cfg_StrEna : std_logic_vector(Streams_g - 1 downto 0); + signal Cfg_GlbEna : std_logic; + signal Cfg_PostTrig : t_aslv32(Streams_g - 1 downto 0); + signal Cfg_Arm : std_logic_vector(Streams_g - 1 downto 0); + signal Cfg_RecMode : t_aslv2(Streams_g - 1 downto 0); + + -- Status + signal Stat_StrIrq : std_logic_vector(Streams_g - 1 downto 0); + signal Stat_StrLastWin : WinType_a(Streams_g - 1 downto 0); + signal Stat_IsArmed : std_logic_vector(Streams_g - 1 downto 0); + signal Stat_IsRecording : std_logic_vector(Streams_g - 1 downto 0); + + -- Context Memory Connections + signal CtxStr_Cmd : ToCtxStr_t; + signal CtxStr_Resp : FromCtx_t; + signal CtxWin_Cmd : ToCtxWin_t; + signal CtxWin_Resp : FromCtx_t; + + -- Others + signal Sm_HasLast : std_logic_vector(Streams_g - 1 downto 0); + signal M_Axi_Areset : std_logic; -- high active reset + signal S_Axi_Areset : std_logic; -- high active reset - -- Input/Statemachine Signals - signal InpSm_HasTlast : std_logic_vector(Streams_g-1 downto 0); - signal InpSm_TsVld : std_logic_vector(Streams_g-1 downto 0); - signal InpSm_TsRdy : std_logic_vector(Streams_g-1 downto 0); - signal InpSm_Level : t_aslv16(Streams_g-1 downto 0); - signal InpSm_TsData : t_aslv64(Streams_g-1 downto 0); - - -- Statemachine/Dma - signal SmDma_Cmd : DaqSm2DaqDma_Cmd_t; - signal SmDma_CmdVld : std_logic; - signal DmaSm_Resp : DaqDma2DaqSm_Resp_t; - signal DmaSm_RespVld : std_logic; - signal DmaSm_RespRdy : std_logic; - signal DmaSm_HasLast : std_logic_vector(Streams_g-1 downto 0); - - -- Input/Dma - signal InpDma_Vld : std_logic_vector(Streams_g-1 downto 0); - signal InpDma_Rdy : std_logic_vector(Streams_g-1 downto 0); - signal InpDma_Data : Input2Daq_Data_a(Streams_g-1 downto 0); - - -- Dma/Mem - signal DmaMem_CmdAddr : std_logic_vector(31 downto 0); - signal DmaMem_CmdSize : std_logic_vector(31 downto 0); - signal DmaMem_CmdVld : std_logic; - signal DmaMem_CmdRdy : std_logic; - signal DmaMem_DatData : std_logic_vector(63 downto 0); - signal DmaMem_DatVld : std_logic; - signal DmaMem_DatRdy : std_logic; - - -- Mem/Statemachine - signal MemSm_Done : std_logic; - - -- Configuration - signal Cfg_StrEna : std_logic_vector(Streams_g-1 downto 0); - signal Cfg_GlbEna : std_logic; - signal Cfg_PostTrig : t_aslv32(Streams_g-1 downto 0); - signal Cfg_Arm : std_logic_vector(Streams_g-1 downto 0); - signal Cfg_RecMode : t_aslv2(Streams_g-1 downto 0); - - -- Status - signal Stat_StrIrq : std_logic_vector(Streams_g-1 downto 0); - signal Stat_StrLastWin : WinType_a(Streams_g-1 downto 0); - signal Stat_IsArmed : std_logic_vector(Streams_g-1 downto 0); - signal Stat_IsRecording : std_logic_vector(Streams_g-1 downto 0); - - -- Context Memory Connections - signal CtxStr_Cmd : ToCtxStr_t; - signal CtxStr_Resp : FromCtx_t; - signal CtxWin_Cmd : ToCtxWin_t; - signal CtxWin_Resp : FromCtx_t; - - -- Others - signal Sm_HasLast : std_logic_vector(Streams_g-1 downto 0); - signal M_Axi_Areset : std_logic; -- high active reset - signal S_Axi_Areset : std_logic; -- high active reset - begin - M_Axi_Areset <= not M_Axi_Aresetn; - S_Axi_Areset <= not S_Axi_Aresetn; - - -------------------------------------------- - -- Register Interface - -------------------------------------------- - i_reg : entity work.psi_ms_daq_reg_axi - generic map ( - Streams_g => Streams_g, - MaxWindows_g => MaxWindows_g, - AxiSlaveIdWidth_g => AxiSlaveIdWidth_g - ) - port map ( - S_Axi_Aclk => S_Axi_Aclk, - S_Axi_Aresetn => S_Axi_Aresetn, - S_Axi_ArId => S_Axi_ArId, - S_Axi_ArAddr => S_Axi_ArAddr, - S_Axi_Arlen => S_Axi_Arlen, - S_Axi_ArSize => S_Axi_ArSize, - S_Axi_ArBurst => S_Axi_ArBurst, - S_Axi_ArLock => S_Axi_ArLock, - S_Axi_ArCache => S_Axi_ArCache, - S_Axi_ArProt => S_Axi_ArProt, - S_Axi_ArValid => S_Axi_ArValid, - S_Axi_ArReady => S_Axi_ArReady, - S_Axi_RId => S_Axi_RId, - S_Axi_RData => S_Axi_RData, - S_Axi_RResp => S_Axi_RResp, - S_Axi_RLast => S_Axi_RLast, - S_Axi_RValid => S_Axi_RValid, - S_Axi_RReady => S_Axi_RReady, - S_Axi_AwId => S_Axi_AwId, - S_Axi_AwAddr => S_Axi_AwAddr, - S_Axi_AwLen => S_Axi_AwLen, - S_Axi_AwSize => S_Axi_AwSize, - S_Axi_AwBurst => S_Axi_AwBurst, - S_Axi_AwLock => S_Axi_AwLock, - S_Axi_AwCache => S_Axi_AwCache, - S_Axi_AwProt => S_Axi_AwProt, - S_Axi_AwValid => S_Axi_AwValid, - S_Axi_AwReady => S_Axi_AwReady, - S_Axi_WData => S_Axi_WData, - S_Axi_WStrb => S_Axi_WStrb, - S_Axi_WLast => S_Axi_WLast, - S_Axi_WValid => S_Axi_WValid, - S_Axi_WReady => S_Axi_WReady, - S_Axi_BId => S_Axi_BId, - S_Axi_BResp => S_Axi_BResp, - S_Axi_BValid => S_Axi_BValid, - S_Axi_BReady => S_Axi_BReady, - IrqOut => Irq, - PostTrig => Cfg_PostTrig, - Arm => Cfg_Arm, - IsArmed => Stat_IsArmed, - IsRecording => Stat_IsRecording, - RecMode => Cfg_RecMode, - ClkMem => M_Axi_Aclk, - RstMem => M_Axi_Areset, - CtxStr_Cmd => CtxStr_Cmd, - CtxStr_Resp => CtxStr_Resp, - CtxWin_Cmd => CtxWin_Cmd, - CtxWin_Resp => CtxWin_Resp, - InLevel => InpSm_Level, - StrIrq => Stat_StrIrq, - StrLastWin => Stat_StrLastWin, - StrEna => Cfg_StrEna, - GlbEna => Cfg_GlbEna - ); + M_Axi_Areset <= not M_Axi_Aresetn; + S_Axi_Areset <= not S_Axi_Aresetn; - -------------------------------------------- - -- Input Logic Instantiation - -------------------------------------------- - g_input : for str in 0 to Streams_g-1 generate - signal InRst : std_logic; - signal StrInput : std_logic_vector(StreamWidth_c(str)-1 downto 0); - begin - -- Reset if stream is disabled - InRst <= M_Axi_Areset or not Cfg_StrEna(str) or not Cfg_GlbEna; - StrInput <= Str_Data(str)(StrInput'range); - - -- Instantiation - i_input : entity work.psi_ms_daq_input - generic map ( - StreamWidth_g => StreamWidth_c(str), - StreamBuffer_g => StreamBuffer_c(str), - StreamTimeout_g => StreamTimeout_c(str), - StreamClkFreq_g => StreamClkFreq_c(str), - StreamTsFifoDepth_g => StreamTsFifoDepth_c(str), - StreamUseTs_g => StreamUseTs_c(str) - ) - port map ( - Str_Clk => Str_Clk(str), - Str_Vld => Str_Vld(str), - Str_Rdy => Str_Rdy(str), - Str_Data => StrInput, - Str_Trig => Str_Trig(str), - Str_Ts => Str_Ts(str), - ClkReg => S_Axi_Aclk, - RstReg => S_Axi_Areset, - PostTrigSpls => Cfg_PostTrig(str), - Mode => Cfg_RecMode(str), - Arm => Cfg_Arm(str), - IsArmed => Stat_IsArmed(str), - IsRecording => Stat_IsRecording(str), - ClkMem => M_Axi_Aclk, - RstMem => InRst, - Daq_Vld => InpDma_Vld(str), - Daq_Rdy => InpDma_Rdy(str), - Daq_Data => InpDma_Data(str), - Daq_Level => InpSm_Level(str), - Daq_HasLast => InpSm_HasTlast(str), - Ts_Vld => InpSm_TsVld(str), - Ts_Rdy => InpSm_TsRdy(str), - Ts_Data => InpSm_TsData(str) - ); - end generate; - - -------------------------------------------- - -- Control State Machine - -------------------------------------------- - -- Detect end-of frame in input buffer or DMA buffer - Sm_HasLast <= InpSm_HasTlast or DmaSm_HasLast; - - -- Instantiation - i_statemachine : entity work.psi_ms_daq_daq_sm - generic map ( - Streams_g => Streams_g, - StreamPrio_g => StreamPrio_c, - StreamWidth_g => StreamWidth_c, - Windows_g => MaxWindows_g, - MinBurstSize_g => MinBurstSize_g, - MaxBurstSize_g => MaxBurstSize_g - ) - port map ( - Clk => M_Axi_Aclk, - Rst => M_Axi_Areset, - GlbEna => Cfg_GlbEna, - StrEna => Cfg_StrEna, - StrIrq => Stat_StrIrq, - StrLastWin => Stat_StrLastWin, - Inp_HasLast => Sm_HasLast, - Inp_Level => InpSm_Level, - Ts_Vld => InpSm_TsVld, - Ts_Rdy => InpSm_TsRdy, - Ts_Data => InpSm_TsData, - Dma_Cmd => SmDma_Cmd, - Dma_Cmd_Vld => SmDma_CmdVld, - Dma_Resp => DmaSm_Resp, - Dma_Resp_Vld => DmaSm_RespVld, - Dma_Resp_Rdy => DmaSm_RespRdy, - TfDone => MemSm_Done, - - -- Context RAM connections - CtxStr_Cmd => CtxStr_Cmd, - CtxStr_Resp => CtxStr_Resp, - CtxWin_Cmd => CtxWin_Cmd, - CtxWin_Resp => CtxWin_Resp - ); + -------------------------------------------- + -- Register Interface + -------------------------------------------- + i_reg : entity work.psi_ms_daq_reg_axi + generic map( + Streams_g => Streams_g, + MaxWindows_g => MaxWindows_g, + AxiSlaveIdWidth_g => AxiSlaveIdWidth_g + ) + port map( + S_Axi_Aclk => S_Axi_Aclk, + S_Axi_Aresetn => S_Axi_Aresetn, + S_Axi_ArId => S_Axi_ArId, + S_Axi_ArAddr => S_Axi_ArAddr, + S_Axi_Arlen => S_Axi_Arlen, + S_Axi_ArSize => S_Axi_ArSize, + S_Axi_ArBurst => S_Axi_ArBurst, + S_Axi_ArLock => S_Axi_ArLock, + S_Axi_ArCache => S_Axi_ArCache, + S_Axi_ArProt => S_Axi_ArProt, + S_Axi_ArValid => S_Axi_ArValid, + S_Axi_ArReady => S_Axi_ArReady, + S_Axi_RId => S_Axi_RId, + S_Axi_RData => S_Axi_RData, + S_Axi_RResp => S_Axi_RResp, + S_Axi_RLast => S_Axi_RLast, + S_Axi_RValid => S_Axi_RValid, + S_Axi_RReady => S_Axi_RReady, + S_Axi_AwId => S_Axi_AwId, + S_Axi_AwAddr => S_Axi_AwAddr, + S_Axi_AwLen => S_Axi_AwLen, + S_Axi_AwSize => S_Axi_AwSize, + S_Axi_AwBurst => S_Axi_AwBurst, + S_Axi_AwLock => S_Axi_AwLock, + S_Axi_AwCache => S_Axi_AwCache, + S_Axi_AwProt => S_Axi_AwProt, + S_Axi_AwValid => S_Axi_AwValid, + S_Axi_AwReady => S_Axi_AwReady, + S_Axi_WData => S_Axi_WData, + S_Axi_WStrb => S_Axi_WStrb, + S_Axi_WLast => S_Axi_WLast, + S_Axi_WValid => S_Axi_WValid, + S_Axi_WReady => S_Axi_WReady, + S_Axi_BId => S_Axi_BId, + S_Axi_BResp => S_Axi_BResp, + S_Axi_BValid => S_Axi_BValid, + S_Axi_BReady => S_Axi_BReady, + IrqOut => Irq, + PostTrig => Cfg_PostTrig, + Arm => Cfg_Arm, + IsArmed => Stat_IsArmed, + IsRecording => Stat_IsRecording, + RecMode => Cfg_RecMode, + ClkMem => M_Axi_Aclk, + RstMem => M_Axi_Areset, + CtxStr_Cmd => CtxStr_Cmd, + CtxStr_Resp => CtxStr_Resp, + CtxWin_Cmd => CtxWin_Cmd, + CtxWin_Resp => CtxWin_Resp, + InLevel => InpSm_Level, + StrIrq => Stat_StrIrq, + StrLastWin => Stat_StrLastWin, + StrEna => Cfg_StrEna, + GlbEna => Cfg_GlbEna + ); - -------------------------------------------- - -- DMA Engine - -------------------------------------------- - i_dma : entity work.psi_ms_daq_daq_dma - generic map ( - Streams_g => Streams_g - ) - port map ( - Clk => M_Axi_Aclk, - Rst => M_Axi_Areset, - DaqSm_Cmd => SmDma_Cmd, - DaqSm_Cmd_Vld => SmDma_CmdVld, - DaqSm_Resp => DmaSm_Resp, - DaqSm_Resp_Vld => DmaSm_RespVld, - DaqSm_Resp_Rdy => DmaSm_RespRdy, - DaqSm_HasLast => DmaSm_HasLast, - Inp_Vld => InpDma_Vld, - Inp_Rdy => InpDma_Rdy, - Inp_Data => InpDma_Data, - Mem_CmdAddr => DmaMem_CmdAddr, - Mem_CmdSize => DmaMem_CmdSize, - Mem_CmdVld => DmaMem_CmdVld, - Mem_CmdRdy => DmaMem_CmdRdy, - Mem_DatData => DmaMem_DatData, - Mem_DatVld => DmaMem_DatVld, - Mem_DatRdy => DmaMem_DatRdy - ); - - -------------------------------------------- - -- Memory Interface - -------------------------------------------- - i_memif : entity work.psi_ms_daq_axi_if - generic map ( - AxiDataWidth_g => AxiDataWidth_g, - AxiMaxBeats_g => AxiMaxBurstBeats_g, - AxiMaxOpenTrasactions_g => AxiMaxOpenTrasactions_g, - MaxOpenCommands_g => max(2, Streams_g), -- ISE tools implement memory as FFs for one stream. Reason is unkown, so we always implement two streams for resource optimization reasons. - DataFifoDepth_g => 1024, - AxiFifoDepth_g => AxiFifoDepth_g, - RamBehavior_g => "RBW" -- Okay for Xilinx chips - ) - port map ( - Clk => M_Axi_Aclk, - Rst_n => M_Axi_Aresetn, - Cmd_Addr => DmaMem_CmdAddr, - Cmd_Size => DmaMem_CmdSize, - Cmd_Vld => DmaMem_CmdVld, - Cmd_Rdy => DmaMem_CmdRdy, - Dat_Data => DmaMem_DatData, - Dat_Vld => DmaMem_DatVld, - Dat_Rdy => DmaMem_DatRdy, - Done => MemSm_Done, - M_Axi_AwAddr => M_Axi_AwAddr, - M_Axi_AwLen => M_Axi_AwLen, - M_Axi_AwSize => M_Axi_AwSize, - M_Axi_AwBurst => M_Axi_AwBurst, - M_Axi_AwLock => M_Axi_AwLock, - M_Axi_AwCache => M_Axi_AwCache, - M_Axi_AwProt => M_Axi_AwProt, - M_Axi_AwValid => M_Axi_AwValid, - M_Axi_AwReady => M_Axi_AwReady, - M_Axi_WData => M_Axi_WData, - M_Axi_WStrb => M_Axi_WStrb, - M_Axi_WLast => M_Axi_WLast, - M_Axi_WValid => M_Axi_WValid, - M_Axi_WReady => M_Axi_WReady, - M_Axi_BResp => M_Axi_BResp, - M_Axi_BValid => M_Axi_BValid, - M_Axi_BReady => M_Axi_BReady, - M_Axi_ArAddr => M_Axi_ArAddr, - M_Axi_ArLen => M_Axi_ArLen, - M_Axi_ArSize => M_Axi_ArSize, - M_Axi_ArBurst => M_Axi_ArBurst, - M_Axi_ArLock => M_Axi_ArLock, - M_Axi_ArCache => M_Axi_ArCache, - M_Axi_ArProt => M_Axi_ArProt, - M_Axi_ArValid => M_Axi_ArValid, - M_Axi_ArReady => M_Axi_ArReady, - M_Axi_RData => M_Axi_RData, - M_Axi_RResp => M_Axi_RResp, - M_Axi_RLast => M_Axi_RLast, - M_Axi_RValid => M_Axi_RValid, - M_Axi_RReady => M_Axi_RReady - ); - -end; + -------------------------------------------- + -- Input Logic Instantiation + -------------------------------------------- + g_input : for str in 0 to Streams_g - 1 generate + signal InRst : std_logic; + signal StrInput : std_logic_vector(StreamWidth_c(str) - 1 downto 0); + begin + -- Reset if stream is disabled + InRst <= M_Axi_Areset or not Cfg_StrEna(str) or not Cfg_GlbEna; + StrInput <= Str_Data(str)(StrInput'range); + -- Instantiation + i_input : entity work.psi_ms_daq_input + generic map( + StreamWidth_g => StreamWidth_c(str), + StreamBuffer_g => StreamBuffer_c(str), + StreamTimeout_g => StreamTimeout_c(str), + StreamClkFreq_g => StreamClkFreq_c(str), + StreamTsFifoDepth_g => StreamTsFifoDepth_c(str), + StreamUseTs_g => StreamUseTs_c(str) + ) + port map( + Str_Clk => Str_Clk(str), + Str_Vld => Str_Vld(str), + Str_Rdy => Str_Rdy(str), + Str_Data => StrInput, + Str_Trig => Str_Trig(str), + Str_Ts => Str_Ts(str), + ClkReg => S_Axi_Aclk, + RstReg => S_Axi_Areset, + PostTrigSpls => Cfg_PostTrig(str), + Mode => Cfg_RecMode(str), + Arm => Cfg_Arm(str), + IsArmed => Stat_IsArmed(str), + IsRecording => Stat_IsRecording(str), + ClkMem => M_Axi_Aclk, + RstMem => InRst, + Daq_Vld => InpDma_Vld(str), + Daq_Rdy => InpDma_Rdy(str), + Daq_Data => InpDma_Data(str), + Daq_Level => InpSm_Level(str), + Daq_HasLast => InpSm_HasTlast(str), + Ts_Vld => InpSm_TsVld(str), + Ts_Rdy => InpSm_TsRdy(str), + Ts_Data => InpSm_TsData(str) + ); + end generate; + -------------------------------------------- + -- Control State Machine + -------------------------------------------- + -- Detect end-of frame in input buffer or DMA buffer + Sm_HasLast <= InpSm_HasTlast or DmaSm_HasLast; + -- Instantiation + i_statemachine : entity work.psi_ms_daq_daq_sm + generic map( + Streams_g => Streams_g, + StreamPrio_g => StreamPrio_c, + StreamWidth_g => StreamWidth_c, + Windows_g => MaxWindows_g, + MinBurstSize_g => MinBurstSize_g, + MaxBurstSize_g => MaxBurstSize_g + ) + port map( + Clk => M_Axi_Aclk, + Rst => M_Axi_Areset, + GlbEna => Cfg_GlbEna, + StrEna => Cfg_StrEna, + StrIrq => Stat_StrIrq, + StrLastWin => Stat_StrLastWin, + Inp_HasLast => Sm_HasLast, + Inp_Level => InpSm_Level, + Ts_Vld => InpSm_TsVld, + Ts_Rdy => InpSm_TsRdy, + Ts_Data => InpSm_TsData, + Dma_Cmd => SmDma_Cmd, + Dma_Cmd_Vld => SmDma_CmdVld, + Dma_Resp => DmaSm_Resp, + Dma_Resp_Vld => DmaSm_RespVld, + Dma_Resp_Rdy => DmaSm_RespRdy, + TfDone => MemSm_Done, + -- Context RAM connections + CtxStr_Cmd => CtxStr_Cmd, + CtxStr_Resp => CtxStr_Resp, + CtxWin_Cmd => CtxWin_Cmd, + CtxWin_Resp => CtxWin_Resp + ); + -------------------------------------------- + -- DMA Engine + -------------------------------------------- + i_dma : entity work.psi_ms_daq_daq_dma + generic map( + Streams_g => Streams_g + ) + port map( + Clk => M_Axi_Aclk, + Rst => M_Axi_Areset, + DaqSm_Cmd => SmDma_Cmd, + DaqSm_Cmd_Vld => SmDma_CmdVld, + DaqSm_Resp => DmaSm_Resp, + DaqSm_Resp_Vld => DmaSm_RespVld, + DaqSm_Resp_Rdy => DmaSm_RespRdy, + DaqSm_HasLast => DmaSm_HasLast, + Inp_Vld => InpDma_Vld, + Inp_Rdy => InpDma_Rdy, + Inp_Data => InpDma_Data, + Mem_CmdAddr => DmaMem_CmdAddr, + Mem_CmdSize => DmaMem_CmdSize, + Mem_CmdVld => DmaMem_CmdVld, + Mem_CmdRdy => DmaMem_CmdRdy, + Mem_DatData => DmaMem_DatData, + Mem_DatVld => DmaMem_DatVld, + Mem_DatRdy => DmaMem_DatRdy + ); + + -------------------------------------------- + -- Memory Interface + -------------------------------------------- + i_memif : entity work.psi_ms_daq_axi_if + generic map( + AxiDataWidth_g => AxiDataWidth_g, + AxiMaxBeats_g => AxiMaxBurstBeats_g, + AxiMaxOpenTrasactions_g => AxiMaxOpenTrasactions_g, + MaxOpenCommands_g => max(2, Streams_g), -- ISE tools implement memory as FFs for one stream. Reason is unkown, so we always implement two streams for resource optimization reasons. + DataFifoDepth_g => 1024, + AxiFifoDepth_g => AxiFifoDepth_g, + RamBehavior_g => "RBW" -- Okay for Xilinx chips + ) + port map( + Clk => M_Axi_Aclk, + Rst_n => M_Axi_Aresetn, + Cmd_Addr => DmaMem_CmdAddr, + Cmd_Size => DmaMem_CmdSize, + Cmd_Vld => DmaMem_CmdVld, + Cmd_Rdy => DmaMem_CmdRdy, + Dat_Data => DmaMem_DatData, + Dat_Vld => DmaMem_DatVld, + Dat_Rdy => DmaMem_DatRdy, + Done => MemSm_Done, + M_Axi_AwAddr => M_Axi_AwAddr, + M_Axi_AwLen => M_Axi_AwLen, + M_Axi_AwSize => M_Axi_AwSize, + M_Axi_AwBurst => M_Axi_AwBurst, + M_Axi_AwLock => M_Axi_AwLock, + M_Axi_AwCache => M_Axi_AwCache, + M_Axi_AwProt => M_Axi_AwProt, + M_Axi_AwValid => M_Axi_AwValid, + M_Axi_AwReady => M_Axi_AwReady, + M_Axi_WData => M_Axi_WData, + M_Axi_WStrb => M_Axi_WStrb, + M_Axi_WLast => M_Axi_WLast, + M_Axi_WValid => M_Axi_WValid, + M_Axi_WReady => M_Axi_WReady, + M_Axi_BResp => M_Axi_BResp, + M_Axi_BValid => M_Axi_BValid, + M_Axi_BReady => M_Axi_BReady, + M_Axi_ArAddr => M_Axi_ArAddr, + M_Axi_ArLen => M_Axi_ArLen, + M_Axi_ArSize => M_Axi_ArSize, + M_Axi_ArBurst => M_Axi_ArBurst, + M_Axi_ArLock => M_Axi_ArLock, + M_Axi_ArCache => M_Axi_ArCache, + M_Axi_ArProt => M_Axi_ArProt, + M_Axi_ArValid => M_Axi_ArValid, + M_Axi_ArReady => M_Axi_ArReady, + M_Axi_RData => M_Axi_RData, + M_Axi_RResp => M_Axi_RResp, + M_Axi_RLast => M_Axi_RLast, + M_Axi_RValid => M_Axi_RValid, + M_Axi_RReady => M_Axi_RReady + ); + +end; diff --git a/hdl/psi_ms_daq_axi_if.vhd b/hdl/psi_ms_daq_axi_if.vhd index ed80a74..75e1d79 100644 --- a/hdl/psi_ms_daq_axi_if.vhd +++ b/hdl/psi_ms_daq_axi_if.vhd @@ -8,217 +8,204 @@ -- Libraries ------------------------------------------------------------------------------ library ieee; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; - +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + library work; - use work.psi_common_math_pkg.all; +use work.psi_common_math_pkg.all; ------------------------------------------------------------------------------ -- Entity Declaration ------------------------------------------------------------------------------ entity psi_ms_daq_axi_if is - generic ( - AxiDataWidth_g : natural range 64 to 1024 := 64; - AxiMaxBeats_g : natural range 1 to 256 := 256; - AxiMaxOpenTrasactions_g : natural range 1 to 8 := 8; - MaxOpenCommands_g : positive := 16; - DataFifoDepth_g : natural := 1024; - AxiFifoDepth_g : natural := 1024; - RamBehavior_g : string := "RBW" - ); - port ( - -- Control Signals - Clk : in std_logic; - Rst_n : in std_logic; - - -- Write Command - Cmd_Addr : in std_logic_vector(31 downto 0); - Cmd_Size : in std_logic_vector(31 downto 0); - Cmd_Vld : in std_logic; - Cmd_Rdy : out std_logic; - - -- Write Data - Dat_Data : in std_logic_vector(63 downto 0); - Dat_Vld : in std_logic; - Dat_Rdy : out std_logic; - - -- Response - Done : out std_logic; - - -- AXI Address Write Channel - M_Axi_AwAddr : out std_logic_vector(31 downto 0); - M_Axi_AwLen : out std_logic_vector(7 downto 0); - M_Axi_AwSize : out std_logic_vector(2 downto 0); - M_Axi_AwBurst : out std_logic_vector(1 downto 0); - M_Axi_AwLock : out std_logic; - M_Axi_AwCache : out std_logic_vector(3 downto 0); - M_Axi_AwProt : out std_logic_vector(2 downto 0); - M_Axi_AwValid : out std_logic; - M_Axi_AwReady : in std_logic := '0'; - - -- AXI Write Data Channel - M_Axi_WData : out std_logic_vector(AxiDataWidth_g-1 downto 0); - M_Axi_WStrb : out std_logic_vector(AxiDataWidth_g/8-1 downto 0); - M_Axi_WLast : out std_logic; - M_Axi_WValid : out std_logic; - M_Axi_WReady : in std_logic := '0'; - - -- AXI Write Response Channel - M_Axi_BResp : in std_logic_vector(1 downto 0) := (others => '0'); - M_Axi_BValid : in std_logic := '0'; - M_Axi_BReady : out std_logic; - - -- AXI Read Address Channel - M_Axi_ArAddr : out std_logic_vector(31 downto 0); - M_Axi_ArLen : out std_logic_vector(7 downto 0); - M_Axi_ArSize : out std_logic_vector(2 downto 0); - M_Axi_ArBurst : out std_logic_vector(1 downto 0); - M_Axi_ArLock : out std_logic; - M_Axi_ArCache : out std_logic_vector(3 downto 0); - M_Axi_ArProt : out std_logic_vector(2 downto 0); - M_Axi_ArValid : out std_logic; - M_Axi_ArReady : in std_logic := '0'; - - -- AXI Read Data Channel - M_Axi_RData : in std_logic_vector(AxiDataWidth_g-1 downto 0) := (others => '0'); - M_Axi_RResp : in std_logic_vector(1 downto 0) := (others => '0'); - M_Axi_RLast : in std_logic := '0'; - M_Axi_RValid : in std_logic := '0'; - M_Axi_RReady : out std_logic - ); + generic( + AxiDataWidth_g : natural range 64 to 1024 := 64; + AxiMaxBeats_g : natural range 1 to 256 := 256; + AxiMaxOpenTrasactions_g : natural range 1 to 8 := 8; + MaxOpenCommands_g : positive := 16; + DataFifoDepth_g : natural := 1024; + AxiFifoDepth_g : natural := 1024; + RamBehavior_g : string := "RBW" + ); + port( + -- Control Signals + Clk : in std_logic; + Rst_n : in std_logic; + -- Write Command + Cmd_Addr : in std_logic_vector(31 downto 0); + Cmd_Size : in std_logic_vector(31 downto 0); + Cmd_Vld : in std_logic; + Cmd_Rdy : out std_logic; + -- Write Data + Dat_Data : in std_logic_vector(63 downto 0); + Dat_Vld : in std_logic; + Dat_Rdy : out std_logic; + -- Response + Done : out std_logic; + -- AXI Address Write Channel + M_Axi_AwAddr : out std_logic_vector(31 downto 0); + M_Axi_AwLen : out std_logic_vector(7 downto 0); + M_Axi_AwSize : out std_logic_vector(2 downto 0); + M_Axi_AwBurst : out std_logic_vector(1 downto 0); + M_Axi_AwLock : out std_logic; + M_Axi_AwCache : out std_logic_vector(3 downto 0); + M_Axi_AwProt : out std_logic_vector(2 downto 0); + M_Axi_AwValid : out std_logic; + M_Axi_AwReady : in std_logic := '0'; + -- AXI Write Data Channel + M_Axi_WData : out std_logic_vector(AxiDataWidth_g - 1 downto 0); + M_Axi_WStrb : out std_logic_vector(AxiDataWidth_g / 8 - 1 downto 0); + M_Axi_WLast : out std_logic; + M_Axi_WValid : out std_logic; + M_Axi_WReady : in std_logic := '0'; + -- AXI Write Response Channel + M_Axi_BResp : in std_logic_vector(1 downto 0) := (others => '0'); + M_Axi_BValid : in std_logic := '0'; + M_Axi_BReady : out std_logic; + -- AXI Read Address Channel + M_Axi_ArAddr : out std_logic_vector(31 downto 0); + M_Axi_ArLen : out std_logic_vector(7 downto 0); + M_Axi_ArSize : out std_logic_vector(2 downto 0); + M_Axi_ArBurst : out std_logic_vector(1 downto 0); + M_Axi_ArLock : out std_logic; + M_Axi_ArCache : out std_logic_vector(3 downto 0); + M_Axi_ArProt : out std_logic_vector(2 downto 0); + M_Axi_ArValid : out std_logic; + M_Axi_ArReady : in std_logic := '0'; + -- AXI Read Data Channel + M_Axi_RData : in std_logic_vector(AxiDataWidth_g - 1 downto 0) := (others => '0'); + M_Axi_RResp : in std_logic_vector(1 downto 0) := (others => '0'); + M_Axi_RLast : in std_logic := '0'; + M_Axi_RValid : in std_logic := '0'; + M_Axi_RReady : out std_logic + ); end entity; - + ------------------------------------------------------------------------------ -- Architecture Declaration ------------------------------------------------------------------------------ -architecture rtl of psi_ms_daq_axi_if is - signal Rst : std_logic; - - subtype CommandAddrRng_c is natural range 31 downto 0; - subtype CommandSizeRng_c is natural range 63 downto 32; - constant WrCmdWidth_c : integer := CommandSizeRng_c'high+1; - signal InfoFifoIn : std_logic_vector(WrCmdWidth_c-1 downto 0); - signal InfoFifoOut : std_logic_vector(WrCmdWidth_c-1 downto 0); - signal WrCmdFifo_Vld : std_logic; - signal WrCmdFifo_Rdy : std_logic; - signal WrCmdFifo_Addr : std_logic_vector(31 downto 0); - signal WrCmdFifo_Size : std_logic_vector(31 downto 0); - signal DoneI : std_logic; - signal ErrorI : std_logic; - +architecture rtl of psi_ms_daq_axi_if is + signal Rst : std_logic; + + subtype CommandAddrRng_c is natural range 31 downto 0; + subtype CommandSizeRng_c is natural range 63 downto 32; + constant WrCmdWidth_c : integer := CommandSizeRng_c'high + 1; + signal InfoFifoIn : std_logic_vector(WrCmdWidth_c - 1 downto 0); + signal InfoFifoOut : std_logic_vector(WrCmdWidth_c - 1 downto 0); + signal WrCmdFifo_Vld : std_logic; + signal WrCmdFifo_Rdy : std_logic; + signal WrCmdFifo_Addr : std_logic_vector(31 downto 0); + signal WrCmdFifo_Size : std_logic_vector(31 downto 0); + signal DoneI : std_logic; + signal ErrorI : std_logic; + begin - Rst <= not Rst_n; - - InfoFifoIn(CommandAddrRng_c) <= Cmd_Addr; - InfoFifoIn(CommandSizeRng_c) <= Cmd_Size; - - i_wrinfo_fifo : entity work.psi_common_sync_fifo - generic map ( - Width_g => WrCmdWidth_c, - Depth_g => MaxOpenCommands_g, - RamStyle_g => "distributed" - ) - port map ( - Clk => Clk, - Rst => Rst, - InData => InfoFifoIn, - InVld => Cmd_Vld, - InRdy => Cmd_Rdy, - OutData => InfoFifoOut, - OutVld => WrCmdFifo_Vld, - OutRdy => WrCmdFifo_Rdy - ); - - WrCmdFifo_Addr <= InfoFifoOut(CommandAddrRng_c); - WrCmdFifo_Size <= InfoFifoOut(CommandSizeRng_c); + Rst <= not Rst_n; - i_axi : entity work.psi_common_axi_master_full - generic map ( - AxiAddrWidth_g => 32, - AxiDataWidth_g => AxiDataWidth_g, - AxiMaxBeats_g => AxiMaxBeats_g, - AxiMaxOpenTrasactions_g => AxiMaxOpenTrasactions_g, - UserTransactionSizeBits_g => 32, - DataFifoDepth_g => DataFifoDepth_g, - DataWidth_g => 64, - ImplRead_g => false, - ImplWrite_g => true, - RamBehavior_g => RamBehavior_g - ) - port map ( - -- Control Signals - M_Axi_Aclk => Clk, - M_Axi_Aresetn => Rst_n, - -- User Command Interface Write - CmdWr_Addr => WrCmdFifo_Addr, - CmdWr_Size => WrCmdFifo_Size, - CmdWr_LowLat => '0', - CmdWr_Vld => WrCmdFifo_Vld, - CmdWr_Rdy => WrCmdFifo_Rdy, - -- User Command Interface Read (unused) - CmdRd_Addr => (others => '0'), - CmdRd_Size => (others => '0'), - CmdRd_LowLat => '0', - CmdRd_Vld => '0', - CmdRd_Rdy => open, - -- Write Data - WrDat_Data => Dat_Data, - WrDat_Vld => Dat_Vld, - WrDat_Rdy => Dat_Rdy, - -- Read Data (unused) - RdDat_Data => open, - RdDat_Vld => open, - RdDat_Rdy => '0', - -- Response - Wr_Done => DoneI, - Wr_Error => ErrorI, - Rd_Done => open, - Rd_Error => open, - -- AXI Address Write Channel - M_Axi_AwAddr => M_Axi_AwAddr, - M_Axi_AwLen => M_Axi_AwLen, - M_Axi_AwSize => M_Axi_AwSize, - M_Axi_AwBurst => M_Axi_AwBurst, - M_Axi_AwLock => M_Axi_AwLock, - M_Axi_AwCache => M_Axi_AwCache, - M_Axi_AwProt => M_Axi_AwProt, - M_Axi_AwValid => M_Axi_AwValid, - M_Axi_AwReady => M_Axi_AwReady, - -- AXI Write Data Channel - M_Axi_WData => M_Axi_WData, - M_Axi_WStrb => M_Axi_WStrb, - M_Axi_WLast => M_Axi_WLast, - M_Axi_WValid => M_Axi_WValid, - M_Axi_WReady => M_Axi_WReady, - -- AXI Write Response Channel - M_Axi_BResp => M_Axi_BResp, - M_Axi_BValid => M_Axi_BValid, - M_Axi_BReady => M_Axi_BReady, - -- AXI Read Address Channel - M_Axi_ArAddr => M_Axi_ArAddr, - M_Axi_ArLen => M_Axi_ArLen, - M_Axi_ArSize => M_Axi_ArSize, - M_Axi_ArBurst => M_Axi_ArBurst, - M_Axi_ArLock => M_Axi_ArLock, - M_Axi_ArCache => M_Axi_ArCache, - M_Axi_ArProt => M_Axi_ArProt, - M_Axi_ArValid => M_Axi_ArValid, - M_Axi_ArReady => M_Axi_ArReady, - -- AXI Read Data Channel - M_Axi_RData => M_Axi_RData, - M_Axi_RResp => M_Axi_RResp, - M_Axi_RLast => M_Axi_RLast, - M_Axi_RValid => M_Axi_RValid, - M_Axi_RReady => M_Axi_RReady - ); - - Done <= DoneI or ErrorI; - - -end; + InfoFifoIn(CommandAddrRng_c) <= Cmd_Addr; + InfoFifoIn(CommandSizeRng_c) <= Cmd_Size; + i_wrinfo_fifo : entity work.psi_common_sync_fifo + generic map( + width_g => WrCmdWidth_c, + depth_g => MaxOpenCommands_g, + ram_style_g => "distributed" + ) + port map( + clk_i => Clk, + rst_i => Rst, + dat_i => InfoFifoIn, + vld_i => Cmd_Vld, + rdy_o => Cmd_Rdy, + dat_o => InfoFifoOut, + vld_o => WrCmdFifo_Vld, + rdy_i => WrCmdFifo_Rdy + ); + WrCmdFifo_Addr <= InfoFifoOut(CommandAddrRng_c); + WrCmdFifo_Size <= InfoFifoOut(CommandSizeRng_c); + i_axi : entity work.psi_common_axi_master_full + generic map( + axi_addr_width_g => 32, + axi_data_width_g => AxiDataWidth_g, + axi_max_beats_g => AxiMaxBeats_g, + axi_max_open_trasactions_g => AxiMaxOpenTrasactions_g, + user_transaction_size_bits_g => 32, + data_fifo_depth_g => DataFifoDepth_g, + data_width_g => 64, + impl_read_g => false, + impl_write_g => true, + ram_behavior_g => RamBehavior_g + ) + port map( + -- Control Signals + m_axi_aclk => Clk, + m_axi_aresetn => Rst_n, + -- User Command Interface Write + cmd_wr_addr_i => WrCmdFifo_Addr, + cmd_wr_size_i => WrCmdFifo_Size, + cmd_wr_low_lat_i => '0', + cmd_wr_vld_i => WrCmdFifo_Vld, + cmd_wr_rdy_o => WrCmdFifo_Rdy, + -- User Command Interface Read (unused) + cmd_rd_addr_i => (others => '0'), + cmd_rd_size_o => (others => '0'), + cmd_rd_low_lat_i => '0', + cmd_rd_vld_i => '0', + cmd_rd_rdy_o => open, + -- Write Data + wr_dat_i => Dat_Data, + wr_vld_i => Dat_Vld, + wr_rdy_o => Dat_Rdy, + -- Read Data (unused) + rd_dat_o => open, + rd_vld_o => open, + rd_rdy_i => '0', + -- Response + wr_done_o => DoneI, + wr_error_o => ErrorI, + rd_done_o => open, + rd_error_o => open, + -- AXI Address Write Channel + m_axi_awaddr => M_Axi_AwAddr, + m_axi_awlen => M_Axi_AwLen, + m_axi_awsize => M_Axi_AwSize, + m_axi_awburst => M_Axi_AwBurst, + m_axi_awlock => M_Axi_AwLock, + m_axi_awcache => M_Axi_AwCache, + m_axi_awprot => M_Axi_AwProt, + m_axi_awvalid => M_Axi_AwValid, + m_axi_awready => M_Axi_AwReady, + -- AXI Write Data Channel + m_axi_wdata => M_Axi_WData, + m_axi_wstrb => M_Axi_WStrb, + m_axi_wlast => M_Axi_WLast, + m_axi_wvalid => M_Axi_WValid, + m_axi_wready => M_Axi_WReady, + -- AXI Write Response Channel + m_axi_bresp => M_Axi_BResp, + m_axi_bvalid => M_Axi_BValid, + m_axi_bready => M_Axi_BReady, + -- AXI Read Address Channel + m_axi_araddr => M_Axi_ArAddr, + m_axi_arlen => M_Axi_ArLen, + m_axi_arsize => M_Axi_ArSize, + m_axi_arburst => M_Axi_ArBurst, + m_axi_arlock => M_Axi_ArLock, + m_axi_arcache => M_Axi_ArCache, + m_axi_arprot => M_Axi_ArProt, + m_axi_arvalid => M_Axi_ArValid, + m_axi_arready => M_Axi_ArReady, + -- AXI Read Data Channel + m_axi_rdata => M_Axi_RData, + m_axi_rresp => M_Axi_RResp, + m_axi_rlast => M_Axi_RLast, + m_axi_rvalid => M_Axi_RValid, + m_axi_rready => M_Axi_RReady + ); + Done <= DoneI or ErrorI; + +end; diff --git a/hdl/psi_ms_daq_daq_dma.vhd b/hdl/psi_ms_daq_daq_dma.vhd index 8ec2dcc..86e1268 100644 --- a/hdl/psi_ms_daq_daq_dma.vhd +++ b/hdl/psi_ms_daq_daq_dma.vhd @@ -13,14 +13,14 @@ -- Libraries ------------------------------------------------------------------------------ library ieee; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; - +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + library work; - use work.psi_common_math_pkg.all; - use work.psi_common_logic_pkg.all; - use work.psi_common_array_pkg.all; - use work.psi_ms_daq_pkg.all; +use work.psi_common_math_pkg.all; +use work.psi_common_logic_pkg.all; +use work.psi_common_array_pkg.all; +use work.psi_ms_daq_pkg.all; ------------------------------------------------------------------------------ -- Entity Declaration @@ -29,372 +29,364 @@ library work; -- $$ processes=control,input,mem_cmd,mem_dat $$ -- $$ tbpkg=work.psi_tb_txt_util,work.psi_tb_compare_pkg,work.psi_tb_activity_pkg $$ entity psi_ms_daq_daq_dma is - generic ( - Streams_g : positive range 1 to 32 := 4 -- $$ constant=4 $$ - ); - port ( - -- Control signals - Clk : in std_logic; -- $$ type=clk; freq=200e6; proc=control,input,mem_dat,mem_cmd $$ - Rst : in std_logic; -- $$ type=rst; clk=Clk; proc=control $$ + generic( + Streams_g : positive range 1 to 32 := 4 -- $$ constant=4 $$ + ); + port( + -- Control signals + Clk : in std_logic; -- $$ type=clk; freq=200e6; proc=control,input,mem_dat,mem_cmd $$ + Rst : in std_logic; -- $$ type=rst; clk=Clk; proc=control $$ - -- DAQ Statemachione Connections - DaqSm_Cmd : in DaqSm2DaqDma_Cmd_t; -- $$ proc=control $$ - DaqSm_Cmd_Vld : in std_logic; -- $$ proc=control $$ - DaqSm_Resp : out DaqDma2DaqSm_Resp_t; -- $$ proc=control $$ - DaqSm_Resp_Vld : out std_logic; -- $$ proc=control $$ - DaqSm_Resp_Rdy : in std_logic; -- $$ proc=control $$ - DaqSm_HasLast : out std_logic_vector(Streams_g-1 downto 0); -- $$ proc=control $$ - - -- Input handling connections - Inp_Vld : in std_logic_vector(Streams_g-1 downto 0); -- $$ proc=input $$ - Inp_Rdy : out std_logic_vector(Streams_g-1 downto 0); -- $$ proc=input $$ - Inp_Data : in Input2Daq_Data_a(Streams_g-1 downto 0); -- $$ proc=input $$ - - -- Memory interface connections - Mem_CmdAddr : out std_logic_vector(31 downto 0); -- $$ proc=mem_cmd $$ - Mem_CmdSize : out std_logic_vector(31 downto 0); -- $$ proc=mem_cmd $$ - Mem_CmdVld : out std_logic; -- $$ proc=mem_cmd $$ - Mem_CmdRdy : in std_logic; -- $$ proc=mem_cmd $$ - Mem_DatData : out std_logic_vector(63 downto 0); -- $$ proc=mem_dat $$ - Mem_DatVld : out std_logic; -- $$ proc=mem_dat $$ - Mem_DatRdy : in std_logic -- $$ proc=mem_dat $$ - ); + -- DAQ Statemachione Connections + DaqSm_Cmd : in DaqSm2DaqDma_Cmd_t; -- $$ proc=control $$ + DaqSm_Cmd_Vld : in std_logic; -- $$ proc=control $$ + DaqSm_Resp : out DaqDma2DaqSm_Resp_t; -- $$ proc=control $$ + DaqSm_Resp_Vld : out std_logic; -- $$ proc=control $$ + DaqSm_Resp_Rdy : in std_logic; -- $$ proc=control $$ + DaqSm_HasLast : out std_logic_vector(Streams_g - 1 downto 0); -- $$ proc=control $$ + + -- Input handling connections + Inp_Vld : in std_logic_vector(Streams_g - 1 downto 0); -- $$ proc=input $$ + Inp_Rdy : out std_logic_vector(Streams_g - 1 downto 0); -- $$ proc=input $$ + Inp_Data : in Input2Daq_Data_a(Streams_g - 1 downto 0); -- $$ proc=input $$ + + -- Memory interface connections + Mem_CmdAddr : out std_logic_vector(31 downto 0); -- $$ proc=mem_cmd $$ + Mem_CmdSize : out std_logic_vector(31 downto 0); -- $$ proc=mem_cmd $$ + Mem_CmdVld : out std_logic; -- $$ proc=mem_cmd $$ + Mem_CmdRdy : in std_logic; -- $$ proc=mem_cmd $$ + Mem_DatData : out std_logic_vector(63 downto 0); -- $$ proc=mem_dat $$ + Mem_DatVld : out std_logic; -- $$ proc=mem_dat $$ + Mem_DatRdy : in std_logic -- $$ proc=mem_dat $$ + ); end entity; - + ------------------------------------------------------------------------------ -- Architecture Declaration ------------------------------------------------------------------------------ architecture rtl of psi_ms_daq_daq_dma is - -- Constants - constant BufferFifoDepth_c : integer := 32; - - -- Number of bits to encode stream is at least 1 (otherwise the special case for one stream would require separate code). - -- .. The overhead generated by this is regarded as aceptable (better wasting a few LUTs than much development time) - constant StreamBits_c : integer := max(log2ceil(Streams_g), 1); + -- Constants + constant BufferFifoDepth_c : integer := 32; - - -- Component Connection Signals - signal CmdFifo_Level_Dbg : std_logic_vector(StreamBits_c downto 0); - signal CmdFifo_InData : std_logic_vector(DaqSm2DaqDma_Cmd_Size_c-1 downto 0); - signal CmdFifo_OutData : std_logic_vector(DaqSm2DaqDma_Cmd_Size_c-1 downto 0); - signal CmdFifo_Cmd : DaqSm2DaqDma_Cmd_t; - signal CmdFifo_Vld : std_logic; - signal RspFifo_Level_Dbg : std_logic_vector(StreamBits_c downto 0); - signal RspFifo_InData : std_logic_vector(DaqDma2DaqSm_Resp_Size_c-1 downto 0); - signal RspFifo_OutData : std_logic_vector(DaqDma2DaqSm_Resp_Size_c-1 downto 0); - signal DatFifo_Level_Dbg : std_logic_vector(log2ceil(BufferFifoDepth_c) downto 0); - signal DatFifo_AlmFull : std_logic; - signal Rem_RdBytes : std_logic_vector(2 downto 0); - signal Rem_Data : std_logic_vector(63 downto 0); - signal Rem_Trigger : std_logic; - signal Rem_Last : std_logic; - - -- Types - type State_t is (Idle_s, RemRd1_s, RemRd2_s, Transfer_s, Done_s, Cmd_s); + -- Number of bits to encode stream is at least 1 (otherwise the special case for one stream would require separate code). + -- .. The overhead generated by this is regarded as aceptable (better wasting a few LUTs than much development time) + constant StreamBits_c : integer := max(log2ceil(Streams_g), 1); + + -- Component Connection Signals + signal CmdFifo_Level_Dbg : std_logic_vector(StreamBits_c downto 0); + signal CmdFifo_InData : std_logic_vector(DaqSm2DaqDma_Cmd_Size_c - 1 downto 0); + signal CmdFifo_OutData : std_logic_vector(DaqSm2DaqDma_Cmd_Size_c - 1 downto 0); + signal CmdFifo_Cmd : DaqSm2DaqDma_Cmd_t; + signal CmdFifo_Vld : std_logic; + signal RspFifo_Level_Dbg : std_logic_vector(StreamBits_c downto 0); + signal RspFifo_InData : std_logic_vector(DaqDma2DaqSm_Resp_Size_c - 1 downto 0); + signal RspFifo_OutData : std_logic_vector(DaqDma2DaqSm_Resp_Size_c - 1 downto 0); + signal DatFifo_Level_Dbg : std_logic_vector(log2ceil(BufferFifoDepth_c) downto 0); + signal DatFifo_AlmFull : std_logic; + signal Rem_RdBytes : std_logic_vector(2 downto 0); + signal Rem_Data : std_logic_vector(63 downto 0); + signal Rem_Trigger : std_logic; + signal Rem_Last : std_logic; + + -- Types + type State_t is (Idle_s, RemRd1_s, RemRd2_s, Transfer_s, Done_s, Cmd_s); + + -- Two process method + type two_process_r is record + CmdFifo_Rdy : std_logic; + RspFifo_Vld : std_logic; + RspFifo_Data : DaqDma2DaqSm_Resp_t; + Mem_DataVld : std_logic; + StreamStdlv : std_logic_vector(StreamBits_c - 1 downto 0); + RemWen : std_logic; + RemWrBytes : std_logic_vector(2 downto 0); + RemData : std_logic_vector(63 downto 0); + RemTrigger : std_logic; + RemLast : std_logic; + RemWrTrigger : std_logic; + RemWrLast : std_logic; + State : State_t; + HndlMaxSize : unsigned(15 downto 0); + RdBytes : unsigned(15 downto 0); + WrBytes : unsigned(15 downto 0); + HndlStream : integer range 0 to MaxStreams_c - 1; + HndlAddress : std_logic_vector(31 downto 0); + UpdateLast : std_logic; + HndlSft : unsigned(2 downto 0); + FirstDma : std_logic_vector(Streams_g - 1 downto 0); + Mem_CmdVld : std_logic; + Trigger : std_logic; + Last : std_logic; + DataSft : std_logic_vector(127 downto 0); + NextDone : std_logic; + DataWritten : std_logic; + HasLast : std_logic_vector(Streams_g - 1 downto 0); + end record; + signal r, r_next : two_process_r; - -- Two process method - type two_process_r is record - CmdFifo_Rdy : std_logic; - RspFifo_Vld : std_logic; - RspFifo_Data : DaqDma2DaqSm_Resp_t; - Mem_DataVld : std_logic; - StreamStdlv : std_logic_vector(StreamBits_c-1 downto 0); - RemWen : std_logic; - RemWrBytes : std_logic_vector(2 downto 0); - RemData : std_logic_vector(63 downto 0); - RemTrigger : std_logic; - RemLast : std_logic; - RemWrTrigger : std_logic; - RemWrLast : std_logic; - State : State_t; - HndlMaxSize : unsigned(15 downto 0); - RdBytes : unsigned(15 downto 0); - WrBytes : unsigned(15 downto 0); - HndlStream : integer range 0 to MaxStreams_c-1; - HndlAddress : std_logic_vector(31 downto 0); - UpdateLast : std_logic; - HndlSft : unsigned(2 downto 0); - FirstDma : std_logic_vector(Streams_g-1 downto 0); - Mem_CmdVld : std_logic; - Trigger : std_logic; - Last : std_logic; - DataSft : std_logic_vector(127 downto 0); - NextDone : std_logic; - DataWritten : std_logic; - HasLast : std_logic_vector(Streams_g-1 downto 0); - end record; - signal r, r_next : two_process_r; - - begin - -------------------------------------------- - -- Combinatorial Process - -------------------------------------------- - p_comb : process( r, DaqSm_Cmd, DaqSm_Cmd_Vld, DaqSm_Resp_Rdy, Inp_Vld, Inp_Data, Mem_CmdRdy, Mem_DatRdy, - CmdFifo_Cmd, CmdFifo_Vld, DatFifo_AlmFull, Rem_RdBytes, Rem_Data, Rem_Trigger, Rem_Last) - variable v : two_process_r; - variable ThisByte_v : std_logic_vector(7 downto 0); - variable RemSft_v : integer range 0 to 7; - begin - -- *** Hold variables stable *** - v := r; - - -- *** Default Values *** - v.CmdFifo_Rdy := '0'; - Inp_Rdy <= (others => '0'); - v.Mem_DataVld := '0'; - v.RspFifo_Vld := '0'; - v.RemWen := '0'; - v.UpdateLast := '0'; - - -- *** State Machine *** - case r.State is - - when Idle_s => - v.HndlMaxSize := unsigned(CmdFifo_Cmd.MaxSize); - v.HndlStream := CmdFifo_Cmd.Stream; - v.StreamStdlv := std_logic_vector(to_unsigned(CmdFifo_Cmd.Stream, v.StreamStdlv'length)); - v.HndlAddress := CmdFifo_Cmd.Address; - v.Trigger := '0'; - v.Last := '0'; - if CmdFifo_Vld = '1' then - v.CmdFifo_Rdy := '1'; - v.State := RemRd1_s; - end if; - - when RemRd1_s => - v.State := RemRd2_s; - - when RemRd2_s => - -- Prevent RAM data from before reset to have an influence - v.WrBytes := (others => '0'); - if r.FirstDma(r.HndlStream) = '1' then - v.HndlSft := (others => '0'); - v.RdBytes := (others => '0'); - v.DataSft := (others => '0'); - v.RemTrigger := '0'; - v.RemLast := '0'; - else - v.HndlSft := unsigned(Rem_RdBytes); - v.DataSft(127 downto 64) := Rem_Data; - v.RdBytes := resize(unsigned(Rem_RdBytes), v.RdBytes'length); - v.RemTrigger := Rem_Trigger; - v.RemLast := Rem_Last; - end if; - v.FirstDma(r.HndlStream) := '0'; - v.State := Transfer_s; - v.NextDone := '0'; - v.DataWritten := '0'; - - when Transfer_s => - -- TF done because of maximum size reached - if r.WrBytes >= r.HndlMaxSize then - v.State := Done_s; - elsif DatFifo_AlmFull = '0' then - if r.NextDone = '0' and Inp_Vld(r.HndlStream) = '1' and r.RemLast = '0' then - v.RdBytes := r.RdBytes + unsigned(Inp_Data(r.HndlStream).Bytes); - end if; - v.WrBytes := r.WrBytes + 8; - -- Combinatorial handling because of fall-through interface at input - if r.RdBytes < r.HndlMaxSize and r.NextDone = '0' and r.RemLast = '0' then - Inp_Rdy(r.HndlStream) <= '1'; - end if; - -- Handling of last frame - if (Inp_Data(r.HndlStream).Last = '1') or (r.RemLast = '1') then - -- Do one more word if not all data can be transferred in the current beat (NextDone = 1) - if (r.HndlSft + unsigned(Inp_Data(r.HndlStream).Bytes) <= 8) or (r.RemLast = '1') then - v.State := Done_s; - else - v.NextDone := '1'; - end if; - if (Inp_Data(r.HndlStream).IsTrig = '1') or (r.RemTrigger = '1') then - v.Trigger :='1'; - end if; - v.Last := '1'; - end if; - if r.NextDone = '1' or Inp_Vld(r.HndlStream) = '0' then - v.State := Done_s; - end if; - -- Data handling - v.DataSft(63 downto 0) := r.DataSft(127 downto 64); - v.DataSft(8*to_integer(r.HndlSft)+63 downto 8*to_integer(r.HndlSft)) := Inp_Data(r.HndlStream).Data; - if Inp_Vld(r.HndlStream) = '1' or r.HndlSft /= 0 then - v.Mem_DataVld := '1'; - v.DataWritten := '1'; - end if; - end if; - - when Done_s => - RemSft_v := to_integer(resize(r.HndlMaxSize, 3)); - v.RemWrTrigger := '0'; - v.RemWrLast := '0'; - if r.HndlMaxSize < r.RdBytes then - v.RemWrBytes := std_logic_vector(resize(r.RdBytes - r.HndlMaxSize, v.RemWrBytes'length)); - v.RdBytes := r.HndlMaxSize; - v.RemWrTrigger := r.Trigger; - v.RemWrLast := r.Last; - v.HasLast(r.HndlStream) := r.Last; - else - v.RemWrBytes := (others => '0'); - v.HasLast(r.HndlStream) := '0'; - end if; - v.RemData := v.DataSft(8*RemSft_v+63 downto 8*RemSft_v); - v.State := Cmd_s; - if r.DataWritten = '1' then - v.Mem_CmdVld := '1'; - end if; - v.RemWen := '1'; - - when Cmd_s => - if Mem_CmdRdy = '1' or r.Mem_CmdVld = '0' then - v.State := Idle_s; - v.Mem_CmdVld := '0'; - v.RspFifo_Vld := '1'; - v.RspFifo_Data.Size := std_logic_vector(r.RdBytes); - -- Only mark as trigger if all samples are completely written to memory (no remaining samples in REM RAM) - if (unsigned(r.RemWrBytes) = 0) and (r.Trigger = '1') then - v.RspFifo_Data.Trigger := '1'; - else - v.RspFifo_Data.Trigger := '0'; - end if; - v.RspFifo_Data.Stream := r.HndlStream; - end if; - when others => null; - end case; - - -- *** Assign to signal *** - r_next <= v; - - end process; - - -- *** Registered Outputs *** - Mem_CmdAddr <= r.HndlAddress; - Mem_CmdSize(r.RdBytes'range) <= std_logic_vector(r.RdBytes); - Mem_CmdSize(Mem_CmdSize'high downto r.RdBytes'high+1) <= (others => '0'); - Mem_CmdVld <= r.Mem_CmdVld; - DaqSm_HasLast <= r.HasLast; - - - -------------------------------------------- - -- Sequential Process - -------------------------------------------- - p_seq : process(Clk) - begin - if rising_edge(Clk) then - r <= r_next; - if Rst = '1' then - r.CmdFifo_Rdy <= '0'; - r.RspFifo_Vld <= '0'; - r.Mem_DataVld <= '0'; - r.RemWen <= '0'; - r.State <= Idle_s; - r.FirstDma <= (others => '1'); - r.Mem_CmdVld <= '0'; - r.HasLast <= (others => '0'); - end if; - end if; - end process; - - -------------------------------------------- - -- Component Instantiation - -------------------------------------------- - -- *** Command FIFO *** - CmdFifo_InData <= DaqSm2DaqDma_Cmd_ToStdlv(DaqSm_Cmd); - i_fifocmd : entity work.psi_common_sync_fifo - generic map ( - Width_g => DaqSm2DaqDma_Cmd_Size_c, - Depth_g => 2**StreamBits_c, - RamStyle_g => "distributed", - RamBehavior_g => "RBW" - ) - port map ( - Clk => Clk, - Rst => Rst, - InData => CmdFifo_InData, - InVld => DaqSm_Cmd_Vld, - OutData => CmdFifo_OutData, - OutVld => CmdFifo_Vld, - OutRdy => r.CmdFifo_Rdy, - OutLevel => CmdFifo_Level_Dbg - ); - CmdFifo_Cmd <= DaqSm2DaqDma_Cmd_FromStdlv(CmdFifo_OutData); - - -- *** Response FIFO *** - -- Ready not required for system reasons: There is never more commands open than streams. - RspFifo_InData <= DaqDma2DaqSm_Resp_ToStdlv(r.RspFifo_Data); - i_fiforsp : entity work.psi_common_sync_fifo - generic map ( - Width_g => DaqDma2DaqSm_Resp_Size_c, - Depth_g => 2**StreamBits_c, - RamStyle_g => "distributed", - RamBehavior_g => "RBW" - ) - port map ( - Clk => Clk, - Rst => Rst, - InData => RspFifo_InData, - InVld => r.RspFifo_Vld, - OutData => RspFifo_OutData, - OutVld => DaqSm_Resp_Vld, - OutRdy => DaqSm_Resp_Rdy, - OutLevel => RspFifo_Level_Dbg - ); - DaqSm_Resp <= DaqDme2DaqSm_Resp_FromStdlv(RspFifo_OutData); - - -- *** Buffer FIFO *** - -- This FIFO allows buffering data for the time the state machine requires to react on a "memory interface not ready for more data" situation. - -- As a result, the backpressure must not handled in the complete pipeline of this block. - -- Rdy is not required since the data pipeline is stopped based on the almost full flag - i_fifodata : entity work.psi_common_sync_fifo - generic map ( - Width_g => 64, - Depth_g => BufferFifoDepth_c, - AlmFullOn_g => true, - AlmFullLevel_g => BufferFifoDepth_c/2, - RamStyle_g => "distributed", - RamBehavior_g => "RBW" - ) - port map ( - Clk => Clk, - Rst => Rst, - InData => r.DataSft(63 downto 0), - InVld => r.Mem_DataVld, - OutData => Mem_DatData, - OutVld => Mem_DatVld, - OutRdy => Mem_DatRdy, - OutLevel => DatFifo_Level_Dbg, - AlmFull => DatFifo_AlmFull - ); - - -- *** Remaining Data RAM *** - i_remram : entity work.psi_common_sdp_ram - generic map ( - Depth_g => 2**StreamBits_c, - Width_g => 1+1+3+64, - IsAsync_g => false, - RamStyle_g => "distributed", - Behavior_g => "RBW" - ) - port map ( - Clk => Clk, - RdClk => Rst, - WrAddr => r.StreamStdlv, - Wr => r.RemWen, - WrData(68) => r.RemWrLast, - WrData(67) => r.RemWrTrigger, - WrData(66 downto 64) => r.RemWrBytes, - WrData(63 downto 0) => r.RemData, - RdAddr => r.StreamStdlv, - RdDAta(68) => Rem_Last, - RdData(67) => Rem_Trigger, - RdData(66 downto 64) => Rem_RdBytes, - RdData(63 downto 0) => Rem_Data - ); - -end; + -------------------------------------------- + -- Combinatorial Process + -------------------------------------------- + p_comb : process(r, DaqSm_Cmd, DaqSm_Cmd_Vld, DaqSm_Resp_Rdy, Inp_Vld, Inp_Data, Mem_CmdRdy, Mem_DatRdy, CmdFifo_Cmd, CmdFifo_Vld, DatFifo_AlmFull, Rem_RdBytes, Rem_Data, Rem_Trigger, Rem_Last) + variable v : two_process_r; + variable ThisByte_v : std_logic_vector(7 downto 0); + variable RemSft_v : integer range 0 to 7; + begin + -- *** Hold variables stable *** + v := r; + -- *** Default Values *** + v.CmdFifo_Rdy := '0'; + Inp_Rdy <= (others => '0'); + v.Mem_DataVld := '0'; + v.RspFifo_Vld := '0'; + v.RemWen := '0'; + v.UpdateLast := '0'; + -- *** State Machine *** + case r.State is + when Idle_s => + v.HndlMaxSize := unsigned(CmdFifo_Cmd.MaxSize); + v.HndlStream := CmdFifo_Cmd.Stream; + v.StreamStdlv := std_logic_vector(to_unsigned(CmdFifo_Cmd.Stream, v.StreamStdlv'length)); + v.HndlAddress := CmdFifo_Cmd.Address; + v.Trigger := '0'; + v.Last := '0'; + if CmdFifo_Vld = '1' then + v.CmdFifo_Rdy := '1'; + v.State := RemRd1_s; + end if; + when RemRd1_s => + v.State := RemRd2_s; + + when RemRd2_s => + -- Prevent RAM data from before reset to have an influence + v.WrBytes := (others => '0'); + if r.FirstDma(r.HndlStream) = '1' then + v.HndlSft := (others => '0'); + v.RdBytes := (others => '0'); + v.DataSft := (others => '0'); + v.RemTrigger := '0'; + v.RemLast := '0'; + else + v.HndlSft := unsigned(Rem_RdBytes); + v.DataSft(127 downto 64) := Rem_Data; + v.RdBytes := resize(unsigned(Rem_RdBytes), v.RdBytes'length); + v.RemTrigger := Rem_Trigger; + v.RemLast := Rem_Last; + end if; + v.FirstDma(r.HndlStream) := '0'; + v.State := Transfer_s; + v.NextDone := '0'; + v.DataWritten := '0'; + + when Transfer_s => + -- TF done because of maximum size reached + if r.WrBytes >= r.HndlMaxSize then + v.State := Done_s; + elsif DatFifo_AlmFull = '0' then + if r.NextDone = '0' and Inp_Vld(r.HndlStream) = '1' and r.RemLast = '0' then + v.RdBytes := r.RdBytes + unsigned(Inp_Data(r.HndlStream).Bytes); + end if; + v.WrBytes := r.WrBytes + 8; + -- Combinatorial handling because of fall-through interface at input + if r.RdBytes < r.HndlMaxSize and r.NextDone = '0' and r.RemLast = '0' then + Inp_Rdy(r.HndlStream) <= '1'; + end if; + -- Handling of last frame + if (Inp_Data(r.HndlStream).Last = '1') or (r.RemLast = '1') then + -- Do one more word if not all data can be transferred in the current beat (NextDone = 1) + if (r.HndlSft + unsigned(Inp_Data(r.HndlStream).Bytes) <= 8) or (r.RemLast = '1') then + v.State := Done_s; + else + v.NextDone := '1'; + end if; + if (Inp_Data(r.HndlStream).IsTrig = '1') or (r.RemTrigger = '1') then + v.Trigger := '1'; + end if; + v.Last := '1'; + end if; + if r.NextDone = '1' or Inp_Vld(r.HndlStream) = '0' then + v.State := Done_s; + end if; + -- Data handling + v.DataSft(63 downto 0) := r.DataSft(127 downto 64); + v.DataSft(8 * to_integer(r.HndlSft) + 63 downto 8 * to_integer(r.HndlSft)) := Inp_Data(r.HndlStream).Data; + if Inp_Vld(r.HndlStream) = '1' or r.HndlSft /= 0 then + v.Mem_DataVld := '1'; + v.DataWritten := '1'; + end if; + end if; + + when Done_s => + RemSft_v := to_integer(resize(r.HndlMaxSize, 3)); + v.RemWrTrigger := '0'; + v.RemWrLast := '0'; + if r.HndlMaxSize < r.RdBytes then + v.RemWrBytes := std_logic_vector(resize(r.RdBytes - r.HndlMaxSize, v.RemWrBytes'length)); + v.RdBytes := r.HndlMaxSize; + v.RemWrTrigger := r.Trigger; + v.RemWrLast := r.Last; + v.HasLast(r.HndlStream) := r.Last; + else + v.RemWrBytes := (others => '0'); + v.HasLast(r.HndlStream) := '0'; + end if; + v.RemData := v.DataSft(8 * RemSft_v + 63 downto 8 * RemSft_v); + v.State := Cmd_s; + if r.DataWritten = '1' then + v.Mem_CmdVld := '1'; + end if; + v.RemWen := '1'; + + when Cmd_s => + if Mem_CmdRdy = '1' or r.Mem_CmdVld = '0' then + v.State := Idle_s; + v.Mem_CmdVld := '0'; + v.RspFifo_Vld := '1'; + v.RspFifo_Data.Size := std_logic_vector(r.RdBytes); + -- Only mark as trigger if all samples are completely written to memory (no remaining samples in REM RAM) + if (unsigned(r.RemWrBytes) = 0) and (r.Trigger = '1') then + v.RspFifo_Data.Trigger := '1'; + else + v.RspFifo_Data.Trigger := '0'; + end if; + v.RspFifo_Data.Stream := r.HndlStream; + end if; + when others => null; + end case; + + -- *** Assign to signal *** + r_next <= v; + + end process; + + -- *** Registered Outputs *** + Mem_CmdAddr <= r.HndlAddress; + Mem_CmdSize(r.RdBytes'range) <= std_logic_vector(r.RdBytes); + Mem_CmdSize(Mem_CmdSize'high downto r.RdBytes'high + 1) <= (others => '0'); + Mem_CmdVld <= r.Mem_CmdVld; + DaqSm_HasLast <= r.HasLast; + + -------------------------------------------- + -- Sequential Process + -------------------------------------------- + p_seq : process(Clk) + begin + if rising_edge(Clk) then + r <= r_next; + if Rst = '1' then + r.CmdFifo_Rdy <= '0'; + r.RspFifo_Vld <= '0'; + r.Mem_DataVld <= '0'; + r.RemWen <= '0'; + r.State <= Idle_s; + r.FirstDma <= (others => '1'); + r.Mem_CmdVld <= '0'; + r.HasLast <= (others => '0'); + end if; + end if; + end process; + + -------------------------------------------- + -- Component Instantiation + -------------------------------------------- + -- *** Command FIFO *** + CmdFifo_InData <= DaqSm2DaqDma_Cmd_ToStdlv(DaqSm_Cmd); + i_fifocmd : entity work.psi_common_sync_fifo + generic map( + width_g => DaqSm2DaqDma_Cmd_Size_c, + depth_g => 2**StreamBits_c, + ram_style_g => "distributed", + ram_behavior_g => "RBW" + ) + port map( + clk_i => Clk, + rst_i => Rst, + dat_i => CmdFifo_InData, + vld_i => DaqSm_Cmd_Vld, + dat_o => CmdFifo_OutData, + vld_o => CmdFifo_Vld, + rdy_i => r.CmdFifo_Rdy, + out_level_o => CmdFifo_Level_Dbg + ); + CmdFifo_Cmd <= DaqSm2DaqDma_Cmd_FromStdlv(CmdFifo_OutData); + + -- *** Response FIFO *** + -- Ready not required for system reasons: There is never more commands open than streams. + RspFifo_InData <= DaqDma2DaqSm_Resp_ToStdlv(r.RspFifo_Data); + i_fiforsp : entity work.psi_common_sync_fifo + generic map( + width_g => DaqDma2DaqSm_Resp_Size_c, + depth_g => 2**StreamBits_c, + ram_style_g => "distributed", + ram_behavior_g => "RBW" + ) + port map( + clk_i => Clk, + rst_i => Rst, + dat_i => RspFifo_InData, + vld_i => r.RspFifo_Vld, + dat_o => RspFifo_OutData, + vld_o => DaqSm_Resp_Vld, + rdy_i => DaqSm_Resp_Rdy, + out_level_o => RspFifo_Level_Dbg + ); + DaqSm_Resp <= DaqDme2DaqSm_Resp_FromStdlv(RspFifo_OutData); + + -- *** Buffer FIFO *** + -- This FIFO allows buffering data for the time the state machine requires to react on a "memory interface not ready for more data" situation. + -- As a result, the backpressure must not handled in the complete pipeline of this block. + -- Rdy is not required since the data pipeline is stopped based on the almost full flag + i_fifodata : entity work.psi_common_sync_fifo + generic map( + width_g => 64, + depth_g => BufferFifoDepth_c, + alm_full_on_g => true, + alm_full_level_g => BufferFifoDepth_c / 2, + ram_style_g => "distributed", + ram_behavior_g => "RBW" + ) + port map( + clk_i => Clk, + rst_i => Rst, + dat_i => r.DataSft(63 downto 0), + vld_i => r.Mem_DataVld, + dat_o => Mem_DatData, + vld_o => Mem_DatVld, + rdy_i => Mem_DatRdy, + out_level_o => DatFifo_Level_Dbg, + alm_full_o => DatFifo_AlmFull + ); + + -- *** Remaining Data RAM *** + i_remram : entity work.psi_common_sdp_ram + generic map( + depth_g => 2**StreamBits_c, + width_g => 1 + 1 + 3 + 64, + is_async_g => false, + ram_style_g => "distributed", + ram_behavior_g => "RBW" + ) + port map( + wr_clk_i => Clk, + rd_clk_i => Rst, + wr_addr_i => r.StreamStdlv, + wr_i => r.RemWen, + wr_dat_i(68) => r.RemWrLast, + wr_dat_i(67) => r.RemWrTrigger, + wr_dat_i(66 downto 64) => r.RemWrBytes, + wr_dat_i(63 downto 0) => r.RemData, + rd_addr_i => r.StreamStdlv, + rd_dat_o(68) => Rem_Last, + rd_dat_o(67) => Rem_Trigger, + rd_dat_o(66 downto 64) => Rem_RdBytes, + rd_dat_o(63 downto 0) => Rem_Data + ); + +end; diff --git a/hdl/psi_ms_daq_daq_sm.vhd b/hdl/psi_ms_daq_daq_sm.vhd index 68be9f7..fbc493e 100644 --- a/hdl/psi_ms_daq_daq_sm.vhd +++ b/hdl/psi_ms_daq_daq_sm.vhd @@ -13,14 +13,14 @@ -- Libraries ------------------------------------------------------------------------------ library ieee; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; - +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + library work; - use work.psi_common_math_pkg.all; - use work.psi_common_logic_pkg.all; - use work.psi_common_array_pkg.all; - use work.psi_ms_daq_pkg.all; +use work.psi_common_math_pkg.all; +use work.psi_common_logic_pkg.all; +use work.psi_common_array_pkg.all; +use work.psi_ms_daq_pkg.all; ------------------------------------------------------------------------------ -- Entity Declaration @@ -29,695 +29,684 @@ library work; -- $$ processes=control,dma_cmd,dma_resp,ctx $$ -- $$ tbpkg=work.psi_tb_txt_util,work.psi_tb_compare_pkg $$ entity psi_ms_daq_daq_sm is - generic ( - Streams_g : positive range 1 to 32 := 4; -- $$ constant=4 $$ - StreamPrio_g : t_ainteger := (1, 2, 3, 1); -- $$ constant=(1, 2, 3, 1) $$ - StreamWidth_g : t_ainteger := (8, 16, 32, 64); -- $$ constant=(8, 16, 32, 64) $$ - Windows_g : positive range 1 to 32 := 4; -- $$ constant=4 $$ - MinBurstSize_g : positive := 512; -- $$ constant=512 $$ - MaxBurstSize_g : positive := 512 -- $$ constant=512 $$ - ); - port ( - -- Control signals - Clk : in std_logic; -- $$ type=clk; freq=200e6; proc=control,dma_cmd,dma_resp,ctx $$ - Rst : in std_logic; -- $$ proc=control $$ - GlbEna : in std_logic; -- $$ proc=control; lowactive=true $$ - StrEna : in std_logic_vector(Streams_g-1 downto 0); -- $$ proc=control; lowactive=true $$ - StrIrq : out std_logic_vector(Streams_g-1 downto 0); -- $$ proc=control,dma_resp,dma_cmd; $$ - StrLastWin : out WinType_a(Streams_g-1 downto 0); - - -- Input logic Connections - Inp_HasLast : in std_logic_vector(Streams_g-1 downto 0); -- $$ proc=control $$ - Inp_Level : in t_aslv16(Streams_g-1 downto 0); -- $$ proc=control $$ - Ts_Vld : in std_logic_vector(Streams_g-1 downto 0); -- $$ proc=control $$ - Ts_Rdy : out std_logic_vector(Streams_g-1 downto 0); -- $$ proc=control $$ - Ts_Data : in t_aslv64(Streams_g-1 downto 0); -- $$ proc=control $$ - - -- Dma Connections - Dma_Cmd : out DaqSm2DaqDma_Cmd_t; -- $$ proc=dma_cmd,control $$ - Dma_Cmd_Vld : out std_logic; -- $$ proc=dma_cmd,control $$ - Dma_Resp : in DaqDma2DaqSm_Resp_t; -- $$ proc=dma_resp $$ - Dma_Resp_Vld : in std_logic; -- $$ proc=dma_resp $$ - Dma_Resp_Rdy : out std_logic; -- $$ proc=dma_resp $$ - - -- Memory Controller - TfDone : in std_logic; -- $$ proc=dma_resp $$ - - -- Context RAM connections - CtxStr_Cmd : out ToCtxStr_t; -- $$ proc=ctx $$ - CtxStr_Resp : in FromCtx_t; -- $$ proc=ctx $$ - CtxWin_Cmd : out ToCtxWin_t; -- $$ proc=ctx $$ - CtxWin_Resp : in FromCtx_t -- $$ proc=ctx $$ - ); + generic( + Streams_g : positive range 1 to 32 := 4; -- $$ constant=4 $$ + StreamPrio_g : t_ainteger := (1, 2, 3, 1); -- $$ constant=(1, 2, 3, 1) $$ + StreamWidth_g : t_ainteger := (8, 16, 32, 64); -- $$ constant=(8, 16, 32, 64) $$ + Windows_g : positive range 1 to 32 := 4; -- $$ constant=4 $$ + MinBurstSize_g : positive := 512; -- $$ constant=512 $$ + MaxBurstSize_g : positive := 512 -- $$ constant=512 $$ + ); + port( + -- Control signals + Clk : in std_logic; -- $$ type=clk; freq=200e6; proc=control,dma_cmd,dma_resp,ctx $$ + Rst : in std_logic; -- $$ proc=control $$ + GlbEna : in std_logic; -- $$ proc=control; lowactive=true $$ + StrEna : in std_logic_vector(Streams_g - 1 downto 0); -- $$ proc=control; lowactive=true $$ + StrIrq : out std_logic_vector(Streams_g - 1 downto 0); -- $$ proc=control,dma_resp,dma_cmd; $$ + StrLastWin : out WinType_a(Streams_g - 1 downto 0); + -- Input logic Connections + Inp_HasLast : in std_logic_vector(Streams_g - 1 downto 0); -- $$ proc=control $$ + Inp_Level : in t_aslv16(Streams_g - 1 downto 0); -- $$ proc=control $$ + Ts_Vld : in std_logic_vector(Streams_g - 1 downto 0); -- $$ proc=control $$ + Ts_Rdy : out std_logic_vector(Streams_g - 1 downto 0); -- $$ proc=control $$ + Ts_Data : in t_aslv64(Streams_g - 1 downto 0); -- $$ proc=control $$ + + -- Dma Connections + Dma_Cmd : out DaqSm2DaqDma_Cmd_t; -- $$ proc=dma_cmd,control $$ + Dma_Cmd_Vld : out std_logic; -- $$ proc=dma_cmd,control $$ + Dma_Resp : in DaqDma2DaqSm_Resp_t; -- $$ proc=dma_resp $$ + Dma_Resp_Vld : in std_logic; -- $$ proc=dma_resp $$ + Dma_Resp_Rdy : out std_logic; -- $$ proc=dma_resp $$ + + -- Memory Controller + TfDone : in std_logic; -- $$ proc=dma_resp $$ + + -- Context RAM connections + CtxStr_Cmd : out ToCtxStr_t; -- $$ proc=ctx $$ + CtxStr_Resp : in FromCtx_t; -- $$ proc=ctx $$ + CtxWin_Cmd : out ToCtxWin_t; -- $$ proc=ctx $$ + CtxWin_Resp : in FromCtx_t -- $$ proc=ctx $$ + ); end entity; - + ------------------------------------------------------------------------------ -- Architecture Declaration ------------------------------------------------------------------------------ architecture rtl of psi_ms_daq_daq_sm is - -- Number of bits to encode stream is at least 1 (otherwise the special case for one stream would require separate code). - -- .. The overhead generated by this is regarded as aceptable (better wasting a few LUTs than much development time) - constant StreamBits_c : integer := max(log2ceil(Streams_g), 1); + -- Number of bits to encode stream is at least 1 (otherwise the special case for one stream would require separate code). + -- .. The overhead generated by this is regarded as aceptable (better wasting a few LUTs than much development time) + constant StreamBits_c : integer := max(log2ceil(Streams_g), 1); - -- Function Definitions - function GetBitsOfStreamPrio( InputVector : std_logic_vector; - Prio : integer) - return std_logic_vector is - variable Result_v : std_logic_vector(count(StreamPrio_g, Prio)-1 downto 0) := (others => '0'); - variable OutIdx_v : integer := 0; - begin - for idx in InputVector'low to InputVector'high loop - if StreamPrio_g(idx) = Prio then - Result_v(OutIdx_v) := InputVector(idx); - OutIdx_v := OutIdx_v + 1; - end if; - end loop; - return Result_v; - end function; - - function GetStreamNrFromGrant( GrantVector : std_logic_vector; - Prio : integer) - return integer is - variable IdxCnt_v : integer := 0; - begin - for idx in StreamPrio_g'low to StreamPrio_g'high loop - if StreamPrio_g(idx) = Prio then - if GrantVector(IdxCnt_v) = '1' then - return idx; - end if; - IdxCnt_v := IdxCnt_v + 1; - end if; - end loop; - return 0; - end function; - - -- Vivado Workarounds (Synthesis fail) - subtype Log2Bytes_t is integer range 0 to log2(MaxStreamWidth_c/8); - type Log2Bytes_a is array (natural range <>) of Log2Bytes_t; - function CalcLog2Bytes return Log2Bytes_a is - variable arr : Log2Bytes_a(0 to Streams_g-1); - begin - for i in 0 to Streams_g-1 loop - arr(i) := log2(StreamWidth_g(i)/8); - end loop; - return arr; - end function; - constant Log2StrBytes_c : Log2Bytes_a(0 to Streams_g-1) := CalcLog2Bytes; - - -- Component Connection Signals - signal AvailPrio1 : std_logic_vector(count(StreamPrio_g, 1)-1 downto 0); - signal AvailPrio2 : std_logic_vector(count(StreamPrio_g, 2)-1 downto 0); - signal AvailPrio3 : std_logic_vector(count(StreamPrio_g, 3)-1 downto 0); - signal GrantPrio1 : std_logic_vector(AvailPrio1'range); - signal GrantPrio2 : std_logic_vector(AvailPrio2'range); - signal GrantPrio3 : std_logic_vector(AvailPrio3'range); - signal GrantVld : std_logic_vector(3 downto 1); - signal IrqFifoAlmFull : std_logic; - signal IrqFifoEmpty : std_logic; - signal IrqFifoGenIrq : std_logic; - signal IrqFifoStream : std_logic_vector(StreamBits_c-1 downto 0); - signal IrqLastWinNr : std_logic_vector(log2ceil(Windows_g)-1 downto 0); - signal IrqFifoIn : std_logic_vector(StreamBits_c+log2ceil(Windows_g) downto 0); - signal IrqFifoOut : std_logic_vector(StreamBits_c+log2ceil(Windows_g) downto 0); - - -- Types - type State_t is (Idle_s, CheckPrio1_s, CheckPrio2_s, CheckPrio3_s, CheckResp_s, TlastCheck_s, ReadCtxStr_s, First_s, ReadCtxWin_s, CalcAccess0_s, CalcAccess1_s, ProcResp0_s, NextWin_s, WriteCtx_s); + -- Function Definitions + function GetBitsOfStreamPrio(InputVector : std_logic_vector; + Prio : integer) + return std_logic_vector is + variable Result_v : std_logic_vector(count(StreamPrio_g, Prio) - 1 downto 0) := (others => '0'); + variable OutIdx_v : integer := 0; + begin + for idx in InputVector'low to InputVector'high loop + if StreamPrio_g(idx) = Prio then + Result_v(OutIdx_v) := InputVector(idx); + OutIdx_v := OutIdx_v + 1; + end if; + end loop; + return Result_v; + end function; + + function GetStreamNrFromGrant(GrantVector : std_logic_vector; + Prio : integer) + return integer is + variable IdxCnt_v : integer := 0; + begin + for idx in StreamPrio_g'low to StreamPrio_g'high loop + if StreamPrio_g(idx) = Prio then + if GrantVector(IdxCnt_v) = '1' then + return idx; + end if; + IdxCnt_v := IdxCnt_v + 1; + end if; + end loop; + return 0; + end function; + + -- Vivado Workarounds (Synthesis fail) + subtype Log2Bytes_t is integer range 0 to log2(MaxStreamWidth_c / 8); + type Log2Bytes_a is array (natural range <>) of Log2Bytes_t; + function CalcLog2Bytes return Log2Bytes_a is + variable arr : Log2Bytes_a(0 to Streams_g - 1); + begin + for i in 0 to Streams_g - 1 loop + arr(i) := log2(StreamWidth_g(i) / 8); + end loop; + return arr; + end function; + constant Log2StrBytes_c : Log2Bytes_a(0 to Streams_g - 1) := CalcLog2Bytes; + + -- Component Connection Signals + signal AvailPrio1 : std_logic_vector(count(StreamPrio_g, 1) - 1 downto 0); + signal AvailPrio2 : std_logic_vector(count(StreamPrio_g, 2) - 1 downto 0); + signal AvailPrio3 : std_logic_vector(count(StreamPrio_g, 3) - 1 downto 0); + signal GrantPrio1 : std_logic_vector(AvailPrio1'range); + signal GrantPrio2 : std_logic_vector(AvailPrio2'range); + signal GrantPrio3 : std_logic_vector(AvailPrio3'range); + signal GrantVld : std_logic_vector(3 downto 1); + signal IrqFifoAlmFull : std_logic; + signal IrqFifoEmpty : std_logic; + signal IrqFifoGenIrq : std_logic; + signal IrqFifoStream : std_logic_vector(StreamBits_c - 1 downto 0); + signal IrqLastWinNr : std_logic_vector(log2ceil(Windows_g) - 1 downto 0); + signal IrqFifoIn : std_logic_vector(StreamBits_c + log2ceil(Windows_g) downto 0); + signal IrqFifoOut : std_logic_vector(StreamBits_c + log2ceil(Windows_g) downto 0); + + -- Types + type State_t is (Idle_s, CheckPrio1_s, CheckPrio2_s, CheckPrio3_s, CheckResp_s, TlastCheck_s, ReadCtxStr_s, First_s, ReadCtxWin_s, CalcAccess0_s, CalcAccess1_s, ProcResp0_s, NextWin_s, WriteCtx_s); + + -- Two process method + type two_process_r is record + GlbEnaReg : std_logic; + StrEnaReg : std_logic_vector(Streams_g - 1 downto 0); + InpDataAvail : std_logic_vector(Streams_g - 1 downto 0); + DataAvailArbIn : std_logic_vector(Streams_g - 1 downto 0); + DataPending : std_logic_vector(Streams_g - 1 downto 0); + OpenCommand : std_logic_vector(Streams_g - 1 downto 0); + WinProtected : std_logic_vector(Streams_g - 1 downto 0); -- Set if the current window is not yet available + NewBuffer : std_logic_vector(Streams_g - 1 downto 0); + FirstAfterEna : std_logic_vector(Streams_g - 1 downto 0); + FirstOngoing : std_logic_vector(Streams_g - 1 downto 0); + GrantVldReg : std_logic_vector(3 downto 1); + State : State_t; + GrantPrio1Reg : std_logic_vector(GrantPrio1'range); + GrantPrio2Reg : std_logic_vector(GrantPrio2'range); + GrantPrio3Reg : std_logic_vector(GrantPrio3'range); + HasLastReg : std_logic_vector(Inp_HasLast'range); + HndlAfterCtxt : State_t; + HndlStream : integer range 0 to Streams_g; + HndlCtxCnt : integer range 0 to 4; + HndlRingbuf : std_logic; + HndlOverwrite : std_logic; + HndlWincnt : std_logic_vector(log2ceil(Windows_g) - 1 downto 0); + HndlWincur : std_logic_vector(log2ceil(Windows_g) - 1 downto 0); + HndlLastWinNr : std_logic_vector(log2ceil(Windows_g) - 1 downto 0); + HndlBufstart : std_logic_vector(31 downto 0); + HndlWinSize : std_logic_vector(31 downto 0); + HndlPtr0 : std_logic_vector(31 downto 0); + HndlPtr1 : std_logic_vector(31 downto 0); + HndlPtr2 : std_logic_vector(31 downto 0); + HndlLevel : std_logic_vector(15 downto 0); + Hndl4kMax : std_logic_vector(12 downto 0); + HndlWinMax : std_logic_vector(31 downto 0); + HndlWinEnd : std_logic_vector(31 downto 0); + HndlWinBytes : std_logic_vector(32 downto 0); + HndlWinLast : std_logic_vector(31 downto 0); + HndlTs : std_logic_vector(63 downto 0); + TfDoneCnt : std_logic_vector(StreamBits_c - 1 downto 0); + TfDoneReg : std_logic; + HndlWinDone : std_logic; + CtxStr_Cmd : ToCtxStr_t; + CtxWin_Cmd : ToCtxWin_t; + Dma_Cmd : DaqSm2DaqDma_Cmd_t; + Dma_Cmd_Vld : std_logic; + Dma_Resp_Rdy : std_logic; + Ts_Rdy : std_logic_vector(Streams_g - 1 downto 0); + ArbDelCnt : integer range 0 to 4; + IrqFifoWrite : std_logic; + IrqFifoRead : std_logic; + StrIrq : std_logic_vector(Streams_g - 1 downto 0); + StrLastWin : WinType_a(Streams_g - 1 downto 0); + EndByTrig : std_logic; + end record; + signal r, r_next : two_process_r; + + -- USED FOR DEBUGGING ONLY! + -- attribute mark_debug : string; + -- attribute mark_debug of r : signal is "true"; + + -- Todo: mask streams that already have a transfer open at the input - -- Two process method - type two_process_r is record - GlbEnaReg : std_logic; - StrEnaReg : std_logic_vector(Streams_g-1 downto 0); - InpDataAvail : std_logic_vector(Streams_g-1 downto 0); - DataAvailArbIn : std_logic_vector(Streams_g-1 downto 0); - DataPending : std_logic_vector(Streams_g-1 downto 0); - OpenCommand : std_logic_vector(Streams_g-1 downto 0); - WinProtected : std_logic_vector(Streams_g-1 downto 0); -- Set if the current window is not yet available - NewBuffer : std_logic_vector(Streams_g-1 downto 0); - FirstAfterEna : std_logic_vector(Streams_g-1 downto 0); - FirstOngoing : std_logic_vector(Streams_g-1 downto 0); - GrantVldReg : std_logic_vector(3 downto 1); - State : State_t; - GrantPrio1Reg : std_logic_vector(GrantPrio1'range); - GrantPrio2Reg : std_logic_vector(GrantPrio2'range); - GrantPrio3Reg : std_logic_vector(GrantPrio3'range); - HasLastReg : std_logic_vector(Inp_HasLast'range); - HndlAfterCtxt : State_t; - HndlStream : integer range 0 to Streams_g; - HndlCtxCnt : integer range 0 to 4; - HndlRingbuf : std_logic; - HndlOverwrite : std_logic; - HndlWincnt : std_logic_vector(log2ceil(Windows_g)-1 downto 0); - HndlWincur : std_logic_vector(log2ceil(Windows_g)-1 downto 0); - HndlLastWinNr : std_logic_vector(log2ceil(Windows_g)-1 downto 0); - HndlBufstart : std_logic_vector(31 downto 0); - HndlWinSize : std_logic_vector(31 downto 0); - HndlPtr0 : std_logic_vector(31 downto 0); - HndlPtr1 : std_logic_vector(31 downto 0); - HndlPtr2 : std_logic_vector(31 downto 0); - HndlLevel : std_logic_vector(15 downto 0); - Hndl4kMax : std_logic_vector(12 downto 0); - HndlWinMax : std_logic_vector(31 downto 0); - HndlWinEnd : std_logic_vector(31 downto 0); - HndlWinBytes : std_logic_vector(32 downto 0); - HndlWinLast : std_logic_vector(31 downto 0); - HndlTs : std_logic_vector(63 downto 0); - TfDoneCnt : std_logic_vector(StreamBits_c-1 downto 0); - TfDoneReg : std_logic; - HndlWinDone : std_logic; - CtxStr_Cmd : ToCtxStr_t; - CtxWin_Cmd : ToCtxWin_t; - Dma_Cmd : DaqSm2DaqDma_Cmd_t; - Dma_Cmd_Vld : std_logic; - Dma_Resp_Rdy : std_logic; - Ts_Rdy : std_logic_vector(Streams_g-1 downto 0); - ArbDelCnt : integer range 0 to 4; - IrqFifoWrite : std_logic; - IrqFifoRead : std_logic; - StrIrq : std_logic_vector(Streams_g-1 downto 0); - StrLastWin : WinType_a(Streams_g-1 downto 0); - EndByTrig : std_logic; - end record; - signal r, r_next : two_process_r; - - -- USED FOR DEBUGGING ONLY! - -- attribute mark_debug : string; - -- attribute mark_debug of r : signal is "true"; - - -- Todo: mask streams that already have a transfer open at the input - begin - -------------------------------------------- - -- Combinatorial Process - -------------------------------------------- - p_comb : process( r, Inp_HasLast, Inp_Level, Ts_Vld, Ts_Data, Dma_Resp, Dma_Resp_Vld, CtxStr_Resp, CtxWin_Resp, GlbEna, StrEna, TfDone, IrqFifoGenIrq, IrqFifoStream, IrqLastWinNr, - GrantVld, GrantPrio1, GrantPrio2, GrantPrio3, IrqFifoAlmFull, IrqFifoEmpty) - variable v : two_process_r; - begin - -- *** Hold variables stable *** - v := r; - - -- *** Default Values *** - v.CtxStr_Cmd.WenLo := '0'; - v.CtxStr_Cmd.WenHi := '0'; - v.CtxWin_Cmd.WenLo := '0'; - v.CtxWin_Cmd.WenHi := '0'; - v.CtxStr_Cmd.Rd := '0'; - v.CtxWin_Cmd.Rd := '0'; - v.Dma_Cmd_Vld := '0'; - v.Ts_Rdy := (others => '0'); - v.Dma_Resp_Rdy := '0'; - v.CtxWin_Cmd.WdatLo := (others => '0'); - v.CtxWin_Cmd.WdatHi := (others => '0'); - v.CtxStr_Cmd.WdatLo := (others => '0'); - v.CtxStr_Cmd.WdatHi := (others => '0'); - v.IrqFifoWrite := '0'; - v.IrqFifoRead := '0'; - v.StrIrq := (others => '0'); - - - -- *** Pure Pipelining (no functional registers) *** - v.GrantVldReg := GrantVld; - v.GrantPrio1Reg := GrantPrio1; - v.GrantPrio2Reg := GrantPrio2; - v.GrantPrio3Reg := GrantPrio3; - v.HasLastReg := Inp_HasLast; - v.StrEnaReg := StrEna; - v.GlbEnaReg := GlbEna; - v.TfDoneReg := TfDone; - - -- *** Check Availability of a full burst *** - for str in 0 to Streams_g-1 loop - if unsigned(Inp_Level(str)) >= MinBurstSize_g then - v.InpDataAvail(str) := r.StrEnaReg(str) and r.GlbEnaReg; - else - v.InpDataAvail(str) := '0'; - end if; - end loop; - v.DataAvailArbIn := r.InpDataAvail and (not r.OpenCommand) and (not r.WinProtected); -- Do not arbitrate new commands on streams that already have a command - v.DataPending := r.InpDataAvail and (not r.WinProtected); -- Do not prevent lower priority channels from access if the window of a higher priority stream is protected - - -- *** Select level of currently handled FIFO *** - v.HndlLevel := Inp_Level(r.HndlStream); - - -- *** State Machine *** - case r.State is - -- *** Idle state *** - when Idle_s => - v.HndlCtxCnt := 0; - v.HndlWinDone := '0'; - -- check if data to write is available (only if IRQ FIFO has space for the response for sure) - if IrqFifoAlmFull = '0' then - v.State := CheckPrio1_s; - v.HndlAfterCtxt := CalcAccess0_s; - end if; - -- Delay arbitration in simulation to allow TB to react - if r.ArbDelCnt /= 4 then - v.State := Idle_s; - v.ArbDelCnt := r.ArbDelCnt + 1; - else - v.ArbDelCnt := 0; - end if; - - -- *** Check for next stream to handle *** - when CheckPrio1_s => - -- Handle command if prio 1 data is available - if r.GrantVldReg(1) = '1' then - v.State := ReadCtxStr_s; - v.HndlStream := GetStreamNrFromGrant(r.GrantPrio1Reg, 1); - -- If data is still pending, check for responses to schedule next transfer - elsif (unsigned(GetBitsOfStreamPrio(r.DataPending, 1)) /= 0) and (count(StreamPrio_g, 1) /= 0) then -- the term after the AND is required because unsigned(null-range) is not guaranteed to be zero in Vivado - v.State := CheckResp_s; - -- Otherwise check lower priority streams - else - v.State := CheckPrio2_s; - end if; - - when CheckPrio2_s => - -- Handle command if prio 2 data is available - if r.GrantVldReg(2) = '1' then - v.State := ReadCtxStr_s; - v.HndlStream := GetStreamNrFromGrant(r.GrantPrio2Reg, 2); - -- If data is still pending, check for responses to schedule next transfer - elsif (unsigned(GetBitsOfStreamPrio(r.DataPending, 2)) /= 0) and (count(StreamPrio_g, 2) /= 0) then -- the term after the AND is required because unsigned(null-range) is not guaranteed to be zero in Vivado - v.State := CheckResp_s; - -- Otherwise check lower priority streams - else - v.State := CheckPrio3_s; - end if; + -------------------------------------------- + -- Combinatorial Process + -------------------------------------------- + p_comb : process(r, Inp_HasLast, Inp_Level, Ts_Vld, Ts_Data, Dma_Resp, Dma_Resp_Vld, CtxStr_Resp, CtxWin_Resp, GlbEna, StrEna, TfDone, IrqFifoGenIrq, IrqFifoStream, IrqLastWinNr, GrantVld, GrantPrio1, GrantPrio2, GrantPrio3, IrqFifoAlmFull, IrqFifoEmpty) + variable v : two_process_r; + begin + -- *** Hold variables stable *** + v := r; - when CheckPrio3_s => - -- Handle command if prio 2 data is available - if r.GrantVldReg(3) = '1' then - v.State := ReadCtxStr_s; - v.HndlStream := GetStreamNrFromGrant(r.GrantPrio3Reg, 3); - -- Otherwise check for frame ends - else - v.State := TlastCheck_s; - end if; - - when TlastCheck_s => - v.State := CheckResp_s; - v.WinProtected := (others => '0'); -- No bursts where available on any stream, so all of them were checked and we can retry whether SW emptied a window. - for idx in 0 to Streams_g-1 loop - if (r.HasLastReg(idx) = '1') and (r.OpenCommand(idx) = '0') and (r.WinProtected(idx) = '0') then - v.State := ReadCtxStr_s; - v.HndlStream := idx; - end if; - end loop; - - when CheckResp_s => - -- Handle response if one is pending (less important thandata transer, therefore at the end) - if Dma_Resp_Vld = '1' then - v.State := ReadCtxStr_s; - v.HndlAfterCtxt := ProcResp0_s; - v.HndlStream := Dma_Resp.Stream; - v.EndByTrig := Dma_Resp.Trigger; - else - v.State := Idle_s; - end if; - - -- *** Read Context Memory *** - -- Read information from stream memory - when ReadCtxStr_s => - -- State handling - if r.HndlCtxCnt = 4 then - v.State := First_s; - v.HndlCtxCnt := 0; - else - v.HndlCtxCnt := r.HndlCtxCnt + 1; - end if; - - -- Command Assertions - v.CtxStr_Cmd.Stream := r.HndlStream; - case r.HndlCtxCnt is - when 0 => v.CtxStr_Cmd.Sel := CtxStr_Sel_Winend_c; - v.CtxStr_Cmd.Rd := '1'; - when 1 => v.CtxStr_Cmd.Sel := CtxStr_Sel_WinsizePtr_c; - v.CtxStr_Cmd.Rd := '1'; - when 2 => v.CtxStr_Cmd.Sel := CtxStr_Sel_ScfgBufstart_c; - v.CtxStr_Cmd.Rd := '1'; - when others => null; - end case; - - -- Response handling - case r.HndlCtxCnt is - when 2 => v.HndlWinEnd := CtxStr_Resp.RdatLo; - when 3 => v.HndlWinSize := CtxStr_Resp.RdatLo; - v.HndlPtr0 := CtxStr_Resp.RdatHi; - when 4 => v.HndlRingbuf := CtxStr_Resp.RdatLo(CtxStr_Sft_SCFG_RINGBUF_c); - v.HndlOverwrite := CtxStr_Resp.RdatLo(CtxStr_Sft_SCFG_OVERWRITE_c); - v.HndlWincnt := CtxStr_Resp.RdatLo(CtxStr_Sft_SCFG_WINCNT_c+v.HndlWincnt'high downto CtxStr_Sft_SCFG_WINCNT_c); - v.HndlWincur := CtxStr_Resp.RdatLo(CtxStr_Sft_SCFG_WINCUR_c+v.HndlWincur'high downto CtxStr_Sft_SCFG_WINCUR_c); - v.HndlBufstart := CtxStr_Resp.RdatHi; - v.Hndl4kMax := std_logic_vector(to_unsigned(4096, 13) - unsigned(r.HndlPtr0(11 downto 0))); -- Calculate maximum size within this 4k Region - v.HndlWinMax := std_logic_vector(unsigned(r.HndlWinEnd) - unsigned(r.HndlPtr0)); -- Calculate maximum size within this window - when others => null; - end case; - - -- Handle first access after enable - when First_s => - -- State handling - v.State := ReadCtxWin_s; - - -- Ensure that command and response are both handled as first or not - if r.HndlAfterCtxt = ProcResp0_s then -- responses - -- nothing to do - else -- command - v.FirstAfterEna(r.HndlStream) := '0'; - v.FirstOngoing(r.HndlStream) := r.FirstAfterEna(r.HndlStream); - end if; - - -- Update values for first access - if v.FirstOngoing(r.HndlStream) = '1' then - v.HndlWinEnd := std_logic_vector(unsigned(r.HndlBufstart) + unsigned(r.HndlWinSize)); - v.HndlPtr0 := r.HndlBufstart; - v.HndlWincur := (others => '0'); - v.Hndl4kMax := std_logic_vector(to_unsigned(4096, 13) - unsigned(r.HndlBufstart(11 downto 0))); - v.HndlWinMax := r.HndlWinSize; - end if; - - - -- Read information from window memory - when ReadCtxWin_s => - -- State handling - if r.HndlCtxCnt = 2 then - v.State := r.HndlAfterCtxt; -- Goto state depends on the context of the read procedure - else - v.HndlCtxCnt := r.HndlCtxCnt + 1; - end if; + -- *** Default Values *** + v.CtxStr_Cmd.WenLo := '0'; + v.CtxStr_Cmd.WenHi := '0'; + v.CtxWin_Cmd.WenLo := '0'; + v.CtxWin_Cmd.WenHi := '0'; + v.CtxStr_Cmd.Rd := '0'; + v.CtxWin_Cmd.Rd := '0'; + v.Dma_Cmd_Vld := '0'; + v.Ts_Rdy := (others => '0'); + v.Dma_Resp_Rdy := '0'; + v.CtxWin_Cmd.WdatLo := (others => '0'); + v.CtxWin_Cmd.WdatHi := (others => '0'); + v.CtxStr_Cmd.WdatLo := (others => '0'); + v.CtxStr_Cmd.WdatHi := (others => '0'); + v.IrqFifoWrite := '0'; + v.IrqFifoRead := '0'; + v.StrIrq := (others => '0'); - -- Command Assertions - v.CtxWin_Cmd.Stream := r.HndlStream; - v.CtxWin_Cmd.Window := to_integer(unsigned(r.HndlWincur)); - case r.HndlCtxCnt is - when 0 => v.CtxWin_Cmd.Sel := CtxWin_Sel_WincntWinlast_c; - v.CtxWin_Cmd.Rd := '1'; - when others => null; - end case; + -- *** Pure Pipelining (no functional registers) *** + v.GrantVldReg := GrantVld; + v.GrantPrio1Reg := GrantPrio1; + v.GrantPrio2Reg := GrantPrio2; + v.GrantPrio3Reg := GrantPrio3; + v.HasLastReg := Inp_HasLast; + v.StrEnaReg := StrEna; + v.GlbEnaReg := GlbEna; + v.TfDoneReg := TfDone; - -- Response handling - case r.HndlCtxCnt is - when 2 => - -- Workaround for Vivado (Range expression was resolved incorrectly) - for i in 0 to Streams_g-1 loop - if i = r.HndlStream then - v.HndlWinBytes := '0' & ShiftLeft(CtxWin_Resp.RdatLo, Log2StrBytes_c(i)); -- guard bit required for calculations - end if; - end loop; - when others => null; - end case; - - -- *** Calculate next access *** - when CalcAccess0_s => - -- Calculate Command - v.Dma_Cmd.Address := r.HndlPtr0; - v.Dma_Cmd.Stream := r.HndlStream; - v.Dma_Cmd.MaxSize := std_logic_vector(to_unsigned(MaxBurstSize_g*8, v.Dma_Cmd.MaxSize'length)); -- 8 bytes per 64-bit QWORD - -- State update (abort if window is not free) - if (r.HndlOverwrite = '0') and (unsigned(r.HndlWinBytes) /= 0) and (r.NewBuffer(r.HndlStream) = '1') then - v.State := Idle_s; - v.WinProtected(r.HndlStream) := '1'; - else - v.State := CalcAccess1_s; - v.NewBuffer(r.HndlStream) := '0'; - -- Mark stream as active - v.OpenCommand(r.HndlStream) := '1'; - end if; - - when CalcAccess1_s => - if unsigned(r.Hndl4kMax) < unsigned(r.HndlWinMax) then - if unsigned(r.Dma_Cmd.MaxSize) > unsigned(r.Hndl4kMax) then - v.Dma_Cmd.MaxSize := std_logic_vector(resize(unsigned(r.Hndl4kMax), v.dma_Cmd.MaxSize'length)); - end if; - else - if unsigned(r.Dma_Cmd.MaxSize) > unsigned(r.HndlWinMax) then - v.Dma_Cmd.MaxSize := std_logic_vector(resize(unsigned(r.HndlWinMax), v.dma_Cmd.MaxSize'length)); - end if; - end if; - v.Dma_Cmd_Vld := '1'; - v.State := Idle_s; + -- *** Check Availability of a full burst *** + for str in 0 to Streams_g - 1 loop + if unsigned(Inp_Level(str)) >= MinBurstSize_g then + v.InpDataAvail(str) := r.StrEnaReg(str) and r.GlbEnaReg; + else + v.InpDataAvail(str) := '0'; + end if; + end loop; + v.DataAvailArbIn := r.InpDataAvail and (not r.OpenCommand) and (not r.WinProtected); -- Do not arbitrate new commands on streams that already have a command + v.DataPending := r.InpDataAvail and (not r.WinProtected); -- Do not prevent lower priority channels from access if the window of a higher priority stream is protected - -- *** Handle response *** - -- Calculate next pointer - when ProcResp0_s => - v.OpenCommand(r.HndlStream) := '0'; - v.FirstOngoing(r.HndlStream) := '0'; - v.HndlPtr1 := std_logic_vector(unsigned(r.HndlPtr0) + unsigned(Dma_Resp.Size)); - v.State := NextWin_s; - -- Update window information step 1 - v.HndlWinBytes := std_logic_vector(unsigned(r.HndlWinBytes) + unsigned(Dma_Resp.Size)); + -- *** Select level of currently handled FIFO *** + v.HndlLevel := Inp_Level(r.HndlStream); - - -- Calculate next window to use - when NextWin_s => - -- Default Values - v.HndlPtr2 := r.HndlPtr1; - -- Do not wait for "transfer done" for zero size transfers (they are not passed to the memory interface) - if unsigned(Dma_Resp.Size) /= 0 then - v.IrqFifoWrite := '1'; - end if; - -- Switch to next window if required - v.HndlLastWinNr := r.HndlWincur; - if ((r.HndlPtr1 = r.HndlWinEnd) and (r.HndlRingbuf = '0')) or (Dma_Resp.Trigger = '1') then - v.HndlWinDone := '1'; - v.NewBuffer(r.HndlStream) := '1'; - if r.HndlWincur = r.HndlWincnt then - v.HndlWincur := (others => '0'); - v.HndlPtr2 := r.HndlBufstart; - v.HndlWinEnd := std_logic_vector(unsigned(r.HndlBufstart) + unsigned(r.HndlWinSize)); - else - v.HndlWincur := std_logic_vector(unsigned(r.HndlWincur) + 1); - v.HndlPtr2 := r.HndlWinEnd; - v.HndlWinEnd := std_logic_vector(unsigned(r.HndlWinEnd) + unsigned(r.HndlWinSize)); - end if; - end if; - -- wraparound for ringbuffer case - if (r.HndlPtr1 = r.HndlWinEnd) and (r.HndlRingbuf = '1') and (Dma_Resp.Trigger = '0') then - v.HndlPtr2 := std_logic_vector(unsigned(r.HndlPtr1) - unsigned(r.HndlWinSize)); - end if; - -- Update window information step 2 (limit to maximum value) - if unsigned(r.HndlWinBytes) > unsigned(r.HndlWinSize) then - v.HndlWinBytes := '0' & r.HndlWinSize; -- value has a guard bit - end if; - -- Store address of last sample in window - v.HndlWinLast := std_logic_vector(unsigned(r.HndlPtr1) - StreamWidth_g(r.HndlStream)/8); - -- Latch timestamp - if (Dma_Resp.Trigger = '1') and (Ts_Vld(r.HndlStream) = '1') then - v.Ts_Rdy(r.HndlStream) := '1'; - v.HndlTs := Ts_Data(r.HndlStream); - else - v.HndlTs := (others => '1'); - end if; - -- Write values - v.State := WriteCtx_s; - v.HndlCtxCnt := 0; - -- Response is processed - v.Dma_Resp_Rdy := '1'; - - -- Write Context Memory Content - when WriteCtx_s => - -- Update State - if r.HndlCtxCnt = 2 then - v.State := Idle_s; - else - v.HndlCtxCnt := r.HndlCtxCnt + 1; - end if; - -- Write Context Memory - v.CtxStr_Cmd.Stream := v.HndlStream; - case r.HndlCtxCnt is - when 0 => - -- Stream Memory - v.CtxStr_Cmd.Sel := CtxStr_Sel_ScfgBufstart_c; - v.CtxStr_Cmd.WenLo := '1'; - v.CtxStr_Cmd.WdatLo(CtxStr_Sft_SCFG_RINGBUF_c) := r.HndlRingbuf; - v.CtxStr_Cmd.WdatLo(CtxStr_Sft_SCFG_OVERWRITE_c) := r.HndlOverwrite; - v.CtxStr_Cmd.WdatLo(CtxStr_Sft_SCFG_WINCNT_c+v.HndlWincnt'high downto CtxStr_Sft_SCFG_WINCNT_c) := r.HndlWincnt; - v.CtxStr_Cmd.WdatLo(CtxStr_Sft_SCFG_WINCUR_c+v.HndlWincur'high downto CtxStr_Sft_SCFG_WINCUR_c) := r.HndlWincur; - -- Window Memory - v.CtxWin_Cmd.Sel := CtxWin_Sel_WincntWinlast_c; - v.CtxWin_Cmd.WenLo := '1'; - v.CtxWin_Cmd.WenHi := '1'; - v.CtxWin_Cmd.WdatLo := ShiftRight(r.HndlWinBytes(31 downto 0), Log2StrBytes_c(r.HndlStream)); -- cut-off guard bit and convert bytes to samples - v.CtxWin_Cmd.WdatLo(31) := r.EndByTrig; - v.CtxWin_Cmd.WdatHi := r.HndlWinLast; - when 1 => - -- Stream Memory - v.CtxStr_Cmd.Sel := CtxStr_Sel_WinsizePtr_c; - v.CtxStr_Cmd.WenHi := '1'; - v.CtxStr_Cmd.WdatHi := r.HndlPtr2; - -- Window Memory - if r.HndlWinDone = '1' then - v.CtxWin_Cmd.Sel := CtxWin_Sel_WinTs_c; - v.CtxWin_Cmd.WenHi := '1'; - v.CtxWin_Cmd.WenLo := '1'; - v.CtxWin_Cmd.WdatLo := r.HndlTs(31 downto 0); - v.CtxWin_Cmd.WdatHi := r.HndlTs(63 downto 32); - end if; - when 2 => - -- Stream Memory - v.CtxStr_Cmd.Sel := CtxStr_Sel_Winend_c; - v.CtxStr_Cmd.WenLo := '1'; - v.CtxStr_Cmd.WdatLo := r.HndlWinEnd; - when others => null; - end case; - end case; - - -- *** Handle Disabled Streams *** - for str in 0 to Streams_g-1 loop - if (r.GlbEnaReg = '0') or (r.StrEnaReg(str) = '0') then - v.FirstAfterEna(str) := '1'; - v.NewBuffer(str) := '1'; - end if; - end loop; - - -- *** IRQ Handling *** - -- Feedback from memory controller - if r.TfDoneReg = '1' then - v.TfDoneCnt := std_logic_vector(unsigned(r.TfDoneCnt) + 1); - end if; - - -- Process transfer completion - if (unsigned(r.TfDoneCnt) /= 0) and (IrqFifoEmpty = '0') then - v.IrqFifoRead := '1'; - v.TfDoneCnt := std_logic_vector(unsigned(v.TfDoneCnt) - 1); - -- Generate IRQ if required - if IrqFifoGenIrq = '1' then - v.StrIrq(to_integer(unsigned(IrqFifoStream))) := '1'; - v.StrLastWin(to_integer(unsigned(IrqFifoStream))) := std_logic_vector(resize(unsigned(IrqLastWinNr), 5)); - end if; - end if; - - -- *** Assign to signal *** - r_next <= v; - - end process; - - -- *** Registered Outputs *** - CtxStr_Cmd <= r.CtxStr_Cmd; - CtxWin_Cmd <= r.CtxWin_Cmd; - Dma_Cmd_Vld <= r.Dma_Cmd_Vld; - Dma_Cmd <= r.Dma_Cmd; - Dma_Resp_Rdy <= r.Dma_Resp_Rdy; - Ts_Rdy <= r.Ts_Rdy; - StrIrq <= r.StrIrq; - StrLastWin <= r.StrLastWin; - - -------------------------------------------- - -- Sequential Process - -------------------------------------------- - p_seq : process(Clk) - begin - if rising_edge(Clk) then - r <= r_next; - if Rst = '1' then - r.ArbDelCnt <= 0; - r.InpDataAvail <= (others => '0'); - r.DataAvailArbIn <= (others => '0'); - r.HndlStream <= 0; - r.State <= Idle_s; - r.CtxStr_Cmd.WenLo <= '0'; - r.CtxStr_Cmd.WenHi <= '0'; - r.CtxWin_Cmd.WenLo <= '0'; - r.CtxWin_Cmd.WenHi <= '0'; - r.Dma_Cmd_Vld <= '0'; - r.OpenCommand <= (others => '0'); - r.WinProtected <= (others => '0'); - r.Dma_Resp_Rdy <= '0'; - r.Ts_Rdy <= (others => '0'); - r.GlbEnaReg <= '0'; - r.FirstOngoing <= (others => '0'); - r.TfDoneCnt <= (others => '0'); - r.TfDoneReg <= '0'; - r.IrqFifoWrite <= '0'; - r.IrqFifoRead <= '0'; - r.StrIrq <= (others => '0'); - r.StrLastWin <= (others => (others => '0')); - end if; - end if; - end process; - - -------------------------------------------- - -- Component Instantiation - -------------------------------------------- - -- *** Round Robin Arbiter - Prio 1 *** - AvailPrio1 <= GetBitsOfStreamPrio(r.DataAvailArbIn, 1); - i_rrarb_1 : entity work.psi_common_arb_priority - generic map ( - Size_g => count(StreamPrio_g, 1) - ) - port map ( - Clk => Clk, - Rst => Rst, - Request => AvailPrio1, - Grant => GrantPrio1 - ); - GrantVld(1) <= '1' when (unsigned(GrantPrio1) /= 0) and (GrantPrio1'length > 0) else '0'; - - -- *** Round Robin Arbiter - Prio 2 *** - AvailPrio2 <= GetBitsOfStreamPrio(r.DataAvailArbIn, 2); - i_rrarb_2 : entity work.psi_common_arb_priority - generic map ( - Size_g => count(StreamPrio_g, 2) - ) - port map ( - Clk => Clk, - Rst => Rst, - Request => AvailPrio2, - Grant => GrantPrio2 - ); - GrantVld(2) <= '1' when (unsigned(GrantPrio2) /= 0) and (GrantPrio2'length > 0) else '0'; + -- *** State Machine *** + case r.State is + -- *** Idle state *** + when Idle_s => + v.HndlCtxCnt := 0; + v.HndlWinDone := '0'; + -- check if data to write is available (only if IRQ FIFO has space for the response for sure) + if IrqFifoAlmFull = '0' then + v.State := CheckPrio1_s; + v.HndlAfterCtxt := CalcAccess0_s; + end if; + -- Delay arbitration in simulation to allow TB to react + if r.ArbDelCnt /= 4 then + v.State := Idle_s; + v.ArbDelCnt := r.ArbDelCnt + 1; + else + v.ArbDelCnt := 0; + end if; - -- *** Round Robin Arbiter - Prio 3 *** - AvailPrio3 <= GetBitsOfStreamPrio(r.DataAvailArbIn, 3); - i_rrarb_3 : entity work.psi_common_arb_priority - generic map ( - Size_g => count(StreamPrio_g, 3) - ) - port map ( - Clk => Clk, - Rst => Rst, - Request => AvailPrio3, - Grant => GrantPrio3 - ); - GrantVld(3) <= '1' when (unsigned(GrantPrio3) /= 0) and (GrantPrio3'length > 0) else '0'; + -- *** Check for next stream to handle *** + when CheckPrio1_s => + -- Handle command if prio 1 data is available + if r.GrantVldReg(1) = '1' then + v.State := ReadCtxStr_s; + v.HndlStream := GetStreamNrFromGrant(r.GrantPrio1Reg, 1); + -- If data is still pending, check for responses to schedule next transfer + elsif (unsigned(GetBitsOfStreamPrio(r.DataPending, 1)) /= 0) and (count(StreamPrio_g, 1) /= 0) then -- the term after the AND is required because unsigned(null-range) is not guaranteed to be zero in Vivado + v.State := CheckResp_s; + -- Otherwise check lower priority streams + else + v.State := CheckPrio2_s; + end if; + when CheckPrio2_s => + -- Handle command if prio 2 data is available + if r.GrantVldReg(2) = '1' then + v.State := ReadCtxStr_s; + v.HndlStream := GetStreamNrFromGrant(r.GrantPrio2Reg, 2); + -- If data is still pending, check for responses to schedule next transfer + elsif (unsigned(GetBitsOfStreamPrio(r.DataPending, 2)) /= 0) and (count(StreamPrio_g, 2) /= 0) then -- the term after the AND is required because unsigned(null-range) is not guaranteed to be zero in Vivado + v.State := CheckResp_s; + -- Otherwise check lower priority streams + else + v.State := CheckPrio3_s; + end if; - -- *** IRQ Information FIFO *** - -- input assembly - IrqFifoIn(StreamBits_c-1 downto 0) <= std_logic_vector(to_unsigned(r.HndlStream, StreamBits_c)); - IrqFifoIn(StreamBits_c+log2ceil(Windows_g)-1 downto StreamBits_c) <= r.HndlLastWinNr; - IrqFifoIn(IrqFifoIn'high) <= r.HndlWinDone; - - -- Instantiation - i_irq_fifo : entity work.psi_common_sync_fifo - generic map ( - Width_g => StreamBits_c+log2ceil(Windows_g)+1, - Depth_g => 2**StreamBits_c*4, - AlmFullOn_g => true, - AlmFullLevel_g => Streams_g*3, - RamStyle_g => "distributed" - ) - port map ( - Clk => Clk, - Rst => Rst, - InData => IrqFifoIn, - InVld => r.IrqFifoWrite, - OutData => IrqFifoOut, - OutRdy => r.IrqFifoRead, - AlmFull => IrqFifoAlmFull, - Empty => IrqFifoEmpty - ); - - -- Output disassembly - IrqFifoStream <= IrqFifoOut(StreamBits_c-1 downto 0); - IrqLastWinNr <= IrqFifoOut(StreamBits_c+log2ceil(Windows_g)-1 downto StreamBits_c); - IrqFifoGenIrq <= IrqFifoOut(IrqFifoOut'high); - - -end; + when CheckPrio3_s => + -- Handle command if prio 2 data is available + if r.GrantVldReg(3) = '1' then + v.State := ReadCtxStr_s; + v.HndlStream := GetStreamNrFromGrant(r.GrantPrio3Reg, 3); + -- Otherwise check for frame ends + else + v.State := TlastCheck_s; + end if; + when TlastCheck_s => + v.State := CheckResp_s; + v.WinProtected := (others => '0'); -- No bursts where available on any stream, so all of them were checked and we can retry whether SW emptied a window. + for idx in 0 to Streams_g - 1 loop + if (r.HasLastReg(idx) = '1') and (r.OpenCommand(idx) = '0') and (r.WinProtected(idx) = '0') then + v.State := ReadCtxStr_s; + v.HndlStream := idx; + end if; + end loop; + when CheckResp_s => + -- Handle response if one is pending (less important thandata transer, therefore at the end) + if Dma_Resp_Vld = '1' then + v.State := ReadCtxStr_s; + v.HndlAfterCtxt := ProcResp0_s; + v.HndlStream := Dma_Resp.Stream; + v.EndByTrig := Dma_Resp.Trigger; + else + v.State := Idle_s; + end if; + -- *** Read Context Memory *** + -- Read information from stream memory + when ReadCtxStr_s => + -- State handling + if r.HndlCtxCnt = 4 then + v.State := First_s; + v.HndlCtxCnt := 0; + else + v.HndlCtxCnt := r.HndlCtxCnt + 1; + end if; + -- Command Assertions + v.CtxStr_Cmd.Stream := r.HndlStream; + case r.HndlCtxCnt is + when 0 => v.CtxStr_Cmd.Sel := CtxStr_Sel_Winend_c; + v.CtxStr_Cmd.Rd := '1'; + when 1 => v.CtxStr_Cmd.Sel := CtxStr_Sel_WinsizePtr_c; + v.CtxStr_Cmd.Rd := '1'; + when 2 => v.CtxStr_Cmd.Sel := CtxStr_Sel_ScfgBufstart_c; + v.CtxStr_Cmd.Rd := '1'; + when others => null; + end case; + + -- Response handling + case r.HndlCtxCnt is + when 2 => v.HndlWinEnd := CtxStr_Resp.RdatLo; + when 3 => v.HndlWinSize := CtxStr_Resp.RdatLo; + v.HndlPtr0 := CtxStr_Resp.RdatHi; + when 4 => v.HndlRingbuf := CtxStr_Resp.RdatLo(CtxStr_Sft_SCFG_RINGBUF_c); + v.HndlOverwrite := CtxStr_Resp.RdatLo(CtxStr_Sft_SCFG_OVERWRITE_c); + v.HndlWincnt := CtxStr_Resp.RdatLo(CtxStr_Sft_SCFG_WINCNT_c + v.HndlWincnt'high downto CtxStr_Sft_SCFG_WINCNT_c); + v.HndlWincur := CtxStr_Resp.RdatLo(CtxStr_Sft_SCFG_WINCUR_c + v.HndlWincur'high downto CtxStr_Sft_SCFG_WINCUR_c); + v.HndlBufstart := CtxStr_Resp.RdatHi; + v.Hndl4kMax := std_logic_vector(to_unsigned(4096, 13) - unsigned(r.HndlPtr0(11 downto 0))); -- Calculate maximum size within this 4k Region + v.HndlWinMax := std_logic_vector(unsigned(r.HndlWinEnd) - unsigned(r.HndlPtr0)); -- Calculate maximum size within this window + when others => null; + end case; + + -- Handle first access after enable + when First_s => + -- State handling + v.State := ReadCtxWin_s; + + -- Ensure that command and response are both handled as first or not + if r.HndlAfterCtxt = ProcResp0_s then -- responses + -- nothing to do + else -- command + v.FirstAfterEna(r.HndlStream) := '0'; + v.FirstOngoing(r.HndlStream) := r.FirstAfterEna(r.HndlStream); + end if; + + -- Update values for first access + if v.FirstOngoing(r.HndlStream) = '1' then + v.HndlWinEnd := std_logic_vector(unsigned(r.HndlBufstart) + unsigned(r.HndlWinSize)); + v.HndlPtr0 := r.HndlBufstart; + v.HndlWincur := (others => '0'); + v.Hndl4kMax := std_logic_vector(to_unsigned(4096, 13) - unsigned(r.HndlBufstart(11 downto 0))); + v.HndlWinMax := r.HndlWinSize; + end if; + + -- Read information from window memory + when ReadCtxWin_s => + -- State handling + if r.HndlCtxCnt = 2 then + v.State := r.HndlAfterCtxt; -- Goto state depends on the context of the read procedure + else + v.HndlCtxCnt := r.HndlCtxCnt + 1; + end if; + + -- Command Assertions + v.CtxWin_Cmd.Stream := r.HndlStream; + v.CtxWin_Cmd.Window := to_integer(unsigned(r.HndlWincur)); + case r.HndlCtxCnt is + when 0 => v.CtxWin_Cmd.Sel := CtxWin_Sel_WincntWinlast_c; + v.CtxWin_Cmd.Rd := '1'; + when others => null; + end case; + + -- Response handling + case r.HndlCtxCnt is + when 2 => + -- Workaround for Vivado (Range expression was resolved incorrectly) + for i in 0 to Streams_g - 1 loop + if i = r.HndlStream then + v.HndlWinBytes := '0' & shift_left(CtxWin_Resp.RdatLo, Log2StrBytes_c(i)); -- guard bit required for calculations + end if; + end loop; + when others => null; + end case; + + -- *** Calculate next access *** + when CalcAccess0_s => + -- Calculate Command + v.Dma_Cmd.Address := r.HndlPtr0; + v.Dma_Cmd.Stream := r.HndlStream; + v.Dma_Cmd.MaxSize := std_logic_vector(to_unsigned(MaxBurstSize_g * 8, v.Dma_Cmd.MaxSize'length)); -- 8 bytes per 64-bit QWORD + -- State update (abort if window is not free) + if (r.HndlOverwrite = '0') and (unsigned(r.HndlWinBytes) /= 0) and (r.NewBuffer(r.HndlStream) = '1') then + v.State := Idle_s; + v.WinProtected(r.HndlStream) := '1'; + else + v.State := CalcAccess1_s; + v.NewBuffer(r.HndlStream) := '0'; + -- Mark stream as active + v.OpenCommand(r.HndlStream) := '1'; + end if; + + when CalcAccess1_s => + if unsigned(r.Hndl4kMax) < unsigned(r.HndlWinMax) then + if unsigned(r.Dma_Cmd.MaxSize) > unsigned(r.Hndl4kMax) then + v.Dma_Cmd.MaxSize := std_logic_vector(resize(unsigned(r.Hndl4kMax), v.dma_Cmd.MaxSize'length)); + end if; + else + if unsigned(r.Dma_Cmd.MaxSize) > unsigned(r.HndlWinMax) then + v.Dma_Cmd.MaxSize := std_logic_vector(resize(unsigned(r.HndlWinMax), v.dma_Cmd.MaxSize'length)); + end if; + end if; + v.Dma_Cmd_Vld := '1'; + v.State := Idle_s; + + -- *** Handle response *** + -- Calculate next pointer + when ProcResp0_s => + v.OpenCommand(r.HndlStream) := '0'; + v.FirstOngoing(r.HndlStream) := '0'; + v.HndlPtr1 := std_logic_vector(unsigned(r.HndlPtr0) + unsigned(Dma_Resp.Size)); + v.State := NextWin_s; + -- Update window information step 1 + v.HndlWinBytes := std_logic_vector(unsigned(r.HndlWinBytes) + unsigned(Dma_Resp.Size)); + + -- Calculate next window to use + when NextWin_s => + -- Default Values + v.HndlPtr2 := r.HndlPtr1; + -- Do not wait for "transfer done" for zero size transfers (they are not passed to the memory interface) + if unsigned(Dma_Resp.Size) /= 0 then + v.IrqFifoWrite := '1'; + end if; + -- Switch to next window if required + v.HndlLastWinNr := r.HndlWincur; + if ((r.HndlPtr1 = r.HndlWinEnd) and (r.HndlRingbuf = '0')) or (Dma_Resp.Trigger = '1') then + v.HndlWinDone := '1'; + v.NewBuffer(r.HndlStream) := '1'; + if r.HndlWincur = r.HndlWincnt then + v.HndlWincur := (others => '0'); + v.HndlPtr2 := r.HndlBufstart; + v.HndlWinEnd := std_logic_vector(unsigned(r.HndlBufstart) + unsigned(r.HndlWinSize)); + else + v.HndlWincur := std_logic_vector(unsigned(r.HndlWincur) + 1); + v.HndlPtr2 := r.HndlWinEnd; + v.HndlWinEnd := std_logic_vector(unsigned(r.HndlWinEnd) + unsigned(r.HndlWinSize)); + end if; + end if; + -- wraparound for ringbuffer case + if (r.HndlPtr1 = r.HndlWinEnd) and (r.HndlRingbuf = '1') and (Dma_Resp.Trigger = '0') then + v.HndlPtr2 := std_logic_vector(unsigned(r.HndlPtr1) - unsigned(r.HndlWinSize)); + end if; + -- Update window information step 2 (limit to maximum value) + if unsigned(r.HndlWinBytes) > unsigned(r.HndlWinSize) then + v.HndlWinBytes := '0' & r.HndlWinSize; -- value has a guard bit + end if; + -- Store address of last sample in window + v.HndlWinLast := std_logic_vector(unsigned(r.HndlPtr1) - StreamWidth_g(r.HndlStream) / 8); + -- Latch timestamp + if (Dma_Resp.Trigger = '1') and (Ts_Vld(r.HndlStream) = '1') then + v.Ts_Rdy(r.HndlStream) := '1'; + v.HndlTs := Ts_Data(r.HndlStream); + else + v.HndlTs := (others => '1'); + end if; + -- Write values + v.State := WriteCtx_s; + v.HndlCtxCnt := 0; + -- Response is processed + v.Dma_Resp_Rdy := '1'; + + -- Write Context Memory Content + when WriteCtx_s => + -- Update State + if r.HndlCtxCnt = 2 then + v.State := Idle_s; + else + v.HndlCtxCnt := r.HndlCtxCnt + 1; + end if; + -- Write Context Memory + v.CtxStr_Cmd.Stream := v.HndlStream; + case r.HndlCtxCnt is + when 0 => + -- Stream Memory + v.CtxStr_Cmd.Sel := CtxStr_Sel_ScfgBufstart_c; + v.CtxStr_Cmd.WenLo := '1'; + v.CtxStr_Cmd.WdatLo(CtxStr_Sft_SCFG_RINGBUF_c) := r.HndlRingbuf; + v.CtxStr_Cmd.WdatLo(CtxStr_Sft_SCFG_OVERWRITE_c) := r.HndlOverwrite; + v.CtxStr_Cmd.WdatLo(CtxStr_Sft_SCFG_WINCNT_c + v.HndlWincnt'high downto CtxStr_Sft_SCFG_WINCNT_c) := r.HndlWincnt; + v.CtxStr_Cmd.WdatLo(CtxStr_Sft_SCFG_WINCUR_c + v.HndlWincur'high downto CtxStr_Sft_SCFG_WINCUR_c) := r.HndlWincur; + -- Window Memory + v.CtxWin_Cmd.Sel := CtxWin_Sel_WincntWinlast_c; + v.CtxWin_Cmd.WenLo := '1'; + v.CtxWin_Cmd.WenHi := '1'; + v.CtxWin_Cmd.WdatLo := shift_right(r.HndlWinBytes(31 downto 0), Log2StrBytes_c(r.HndlStream)); -- cut-off guard bit and convert bytes to samples + v.CtxWin_Cmd.WdatLo(31) := r.EndByTrig; + v.CtxWin_Cmd.WdatHi := r.HndlWinLast; + when 1 => + -- Stream Memory + v.CtxStr_Cmd.Sel := CtxStr_Sel_WinsizePtr_c; + v.CtxStr_Cmd.WenHi := '1'; + v.CtxStr_Cmd.WdatHi := r.HndlPtr2; + -- Window Memory + if r.HndlWinDone = '1' then + v.CtxWin_Cmd.Sel := CtxWin_Sel_WinTs_c; + v.CtxWin_Cmd.WenHi := '1'; + v.CtxWin_Cmd.WenLo := '1'; + v.CtxWin_Cmd.WdatLo := r.HndlTs(31 downto 0); + v.CtxWin_Cmd.WdatHi := r.HndlTs(63 downto 32); + end if; + when 2 => + -- Stream Memory + v.CtxStr_Cmd.Sel := CtxStr_Sel_Winend_c; + v.CtxStr_Cmd.WenLo := '1'; + v.CtxStr_Cmd.WdatLo := r.HndlWinEnd; + when others => null; + end case; + end case; + + -- *** Handle Disabled Streams *** + for str in 0 to Streams_g - 1 loop + if (r.GlbEnaReg = '0') or (r.StrEnaReg(str) = '0') then + v.FirstAfterEna(str) := '1'; + v.NewBuffer(str) := '1'; + end if; + end loop; + + -- *** IRQ Handling *** + -- Feedback from memory controller + if r.TfDoneReg = '1' then + v.TfDoneCnt := std_logic_vector(unsigned(r.TfDoneCnt) + 1); + end if; + + -- Process transfer completion + if (unsigned(r.TfDoneCnt) /= 0) and (IrqFifoEmpty = '0') then + v.IrqFifoRead := '1'; + v.TfDoneCnt := std_logic_vector(unsigned(v.TfDoneCnt) - 1); + -- Generate IRQ if required + if IrqFifoGenIrq = '1' then + v.StrIrq(to_integer(unsigned(IrqFifoStream))) := '1'; + v.StrLastWin(to_integer(unsigned(IrqFifoStream))) := std_logic_vector(resize(unsigned(IrqLastWinNr), 5)); + end if; + end if; + + -- *** Assign to signal *** + r_next <= v; + + end process; + + -- *** Registered Outputs *** + CtxStr_Cmd <= r.CtxStr_Cmd; + CtxWin_Cmd <= r.CtxWin_Cmd; + Dma_Cmd_Vld <= r.Dma_Cmd_Vld; + Dma_Cmd <= r.Dma_Cmd; + Dma_Resp_Rdy <= r.Dma_Resp_Rdy; + Ts_Rdy <= r.Ts_Rdy; + StrIrq <= r.StrIrq; + StrLastWin <= r.StrLastWin; + + -------------------------------------------- + -- Sequential Process + -------------------------------------------- + p_seq : process(Clk) + begin + if rising_edge(Clk) then + r <= r_next; + if Rst = '1' then + r.ArbDelCnt <= 0; + r.InpDataAvail <= (others => '0'); + r.DataAvailArbIn <= (others => '0'); + r.HndlStream <= 0; + r.State <= Idle_s; + r.CtxStr_Cmd.WenLo <= '0'; + r.CtxStr_Cmd.WenHi <= '0'; + r.CtxWin_Cmd.WenLo <= '0'; + r.CtxWin_Cmd.WenHi <= '0'; + r.Dma_Cmd_Vld <= '0'; + r.OpenCommand <= (others => '0'); + r.WinProtected <= (others => '0'); + r.Dma_Resp_Rdy <= '0'; + r.Ts_Rdy <= (others => '0'); + r.GlbEnaReg <= '0'; + r.FirstOngoing <= (others => '0'); + r.TfDoneCnt <= (others => '0'); + r.TfDoneReg <= '0'; + r.IrqFifoWrite <= '0'; + r.IrqFifoRead <= '0'; + r.StrIrq <= (others => '0'); + r.StrLastWin <= (others => (others => '0')); + end if; + end if; + end process; + + -------------------------------------------- + -- Component Instantiation + -------------------------------------------- + -- *** Round Robin Arbiter - Prio 1 *** + AvailPrio1 <= GetBitsOfStreamPrio(r.DataAvailArbIn, 1); + i_rrarb_1 : entity work.psi_common_arb_priority + generic map( + width_g => count(StreamPrio_g, 1) + ) + port map( + clk_i => Clk, + rst_i => Rst, + req_i => AvailPrio1, + grant_o => GrantPrio1 + ); + GrantVld(1) <= '1' when (unsigned(GrantPrio1) /= 0) and (GrantPrio1'length > 0) else '0'; + + -- *** Round Robin Arbiter - Prio 2 *** + AvailPrio2 <= GetBitsOfStreamPrio(r.DataAvailArbIn, 2); + i_rrarb_2 : entity work.psi_common_arb_priority + generic map( + width_g => count(StreamPrio_g, 2) + ) + port map( + clk_i => Clk, + rst_i => Rst, + req_i => AvailPrio2, + grant_o => GrantPrio2 + ); + GrantVld(2) <= '1' when (unsigned(GrantPrio2) /= 0) and (GrantPrio2'length > 0) else '0'; + + -- *** Round Robin Arbiter - Prio 3 *** + AvailPrio3 <= GetBitsOfStreamPrio(r.DataAvailArbIn, 3); + i_rrarb_3 : entity work.psi_common_arb_priority + generic map( + width_g => count(StreamPrio_g, 3) + ) + port map( + clk_i => Clk, + rst_i => Rst, + req_i => AvailPrio3, + grant_o => GrantPrio3 + ); + GrantVld(3) <= '1' when (unsigned(GrantPrio3) /= 0) and (GrantPrio3'length > 0) else '0'; + + -- *** IRQ Information FIFO *** + -- input assembly + IrqFifoIn(StreamBits_c - 1 downto 0) <= std_logic_vector(to_unsigned(r.HndlStream, StreamBits_c)); + IrqFifoIn(StreamBits_c + log2ceil(Windows_g) - 1 downto StreamBits_c) <= r.HndlLastWinNr; + IrqFifoIn(IrqFifoIn'high) <= r.HndlWinDone; + + -- Instantiation + i_irq_fifo : entity work.psi_common_sync_fifo + generic map( + width_g => StreamBits_c + log2ceil(Windows_g) + 1, + depth_g => 2**StreamBits_c * 4, + alm_full_on_g => true, + alm_full_level_g => Streams_g * 3, + ram_style_g => "distributed" + ) + port map( + clk_i => Clk, + rst_i => Rst, + dat_i => IrqFifoIn, + vld_i => r.IrqFifoWrite, + dat_o => IrqFifoOut, + rdy_i => r.IrqFifoRead, + alm_full_o => IrqFifoAlmFull, + empty_o => IrqFifoEmpty + ); + + -- Output disassembly + IrqFifoStream <= IrqFifoOut(StreamBits_c - 1 downto 0); + IrqLastWinNr <= IrqFifoOut(StreamBits_c + log2ceil(Windows_g) - 1 downto StreamBits_c); + IrqFifoGenIrq <= IrqFifoOut(IrqFifoOut'high); + +end; diff --git a/hdl/psi_ms_daq_input.vhd b/hdl/psi_ms_daq_input.vhd index 4c7572f..53ce32c 100644 --- a/hdl/psi_ms_daq_input.vhd +++ b/hdl/psi_ms_daq_input.vhd @@ -13,13 +13,13 @@ -- Libraries ------------------------------------------------------------------------------ library ieee; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; - +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + library work; - use work.psi_common_math_pkg.all; - use work.psi_ms_daq_pkg.all; - +use work.psi_common_math_pkg.all; +use work.psi_ms_daq_pkg.all; + ------------------------------------------------------------------------------ -- Entity Declaration ------------------------------------------------------------------------------ @@ -27,558 +27,544 @@ library work; -- $$ processes=stream,daq $$ -- $$ tbpkg=work.psi_tb_txt_util $$ entity psi_ms_daq_input is - generic ( - StreamWidth_g : positive range 8 to 64 := 16; -- Must be 8, 16, 32 or 64 $$ export=true $$ - StreamBuffer_g : positive range 1 to 65535 := 1024; -- Buffer depth in QWORDs $$ constant=32 $$ - StreamTimeout_g : real := 1.0e-3; -- Timeout in seconds $$ constant=10.0e-6 $$ - StreamClkFreq_g : real := 125.0e6; -- Input clock frequency in Hz $$ constant=125.0e6 $$ - StreamTsFifoDepth_g : positive := 16; -- Timestamp FIFO depth $$ constant=3 $$ - StreamUseTs_g : boolean := true -- Enable/Disable the timestamp acquisition $$ constant=true $$ - ); - port ( - -- Data Stream Input - Str_Clk : in std_logic; -- $$ type=clk; freq=125e6; proc=stream $$ - Str_Vld : in std_logic; -- $$ proc=stream $$ - Str_Rdy : out std_logic; -- $$ proc=stream $$ - Str_Data : in std_logic_vector(StreamWidth_g-1 downto 0); -- $$ proc=stream $$ - Str_Trig : in std_logic; -- $$ proc=stream $$ - Str_Ts : in std_logic_vector(63 downto 0); -- $$ proc=stream $$ - - -- Configuration Signals - ClkReg : in std_logic; - RstReg : in std_logic; - PostTrigSpls : in std_logic_vector(31 downto 0); -- $$ proc=daq $$ - Mode : in RecMode_t; -- $$ proc=daq $$ - Arm : in std_logic; -- $$ proc=stream $$ - IsArmed : out std_logic; -- $$ proc=stream $$ - IsRecording : out std_logic; -- $$ proc=stream $$ - - -- DAQ control signals - ClkMem : in std_logic; -- $$ type=clk; freq=200e6; proc=daq,stream $$ - RstMem : in std_logic; -- $$ type=rst; clk=Clk $$ - - -- DAQ logic Connections - Daq_Vld : out std_logic; -- $$ proc=daq $$ - Daq_Rdy : in std_logic; -- $$ proc=daq $$ - Daq_Data : out Input2Daq_Data_t; -- $$ proc=daq $$ - Daq_Level : out std_logic_vector(15 downto 0); -- $$ proc=daq $$ - Daq_HasLast : out std_logic; -- $$ proc=daq $$ - - -- Timestamp connections - Ts_Vld : out std_logic; -- $$ proc=daq $$ - Ts_Rdy : in std_logic; -- $$ proc=daq $$ - Ts_Data : out std_logic_vector(63 downto 0) -- $$ proc=daq $$ - ); + generic( + StreamWidth_g : positive range 8 to 64 := 16; -- Must be 8, 16, 32 or 64 $$ export=true $$ + StreamBuffer_g : positive range 1 to 65535 := 1024; -- Buffer depth in QWORDs $$ constant=32 $$ + StreamTimeout_g : real := 1.0e-3; -- Timeout in seconds $$ constant=10.0e-6 $$ + StreamClkFreq_g : real := 125.0e6; -- Input clock frequency in Hz $$ constant=125.0e6 $$ + StreamTsFifoDepth_g : positive := 16; -- Timestamp FIFO depth $$ constant=3 $$ + StreamUseTs_g : boolean := true -- Enable/Disable the timestamp acquisition $$ constant=true $$ + ); + port( + -- Data Stream Input + Str_Clk : in std_logic; -- $$ type=clk; freq=125e6; proc=stream $$ + Str_Vld : in std_logic; -- $$ proc=stream $$ + Str_Rdy : out std_logic; -- $$ proc=stream $$ + Str_Data : in std_logic_vector(StreamWidth_g - 1 downto 0); -- $$ proc=stream $$ + Str_Trig : in std_logic; -- $$ proc=stream $$ + Str_Ts : in std_logic_vector(63 downto 0); -- $$ proc=stream $$ + + -- Configuration Signals + ClkReg : in std_logic; + RstReg : in std_logic; + PostTrigSpls : in std_logic_vector(31 downto 0); -- $$ proc=daq $$ + Mode : in RecMode_t; -- $$ proc=daq $$ + Arm : in std_logic; -- $$ proc=stream $$ + IsArmed : out std_logic; -- $$ proc=stream $$ + IsRecording : out std_logic; -- $$ proc=stream $$ + + -- DAQ control signals + ClkMem : in std_logic; -- $$ type=clk; freq=200e6; proc=daq,stream $$ + RstMem : in std_logic; -- $$ type=rst; clk=Clk $$ + + -- DAQ logic Connections + Daq_Vld : out std_logic; -- $$ proc=daq $$ + Daq_Rdy : in std_logic; -- $$ proc=daq $$ + Daq_Data : out Input2Daq_Data_t; -- $$ proc=daq $$ + Daq_Level : out std_logic_vector(15 downto 0); -- $$ proc=daq $$ + Daq_HasLast : out std_logic; -- $$ proc=daq $$ + + -- Timestamp connections + Ts_Vld : out std_logic; -- $$ proc=daq $$ + Ts_Rdy : in std_logic; -- $$ proc=daq $$ + Ts_Data : out std_logic_vector(63 downto 0) -- $$ proc=daq $$ + ); end entity; - + ------------------------------------------------------------------------------ -- Architecture Declaration ------------------------------------------------------------------------------ architecture rtl of psi_ms_daq_input is - -- Use distributed RAM for small Timstamp FIFOs (< 64 entries) - constant TsFifoStyle_c : string := choose(StreamTsFifoDepth_g <= 64, "distributed", "block"); + -- Use distributed RAM for small Timstamp FIFOs (< 64 entries) + constant TsFifoStyle_c : string := choose(StreamTsFifoDepth_g <= 64, "distributed", "block"); - -- Constants - constant TimeoutLimit_c : integer := integer(StreamClkFreq_g*StreamTimeout_g)-1; - constant WconvFactor_c : positive := 64/StreamWidth_g; - constant TlastCntWidth_c : positive := log2ceil(StreamBuffer_g) + 1; - - -- Two process method - type two_process_r is record - ModeReg : RecMode_t; - ArmReg : std_logic; - DataSftReg : std_logic_vector(63 downto 0); - WordCnt : unsigned(log2ceil(WconvFactor_c) downto 0); - DataFifoBytes : unsigned(3 downto 0); - TrigLatch : std_logic; - DataFifoVld : std_logic; - DataFifoIsTo : std_logic; - DataFifoIsTrig : std_logic; - TimeoutCnt : integer range 0 to TimeoutLimit_c; - Timeout : std_logic; - PostTrigCnt : unsigned(31 downto 0); - TLastCnt : std_logic_vector(TlastCntWidth_c-1 downto 0); - TsLatch : std_logic_vector(63 downto 0); - TsOverflow : std_logic; - HasTlastSync : std_logic_vector(0 to 1); - IsArmed : std_logic; - RecEna : std_logic; - end record; - signal r, r_next : two_process_r; - - -- General Instantiation signals - signal Str_Rst : std_logic; + -- Constants + constant TimeoutLimit_c : integer := integer(StreamClkFreq_g * StreamTimeout_g) - 1; + constant WconvFactor_c : positive := 64 / StreamWidth_g; + constant TlastCntWidth_c : positive := log2ceil(StreamBuffer_g) + 1; + + -- Two process method + type two_process_r is record + ModeReg : RecMode_t; + ArmReg : std_logic; + DataSftReg : std_logic_vector(63 downto 0); + WordCnt : unsigned(log2ceil(WconvFactor_c) downto 0); + DataFifoBytes : unsigned(3 downto 0); + TrigLatch : std_logic; + DataFifoVld : std_logic; + DataFifoIsTo : std_logic; + DataFifoIsTrig : std_logic; + TimeoutCnt : integer range 0 to TimeoutLimit_c; + Timeout : std_logic; + PostTrigCnt : unsigned(31 downto 0); + TLastCnt : std_logic_vector(TlastCntWidth_c - 1 downto 0); + TsLatch : std_logic_vector(63 downto 0); + TsOverflow : std_logic; + HasTlastSync : std_logic_vector(0 to 1); + IsArmed : std_logic; + RecEna : std_logic; + end record; + signal r, r_next : two_process_r; + + -- General Instantiation signals + signal Str_Rst : std_logic; + + -- Data FIFO signals + signal DataFifo_InRdy : std_logic; + signal DataFifo_InData : std_logic_vector(69 downto 0); + signal DataFifo_OutData : std_logic_vector(69 downto 0); + signal DataFifo_PlData : std_logic_vector(69 downto 0); + signal DataFifo_PlVld : std_logic; + signal DataFifo_PlRdy : std_logic; + signal DataFifo_Level : std_logic_vector(log2ceil(StreamBuffer_g) downto 0); + signal DataPl_Level : unsigned(1 downto 0); + + -- Internally reused signals + signal Daq_Data_I : Input2Daq_Data_t; + signal Daq_Vld_I : std_logic; + signal Daq_HasLast_I : std_logic; + signal Ts_Vld_I : std_logic; + + -- Signal output side TLAST handling + signal OutTlastCnt : std_logic_vector(TlastCntWidth_c - 1 downto 0); + signal InTlastCnt : std_logic_vector(TlastCntWidth_c - 1 downto 0); + + -- Timestamp FIFO signals + signal TsFifo_InRdy : std_logic; + signal TsFifo_InVld : std_logic; + signal TsFifo_RdData : std_logic_vector(63 downto 0); + signal TsFifo_AlmFull : std_logic; + signal TsFifo_Empty : std_logic; + + -- Clock Crossing Signals + signal PostTrigSpls_Sync : std_logic_vector(PostTrigSpls'range); + signal Mode_Sync : RecMode_t; + signal Arm_Sync : std_logic; + signal RstReg_Sync : std_logic; + signal RstAcq_Sync : std_logic; - -- Data FIFO signals - signal DataFifo_InRdy : std_logic; - signal DataFifo_InData : std_logic_vector(69 downto 0); - signal DataFifo_OutData : std_logic_vector(69 downto 0); - signal DataFifo_PlData : std_logic_vector(69 downto 0); - signal DataFifo_PlVld : std_logic; - signal DataFifo_PlRdy : std_logic; - signal DataFifo_Level : std_logic_vector(log2ceil(StreamBuffer_g) downto 0); - signal DataPl_Level : unsigned(1 downto 0); - - -- Internally reused signals - signal Daq_Data_I : Input2Daq_Data_t; - signal Daq_Vld_I : std_logic; - signal Daq_HasLast_I : std_logic; - signal Ts_Vld_I : std_logic; - - -- Signal output side TLAST handling - signal OutTlastCnt : std_logic_vector(TlastCntWidth_c-1 downto 0); - signal InTlastCnt : std_logic_vector(TlastCntWidth_c-1 downto 0); - - -- Timestamp FIFO signals - signal TsFifo_InRdy : std_logic; - signal TsFifo_InVld : std_logic; - signal TsFifo_RdData : std_logic_vector(63 downto 0); - signal TsFifo_AlmFull : std_logic; - signal TsFifo_Empty : std_logic; - - -- Clock Crossing Signals - signal PostTrigSpls_Sync : std_logic_vector(PostTrigSpls'range); - signal Mode_Sync : RecMode_t; - signal Arm_Sync : std_logic; - signal RstReg_Sync : std_logic; - signal RstAcq_Sync : std_logic; - begin - -------------------------------------------- - -- Combinatorial Process - -------------------------------------------- - p_comb : process( r, - Str_Vld, Str_Data, Str_Trig, Str_Ts, PostTrigSpls_Sync, Daq_Rdy, Ts_Rdy, Mode_Sync, Arm_Sync, - DataFifo_InRdy, DataFifo_InData, DataFifo_OutData, Daq_Vld_I, Daq_Data_I, Daq_HasLast_I, Ts_Vld_I, OutTlastCnt, TsFifo_AlmFull, TsFifo_Empty, - InTlastCnt, TsFifo_InRdy, TsFifo_RdData) - variable v : two_process_r; - variable ProcessSample_v : boolean; - variable TriggerSample_v : boolean; - variable AddSamples_v : integer range 0 to 1; - variable TrigMasked_v : std_logic; - begin - -- *** Hold variables stable *** - v := r; - - -- *** Simplification Variables *** - ProcessSample_v := (DataFifo_InRdy = '1') and (Str_Vld = '1'); - - -- *** Input Logic Stage *** - -- Default values - v.DataFifoIsTo := '0'; - v.DataFifoIsTrig := '0'; - v.ModeReg := Mode_Sync; - v.ArmReg := Arm_Sync; - - -- Masking trigger according to recording mode - case r.ModeReg is - when RecMode_Continuous_c => - TrigMasked_v := Str_Trig; - when RecMode_TriggerMask_c | + -------------------------------------------- + -- Combinatorial Process + -------------------------------------------- + p_comb : process(r, Str_Vld, Str_Data, Str_Trig, Str_Ts, PostTrigSpls_Sync, Daq_Rdy, Ts_Rdy, Mode_Sync, Arm_Sync, DataFifo_InRdy, DataFifo_InData, DataFifo_OutData, Daq_Vld_I, Daq_Data_I, Daq_HasLast_I, Ts_Vld_I, OutTlastCnt, TsFifo_AlmFull, TsFifo_Empty, InTlastCnt, TsFifo_InRdy, TsFifo_RdData) + variable v : two_process_r; + variable ProcessSample_v : boolean; + variable TriggerSample_v : boolean; + variable AddSamples_v : integer range 0 to 1; + variable TrigMasked_v : std_logic; + begin + -- *** Hold variables stable *** + v := r; + + -- *** Simplification Variables *** + ProcessSample_v := (DataFifo_InRdy = '1') and (Str_Vld = '1'); + + -- *** Input Logic Stage *** + -- Default values + v.DataFifoIsTo := '0'; + v.DataFifoIsTrig := '0'; + v.ModeReg := Mode_Sync; + v.ArmReg := Arm_Sync; + + -- Masking trigger according to recording mode + case r.ModeReg is + when RecMode_Continuous_c => + TrigMasked_v := Str_Trig; + when RecMode_TriggerMask_c | RecMode_SingleShot_c => - TrigMasked_v := Str_Trig and r.IsArmed; - when RecMode_ManuelMode_c => - TrigMasked_v := r.ArmReg; - when others => null; - end case; - - - -- Keep FifoVld high until data is written - v.DataFifoVld := r.DataFifoVld and not DataFifo_InRdy; - - -- Trigger Latching - if ProcessSample_v then - v.TrigLatch := '0'; - else - v.TrigLatch := r.TrigLatch or TrigMasked_v; - end if; - - -- Detect timestamp FIFO overflows - if StreamUseTs_g then - v.HasTlastSync(0) := Daq_HasLast_I; - v.HasTlastSync(1) := r.HasTlastSync(0); - if (TsFifo_AlmFull = '1' ) and (r.DataFifoVld = '1') then - v.TsOverflow := '1'; - elsif (r.HasTlastSync(1) = '0') and (TsFifo_Empty = '1' ) then - v.TsOverflow := '0'; - end if; - end if; - - -- Timestamp latching - if StreamUseTs_g then - if (TrigMasked_v = '1') and (unsigned(r.PostTrigCnt) = 0) then - if (TsFifo_AlmFull = '1') or (r.TsOverflow = '1') then - v.TsLatch := (others => '1'); - else - v.TsLatch := Str_Ts; - end if; - end if; - end if; - - -- Trigger handling and post trigger counter - if ProcessSample_v and r.RecEna = '1' then - if r.PostTrigCnt /= 0 then - v.PostTrigCnt := r.PostTrigCnt - 1; - if r.PostTrigCnt = 1 then - v.DataFifoIsTrig := '1'; - v.DataFifoVld := r.DataFifoVld or r.RecEna; - v.RecEna := '0'; -- stop recording after frame - end if; - elsif (r.TrigLatch = '1') or (TrigMasked_v = '1') then - -- Handle incoming trigger sample - if unsigned(PostTrigSpls_Sync) = 0 then - v.DataFifoIsTrig := '1'; - v.DataFifoVld := r.DataFifoVld or r.RecEna; - v.RecEna := '0'; -- stop recording after frame - else - v.PostTrigCnt := unsigned(PostTrigSpls_Sync); - end if; - end if; - end if; - - -- Detect Timeout - if Str_Vld = '1' then - v.TimeoutCnt := 0; - else - if r.TimeoutCnt = TimeoutLimit_c then - v.TimeoutCnt := 0; - v.Timeout := '1'; - else - v.TimeoutCnt := r.TimeoutCnt + 1; - end if; - end if; - - -- TLast counter - if (r.DataFifoVld = '1') and ((r.DataFifoIsTo = '1') or (r.DataFifoIsTrig = '1')) then - v.TLastCnt := std_logic_vector(unsigned(r.TLastCnt) + 1); - end if; - - -- Write because timeout occured (only if data is stuck in conversion) - if r.Timeout = '1' then - v.DataFifoVld := r.DataFifoVld or r.RecEna; - v.DataFifoIsTo := '1'; - v.Timeout := '0'; -- reser timeout after data was flushed to the FIFO - end if; - -- Process input data - if ProcessSample_v and r.RecEna = '1' then - v.WordCnt := r.WordCnt + 1; - -- Write because 64-bits are ready - if r.WordCnt = WconvFactor_c-1 then - v.DataFifoVld := r.DataFifoVld or r.RecEna; - end if; - v.DataSftReg((to_integer(r.WordCnt)+1)*StreamWidth_g-1 downto to_integer(r.WordCnt)*StreamWidth_g) := Str_Data; - end if; - -- Reset counter if data is being written to FIFO - if v.DataFifoVld = '1' then - v.WordCnt := (others => '0'); - end if; - - -- Convert word counter to byte counter - v.DataFifoBytes := (others => '0'); - if r.Timeout = '1' then - AddSamples_v := 0; - else - AddSamples_v := 1; - end if; - case StreamWidth_g is - when 8 => v.DataFifoBytes := r.WordCnt + AddSamples_v; - when 16 => v.DataFifoBytes := (r.WordCnt + AddSamples_v) & "0"; - when 32 => v.DataFifoBytes := (r.WordCnt + AddSamples_v) & "00"; - when 64 => v.DataFifoBytes := (r.WordCnt + AddSamples_v) & "000"; - when others => null; - end case; - - -- Handle Arming Logic - if (r.ModeReg /= Mode_Sync) or (r.ModeReg = RecMode_Continuous_c) or (r.ModeReg = RecMode_ManuelMode_c) then -- reset on mode change! - v.IsArmed := '0'; - elsif r.ArmReg = '1' then - v.IsArmed := '1'; - elsif TrigMasked_v = '1' then - v.IsArmed := '0'; - end if; - - -- Enable Recording Logic - case r.ModeReg is - when RecMode_Continuous_c | - RecMode_TriggerMask_c => - -- always enabled - v.RecEna := '1'; - when RecMode_SingleShot_c | + TrigMasked_v := Str_Trig and r.IsArmed; + when RecMode_ManuelMode_c => + TrigMasked_v := r.ArmReg; + when others => null; + end case; + + -- Keep FifoVld high until data is written + v.DataFifoVld := r.DataFifoVld and not DataFifo_InRdy; + + -- Trigger Latching + if ProcessSample_v then + v.TrigLatch := '0'; + else + v.TrigLatch := r.TrigLatch or TrigMasked_v; + end if; + + -- Detect timestamp FIFO overflows + if StreamUseTs_g then + v.HasTlastSync(0) := Daq_HasLast_I; + v.HasTlastSync(1) := r.HasTlastSync(0); + if (TsFifo_AlmFull = '1') and (r.DataFifoVld = '1') then + v.TsOverflow := '1'; + elsif (r.HasTlastSync(1) = '0') and (TsFifo_Empty = '1') then + v.TsOverflow := '0'; + end if; + end if; + + -- Timestamp latching + if StreamUseTs_g then + if (TrigMasked_v = '1') and (unsigned(r.PostTrigCnt) = 0) then + if (TsFifo_AlmFull = '1') or (r.TsOverflow = '1') then + v.TsLatch := (others => '1'); + else + v.TsLatch := Str_Ts; + end if; + end if; + end if; + + -- Trigger handling and post trigger counter + if ProcessSample_v and r.RecEna = '1' then + if r.PostTrigCnt /= 0 then + v.PostTrigCnt := r.PostTrigCnt - 1; + if r.PostTrigCnt = 1 then + v.DataFifoIsTrig := '1'; + v.DataFifoVld := r.DataFifoVld or r.RecEna; + v.RecEna := '0'; -- stop recording after frame + end if; + elsif (r.TrigLatch = '1') or (TrigMasked_v = '1') then + -- Handle incoming trigger sample + if unsigned(PostTrigSpls_Sync) = 0 then + v.DataFifoIsTrig := '1'; + v.DataFifoVld := r.DataFifoVld or r.RecEna; + v.RecEna := '0'; -- stop recording after frame + else + v.PostTrigCnt := unsigned(PostTrigSpls_Sync); + end if; + end if; + end if; + + -- Detect Timeout + if Str_Vld = '1' then + v.TimeoutCnt := 0; + else + if r.TimeoutCnt = TimeoutLimit_c then + v.TimeoutCnt := 0; + v.Timeout := '1'; + else + v.TimeoutCnt := r.TimeoutCnt + 1; + end if; + end if; + + -- TLast counter + if (r.DataFifoVld = '1') and ((r.DataFifoIsTo = '1') or (r.DataFifoIsTrig = '1')) then + v.TLastCnt := std_logic_vector(unsigned(r.TLastCnt) + 1); + end if; + + -- Write because timeout occured (only if data is stuck in conversion) + if r.Timeout = '1' then + v.DataFifoVld := r.DataFifoVld or r.RecEna; + v.DataFifoIsTo := '1'; + v.Timeout := '0'; -- reser timeout after data was flushed to the FIFO + end if; + -- Process input data + if ProcessSample_v and r.RecEna = '1' then + v.WordCnt := r.WordCnt + 1; + -- Write because 64-bits are ready + if r.WordCnt = WconvFactor_c - 1 then + v.DataFifoVld := r.DataFifoVld or r.RecEna; + end if; + v.DataSftReg((to_integer(r.WordCnt) + 1) * StreamWidth_g - 1 downto to_integer(r.WordCnt) * StreamWidth_g) := Str_Data; + end if; + -- Reset counter if data is being written to FIFO + if v.DataFifoVld = '1' then + v.WordCnt := (others => '0'); + end if; + + -- Convert word counter to byte counter + v.DataFifoBytes := (others => '0'); + if r.Timeout = '1' then + AddSamples_v := 0; + else + AddSamples_v := 1; + end if; + case StreamWidth_g is + when 8 => v.DataFifoBytes := r.WordCnt + AddSamples_v; + when 16 => v.DataFifoBytes := (r.WordCnt + AddSamples_v) & "0"; + when 32 => v.DataFifoBytes := (r.WordCnt + AddSamples_v) & "00"; + when 64 => v.DataFifoBytes := (r.WordCnt + AddSamples_v) & "000"; + when others => null; + end case; + + -- Handle Arming Logic + if (r.ModeReg /= Mode_Sync) or (r.ModeReg = RecMode_Continuous_c) or (r.ModeReg = RecMode_ManuelMode_c) then -- reset on mode change! + v.IsArmed := '0'; + elsif r.ArmReg = '1' then + v.IsArmed := '1'; + elsif TrigMasked_v = '1' then + v.IsArmed := '0'; + end if; + + -- Enable Recording Logic + case r.ModeReg is + when RecMode_Continuous_c | + RecMode_TriggerMask_c => + -- always enabled + v.RecEna := '1'; + when RecMode_SingleShot_c | RecMode_ManuelMode_c => - -- enable on arming (disable happens after recording) - if v.ArmReg = '1' then - v.RecEna := '1'; - end if; - when others => null; - end case; - if r.ModeReg /= Mode_Sync then - v.RecEna := '0'; - end if; - - -- *** Assign to signal *** - r_next <= v; - - end process; - - -------------------------------------------- - -- Sequential Process - -------------------------------------------- - p_seq : process(Str_Clk) - begin - if rising_edge(Str_Clk) then - r <= r_next; - if Str_Rst = '1' then - r.WordCnt <= (others => '0'); - r.TrigLatch <= '0'; - r.TimeoutCnt <= 0; - r.Timeout <= '0'; - r.PostTrigCnt <= (others => '0'); - r.TLastCnt <= (others => '0'); - r.TsOverflow <= '0'; - r.HasTlastSync <= (others => '0'); - r.IsArmed <= '0'; - r.RecEna <= '0'; - r.ArmReg <= '0'; - end if; - end if; - end process; - - -------------------------------------------- - -- Output Side TLAST handling - -------------------------------------------- - p_outlast : process(ClkMem) - variable PlLevel_v : unsigned(DataPl_Level'range); - begin - if rising_edge(ClkMem) then - -- Default Value - Daq_HasLast_I <= '0'; - - -- Count TLAST read from output buffer - if (Daq_Vld_I = '1') and (Daq_Rdy = '1') and (Daq_Data_I.Last = '1') then - OutTlastCnt <= std_logic_vector(unsigned(OutTlastCnt) + 1); - end if; - - -- Detect if there are TLASTs in the buffer - if OutTlastCnt /= InTlastCnt then - Daq_HasLast_I <= '1'; - end if; - - -- Level Calculation (add samples in PL stage) - PlLevel_v := DataPl_Level; - if DataFifo_PlRdy = '1' and DataFifo_PlVld = '1' then - PlLevel_v := PlLevel_v + 1; - end if; - if Daq_Vld_I = '1' and Daq_Rdy = '1' then - PlLevel_v := PlLevel_v - 1; - end if; - DataPl_Level <= PlLevel_v; - -- We calculate the level one cycle late but this does not play any role (the DAQ FSM only runs after data is transferred) - Daq_Level <= std_logic_vector(resize(unsigned(DataFifo_Level), Daq_Level'length) + DataPl_Level); - - -- Reset - if RstMem = '1' then - OutTlastCnt <= (others => '0'); - Daq_Level <= (others => '0'); - DataPl_Level <= (others => '0'); - end if; - - end if; - end process; - Daq_HasLast <= Daq_HasLast_I; + -- enable on arming (disable happens after recording) + if v.ArmReg = '1' then + v.RecEna := '1'; + end if; + when others => null; + end case; + if r.ModeReg /= Mode_Sync then + v.RecEna := '0'; + end if; - -------------------------------------------- - -- Component Instantiation - -------------------------------------------- - -- *** Register Interface clock crossings *** - i_cc_reg_status : entity work.psi_common_status_cc - generic map ( - DataWidth_g => 34 - ) - port map ( - ClkA => ClkReg, - RstInA => '0', - DataA(31 downto 0) => PostTrigSpls, - DataA(33 downto 32) => Mode, - ClkB => Str_Clk, - RstInB => Str_Rst, - DataB(31 downto 0) => PostTrigSpls_Sync, - DataB(33 downto 32) => Mode_Sync - ); - - i_cc_status : entity work.psi_common_bit_cc - generic map ( - NumBits_g => 2 - ) - port map ( - BitsA(0) => r.IsArmed, - BitsA(1) => r.RecEna, - ClkB => ClkReg, - BitsB(0) => IsArmed, - BitsB(1) => IsRecording - ); + -- *** Assign to signal *** + r_next <= v; - i_cc_reg_pulse : entity work.psi_common_pulse_cc - generic map ( - NumPulses_g => 1 - ) - port map ( - ClkA => ClkReg, - RstInA => '0', - PulseA(0) => Arm, - ClkB => Str_Clk, - RstInB => Str_Rst, - RstOutB => open, - PulseB(0) => Arm_Sync - ); - - - - -- *** Reset Handling *** - icc_reg_rst : entity work.psi_common_bit_cc - generic map ( - NumBits_g => 1 - ) - port map ( - BitsA(0) => RstReg, - ClkB => Str_Clk, - BitsB(0) => RstReg_Sync - ); - - icc_mem_rst : entity work.psi_common_bit_cc - generic map ( - NumBits_g => 1 - ) - port map ( - BitsA(0) => RstMem, - ClkB => Str_Clk, - BitsB(0) => RstAcq_Sync - ); - Str_Rst <= RstReg_Sync or RstAcq_Sync; - - -- *** Acquisition Clock Crossing *** - -- Clock crossing for reset and TLAST counter - i_cc : entity work.psi_common_status_cc - generic map ( - DataWidth_g => TlastCntWidth_c - ) - port map ( - ClkA => Str_Clk, - RstInA => Str_Rst, - RstOutA => open, - DataA => r.TLastCnt, - ClkB => ClkMem, - RstInB => '0', - DataB => InTlastCnt - ); - - - -- Data FIFO - DataFifo_InData(63 downto 0) <= r.DataSftReg; - DataFifo_InData(67 downto 64) <= std_logic_vector(r.DataFifoBytes); - DataFifo_InData(68) <= r.DataFifoIsTo; - DataFifo_InData(69) <= r.DataFifoIsTrig; - - - i_dfifo : entity work.psi_common_async_fifo - generic map ( - Width_g => 70, - Depth_g => StreamBuffer_g, - AlmFullOn_g => false, - AlmEmptyOn_g => false - ) - port map ( - InClk => Str_Clk, - InRst => Str_Rst, - OutClk => ClkMem, - OutRst => '0', - InData => DataFifo_InData, - InVld => r.DataFifoVld, - InRdy => DataFifo_InRdy, - OutData => DataFifo_PlData, - OutVld => DataFifo_PlVld, - OutRdy => DataFifo_PlRdy, - OutLevel => DataFifo_Level - ); - - -- An additional pipeline stage after the FIFO is required for timing reasons - i_dplstage : entity work.psi_common_pl_stage - generic map ( - Width_g => 70, - UseRdy_g => true - ) - port map ( - Clk => ClkMem, - Rst => RstMem, - InVld => DataFifo_PlVld, - InRdy => DataFifo_PlRdy, - InData => DataFifo_PlData, - OutVld => Daq_Vld_I, - OutRdy => Daq_Rdy, - OutData => DataFifo_OutData - ); - Str_Rdy <= DataFifo_InRdy; - - Daq_Data_I.Data <= DataFifo_OutData(63 downto 0); - Daq_Data_I.Bytes <= DataFifo_OutData(67 downto 64); - Daq_Data_I.IsTo <= DataFifo_OutData(68); - Daq_Data_I.IsTrig <= DataFifo_OutData(69); - Daq_Data_I.Last <= Daq_Data_I.IsTo or Daq_Data_I.IsTrig; - Daq_Data <= Daq_Data_I; - Daq_Vld <= Daq_Vld_I; - - - -- Timestamp FIFO - g_timestamp : if StreamUseTs_g generate - TsFifo_InVld <= r.DataFifoVld and r.DataFifoIsTrig; - - i_tsfifo : entity work.psi_common_async_fifo - generic map ( - Width_g => 64, - Depth_g => StreamTsFifoDepth_g, - AlmFullOn_g => True, - AlmFullLevel_g => StreamTsFifoDepth_g-1, - AlmEmptyOn_g => false, - RamStyle_g => TsFifoStyle_c - ) - port map ( - InClk => Str_Clk, - InRst => Str_Rst, - OutClk => ClkMem, - OutRst => '0', - InData => r.TsLatch, - InVld => TsFifo_InVld, - InRdy => TsFifo_InRdy, - InAlmFull => TsFifo_AlmFull, - InEmpty => TsFifo_Empty, - OutData => TsFifo_RdData, - OutVld => Ts_Vld_I, - OutRdy => Ts_Rdy - ); - Ts_Vld <= Ts_Vld_I; - -- Replace data by 0xFF... if no valid timestamp is available - Ts_Data <= (others => '1') when Ts_Vld_I = '0' else TsFifo_RdData; - end generate; - - g_ntimestamp : if not StreamUseTs_g generate - Ts_Vld <= '0'; - Ts_Data <= (others => '1'); - end generate; - - - -------------------------------------------- - -- Assertions - -------------------------------------------- - p_assert : process(ClkMem) - begin - if rising_edge(ClkMem) then - assert StreamWidth_g = 8 or StreamWidth_g = 16 or StreamWidth_g = 32 or StreamWidth_g = 64 report "###ERROR###: psi_ms_daq_input: StreamWidth_g must be 8, 16, 32 or 64" severity error; - end if; - end process; - -end; + end process; + -------------------------------------------- + -- Sequential Process + -------------------------------------------- + p_seq : process(Str_Clk) + begin + if rising_edge(Str_Clk) then + r <= r_next; + if Str_Rst = '1' then + r.WordCnt <= (others => '0'); + r.TrigLatch <= '0'; + r.TimeoutCnt <= 0; + r.Timeout <= '0'; + r.PostTrigCnt <= (others => '0'); + r.TLastCnt <= (others => '0'); + r.TsOverflow <= '0'; + r.HasTlastSync <= (others => '0'); + r.IsArmed <= '0'; + r.RecEna <= '0'; + r.ArmReg <= '0'; + end if; + end if; + end process; + -------------------------------------------- + -- Output Side TLAST handling + -------------------------------------------- + p_outlast : process(ClkMem) + variable PlLevel_v : unsigned(DataPl_Level'range); + begin + if rising_edge(ClkMem) then + -- Default Value + Daq_HasLast_I <= '0'; + -- Count TLAST read from output buffer + if (Daq_Vld_I = '1') and (Daq_Rdy = '1') and (Daq_Data_I.Last = '1') then + OutTlastCnt <= std_logic_vector(unsigned(OutTlastCnt) + 1); + end if; + -- Detect if there are TLASTs in the buffer + if OutTlastCnt /= InTlastCnt then + Daq_HasLast_I <= '1'; + end if; + + -- Level Calculation (add samples in PL stage) + PlLevel_v := DataPl_Level; + if DataFifo_PlRdy = '1' and DataFifo_PlVld = '1' then + PlLevel_v := PlLevel_v + 1; + end if; + if Daq_Vld_I = '1' and Daq_Rdy = '1' then + PlLevel_v := PlLevel_v - 1; + end if; + DataPl_Level <= PlLevel_v; + -- We calculate the level one cycle late but this does not play any role (the DAQ FSM only runs after data is transferred) + Daq_Level <= std_logic_vector(resize(unsigned(DataFifo_Level), Daq_Level'length) + DataPl_Level); + + -- Reset + if RstMem = '1' then + OutTlastCnt <= (others => '0'); + Daq_Level <= (others => '0'); + DataPl_Level <= (others => '0'); + end if; + + end if; + end process; + Daq_HasLast <= Daq_HasLast_I; + + -------------------------------------------- + -- Component Instantiation + -------------------------------------------- + -- *** Register Interface clock crossings *** + i_cc_reg_status : entity work.psi_common_status_cc + generic map( + width_g => 34 + ) + port map( + a_clk_i => ClkReg, + a_rst_i => '0', + a_dat_i(31 downto 0) => PostTrigSpls, + a_dat_i(33 downto 32) => Mode, + b_clk_i => Str_Clk, + b_rst_i => Str_Rst, + b_dat_o(31 downto 0) => PostTrigSpls_Sync, + b_dat_o(33 downto 32) => Mode_Sync + ); + + i_cc_status : entity work.psi_common_bit_cc + generic map( + width_g => 2 + ) + port map( + dat_i(0) => r.IsArmed, + dat_i(1) => r.RecEna, + clk_i => ClkReg, + dat_o(0) => IsArmed, + dat_o(1) => IsRecording + ); + + i_cc_reg_pulse : entity work.psi_common_pulse_cc + generic map( + num_pulses_g => 1 + ) + port map( + a_clk_i => ClkReg, + a_rst_i => '0', + a_dat_i(0) => Arm, + b_clk_i => Str_Clk, + b_rst_i => Str_Rst, + b_rst_o => open, + b_dat_o(0) => Arm_Sync + ); + + -- *** Reset Handling *** + icc_reg_rst : entity work.psi_common_bit_cc + generic map( + width_g => 1 + ) + port map( + dat_i(0) => RstReg, + clk_i => Str_Clk, + dat_o(0) => RstReg_Sync + ); + + icc_mem_rst : entity work.psi_common_bit_cc + generic map( + width_g => 1 + ) + port map( + dat_i(0) => RstMem, + clk_i => Str_Clk, + dat_o(0) => RstAcq_Sync + ); + Str_Rst <= RstReg_Sync or RstAcq_Sync; + + -- *** Acquisition Clock Crossing *** + -- Clock crossing for reset and TLAST counter + i_cc : entity work.psi_common_status_cc + generic map( + width_g => TlastCntWidth_c + ) + port map( + a_clk_i => Str_Clk, + a_rst_i => Str_Rst, + a_rst_o => open, + a_dat_i => r.TLastCnt, + b_clk_i => ClkMem, + b_rst_i => '0', + b_dat_o => InTlastCnt + ); + + -- Data FIFO + DataFifo_InData(63 downto 0) <= r.DataSftReg; + DataFifo_InData(67 downto 64) <= std_logic_vector(r.DataFifoBytes); + DataFifo_InData(68) <= r.DataFifoIsTo; + DataFifo_InData(69) <= r.DataFifoIsTrig; + + i_dfifo : entity work.psi_common_async_fifo + generic map( + width_g => 70, + depth_g => StreamBuffer_g, + afull_on_g => false, + aempty_on_g => false + ) + port map( + in_clk_i => Str_Clk, + in_rst_i => Str_Rst, + out_clk_i => ClkMem, + out_rst_i => '0', + in_dat_i => DataFifo_InData, + in_vld_i => r.DataFifoVld, + in_rdy_o => DataFifo_InRdy, + out_dat_o => DataFifo_PlData, + out_vld_o => DataFifo_PlVld, + out_rdy_o => DataFifo_PlRdy, + out_lvl_o => DataFifo_Level + ); + + -- An additional pipeline stage after the FIFO is required for timing reasons + i_dplstage : entity work.psi_common_pl_stage + generic map( + width_g => 70, + use_rdy_g => true + ) + port map( + clk_i => ClkMem, + rst_i => RstMem, + vld_i => DataFifo_PlVld, + rdy_o => DataFifo_PlRdy, + dat_i => DataFifo_PlData, + vld_o => Daq_Vld_I, + rdy_i => Daq_Rdy, + dat_o => DataFifo_OutData + ); + Str_Rdy <= DataFifo_InRdy; + + Daq_Data_I.Data <= DataFifo_OutData(63 downto 0); + Daq_Data_I.Bytes <= DataFifo_OutData(67 downto 64); + Daq_Data_I.IsTo <= DataFifo_OutData(68); + Daq_Data_I.IsTrig <= DataFifo_OutData(69); + Daq_Data_I.Last <= Daq_Data_I.IsTo or Daq_Data_I.IsTrig; + Daq_Data <= Daq_Data_I; + Daq_Vld <= Daq_Vld_I; + + -- Timestamp FIFO + g_timestamp : if StreamUseTs_g generate + TsFifo_InVld <= r.DataFifoVld and r.DataFifoIsTrig; + + i_tsfifo : entity work.psi_common_async_fifo + generic map( + width_g => 64, + depth_g => StreamTsFifoDepth_g, + afull_on_g => True, + afull_lvl_g => StreamTsFifoDepth_g - 1, + aempty_on_g => false, + ram_style_g => TsFifoStyle_c + ) + port map( + in_clk_i => Str_Clk, + in_rst_i => Str_Rst, + out_clk_i => ClkMem, + out_rst_i => '0', + in_dat_i => r.TsLatch, + in_vld_i => TsFifo_InVld, + in_rdy_o => TsFifo_InRdy, + in_afull_o => TsFifo_AlmFull, + in_empty_o => TsFifo_Empty, + out_dat_o => TsFifo_RdData, + out_vld_o => Ts_Vld_I, + out_rdy_o => Ts_Rdy + ); + Ts_Vld <= Ts_Vld_I; + -- Replace data by 0xFF... if no valid timestamp is available + Ts_Data <= (others => '1') when Ts_Vld_I = '0' else TsFifo_RdData; + end generate; + + g_ntimestamp : if not StreamUseTs_g generate + Ts_Vld <= '0'; + Ts_Data <= (others => '1'); + end generate; + + -------------------------------------------- + -- Assertions + -------------------------------------------- + p_assert : process(ClkMem) + begin + if rising_edge(ClkMem) then + assert StreamWidth_g = 8 or StreamWidth_g = 16 or StreamWidth_g = 32 or StreamWidth_g = 64 report "###ERROR###: psi_ms_daq_input: StreamWidth_g must be 8, 16, 32 or 64" severity error; + end if; + end process; + +end; diff --git a/hdl/psi_ms_daq_pkg.vhd b/hdl/psi_ms_daq_pkg.vhd index 7eb9854..830764e 100644 --- a/hdl/psi_ms_daq_pkg.vhd +++ b/hdl/psi_ms_daq_pkg.vhd @@ -8,157 +8,153 @@ -- Libraries ------------------------------------------------------------------------------ library ieee; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; - +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + library work; - use work.psi_common_math_pkg.all; +use work.psi_common_math_pkg.all; ------------------------------------------------------------------------------ -- Package Header ------------------------------------------------------------------------------ package psi_ms_daq_pkg is - constant MaxStreams_c : integer := 32; - constant MaxWindows_c : integer := 32; - constant MaxStreamsBits_c : integer := log2ceil(MaxStreams_c); - constant MaxWindowsBits_c : integer := log2ceil(MaxWindows_c); - constant MaxStreamWidth_c : integer := 64; - - subtype RecMode_t is std_logic_vector(1 downto 0); - constant RecMode_Continuous_c : RecMode_t := std_logic_vector(to_unsigned(0, RecMode_t'length)); - constant RecMode_TriggerMask_c : RecMode_t := std_logic_vector(to_unsigned(1, RecMode_t'length)); - constant RecMode_SingleShot_c : RecMode_t := std_logic_vector(to_unsigned(2, RecMode_t'length)); - constant RecMode_ManuelMode_c : RecMode_t := std_logic_vector(to_unsigned(3, RecMode_t'length)); - - subtype WinType_t is std_logic_vector(MaxWindowsBits_c-1 downto 0); - type WinType_a is array (natural range <>) of WinType_t; - - type Input2Daq_Data_t is record - Last : std_logic; - Data : std_logic_vector(63 downto 0); - Bytes : std_logic_vector(3 downto 0); - IsTo : std_logic; - IsTrig : std_logic; - end record; - type Input2Daq_Data_a is array (natural range <>) of Input2Daq_Data_t; - - type DaqSm2DaqDma_Cmd_t is record - Address : std_logic_vector(31 downto 0); - MaxSize : std_logic_vector(15 downto 0); - Stream : integer range 0 to MaxStreams_c-1; - end record; - constant DaqSm2DaqDma_Cmd_Size_c : integer := 32+16+MaxStreamsBits_c; - function DaqSm2DaqDma_Cmd_ToStdlv( rec : DaqSm2DaqDma_Cmd_t) return std_logic_vector; - function DaqSm2DaqDma_Cmd_FromStdlv( stdlv : std_logic_vector) return DaqSm2DaqDma_Cmd_t; - - type DaqDma2DaqSm_Resp_t is record - Size : std_logic_vector(15 downto 0); - Trigger : std_logic; - Stream : integer range 0 to MaxStreams_c-1; - end record; - constant DaqDma2DaqSm_Resp_Size_c : integer := 16+1+MaxStreamsBits_c; - function DaqDma2DaqSm_Resp_ToStdlv( rec : DaqDma2DaqSm_Resp_t) return std_logic_vector; - function DaqDme2DaqSm_Resp_FromStdlv( stdlv : std_logic_vector) return DaqDma2DaqSm_Resp_t; - - type ToCtxStr_t is record - Stream : integer range 0 to MaxStreams_c-1; - Sel : std_logic_vector(1 downto 0); - Rd : std_logic; - WenLo : std_logic; - WenHi : std_logic; - WdatLo : std_logic_vector(31 downto 0); - WdatHi : std_logic_vector(31 downto 0); - end record; - constant CtxStr_Sel_ScfgBufstart_c : std_logic_vector(1 downto 0) := "00"; - constant CtxStr_Sel_WinsizePtr_c : std_logic_vector(1 downto 0) := "01"; - constant CtxStr_Sel_Winend_c : std_logic_vector(1 downto 0) := "10"; - constant CtxStr_Sft_SCFG_RINGBUF_c : integer := 0; - constant CtxStr_Sft_SCFG_OVERWRITE_c : integer := 8; - constant CtxStr_Sft_SCFG_WINCNT_c : integer := 16; - constant CtxStr_Sft_SCFG_WINCUR_c : integer := 24; - - type ToCtxWin_t is record - Stream : integer range 0 to MaxStreams_c-1; - Window : integer range 0 to MaxWindows_c-1; - Sel : std_logic_vector(0 downto 0); - Rd : std_logic; - WenLo : std_logic; - WenHi : std_logic; - WdatLo : std_logic_vector(31 downto 0); - WdatHi : std_logic_vector(31 downto 0); - end record; - constant CtxWin_Sel_WincntWinlast_c : std_logic_vector(0 downto 0) := "0"; - constant CtxWin_Sel_WinTs_c : std_logic_vector(0 downto 0) := "1"; - - type FromCtx_t is record - RdatLo : std_logic_vector(31 downto 0); - RdatHi : std_logic_vector(31 downto 0); - end record; - - type TmemRqst_t is record - ADD : std_logic_vector(23 downto 0); - DATW : std_logic_vector(63 downto 0); - ENA : std_logic; - WE : std_logic_vector(7 downto 0); - CS : std_logic_vector(1 downto 0); - end record; - constant TmemRqst_init_c : TmemRqst_t := ((others => '0'), (others => '0'), '0', (others => '0'), (others => '0')); - - type TmemResp_t is record - DATR : std_logic_vector(63 downto 0); - BUSY : std_logic; - PIPE : std_logic_vector(1 downto 0); - end record; - -end psi_ms_daq_pkg; + constant MaxStreams_c : integer := 32; + constant MaxWindows_c : integer := 32; + constant MaxStreamsBits_c : integer := log2ceil(MaxStreams_c); + constant MaxWindowsBits_c : integer := log2ceil(MaxWindows_c); + constant MaxStreamWidth_c : integer := 64; + + subtype RecMode_t is std_logic_vector(1 downto 0); + constant RecMode_Continuous_c : RecMode_t := std_logic_vector(to_unsigned(0, RecMode_t'length)); + constant RecMode_TriggerMask_c : RecMode_t := std_logic_vector(to_unsigned(1, RecMode_t'length)); + constant RecMode_SingleShot_c : RecMode_t := std_logic_vector(to_unsigned(2, RecMode_t'length)); + constant RecMode_ManuelMode_c : RecMode_t := std_logic_vector(to_unsigned(3, RecMode_t'length)); + + subtype WinType_t is std_logic_vector(MaxWindowsBits_c - 1 downto 0); + type WinType_a is array (natural range <>) of WinType_t; + + type Input2Daq_Data_t is record + Last : std_logic; + Data : std_logic_vector(63 downto 0); + Bytes : std_logic_vector(3 downto 0); + IsTo : std_logic; + IsTrig : std_logic; + end record; + type Input2Daq_Data_a is array (natural range <>) of Input2Daq_Data_t; + + type DaqSm2DaqDma_Cmd_t is record + Address : std_logic_vector(31 downto 0); + MaxSize : std_logic_vector(15 downto 0); + Stream : integer range 0 to MaxStreams_c - 1; + end record; + constant DaqSm2DaqDma_Cmd_Size_c : integer := 32 + 16 + MaxStreamsBits_c; + function DaqSm2DaqDma_Cmd_ToStdlv(rec : DaqSm2DaqDma_Cmd_t) return std_logic_vector; + function DaqSm2DaqDma_Cmd_FromStdlv(stdlv : std_logic_vector) return DaqSm2DaqDma_Cmd_t; + + type DaqDma2DaqSm_Resp_t is record + Size : std_logic_vector(15 downto 0); + Trigger : std_logic; + Stream : integer range 0 to MaxStreams_c - 1; + end record; + constant DaqDma2DaqSm_Resp_Size_c : integer := 16 + 1 + MaxStreamsBits_c; + function DaqDma2DaqSm_Resp_ToStdlv(rec : DaqDma2DaqSm_Resp_t) return std_logic_vector; + function DaqDme2DaqSm_Resp_FromStdlv(stdlv : std_logic_vector) return DaqDma2DaqSm_Resp_t; + + type ToCtxStr_t is record + Stream : integer range 0 to MaxStreams_c - 1; + Sel : std_logic_vector(1 downto 0); + Rd : std_logic; + WenLo : std_logic; + WenHi : std_logic; + WdatLo : std_logic_vector(31 downto 0); + WdatHi : std_logic_vector(31 downto 0); + end record; + constant CtxStr_Sel_ScfgBufstart_c : std_logic_vector(1 downto 0) := "00"; + constant CtxStr_Sel_WinsizePtr_c : std_logic_vector(1 downto 0) := "01"; + constant CtxStr_Sel_Winend_c : std_logic_vector(1 downto 0) := "10"; + constant CtxStr_Sft_SCFG_RINGBUF_c : integer := 0; + constant CtxStr_Sft_SCFG_OVERWRITE_c : integer := 8; + constant CtxStr_Sft_SCFG_WINCNT_c : integer := 16; + constant CtxStr_Sft_SCFG_WINCUR_c : integer := 24; + + type ToCtxWin_t is record + Stream : integer range 0 to MaxStreams_c - 1; + Window : integer range 0 to MaxWindows_c - 1; + Sel : std_logic_vector(0 downto 0); + Rd : std_logic; + WenLo : std_logic; + WenHi : std_logic; + WdatLo : std_logic_vector(31 downto 0); + WdatHi : std_logic_vector(31 downto 0); + end record; + constant CtxWin_Sel_WincntWinlast_c : std_logic_vector(0 downto 0) := "0"; + constant CtxWin_Sel_WinTs_c : std_logic_vector(0 downto 0) := "1"; + + type FromCtx_t is record + RdatLo : std_logic_vector(31 downto 0); + RdatHi : std_logic_vector(31 downto 0); + end record; + + type TmemRqst_t is record + ADD : std_logic_vector(23 downto 0); + DATW : std_logic_vector(63 downto 0); + ENA : std_logic; + WE : std_logic_vector(7 downto 0); + CS : std_logic_vector(1 downto 0); + end record; + constant TmemRqst_init_c : TmemRqst_t := ((others => '0'), (others => '0'), '0', (others => '0'), (others => '0')); + + type TmemResp_t is record + DATR : std_logic_vector(63 downto 0); + BUSY : std_logic; + PIPE : std_logic_vector(1 downto 0); + end record; + +end psi_ms_daq_pkg; ------------------------------------------------------------------------------ -- Package Body ------------------------------------------------------------------------------ -package body psi_ms_daq_pkg is - - -- *** DaqSm2DaqDma_Cmd *** - function DaqSm2DaqDma_Cmd_ToStdlv( rec : DaqSm2DaqDma_Cmd_t) return std_logic_vector is - variable stdlv : std_logic_vector(DaqSm2DaqDma_Cmd_Size_c-1 downto 0); - begin - stdlv(31 downto 0) := rec.Address; - stdlv(47 downto 32) := rec.MaxSize; - stdlv(stdlv'left downto 48) := std_logic_vector(to_unsigned(rec.Stream, MaxStreamsBits_c)); - return stdlv; - end function; - - function DaqSm2DaqDma_Cmd_FromStdlv( stdlv : std_logic_vector) return DaqSm2DaqDma_Cmd_t is - variable rec : DaqSm2DaqDma_Cmd_t; - begin - rec.Address := stdlv(31 downto 0); - rec.MaxSize := stdlv(47 downto 32); - rec.Stream := to_integer(unsigned(stdlv(stdlv'left downto 48))); - return rec; - end function; - - -- *** DaqDma2DaqSm_Resp *** - function DaqDma2DaqSm_Resp_ToStdlv( rec : DaqDma2DaqSm_Resp_t) return std_logic_vector is - variable stdlv : std_logic_vector(DaqDma2DaqSm_Resp_Size_c-1 downto 0); - begin - stdlv(15 downto 0) := rec.Size; - stdlv(16) := rec.Trigger; - stdlv(stdlv'left downto 17) := std_logic_vector(to_unsigned(rec.Stream, MaxStreamsBits_c)); - return stdlv; - end function; - - function DaqDme2DaqSm_Resp_FromStdlv( stdlv : std_logic_vector) return DaqDma2DaqSm_Resp_t is - variable rec : DaqDma2DaqSm_Resp_t; - begin - rec.Size := stdlv(15 downto 0); - rec.Trigger := stdlv(16); - rec.Stream := to_integer(unsigned(stdlv(stdlv'left downto 17))); - return rec; - end function; - +package body psi_ms_daq_pkg is + + -- *** DaqSm2DaqDma_Cmd *** + function DaqSm2DaqDma_Cmd_ToStdlv(rec : DaqSm2DaqDma_Cmd_t) return std_logic_vector is + variable stdlv : std_logic_vector(DaqSm2DaqDma_Cmd_Size_c - 1 downto 0); + begin + stdlv(31 downto 0) := rec.Address; + stdlv(47 downto 32) := rec.MaxSize; + stdlv(stdlv'left downto 48) := std_logic_vector(to_unsigned(rec.Stream, MaxStreamsBits_c)); + return stdlv; + end function; + + function DaqSm2DaqDma_Cmd_FromStdlv(stdlv : std_logic_vector) return DaqSm2DaqDma_Cmd_t is + variable rec : DaqSm2DaqDma_Cmd_t; + begin + rec.Address := stdlv(31 downto 0); + rec.MaxSize := stdlv(47 downto 32); + rec.Stream := to_integer(unsigned(stdlv(stdlv'left downto 48))); + return rec; + end function; + + -- *** DaqDma2DaqSm_Resp *** + function DaqDma2DaqSm_Resp_ToStdlv(rec : DaqDma2DaqSm_Resp_t) return std_logic_vector is + variable stdlv : std_logic_vector(DaqDma2DaqSm_Resp_Size_c - 1 downto 0); + begin + stdlv(15 downto 0) := rec.Size; + stdlv(16) := rec.Trigger; + stdlv(stdlv'left downto 17) := std_logic_vector(to_unsigned(rec.Stream, MaxStreamsBits_c)); + return stdlv; + end function; + + function DaqDme2DaqSm_Resp_FromStdlv(stdlv : std_logic_vector) return DaqDma2DaqSm_Resp_t is + variable rec : DaqDma2DaqSm_Resp_t; + begin + rec.Size := stdlv(15 downto 0); + rec.Trigger := stdlv(16); + rec.Stream := to_integer(unsigned(stdlv(stdlv'left downto 17))); + return rec; + end function; + end psi_ms_daq_pkg; - - - - diff --git a/hdl/psi_ms_daq_reg_axi.vhd b/hdl/psi_ms_daq_reg_axi.vhd index 40abbe0..302925f 100644 --- a/hdl/psi_ms_daq_reg_axi.vhd +++ b/hdl/psi_ms_daq_reg_axi.vhd @@ -7,556 +7,546 @@ ------------------------------------------------------------------------------ -- Libraries ------------------------------------------------------------------------------ - library ieee; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; library work; - use work.psi_common_math_pkg.all; - use work.psi_common_array_pkg.all; - use work.psi_common_logic_pkg.all; - use work.psi_ms_daq_pkg.all; +use work.psi_common_math_pkg.all; +use work.psi_common_array_pkg.all; +use work.psi_common_logic_pkg.all; +use work.psi_ms_daq_pkg.all; ------------------------------------------------------------------------------ -- Entity Declaration ------------------------------------------------------------------------------ entity psi_ms_daq_reg_axi is - generic ( - Streams_g : integer range 1 to 32; - MaxWindows_g : integer range 1 to 32; - AxiSlaveIdWidth_g : integer - ); - port ( - -- AXI Control Signals - S_Axi_Aclk : in std_logic; - S_Axi_Aresetn : in std_logic; - -- AXI Read address channel - S_Axi_ArId : in std_logic_vector(AxiSlaveIdWidth_g-1 downto 0); - S_Axi_ArAddr : in std_logic_vector(15 downto 0); - S_Axi_Arlen : in std_logic_vector(7 downto 0); - S_Axi_ArSize : in std_logic_vector(2 downto 0); - S_Axi_ArBurst : in std_logic_vector(1 downto 0); - S_Axi_ArLock : in std_logic; - S_Axi_ArCache : in std_logic_vector(3 downto 0); - S_Axi_ArProt : in std_logic_vector(2 downto 0); - S_Axi_ArValid : in std_logic; - S_Axi_ArReady : out std_logic; - -- AXI Read data channel - S_Axi_RId : out std_logic_vector(AxiSlaveIdWidth_g-1 downto 0); - S_Axi_RData : out std_logic_vector(31 downto 0); - S_Axi_RResp : out std_logic_vector(1 downto 0); - S_Axi_RLast : out std_logic; - S_Axi_RValid : out std_logic; - S_Axi_RReady : in std_logic; - -- AXI Write address channel - S_Axi_AwId : in std_logic_vector(AxiSlaveIdWidth_g-1 downto 0); - S_Axi_AwAddr : in std_logic_vector(15 downto 0); - S_Axi_AwLen : in std_logic_vector(7 downto 0); - S_Axi_AwSize : in std_logic_vector(2 downto 0); - S_Axi_AwBurst : in std_logic_vector(1 downto 0); - S_Axi_AwLock : in std_logic; - S_Axi_AwCache : in std_logic_vector(3 downto 0); - S_Axi_AwProt : in std_logic_vector(2 downto 0); - S_Axi_AwValid : in std_logic; - S_Axi_AwReady : out std_logic; - -- AXI Write data channel - S_Axi_WData : in std_logic_vector(31 downto 0); - S_Axi_WStrb : in std_logic_vector(3 downto 0); - S_Axi_WLast : in std_logic; - S_Axi_WValid : in std_logic; - S_Axi_WReady : out std_logic; - -- AXI Write response channel - S_Axi_BId : out std_logic_vector(AxiSlaveIdWidth_g-1 downto 0); - S_Axi_BResp : out std_logic_vector(1 downto 0); - S_Axi_BValid : out std_logic; - S_Axi_BReady : in std_logic; - - -- Control Signals (AXI-S Clk) - Arm : out std_logic_vector(Streams_g-1 downto 0); - IsArmed : in std_logic_vector(Streams_g-1 downto 0); - IsRecording : in std_logic_vector(Streams_g-1 downto 0); - PostTrig : out t_aslv32(Streams_g-1 downto 0); - RecMode : out t_aslv2(Streams_g-1 downto 0); - IrqOut : out std_logic; - - -- Memory Interfae Clock domain control singals - ClkMem : in std_logic; - RstMem : in std_logic; - - -- Context Memory Interface (MemClk) - CtxStr_Cmd : in ToCtxStr_t; - CtxStr_Resp : out FromCtx_t; - CtxWin_Cmd : in ToCtxWin_t; - CtxWin_Resp : out FromCtx_t; - - -- Logic Interface (MemClk) - StrIrq : in std_logic_vector(Streams_g-1 downto 0); - StrLastWin : in WinType_a(Streams_g-1 downto 0); - StrEna : out std_logic_vector(Streams_g-1 downto 0); - GlbEna : out std_logic; - InLevel : in t_aslv16(Streams_g-1 downto 0) - ); + generic( + Streams_g : integer range 1 to 32; + MaxWindows_g : integer range 1 to 32; + AxiSlaveIdWidth_g : integer + ); + port( + -- AXI Control Signals + S_Axi_Aclk : in std_logic; + S_Axi_Aresetn : in std_logic; + -- AXI Read address channel + S_Axi_ArId : in std_logic_vector(AxiSlaveIdWidth_g - 1 downto 0); + S_Axi_ArAddr : in std_logic_vector(15 downto 0); + S_Axi_Arlen : in std_logic_vector(7 downto 0); + S_Axi_ArSize : in std_logic_vector(2 downto 0); + S_Axi_ArBurst : in std_logic_vector(1 downto 0); + S_Axi_ArLock : in std_logic; + S_Axi_ArCache : in std_logic_vector(3 downto 0); + S_Axi_ArProt : in std_logic_vector(2 downto 0); + S_Axi_ArValid : in std_logic; + S_Axi_ArReady : out std_logic; + -- AXI Read data channel + S_Axi_RId : out std_logic_vector(AxiSlaveIdWidth_g - 1 downto 0); + S_Axi_RData : out std_logic_vector(31 downto 0); + S_Axi_RResp : out std_logic_vector(1 downto 0); + S_Axi_RLast : out std_logic; + S_Axi_RValid : out std_logic; + S_Axi_RReady : in std_logic; + -- AXI Write address channel + S_Axi_AwId : in std_logic_vector(AxiSlaveIdWidth_g - 1 downto 0); + S_Axi_AwAddr : in std_logic_vector(15 downto 0); + S_Axi_AwLen : in std_logic_vector(7 downto 0); + S_Axi_AwSize : in std_logic_vector(2 downto 0); + S_Axi_AwBurst : in std_logic_vector(1 downto 0); + S_Axi_AwLock : in std_logic; + S_Axi_AwCache : in std_logic_vector(3 downto 0); + S_Axi_AwProt : in std_logic_vector(2 downto 0); + S_Axi_AwValid : in std_logic; + S_Axi_AwReady : out std_logic; + -- AXI Write data channel + S_Axi_WData : in std_logic_vector(31 downto 0); + S_Axi_WStrb : in std_logic_vector(3 downto 0); + S_Axi_WLast : in std_logic; + S_Axi_WValid : in std_logic; + S_Axi_WReady : out std_logic; + -- AXI Write response channel + S_Axi_BId : out std_logic_vector(AxiSlaveIdWidth_g - 1 downto 0); + S_Axi_BResp : out std_logic_vector(1 downto 0); + S_Axi_BValid : out std_logic; + S_Axi_BReady : in std_logic; + -- Control Signals (AXI-S Clk) + Arm : out std_logic_vector(Streams_g - 1 downto 0); + IsArmed : in std_logic_vector(Streams_g - 1 downto 0); + IsRecording : in std_logic_vector(Streams_g - 1 downto 0); + PostTrig : out t_aslv32(Streams_g - 1 downto 0); + RecMode : out t_aslv2(Streams_g - 1 downto 0); + IrqOut : out std_logic; + -- Memory Interfae Clock domain control singals + ClkMem : in std_logic; + RstMem : in std_logic; + -- Context Memory Interface (MemClk) + CtxStr_Cmd : in ToCtxStr_t; + CtxStr_Resp : out FromCtx_t; + CtxWin_Cmd : in ToCtxWin_t; + CtxWin_Resp : out FromCtx_t; + -- Logic Interface (MemClk) + StrIrq : in std_logic_vector(Streams_g - 1 downto 0); + StrLastWin : in WinType_a(Streams_g - 1 downto 0); + StrEna : out std_logic_vector(Streams_g - 1 downto 0); + GlbEna : out std_logic; + InLevel : in t_aslv16(Streams_g - 1 downto 0) + ); end entity; architecture rtl of psi_ms_daq_reg_axi is - -- Two process method - type two_process_r is record - Reg_Gcfg_Ena : std_logic; - Reg_Gcfg_IrqEna : std_logic; - Reg_IrqVec : std_logic_vector(Streams_g-1 downto 0); - Reg_IrqEna : std_logic_vector(Streams_g-1 downto 0); - Reg_StrEna : std_logic_vector(Streams_g-1 downto 0); - Reg_PostTrig : t_aslv32(Streams_g-1 downto 0); - Reg_Mode_Recm : t_aslv2(Streams_g-1 downto 0); - Reg_Mode_Arm : std_logic_vector(Streams_g-1 downto 0); - Irq : std_logic; - RegRdval : std_logic_vector(31 downto 0); - AddrReg : std_logic_vector(15 downto 0); - MaxLvlClr : std_logic_vector(Streams_g-1 downto 0); - end record; - signal r, r_next : two_process_r; - - constant DwWrite_c : std_logic_vector(3 downto 0) := "1111"; - - constant DepthCtxStr_c : integer := Streams_g*32/8; - constant CtxStrAddrHigh_c : integer := log2ceil(Streams_g*32)-1; - signal CtxStr_WeLo : std_logic; - signal CtxStr_WeHi : std_logic; - signal CtxStr_Rdval : std_logic_vector(63 downto 0); - signal CtxStr_AddrB : std_logic_vector(log2ceil(DepthCtxStr_c)-1 downto 0); - signal AddrCtxStr : boolean; - - constant DepthCtxWin_c : integer := Streams_g*MaxWindows_g*16/8; - constant CtxWinAddrHigh_c : integer := log2ceil(Streams_g*MaxWindows_g*16)-1; - signal CtxWin_WeLo : std_logic; - signal CtxWin_WeHi : std_logic; - signal CtxWin_Rdval : std_logic_vector(63 downto 0); - signal CtxWin_AddrB : std_logic_vector(log2ceil(DepthCtxWin_c)-1 downto 0); - signal AddrCtxWin : boolean; - - -- High active reset - signal A_Axi_Areset : std_logic; - - -- Maximum Level Latching - signal MaxLevel : t_aslv16(Streams_g-1 downto 0); - - -- Clock Crossing Signals - signal StrIrq_Sync : std_logic_vector(Streams_g-1 downto 0); - signal StrLastWin_Sync : WinType_a(Streams_g-1 downto 0); - signal MaxLevel_Sync : t_aslv16(Streams_g-1 downto 0); - signal MaxLevelClr_Sync : std_logic_vector(Streams_g-1 downto 0); - - -- Axi Accesses - signal AccAddr : std_logic_vector(15 downto 0); - signal AccAddrOffs : std_logic_vector(15 downto 0); - signal AccWr : std_logic_vector(3 downto 0); - signal AccWrData : std_logic_vector(31 downto 0); - signal AccRdData : std_logic_vector(31 downto 0); - signal RegWrVal : t_aslv32(0 to 15); - signal RegRdVal : t_aslv32(0 to 15) := (others => (others => '0')); - signal RegWr : std_logic_vector(15 downto 0); + -- Two process method + type two_process_r is record + Reg_Gcfg_Ena : std_logic; + Reg_Gcfg_IrqEna : std_logic; + Reg_IrqVec : std_logic_vector(Streams_g - 1 downto 0); + Reg_IrqEna : std_logic_vector(Streams_g - 1 downto 0); + Reg_StrEna : std_logic_vector(Streams_g - 1 downto 0); + Reg_PostTrig : t_aslv32(Streams_g - 1 downto 0); + Reg_Mode_Recm : t_aslv2(Streams_g - 1 downto 0); + Reg_Mode_Arm : std_logic_vector(Streams_g - 1 downto 0); + Irq : std_logic; + RegRdval : std_logic_vector(31 downto 0); + AddrReg : std_logic_vector(15 downto 0); + MaxLvlClr : std_logic_vector(Streams_g - 1 downto 0); + end record; + signal r, r_next : two_process_r; + + constant DwWrite_c : std_logic_vector(3 downto 0) := "1111"; + + constant DepthCtxStr_c : integer := Streams_g * 32 / 8; + constant CtxStrAddrHigh_c : integer := log2ceil(Streams_g * 32) - 1; + signal CtxStr_WeLo : std_logic; + signal CtxStr_WeHi : std_logic; + signal CtxStr_Rdval : std_logic_vector(63 downto 0); + signal CtxStr_AddrB : std_logic_vector(log2ceil(DepthCtxStr_c) - 1 downto 0); + signal AddrCtxStr : boolean; + + constant DepthCtxWin_c : integer := Streams_g * MaxWindows_g * 16 / 8; + constant CtxWinAddrHigh_c : integer := log2ceil(Streams_g * MaxWindows_g * 16) - 1; + signal CtxWin_WeLo : std_logic; + signal CtxWin_WeHi : std_logic; + signal CtxWin_Rdval : std_logic_vector(63 downto 0); + signal CtxWin_AddrB : std_logic_vector(log2ceil(DepthCtxWin_c) - 1 downto 0); + signal AddrCtxWin : boolean; + + -- High active reset + signal A_Axi_Areset : std_logic; + + -- Maximum Level Latching + signal MaxLevel : t_aslv16(Streams_g - 1 downto 0); + + -- Clock Crossing Signals + signal StrIrq_Sync : std_logic_vector(Streams_g - 1 downto 0); + signal StrLastWin_Sync : WinType_a(Streams_g - 1 downto 0); + signal MaxLevel_Sync : t_aslv16(Streams_g - 1 downto 0); + signal MaxLevelClr_Sync : std_logic_vector(Streams_g - 1 downto 0); + + -- Axi Accesses + signal AccAddr : std_logic_vector(15 downto 0); + signal AccAddrOffs : std_logic_vector(15 downto 0); + signal AccWr : std_logic_vector(3 downto 0); + signal AccWrData : std_logic_vector(31 downto 0); + signal AccRdData : std_logic_vector(31 downto 0); + signal RegWrVal : t_aslv32(0 to 15); + signal RegRdVal : t_aslv32(0 to 15) := (others => (others => '0')); + signal RegWr : std_logic_vector(15 downto 0); begin - A_Axi_Areset <= not S_Axi_Aresetn; + A_Axi_Areset <= not S_Axi_Aresetn; - -------------------------------------------- - -- Combinatorial Process - -------------------------------------------- - p_comb : process( r, AccAddr, AccWr, AccWrData, StrIrq_Sync, IsArmed, IsRecording, CtxStr_Rdval, CtxWin_Rdval, MaxLevel, StrLastWin_Sync, RegWr, RegWrVal) - variable v : two_process_r; - variable Stream_v : integer range 0 to Streams_g-1; - begin - -- *** Hold variables stable *** - v := r; - - -- *** General Register Accesses *** - -- GCFG - if RegWr(16#00#/4) = '1' then - v.Reg_Gcfg_Ena := RegWrVal(16#00#/4)(0); - v.Reg_Gcfg_IrqEna := RegWrVal(16#00#/4)(8); - end if; - RegRdVal(16#00#/4)(0) <= r.Reg_Gcfg_Ena; - RegRdVal(16#00#/4)(8) <= r.Reg_Gcfg_IrqEna; - - -- GSTAT - if RegWr(16#04#/4) = '1' then - null; - end if; - RegRdVal(16#04#/4) <= (others => '0'); - - -- IRQVEC - if RegWr(16#10#/4) = '1' then - v.Reg_IrqVec := r.Reg_IrqVec and (not RegWrVal(16#10#/4)(Streams_g-1 downto 0)); - end if; - RegRdVal(16#10#/4)(Streams_g-1 downto 0) <= r.Reg_IrqVec; - - -- IRQENA - if RegWr(16#14#/4) = '1' then - v.Reg_IrqEna := RegWrVal(16#14#/4)(Streams_g-1 downto 0); - end if; - RegRdVal(16#14#/4)(Streams_g-1 downto 0) <= r.Reg_IrqEna; - - -- STRENA - if RegWr(16#20#/4) = '1' then - v.Reg_StrEna := RegWrVal(16#20#/4)(Streams_g-1 downto 0); - end if; - RegRdVal(16#20#/4)(Streams_g-1 downto 0) <= r.Reg_StrEna; - - -- *** Stream Register Accesses *** - v.RegRdval := (others => '0'); - v.Reg_Mode_Arm := (others => '0'); - v.MaxLvlClr := (others => '0'); - if AccAddr(15 downto 9) = X"0" & "001" then - Stream_v := work.psi_common_math_pkg.min(to_integer(unsigned(AccAddr(8 downto 4))), Streams_g-1); - - -- MAXLVLn - if AccAddr(3 downto 0) = X"0" then - if AccWr = DwWrite_c then - v.MaxLvlClr(Stream_v) := '1'; - end if; - v.RegRdval(15 downto 0) := MaxLevel(Stream_v); - end if; - - -- POSTTRIGn - if AccAddr(3 downto 0) = X"4" then - if AccWr = DwWrite_c then - v.Reg_PostTrig(Stream_v) := AccWrData; - end if; - v.RegRdval := r.Reg_PostTrig(Stream_v); - end if; - - -- MODEn / LASTWINn - if AccAddr(3 downto 0) = X"8" then - if AccWr(0) = '1' then - v.Reg_Mode_Recm(Stream_v) := AccWrData(1 downto 0); - end if; - if AccWr(1) = '1' then - v.Reg_Mode_Arm(Stream_v) := AccWrData(8); - end if; - v.RegRdval(1 downto 0) := r.Reg_Mode_Recm(Stream_v); - v.RegRdval(8) := IsArmed(Stream_v); - v.RegRdval(16) := IsRecording(Stream_v); - end if; - - -- LASTWINn - if AccAddr(3 downto 0) = X"C" then - -- LASTWINn - v.RegRdval(MaxWindowsBits_c-1 downto 0) := StrLastWin_Sync(Stream_v); - end if; - - - end if; - - -- *** Read Data MUX *** - v.AddrReg := AccAddr; - AccRdData <= (others => '0'); - if r.AddrReg(15 downto 12) = X"0" then - AccRdData <= r.RegRdval; - elsif r.AddrReg(15 downto 12) = X"1" then - -- High-low dword in different memories - if r.AddrReg(2) = '0' then - AccRdData <= CtxStr_Rdval(31 downto 0); - else - AccRdData <= CtxStr_Rdval(63 downto 32); - end if; - elsif r.AddrReg(15 downto 14) = "01" then - -- High-low dword in different memories - if r.AddrReg(2) = '0' then - AccRdData <= CtxWin_Rdval(31 downto 0); - else - AccRdData <= CtxWin_Rdval(63 downto 32); - end if; - end if; - - -- *** IRQ Handling *** - for i in 0 to Streams_g-1 loop - if (StrIrq_Sync(i) = '1') and (r.Reg_StrEna(i) = '1') then - v.Reg_IrqVec(i) := '1'; - end if; - end loop; - if ((r.Reg_IrqVec and r.Reg_IrqEna) /= ZerosVector(Streams_g)) and (r.Reg_Gcfg_IrqEna = '1') then - v.Irq := '1'; - else - v.Irq := '0'; - end if; - + -------------------------------------------- + -- Combinatorial Process + -------------------------------------------- + p_comb : process(r, AccAddr, AccWr, AccWrData, StrIrq_Sync, IsArmed, IsRecording, CtxStr_Rdval, CtxWin_Rdval, MaxLevel, StrLastWin_Sync, RegWr, RegWrVal) + variable v : two_process_r; + variable Stream_v : integer range 0 to Streams_g - 1; + begin + -- *** Hold variables stable *** + v := r; - - -- *** Assign to signal *** - r_next <= v; - - end process; - - -- *** Registered Outputs *** - IrqOut <= r.Irq; - PostTrig <= r.Reg_PostTrig; - Arm <= r.Reg_Mode_Arm; - RecMode <= r.Reg_Mode_Recm; - - -------------------------------------------- - -- Sequential Process - -------------------------------------------- - p_seq : process(S_Axi_Aclk) - begin - if rising_edge(S_Axi_Aclk) then - r <= r_next; - if A_Axi_Areset = '1' then - r.Reg_Gcfg_Ena <= '0'; - r.Reg_Gcfg_IrqEna <= '0'; - r.Reg_IrqVec <= (others => '0'); - r.Reg_IrqEna <= (others => '0'); - r.Reg_StrEna <= (others => '0'); - r.Irq <= '0'; - r.Reg_PostTrig <= (others => (others => '0')); - r.Reg_Mode_Recm <= (others => (others => '0')); - r.Reg_Mode_Arm <= (others => '0'); - end if; - end if; - end process; - - -------------------------------------------- - -- Maximum Level Latching (MemClk) - -------------------------------------------- - p_maxlvl : process(ClkMem) - begin - if rising_edge(ClkMem) then - if RstMem = '1' then - MaxLevel <= (others => (others => '0')); - else - -- Latch maximum level - for i in 0 to Streams_g-1 loop - if MaxLevelClr_Sync(i) = '1' then - MaxLevel(i) <= (others => '0'); - elsif unsigned(InLevel(i)) > unsigned(MaxLevel(i)) then - MaxLevel(i) <= InLevel(i); - end if; - end loop; - end if; - end if; - end process; + -- *** General Register Accesses *** + -- GCFG + if RegWr(16#00# / 4) = '1' then + v.Reg_Gcfg_Ena := RegWrVal(16#00# / 4)(0); + v.Reg_Gcfg_IrqEna := RegWrVal(16#00# / 4)(8); + end if; + RegRdVal(16#00# / 4)(0) <= r.Reg_Gcfg_Ena; + RegRdVal(16#00# / 4)(8) <= r.Reg_Gcfg_IrqEna; - -------------------------------------------- - -- Component Instantiations - -------------------------------------------- - - -- *** AXI Interface *** - i_axi : entity work.psi_common_axi_slave_ipif - generic map ( - NumReg_g => 16, - ResetVal_g => (0 => (others => '0'), 1 => (others => '0'), 2 => (others => '0'), 3 => (others => '0'), - 4 => (others => '0'), 5 => (others => '0'), 6 => (others => '0'), 7 => (others => '0'), - 8 => (others => '0'), 9 => (others => '0'), 10 => (others => '0'), 11 => (others => '0'), - 12 => (others => '0'), 13 => (others => '0'), 14 => (others => '0'), 15 => (others => '0')), - UseMem_g => true, - AxiIdWidth_g => AxiSlaveIdWidth_g, - AxiAddrWidth_g => 16 - ) - port map ( - s_axi_aclk => S_Axi_Aclk, - s_axi_aresetn => S_Axi_Aresetn, - s_axi_arid => S_Axi_ArId, - s_axi_araddr => S_Axi_ArAddr, - s_axi_arlen => S_Axi_Arlen, - s_axi_arsize => S_Axi_ArSize, - s_axi_arburst => S_Axi_ArBurst, - s_axi_arlock => S_Axi_ArLock, - s_axi_arcache => S_Axi_ArCache, - s_axi_arprot => S_Axi_ArProt, - s_axi_arvalid => S_Axi_ArValid, - s_axi_arready => S_Axi_ArReady, - s_axi_rid => S_Axi_RId, - s_axi_rdata => S_Axi_RData, - s_axi_rresp => S_Axi_RResp, - s_axi_rlast => S_Axi_RLast, - s_axi_rvalid => S_Axi_RValid, - s_axi_rready => S_Axi_RReady, - s_axi_awid => S_Axi_AwId, - s_axi_awaddr => S_Axi_AwAddr, - s_axi_awlen => S_Axi_AwLen, - s_axi_awsize => S_Axi_AwSize, - s_axi_awburst => S_Axi_AwBurst, - s_axi_awlock => S_Axi_AwLock, - s_axi_awcache => S_Axi_AwCache, - s_axi_awprot => S_Axi_AwProt, - s_axi_awvalid => S_Axi_AwValid, - s_axi_awready => S_Axi_AwReady, - s_axi_wdata => S_Axi_WData, - s_axi_wstrb => S_Axi_WStrb, - s_axi_wlast => S_Axi_WLast, - s_axi_wvalid => S_Axi_WValid, - s_axi_wready => S_Axi_WReady, - s_axi_bid => S_Axi_BId, - s_axi_bresp => S_Axi_BResp, - s_axi_bvalid => S_Axi_BValid, - s_axi_bready => S_Axi_BReady, - o_reg_rd => open, - i_reg_rdata => RegRdVal, - o_reg_wr => RegWr, - o_reg_wdata => RegWrVal, - o_mem_addr => AccAddrOffs, - o_mem_wr => AccWr, - o_mem_wdata => AccWrData, - i_mem_rdata => AccRdData - ); - - AccAddr <= std_logic_vector(unsigned(AccAddrOffs) + 16*4); - - -- *** Clock Crossings *** - blk_cc_irq : block - begin - g_in : for i in 0 to Streams_g-1 generate - - i_cc_irq : entity work.psi_common_simple_cc - generic map ( - DataWidth_g => log2ceil(MaxWindows_c) - ) - port map ( - ClkA => ClkMem, - RstInA => RstMem, - DataA => StrLastWin(i), - VldA => StrIrq(i), - ClkB => S_Axi_Aclk, - RstInB => A_Axi_Areset, - DataB => StrLastWin_Sync(i), - VldB => StrIrq_Sync(i) - ); - end generate; - end block; - - blk_cc_mem_out : block - signal ccIn, ccOut : std_logic_vector(Streams_g downto 0); - begin - -- Input Assembly - ccIn(Streams_g-1 downto 0) <= r.Reg_StrEna; - ccIn(Streams_g) <= r.Reg_Gcfg_Ena; - - -- Instantiation - i_cc_mem_out : entity work.psi_common_bit_cc - generic map ( - NumBits_g => Streams_g+1 - ) - port map ( - BitsA => ccIn, - ClkB => ClkMem, - BitsB => ccOut - ); - - -- Output assembly - StrEna <= ccOut(Streams_g-1 downto 0); - GlbEna <= ccOut(Streams_g); - end block; - - i_cc_mem_out_pulse : entity work.psi_common_pulse_cc - generic map ( - NumPulses_g => Streams_g - ) - port map ( - ClkA => S_Axi_Aclk, - RstInA => A_Axi_Areset, - PulseA => r.MaxLvlClr, - ClkB => ClkMem, - RstInB => RstMem, - PulseB => MaxLevelClr_Sync - ); - - - -- *** Stream Context Memory *** - -- Signal Assembly - AddrCtxStr <= AccAddr(15 downto 12) = X"1"; - CtxStr_WeLo <= '1' when AccWr = DwWrite_c and AddrCtxStr and AccAddr(2) = '0' else '0'; - CtxStr_WeHi <= '1' when AccWr = DwWrite_c and AddrCtxStr and AccAddr(2) = '1' else '0'; - CtxStr_AddrB <= std_logic_vector(to_unsigned(CtxStr_Cmd.Stream, log2ceil(Streams_g))) & CtxStr_Cmd.Sel; - - -- Memory is split organized as 64 bit memory for historical reasons (Tosca TMEM is 64-bit) - - -- Low DWORD memory - i_mem_ctx_lo : entity work.psi_common_tdp_ram - generic map ( - Depth_g => DepthCtxStr_c, - Width_g => 32, - Behavior_g => "RBW" - ) - port map ( - ClkA => S_Axi_Aclk, - AddrA => AccAddr(CtxStrAddrHigh_c downto 3), - WrA => CtxStr_WeLo, - DinA => AccWrData, - DoutA => CtxStr_Rdval(31 downto 0), - ClkB => ClkMem, - AddrB => CtxStr_AddrB, - WrB => CtxStr_Cmd.WenLo, - DinB => CtxStr_Cmd.WdatLo, - DoutB => CtxStr_Resp.RdatLo - ); - - -- High DWORD memory - i_mem_ctx_hi : entity work.psi_common_tdp_ram - generic map ( - Depth_g => DepthCtxStr_c, - Width_g => 32, - Behavior_g => "RBW" - ) - port map ( - ClkA => S_Axi_Aclk, - AddrA => AccAddr(CtxStrAddrHigh_c downto 3), - WrA => CtxStr_WeHi, - DinA => AccWrData, - DoutA => CtxStr_Rdval(63 downto 32), - ClkB => ClkMem, - AddrB => CtxStr_AddrB, - WrB => CtxStr_Cmd.WenHi, - DinB => CtxStr_Cmd.WdatHi, - DoutB => CtxStr_Resp.RdatHi - ); + -- GSTAT + if RegWr(16#04# / 4) = '1' then + null; + end if; + RegRdVal(16#04# / 4) <= (others => '0'); - -- *** Window Context Memory *** - -- Signal Assembly - AddrCtxWin <= AccAddr(15 downto 14) = "01"; - CtxWin_WeLo <= '1' when AccWr = DwWrite_c and AddrCtxWin and AccAddr(2) = '0' else '0'; - CtxWin_WeHi <= '1' when AccWr = DwWrite_c and AddrCtxWin and AccAddr(2) = '1' else '0'; - CtxWin_AddrB <= std_logic_vector(to_unsigned(CtxWin_Cmd.Stream, log2ceil(Streams_g))) & - std_logic_vector(to_unsigned(CtxWin_Cmd.Window, log2ceil(MaxWindows_g))) & - CtxWin_Cmd.Sel; - - -- Memory is split organized as 64 bit memory for historical reasons (Tosca TMEM is 64-bit) - - -- Low DWORD memory - i_mem_win_lo : entity work.psi_common_tdp_ram - generic map ( - Depth_g => DepthCtxWin_c, - Width_g => 32, - Behavior_g => "RBW" - ) - port map ( - ClkA => S_Axi_Aclk, - AddrA => AccAddr(CtxWinAddrHigh_c downto 3), - WrA => CtxWin_WeLo, - DinA => AccWrData, - DoutA => CtxWin_Rdval(31 downto 0), - ClkB => ClkMem, - AddrB => CtxWin_AddrB, - WrB => CtxWin_Cmd.WenLo, - DinB => CtxWin_Cmd.WdatLo, - DoutB => CtxWin_Resp.RdatLo - ); - - -- High DWORD memory - i_mem_win_hi : entity work.psi_common_tdp_ram - generic map ( - Depth_g => DepthCtxWin_c, - Width_g => 32, - Behavior_g => "RBW" - ) - port map ( - ClkA => S_Axi_Aclk, - AddrA => AccAddr(CtxWinAddrHigh_c downto 3), - WrA => CtxWin_WeHi, - DinA => AccWrData, - DoutA => CtxWin_Rdval(63 downto 32), - ClkB => ClkMem, - AddrB => CtxWin_AddrB, - WrB => CtxWin_Cmd.WenHi, - DinB => CtxWin_Cmd.WdatHi, - DoutB => CtxWin_Resp.RdatHi - ); + -- IRQVEC + if RegWr(16#10# / 4) = '1' then + v.Reg_IrqVec := r.Reg_IrqVec and (not RegWrVal(16#10# / 4)(Streams_g - 1 downto 0)); + end if; + RegRdVal(16#10# / 4)(Streams_g - 1 downto 0) <= r.Reg_IrqVec; + + -- IRQENA + if RegWr(16#14# / 4) = '1' then + v.Reg_IrqEna := RegWrVal(16#14# / 4)(Streams_g - 1 downto 0); + end if; + RegRdVal(16#14# / 4)(Streams_g - 1 downto 0) <= r.Reg_IrqEna; + + -- STRENA + if RegWr(16#20# / 4) = '1' then + v.Reg_StrEna := RegWrVal(16#20# / 4)(Streams_g - 1 downto 0); + end if; + RegRdVal(16#20# / 4)(Streams_g - 1 downto 0) <= r.Reg_StrEna; + + -- *** Stream Register Accesses *** + v.RegRdval := (others => '0'); + v.Reg_Mode_Arm := (others => '0'); + v.MaxLvlClr := (others => '0'); + if AccAddr(15 downto 9) = X"0" & "001" then + Stream_v := work.psi_common_math_pkg.min(to_integer(unsigned(AccAddr(8 downto 4))), Streams_g - 1); + + -- MAXLVLn + if AccAddr(3 downto 0) = X"0" then + if AccWr = DwWrite_c then + v.MaxLvlClr(Stream_v) := '1'; + end if; + v.RegRdval(15 downto 0) := MaxLevel(Stream_v); + end if; + + -- POSTTRIGn + if AccAddr(3 downto 0) = X"4" then + if AccWr = DwWrite_c then + v.Reg_PostTrig(Stream_v) := AccWrData; + end if; + v.RegRdval := r.Reg_PostTrig(Stream_v); + end if; + + -- MODEn / LASTWINn + if AccAddr(3 downto 0) = X"8" then + if AccWr(0) = '1' then + v.Reg_Mode_Recm(Stream_v) := AccWrData(1 downto 0); + end if; + if AccWr(1) = '1' then + v.Reg_Mode_Arm(Stream_v) := AccWrData(8); + end if; + v.RegRdval(1 downto 0) := r.Reg_Mode_Recm(Stream_v); + v.RegRdval(8) := IsArmed(Stream_v); + v.RegRdval(16) := IsRecording(Stream_v); + end if; + + -- LASTWINn + if AccAddr(3 downto 0) = X"C" then + -- LASTWINn + v.RegRdval(MaxWindowsBits_c - 1 downto 0) := StrLastWin_Sync(Stream_v); + end if; + + end if; + + -- *** Read Data MUX *** + v.AddrReg := AccAddr; + AccRdData <= (others => '0'); + if r.AddrReg(15 downto 12) = X"0" then + AccRdData <= r.RegRdval; + elsif r.AddrReg(15 downto 12) = X"1" then + -- High-low dword in different memories + if r.AddrReg(2) = '0' then + AccRdData <= CtxStr_Rdval(31 downto 0); + else + AccRdData <= CtxStr_Rdval(63 downto 32); + end if; + elsif r.AddrReg(15 downto 14) = "01" then + -- High-low dword in different memories + if r.AddrReg(2) = '0' then + AccRdData <= CtxWin_Rdval(31 downto 0); + else + AccRdData <= CtxWin_Rdval(63 downto 32); + end if; + end if; + + -- *** IRQ Handling *** + for i in 0 to Streams_g - 1 loop + if (StrIrq_Sync(i) = '1') and (r.Reg_StrEna(i) = '1') then + v.Reg_IrqVec(i) := '1'; + end if; + end loop; + if ((r.Reg_IrqVec and r.Reg_IrqEna) /= zeros_vector(Streams_g)) and (r.Reg_Gcfg_IrqEna = '1') then + v.Irq := '1'; + else + v.Irq := '0'; + end if; + + -- *** Assign to signal *** + r_next <= v; + + end process; + + -- *** Registered Outputs *** + IrqOut <= r.Irq; + PostTrig <= r.Reg_PostTrig; + Arm <= r.Reg_Mode_Arm; + RecMode <= r.Reg_Mode_Recm; + + -------------------------------------------- + -- Sequential Process + -------------------------------------------- + p_seq : process(S_Axi_Aclk) + begin + if rising_edge(S_Axi_Aclk) then + r <= r_next; + if A_Axi_Areset = '1' then + r.Reg_Gcfg_Ena <= '0'; + r.Reg_Gcfg_IrqEna <= '0'; + r.Reg_IrqVec <= (others => '0'); + r.Reg_IrqEna <= (others => '0'); + r.Reg_StrEna <= (others => '0'); + r.Irq <= '0'; + r.Reg_PostTrig <= (others => (others => '0')); + r.Reg_Mode_Recm <= (others => (others => '0')); + r.Reg_Mode_Arm <= (others => '0'); + end if; + end if; + end process; + + -------------------------------------------- + -- Maximum Level Latching (MemClk) + -------------------------------------------- + p_maxlvl : process(ClkMem) + begin + if rising_edge(ClkMem) then + if RstMem = '1' then + MaxLevel <= (others => (others => '0')); + else + -- Latch maximum level + for i in 0 to Streams_g - 1 loop + if MaxLevelClr_Sync(i) = '1' then + MaxLevel(i) <= (others => '0'); + elsif unsigned(InLevel(i)) > unsigned(MaxLevel(i)) then + MaxLevel(i) <= InLevel(i); + end if; + end loop; + end if; + end if; + end process; + + -------------------------------------------- + -- Component Instantiations + -------------------------------------------- + + -- *** AXI Interface *** + i_axi : entity work.psi_common_axi_slave_ipif + generic map( + num_reg_g => 16, + rst_val_g => (0 => (others => '0'), 1 => (others => '0'), 2 => (others => '0'), 3 => (others => '0'), + 4 => (others => '0'), 5 => (others => '0'), 6 => (others => '0'), 7 => (others => '0'), + 8 => (others => '0'), 9 => (others => '0'), 10 => (others => '0'), 11 => (others => '0'), + 12 => (others => '0'), 13 => (others => '0'), 14 => (others => '0'), 15 => (others => '0')), + use_mem_g => true, + axi_id_width_g => AxiSlaveIdWidth_g, + axi_addr_width_g => 16 + ) + port map( + s_axi_aclk => S_Axi_Aclk, + s_axi_aresetn => S_Axi_Aresetn, + s_axi_arid => S_Axi_ArId, + s_axi_araddr => S_Axi_ArAddr, + s_axi_arlen => S_Axi_Arlen, + s_axi_arsize => S_Axi_ArSize, + s_axi_arburst => S_Axi_ArBurst, + s_axi_arlock => S_Axi_ArLock, + s_axi_arcache => S_Axi_ArCache, + s_axi_arprot => S_Axi_ArProt, + s_axi_arvalid => S_Axi_ArValid, + s_axi_arready => S_Axi_ArReady, + s_axi_rid => S_Axi_RId, + s_axi_rdata => S_Axi_RData, + s_axi_rresp => S_Axi_RResp, + s_axi_rlast => S_Axi_RLast, + s_axi_rvalid => S_Axi_RValid, + s_axi_rready => S_Axi_RReady, + s_axi_awid => S_Axi_AwId, + s_axi_awaddr => S_Axi_AwAddr, + s_axi_awlen => S_Axi_AwLen, + s_axi_awsize => S_Axi_AwSize, + s_axi_awburst => S_Axi_AwBurst, + s_axi_awlock => S_Axi_AwLock, + s_axi_awcache => S_Axi_AwCache, + s_axi_awprot => S_Axi_AwProt, + s_axi_awvalid => S_Axi_AwValid, + s_axi_awready => S_Axi_AwReady, + s_axi_wdata => S_Axi_WData, + s_axi_wstrb => S_Axi_WStrb, + s_axi_wlast => S_Axi_WLast, + s_axi_wvalid => S_Axi_WValid, + s_axi_wready => S_Axi_WReady, + s_axi_bid => S_Axi_BId, + s_axi_bresp => S_Axi_BResp, + s_axi_bvalid => S_Axi_BValid, + s_axi_bready => S_Axi_BReady, + o_reg_rd => open, + i_reg_rdata => RegRdVal, + o_reg_wr => RegWr, + o_reg_wdata => RegWrVal, + o_mem_addr => AccAddrOffs, + o_mem_wr => AccWr, + o_mem_wdata => AccWrData, + i_mem_rdata => AccRdData + ); + + AccAddr <= std_logic_vector(unsigned(AccAddrOffs) + 16 * 4); + + -- *** Clock Crossings *** + blk_cc_irq : block + begin + g_in : for i in 0 to Streams_g - 1 generate + + i_cc_irq : entity work.psi_common_simple_cc + generic map( + width_g => log2ceil(MaxWindows_c) + ) + port map( + a_clk_i => ClkMem, + a_rst_i => RstMem, + a_dat_i => StrLastWin(i), + a_vld_i => StrIrq(i), + b_clk_i => S_Axi_Aclk, + b_rst_i => A_Axi_Areset, + b_dat_o => StrLastWin_Sync(i), + b_vld_o => StrIrq_Sync(i) + ); + end generate; + end block; + + blk_cc_mem_out : block + signal ccIn, ccOut : std_logic_vector(Streams_g downto 0); + begin + -- Input Assembly + ccIn(Streams_g - 1 downto 0) <= r.Reg_StrEna; + ccIn(Streams_g) <= r.Reg_Gcfg_Ena; + + -- Instantiation + i_cc_mem_out : entity work.psi_common_bit_cc + generic map( + width_g => Streams_g + 1 + ) + port map( + dat_i => ccIn, + clk_i => ClkMem, + dat_o => ccOut + ); + + -- Output assembly + StrEna <= ccOut(Streams_g - 1 downto 0); + GlbEna <= ccOut(Streams_g); + end block; + + i_cc_mem_out_pulse : entity work.psi_common_pulse_cc + generic map( + num_pulses_g => Streams_g + ) + port map( + a_clk_i => S_Axi_Aclk, + a_rst_i => A_Axi_Areset, + a_dat_i => r.MaxLvlClr, + b_clk_i => ClkMem, + b_rst_i => RstMem, + b_dat_o => MaxLevelClr_Sync + ); + + -- *** Stream Context Memory *** + -- Signal Assembly + AddrCtxStr <= AccAddr(15 downto 12) = X"1"; + CtxStr_WeLo <= '1' when AccWr = DwWrite_c and AddrCtxStr and AccAddr(2) = '0' else '0'; + CtxStr_WeHi <= '1' when AccWr = DwWrite_c and AddrCtxStr and AccAddr(2) = '1' else '0'; + CtxStr_AddrB <= std_logic_vector(to_unsigned(CtxStr_Cmd.Stream, log2ceil(Streams_g))) & CtxStr_Cmd.Sel; + + -- Memory is split organized as 64 bit memory for historical reasons (Tosca TMEM is 64-bit) + + -- Low DWORD memory + i_mem_ctx_lo : entity work.psi_common_tdp_ram + generic map( + depth_g => DepthCtxStr_c, + width_g => 32, + behavior_g => "RBW" + ) + port map( + a_clk_i => S_Axi_Aclk, + a_addr_i => AccAddr(CtxStrAddrHigh_c downto 3), + a_wr_i => CtxStr_WeLo, + a_dat_i => AccWrData, + a_dat_o => CtxStr_Rdval(31 downto 0), + b_clk_i => ClkMem, + b_addr_i => CtxStr_AddrB, + b_wr_i => CtxStr_Cmd.WenLo, + b_dat_i => CtxStr_Cmd.WdatLo, + b_dat_o => CtxStr_Resp.RdatLo + ); + + -- High DWORD memory + i_mem_ctx_hi : entity work.psi_common_tdp_ram + generic map( + depth_g => DepthCtxStr_c, + width_g => 32, + behavior_g => "RBW" + ) + port map( + a_clk_i => S_Axi_Aclk, + a_addr_i => AccAddr(CtxStrAddrHigh_c downto 3), + a_wr_i => CtxStr_WeHi, + a_dat_i => AccWrData, + a_dat_o => CtxStr_Rdval(63 downto 32), + b_clk_i => ClkMem, + b_addr_i => CtxStr_AddrB, + b_wr_i => CtxStr_Cmd.WenHi, + b_dat_i => CtxStr_Cmd.WdatHi, + b_dat_o => CtxStr_Resp.RdatHi + ); + + -- *** Window Context Memory *** + -- Signal Assembly + AddrCtxWin <= AccAddr(15 downto 14) = "01"; + CtxWin_WeLo <= '1' when AccWr = DwWrite_c and AddrCtxWin and AccAddr(2) = '0' else '0'; + CtxWin_WeHi <= '1' when AccWr = DwWrite_c and AddrCtxWin and AccAddr(2) = '1' else '0'; + CtxWin_AddrB <= std_logic_vector(to_unsigned(CtxWin_Cmd.Stream, log2ceil(Streams_g))) & std_logic_vector(to_unsigned(CtxWin_Cmd.Window, log2ceil(MaxWindows_g))) & CtxWin_Cmd.Sel; + + -- Memory is split organized as 64 bit memory for historical reasons (Tosca TMEM is 64-bit) + + -- Low DWORD memory + i_mem_win_lo : entity work.psi_common_tdp_ram + generic map( + depth_g => DepthCtxWin_c, + width_g => 32, + behavior_g => "RBW" + ) + port map( + a_clk_i => S_Axi_Aclk, + a_addr_i => AccAddr(CtxWinAddrHigh_c downto 3), + a_wr_i => CtxWin_WeLo, + a_dat_i => AccWrData, + a_dat_o => CtxWin_Rdval(31 downto 0), + b_clk_i => ClkMem, + b_addr_i => CtxWin_AddrB, + b_wr_i => CtxWin_Cmd.WenLo, + b_dat_i => CtxWin_Cmd.WdatLo, + b_dat_o => CtxWin_Resp.RdatLo + ); + + -- High DWORD memory + i_mem_win_hi : entity work.psi_common_tdp_ram + generic map( + depth_g => DepthCtxWin_c, + width_g => 32, + behavior_g => "RBW" + ) + port map( + a_clk_i => S_Axi_Aclk, + a_addr_i => AccAddr(CtxWinAddrHigh_c downto 3), + a_wr_i => CtxWin_WeHi, + a_dat_i => AccWrData, + a_dat_o => CtxWin_Rdval(63 downto 32), + b_clk_i => ClkMem, + b_addr_i => CtxWin_AddrB, + b_wr_i => CtxWin_Cmd.WenHi, + b_dat_i => CtxWin_Cmd.WdatHi, + b_dat_o => CtxWin_Resp.RdatHi + ); end architecture;