Compare commits
16 Commits
1.2.0
...
feature/10
| Author | SHA1 | Date | |
|---|---|---|---|
| 5249ac7223 | |||
| 28b79e93a9 | |||
| 7a45fa8df8 | |||
|
|
a0464c6a9d | ||
|
|
5390c0c3c0 | ||
|
|
cec193edca | ||
|
|
141d54dd4f | ||
|
|
8b2211d07a | ||
|
|
7de31cc946 | ||
|
|
2838d1e3e9 | ||
|
|
404af6d979 | ||
|
|
df29e19f6d | ||
|
|
7f22ec9050 | ||
|
|
3efc256530 | ||
|
|
be272f611c | ||
|
|
9ad003bc41 |
16
Changelog.md
16
Changelog.md
@@ -1,3 +1,19 @@
|
||||
## 1.2.3
|
||||
* Doc
|
||||
* Changed repository mantainer
|
||||
|
||||
## 1.2.2
|
||||
* Bugfixes
|
||||
* Workaround for ISE tools implementing memory as FFs in case of 1 stream
|
||||
|
||||
## 1.2.1
|
||||
* Bugfixes
|
||||
* Optimized timing between input FIFO and DMA
|
||||
* Fix data unwrapping in driver
|
||||
* Corrected several issues in documentation
|
||||
* Made driver C++ tolerant
|
||||
* Made code working for only one streamgit
|
||||
|
||||
## 1.2.0
|
||||
* First Open Source Release (older versions not kept in history)
|
||||
* Added license and copyright headers
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
# General Information
|
||||
|
||||
## Maintainer
|
||||
Oliver Bründler [oliver.bruendler@psi.ch]
|
||||
Daniele Felici [daniele.felici@psi.ch]
|
||||
|
||||
## Author
|
||||
Oliver Bründler [oli.bruendler@gmx.ch]
|
||||
|
||||
## License
|
||||
This library is published under [PSI HDL Library License](License.txt), which is [LGPL](LGPL2_1.txt) plus some additional exceptions to clarify the LGPL terms in the context of firmware development.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen 1.8.14"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<title>Driver Documentation: D:/gfa/Libraries/Firmware/VHDL/psi_multi_stream_daq/driver Directory Reference</title>
|
||||
<title>Driver Documentation: D:/gfa/RF/HIPA/LLRF_v1/post_mortem/Lib/VHDL/psi_multi_stream_daq/driver Directory Reference</title>
|
||||
<link href="tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="jquery.js"></script>
|
||||
<script type="text/javascript" src="dynsections.js"></script>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen 1.8.14"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<title>Driver Documentation: D:/gfa/Libraries/Firmware/VHDL/psi_multi_stream_daq/driver/psi_ms_daq.h File Reference</title>
|
||||
<title>Driver Documentation: D:/gfa/RF/HIPA/LLRF_v1/post_mortem/Lib/VHDL/psi_multi_stream_daq/driver/psi_ms_daq.h File Reference</title>
|
||||
<link href="tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="jquery.js"></script>
|
||||
<script type="text/javascript" src="dynsections.js"></script>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -160,7 +160,7 @@ Public Attributes</h2></td></tr>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>The documentation for this struct was generated from the following file:<ul>
|
||||
<li>D:/gfa/Libraries/Firmware/VHDL/psi_multi_stream_daq/driver/<a class="el" href="psi__ms__daq_8h_source.html">psi_ms_daq.h</a></li>
|
||||
<li>D:/gfa/RF/HIPA/LLRF_v1/post_mortem/Lib/VHDL/psi_multi_stream_daq/driver/<a class="el" href="psi__ms__daq_8h_source.html">psi_ms_daq.h</a></li>
|
||||
</ul>
|
||||
</div><!-- contents -->
|
||||
</div><!-- doc-content -->
|
||||
|
||||
@@ -255,7 +255,7 @@ Public Attributes</h2></td></tr>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>The documentation for this struct was generated from the following file:<ul>
|
||||
<li>D:/gfa/Libraries/Firmware/VHDL/psi_multi_stream_daq/driver/<a class="el" href="psi__ms__daq_8h_source.html">psi_ms_daq.h</a></li>
|
||||
<li>D:/gfa/RF/HIPA/LLRF_v1/post_mortem/Lib/VHDL/psi_multi_stream_daq/driver/<a class="el" href="psi__ms__daq_8h_source.html">psi_ms_daq.h</a></li>
|
||||
</ul>
|
||||
</div><!-- contents -->
|
||||
</div><!-- doc-content -->
|
||||
|
||||
@@ -161,7 +161,7 @@ Public Attributes</h2></td></tr>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>The documentation for this struct was generated from the following file:<ul>
|
||||
<li>D:/gfa/Libraries/Firmware/VHDL/psi_multi_stream_daq/driver/<a class="el" href="psi__ms__daq_8h_source.html">psi_ms_daq.h</a></li>
|
||||
<li>D:/gfa/RF/HIPA/LLRF_v1/post_mortem/Lib/VHDL/psi_multi_stream_daq/driver/<a class="el" href="psi__ms__daq_8h_source.html">psi_ms_daq.h</a></li>
|
||||
</ul>
|
||||
</div><!-- contents -->
|
||||
</div><!-- doc-content -->
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -406,6 +406,18 @@ PsiMsDaq_RetCode_t PsiMsDaq_Str_GetMaxLvl( PsiMsDaq_StrHandle strHndl,
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_ClrMaxLvl( PsiMsDaq_StrHandle strHndl)
|
||||
{
|
||||
//Pointer Cast
|
||||
PsiMsDaq_StrInst_t* inst_p = (PsiMsDaq_StrInst_t*) strHndl;
|
||||
PsiMsDaq_IpHandle ipHandle = inst_p->ipHandle;
|
||||
const uint8_t strNr = inst_p->nr;
|
||||
//Implementation
|
||||
SAFE_CALL(PsiMsDaq_RegWrite(ipHandle, PSI_MS_DAQ_REG_MAXLVL(strNr), 0));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetFreeWindows( PsiMsDaq_StrHandle strHndl,
|
||||
uint8_t* const freeWindows_p)
|
||||
{
|
||||
@@ -499,7 +511,6 @@ PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetNoOfSamples( PsiMsDaq_WinInfo_t winInfo,
|
||||
{
|
||||
//Pointer Case
|
||||
PsiMsDaq_Inst_t* ip_p = (PsiMsDaq_Inst_t*)winInfo.ipHandle;
|
||||
PsiMsDaq_StrInst_t* str_p = (PsiMsDaq_StrInst_t*)winInfo.strHandle;
|
||||
//Setup
|
||||
uint8_t strNr;
|
||||
SAFE_CALL(PsiMsDaq_Str_GetStrNr(winInfo.strHandle, &strNr));
|
||||
@@ -507,13 +518,11 @@ PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetNoOfSamples( PsiMsDaq_WinInfo_t winInfo,
|
||||
SAFE_CALL(CheckStrNr(winInfo.ipHandle, strNr))
|
||||
SAFE_CALL(CheckWinNr(winInfo.strHandle, winInfo.winNr))
|
||||
//Implementation
|
||||
uint32_t noOfBytes;
|
||||
SAFE_CALL(PsiMsDaq_RegGetField( winInfo.ipHandle,
|
||||
PSI_MS_DAQ_WIN_WINCNT(strNr, winInfo.winNr, ip_p->strAddrOffs),
|
||||
PSI_MS_DAQ_WIN_WINCNT_LSB_CNT,
|
||||
PSI_MS_DAQ_WIN_WINCNT_MSB_CNT,
|
||||
&noOfBytes));
|
||||
*noOfSamples_p = noOfBytes / str_p->widthBytes;
|
||||
noOfSamples_p));
|
||||
//Done
|
||||
return PsiMsDaq_RetCode_Success;
|
||||
}
|
||||
@@ -601,7 +610,7 @@ PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetDataUnwrapped( PsiMsDaq_WinInfo_t winInfo,
|
||||
//Calculate address of last byte and trigger byte (with regard to wrapping)
|
||||
uint32_t lastSplAddr;
|
||||
SAFE_CALL(PsiMsDaq_StrWin_GetLastSplAddr(winInfo, &lastSplAddr));
|
||||
uint32_t trigByteAddr = lastSplAddr - (str_p->postTrig+1)*str_p->widthBytes; //+1 because trigger is not included in postTrigger
|
||||
uint32_t trigByteAddr = lastSplAddr - str_p->postTrig*str_p->widthBytes;
|
||||
if (trigByteAddr < winStart) {
|
||||
trigByteAddr += str_p->winSize;
|
||||
}
|
||||
@@ -612,7 +621,7 @@ PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetDataUnwrapped( PsiMsDaq_WinInfo_t winInfo,
|
||||
|
||||
|
||||
//If all bytes are written without wrap, copy directly
|
||||
const uint32_t firstByteLinear = lastByteAddr - bytes + 1;
|
||||
const int64_t firstByteLinear = (int64_t)lastByteAddr - bytes + 1;
|
||||
if (firstByteLinear >= winStart) {
|
||||
ip_p->memcpyFct(buffer_p, (void*)(size_t)firstByteLinear, bytes);
|
||||
}
|
||||
@@ -620,9 +629,9 @@ PsiMsDaq_RetCode_t PsiMsDaq_StrWin_GetDataUnwrapped( PsiMsDaq_WinInfo_t winInfo,
|
||||
else {
|
||||
const uint32_t secondChunkSize = lastByteAddr - winStart + 1;
|
||||
const uint32_t firstChunkSize = bytes-secondChunkSize;
|
||||
const uint32_t firstChunkStartAddr = winLast-firstChunkSize+1;
|
||||
ip_p->memcpyFct(buffer_p, (void*)(size_t)firstChunkStartAddr, firstChunkSize);
|
||||
ip_p->memcpyFct(buffer_p+firstChunkSize, (void*)(size_t)winStart, secondChunkSize);
|
||||
const int64_t firstChunkStartAddr = winLast-firstChunkSize+1;
|
||||
ip_p->memcpyFct(buffer_p, (void*)(size_t)firstChunkStartAddr, firstChunkSize);
|
||||
ip_p->memcpyFct((void*)((uint32_t)buffer_p+firstChunkSize), (void*)(size_t)winStart, secondChunkSize);
|
||||
}
|
||||
|
||||
//Done
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//*******************************************************************************
|
||||
// Documentation
|
||||
//*******************************************************************************
|
||||
@@ -113,13 +117,13 @@
|
||||
* .winSize = <sizePerWindow>, //in bytes
|
||||
* .streamWidthBits = <widthInBits>
|
||||
* };
|
||||
* PsiMsDaq_Str_Configure(daqHandle, &cfg);
|
||||
* PsiMsDaq_Str_Configure(daqStrHandle, &cfg);
|
||||
* //Register ballback
|
||||
* PsiMsDaq_Str_SetIrqCallbackWin(daqHandle, UserDaqIsr, NULL);
|
||||
* PsiMsDaq_Str_SetIrqCallbackWin(daqStrHandle, UserDaqIsr, NULL);
|
||||
* //Enable IRQ
|
||||
* PsiMsDaq_Str_SetIrqEnable(daqHandle, true);
|
||||
* PsiMsDaq_Str_SetIrqEnable(daqStrHandle, true);
|
||||
* //Enable recorder for stream
|
||||
* PsiMsDaq_Str_SetEnable(daqHandle, true);
|
||||
* PsiMsDaq_Str_SetEnable(daqStrHandle, true);
|
||||
*
|
||||
* //Wait in endless loop for IRQs comming in
|
||||
* while(1){};
|
||||
@@ -252,7 +256,7 @@ typedef enum {
|
||||
PsiMsDaqn_RecMode_Continuous = 0, ///< Continuous recording
|
||||
PsiMsDaqn_RecMode_TriggerMask = 1, ///< Continuously record pre-trigger data but only detect triggers after PsiMsDaq_Str_Arm() was called
|
||||
PsiMsDaqn_RecMode_SingleShot = 2, ///< Only record pre-trigger after PsiMsDaq_Str_Arm() was called and stop recording after one trigger
|
||||
PsiMsDaqn_RecMode_Manual = 3, ///< Manaully control the recording by setting and clearing the arm bit
|
||||
PsiMsDaqn_RecMode_Manual = 3 ///< Manaully control the recording by setting and clearing the arm bit
|
||||
} PsiMsDaq_RecMode_t;
|
||||
|
||||
/**
|
||||
@@ -421,6 +425,14 @@ PsiMsDaq_RetCode_t PsiMsDaq_Str_Arm(PsiMsDaq_StrHandle strHndl);
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_GetMaxLvl( PsiMsDaq_StrHandle strHndl,
|
||||
uint32_t* const maxLvl_p);
|
||||
|
||||
/**
|
||||
* @brief Clear the maximum input buffer fill level
|
||||
*
|
||||
* @param strHndl Driver handle for the stream
|
||||
* @return Return Code
|
||||
*/
|
||||
PsiMsDaq_RetCode_t PsiMsDaq_Str_ClrMaxLvl( PsiMsDaq_StrHandle strHndl);
|
||||
|
||||
/**
|
||||
* @brief Get the number of free windows.
|
||||
@@ -697,6 +709,10 @@ PsiMsDaq_RetCode_t PsiMsDaq_RegGetBit( PsiMsDaq_IpHandle ipHandle,
|
||||
const uint32_t addr,
|
||||
const uint32_t mask,
|
||||
bool* const value_p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,16 +37,16 @@ entity psi_ms_daq_axi is
|
||||
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;
|
||||
AxiMaxBurstBeats_g : integer range 1 to 256 := 64;
|
||||
AxiMaxOpenTrasactions_g : natural range 1 to 8 := 8;
|
||||
AxiFifoDepth_g : natural := 1024;
|
||||
-- Axi Slave
|
||||
AxiSlaveIdWidth_g : integer := 0
|
||||
);
|
||||
port (
|
||||
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_Data : in t_aslv512(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);
|
||||
@@ -170,25 +170,25 @@ architecture rtl of psi_ms_daq_axi is
|
||||
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_DatData : std_logic_vector(MemoryBusWidth_c-1 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);
|
||||
-- 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);
|
||||
signal Cfg_PreTrigDisable : std_logic_vector(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;
|
||||
@@ -259,7 +259,8 @@ begin
|
||||
IsArmed => Stat_IsArmed,
|
||||
IsRecording => Stat_IsRecording,
|
||||
RecMode => Cfg_RecMode,
|
||||
ClkMem => M_Axi_Aclk,
|
||||
PreTrigDisable => Cfg_PreTrigDisable,
|
||||
ClkMem => M_Axi_Aclk,
|
||||
RstMem => M_Axi_Areset,
|
||||
CtxStr_Cmd => CtxStr_Cmd,
|
||||
CtxStr_Resp => CtxStr_Resp,
|
||||
@@ -304,6 +305,7 @@ begin
|
||||
RstReg => S_Axi_Areset,
|
||||
PostTrigSpls => Cfg_PostTrig(str),
|
||||
Mode => Cfg_RecMode(str),
|
||||
PreTrigDisable => Cfg_PreTrigDisable(str),
|
||||
Arm => Cfg_Arm(str),
|
||||
IsArmed => Stat_IsArmed(str),
|
||||
IsRecording => Stat_IsRecording(str),
|
||||
@@ -398,9 +400,9 @@ begin
|
||||
AxiDataWidth_g => AxiDataWidth_g,
|
||||
AxiMaxBeats_g => AxiMaxBurstBeats_g,
|
||||
AxiMaxOpenTrasactions_g => AxiMaxOpenTrasactions_g,
|
||||
MaxOpenCommands_g => Streams_g,
|
||||
DataFifoDepth_g => 1024,
|
||||
AxiFifoDepth_g => AxiFifoDepth_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 => 4096,
|
||||
-- AxiFifoDepth_g => AxiFifoDepth_g,
|
||||
RamBehavior_g => "RBW" -- Okay for Xilinx chips
|
||||
)
|
||||
port map (
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
|
||||
use ieee.math_real.all;
|
||||
|
||||
library work;
|
||||
use work.psi_common_math_pkg.all;
|
||||
|
||||
use work.psi_ms_daq_pkg.all;
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Entity Declaration
|
||||
------------------------------------------------------------------------------
|
||||
@@ -24,7 +27,6 @@ entity psi_ms_daq_axi_if is
|
||||
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 (
|
||||
@@ -39,7 +41,7 @@ entity psi_ms_daq_axi_if is
|
||||
Cmd_Rdy : out std_logic;
|
||||
|
||||
-- Write Data
|
||||
Dat_Data : in std_logic_vector(63 downto 0);
|
||||
Dat_Data : in std_logic_vector(MemoryBusWidth_c-1 downto 0);
|
||||
Dat_Vld : in std_logic;
|
||||
Dat_Rdy : out std_logic;
|
||||
|
||||
@@ -106,17 +108,18 @@ architecture rtl of psi_ms_daq_axi_if is
|
||||
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;
|
||||
|
||||
InfoFifoIn(CommandSizeRng_c) <= Cmd_Size;
|
||||
|
||||
|
||||
i_wrinfo_fifo : entity work.psi_common_sync_fifo
|
||||
generic map (
|
||||
Width_g => WrCmdWidth_c,
|
||||
Depth_g => MaxOpenCommands_g,
|
||||
Depth_g => MaxOpenCommands_g*16,
|
||||
RamStyle_g => "distributed"
|
||||
)
|
||||
port map (
|
||||
@@ -141,7 +144,7 @@ begin
|
||||
AxiMaxOpenTrasactions_g => AxiMaxOpenTrasactions_g,
|
||||
UserTransactionSizeBits_g => 32,
|
||||
DataFifoDepth_g => DataFifoDepth_g,
|
||||
DataWidth_g => 64,
|
||||
DataWidth_g => MemoryBusWidth_c,
|
||||
ImplRead_g => false,
|
||||
ImplWrite_g => true,
|
||||
RamBehavior_g => RamBehavior_g
|
||||
@@ -212,7 +215,7 @@ begin
|
||||
M_Axi_RValid => M_Axi_RValid,
|
||||
M_Axi_RReady => M_Axi_RReady
|
||||
);
|
||||
|
||||
|
||||
Done <= DoneI or ErrorI;
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ entity psi_ms_daq_daq_dma is
|
||||
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_DatData : out std_logic_vector(MemoryBusWidth_c-1 downto 0); -- $$ proc=mem_dat $$
|
||||
Mem_DatVld : out std_logic; -- $$ proc=mem_dat $$
|
||||
Mem_DatRdy : in std_logic -- $$ proc=mem_dat $$
|
||||
);
|
||||
@@ -66,26 +66,35 @@ end entity;
|
||||
------------------------------------------------------------------------------
|
||||
architecture rtl of psi_ms_daq_daq_dma is
|
||||
|
||||
-- Constants
|
||||
constant BufferFifoDepth_c : integer := 32;
|
||||
-- Constants
|
||||
constant BufferFifoDepth_c : integer := 32;
|
||||
constant RemShifts_c : natural := log2(MemoryBusBytes_c);
|
||||
constant RemRamWidth_c : natural := 1+1+RemShifts_c+MemoryBusWidth_c;
|
||||
|
||||
-- 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(log2ceil(Streams_g) downto 0);
|
||||
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(log2ceil(Streams_g) downto 0);
|
||||
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_RdBytes : std_logic_vector(RemShifts_c-1 downto 0);
|
||||
signal Rem_Data : std_logic_vector(MemoryBusWidth_c-1 downto 0);
|
||||
signal Rem_Trigger : std_logic;
|
||||
signal Rem_Last : std_logic;
|
||||
|
||||
|
||||
signal RemRam_WrData : std_logic_vector(RemRamWidth_c-1 downto 0);
|
||||
signal RemRam_RdData : std_logic_vector(RemRamWidth_c-1 downto 0);
|
||||
|
||||
-- Types
|
||||
type State_t is (Idle_s, RemRd1_s, RemRd2_s, Transfer_s, Done_s, Cmd_s);
|
||||
|
||||
@@ -95,10 +104,10 @@ architecture rtl of psi_ms_daq_daq_dma is
|
||||
RspFifo_Vld : std_logic;
|
||||
RspFifo_Data : DaqDma2DaqSm_Resp_t;
|
||||
Mem_DataVld : std_logic;
|
||||
StreamStdlv : std_logic_vector(log2ceil(Streams_g)-1 downto 0);
|
||||
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);
|
||||
RemWrBytes : std_logic_vector(RemShifts_c-1 downto 0);
|
||||
RemData : std_logic_vector(MemoryBusWidth_c-1 downto 0);
|
||||
RemTrigger : std_logic;
|
||||
RemLast : std_logic;
|
||||
RemWrTrigger : std_logic;
|
||||
@@ -110,12 +119,12 @@ architecture rtl of psi_ms_daq_daq_dma is
|
||||
HndlStream : integer range 0 to MaxStreams_c-1;
|
||||
HndlAddress : std_logic_vector(31 downto 0);
|
||||
UpdateLast : std_logic;
|
||||
HndlSft : unsigned(2 downto 0);
|
||||
HndlSft : unsigned(log2(MemoryBusBytes_c)-1 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);
|
||||
DataSft : std_logic_vector(2*MemoryBusWidth_c-1 downto 0);
|
||||
NextDone : std_logic;
|
||||
DataWritten : std_logic;
|
||||
HasLast : std_logic_vector(Streams_g-1 downto 0);
|
||||
@@ -130,8 +139,7 @@ begin
|
||||
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;
|
||||
variable RemSft_v : integer range 0 to MemoryBusBytes_c-1;
|
||||
begin
|
||||
-- *** Hold variables stable ***
|
||||
v := r;
|
||||
@@ -173,7 +181,7 @@ begin
|
||||
v.RemLast := '0';
|
||||
else
|
||||
v.HndlSft := unsigned(Rem_RdBytes);
|
||||
v.DataSft(127 downto 64) := Rem_Data;
|
||||
v.DataSft(2*MemoryBusWidth_c-1 downto MemoryBusWidth_c) := Rem_Data;
|
||||
v.RdBytes := resize(unsigned(Rem_RdBytes), v.RdBytes'length);
|
||||
v.RemTrigger := Rem_Trigger;
|
||||
v.RemLast := Rem_Last;
|
||||
@@ -191,7 +199,7 @@ begin
|
||||
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;
|
||||
v.WrBytes := r.WrBytes + MemoryBusBytes_c;
|
||||
-- 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';
|
||||
@@ -199,7 +207,7 @@ begin
|
||||
-- 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
|
||||
if (r.HndlSft + unsigned(Inp_Data(r.HndlStream).Bytes) <= MemoryBusBytes_c) or (r.RemLast = '1') then
|
||||
v.State := Done_s;
|
||||
else
|
||||
v.NextDone := '1';
|
||||
@@ -213,8 +221,8 @@ begin
|
||||
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;
|
||||
v.DataSft(MemoryBusWidth_c-1 downto 0) := r.DataSft(2*MemoryBusWidth_c-1 downto MemoryBusWidth_c);
|
||||
v.DataSft(8*to_integer(r.HndlSft)+(MemoryBusWidth_c-1) 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';
|
||||
@@ -222,7 +230,7 @@ begin
|
||||
end if;
|
||||
|
||||
when Done_s =>
|
||||
RemSft_v := to_integer(resize(r.HndlMaxSize, 3));
|
||||
RemSft_v := to_integer(resize(r.HndlMaxSize, RemShifts_c));
|
||||
v.RemWrTrigger := '0';
|
||||
v.RemWrLast := '0';
|
||||
if r.HndlMaxSize < r.RdBytes then
|
||||
@@ -235,7 +243,7 @@ begin
|
||||
v.RemWrBytes := (others => '0');
|
||||
v.HasLast(r.HndlStream) := '0';
|
||||
end if;
|
||||
v.RemData := v.DataSft(8*RemSft_v+63 downto 8*RemSft_v);
|
||||
v.RemData := v.DataSft(8*RemSft_v+(MemoryBusWidth_c-1) downto 8*RemSft_v);
|
||||
v.State := Cmd_s;
|
||||
if r.DataWritten = '1' then
|
||||
v.Mem_CmdVld := '1';
|
||||
@@ -300,7 +308,7 @@ begin
|
||||
i_fifocmd : entity work.psi_common_sync_fifo
|
||||
generic map (
|
||||
Width_g => DaqSm2DaqDma_Cmd_Size_c,
|
||||
Depth_g => Streams_g,
|
||||
Depth_g => 2**StreamBits_c,
|
||||
RamStyle_g => "distributed",
|
||||
RamBehavior_g => "RBW"
|
||||
)
|
||||
@@ -322,7 +330,7 @@ begin
|
||||
i_fiforsp : entity work.psi_common_sync_fifo
|
||||
generic map (
|
||||
Width_g => DaqDma2DaqSm_Resp_Size_c,
|
||||
Depth_g => Streams_g,
|
||||
Depth_g => 2**StreamBits_c,
|
||||
RamStyle_g => "distributed",
|
||||
RamBehavior_g => "RBW"
|
||||
)
|
||||
@@ -344,7 +352,7 @@ begin
|
||||
-- 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,
|
||||
Width_g => MemoryBusWidth_c,
|
||||
Depth_g => BufferFifoDepth_c,
|
||||
AlmFullOn_g => true,
|
||||
AlmFullLevel_g => BufferFifoDepth_c/2,
|
||||
@@ -354,7 +362,7 @@ begin
|
||||
port map (
|
||||
Clk => Clk,
|
||||
Rst => Rst,
|
||||
InData => r.DataSft(63 downto 0),
|
||||
InData => r.DataSft(MemoryBusWidth_c-1 downto 0),
|
||||
InVld => r.Mem_DataVld,
|
||||
OutData => Mem_DatData,
|
||||
OutVld => Mem_DatVld,
|
||||
@@ -362,31 +370,38 @@ begin
|
||||
OutLevel => DatFifo_Level_Dbg,
|
||||
AlmFull => DatFifo_AlmFull
|
||||
);
|
||||
|
||||
-- *** Remaining Data RAM ***
|
||||
i_remram : entity work.psi_common_sdp_ram
|
||||
generic map (
|
||||
Depth_g => Streams_g,
|
||||
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
|
||||
);
|
||||
|
||||
|
||||
|
||||
Rem_Last <= RemRam_RdData(0);
|
||||
Rem_Trigger <= RemRam_RdData(1);
|
||||
Rem_RdBytes <= RemRam_RdData(RemShifts_c-1+2 downto 2);
|
||||
Rem_Data <= RemRam_RdData(RemRamWidth_c-1 downto RemShifts_c+2);
|
||||
|
||||
RemRam_WrData(0) <= r.RemWrLast;
|
||||
RemRam_WrData(1) <= r.RemWrTrigger;
|
||||
RemRam_WrData(RemShifts_c-1+2 downto 2) <= r.RemWrBytes;
|
||||
RemRam_WrData(RemRamWidth_c-1 downto RemShifts_c+2) <= r.RemData;
|
||||
|
||||
-- *** Remaining Data RAM ***
|
||||
i_remram : entity work.psi_common_sdp_ram
|
||||
generic map (
|
||||
Depth_g => 2**StreamBits_c,
|
||||
Width_g => RemRamWidth_c,
|
||||
IsAsync_g => false,
|
||||
RamStyle_g => "distributed",
|
||||
Behavior_g => "RBW"
|
||||
)
|
||||
port map (
|
||||
Clk => Clk,
|
||||
RdClk => Rst,
|
||||
WrAddr => r.StreamStdlv,
|
||||
Wr => r.RemWen,
|
||||
WrData => RemRam_WrData,
|
||||
RdAddr => r.StreamStdlv,
|
||||
RdData => RemRam_RdData
|
||||
|
||||
);
|
||||
|
||||
end;
|
||||
|
||||
|
||||
@@ -76,6 +76,10 @@ end entity;
|
||||
------------------------------------------------------------------------------
|
||||
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);
|
||||
|
||||
-- Function Definitions
|
||||
function GetBitsOfStreamPrio( InputVector : std_logic_vector;
|
||||
Prio : integer)
|
||||
@@ -132,10 +136,10 @@ architecture rtl of psi_ms_daq_daq_sm is
|
||||
signal IrqFifoAlmFull : std_logic;
|
||||
signal IrqFifoEmpty : std_logic;
|
||||
signal IrqFifoGenIrq : std_logic;
|
||||
signal IrqFifoStream : std_logic_vector(log2ceil(Streams_g)-1 downto 0);
|
||||
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(log2ceil(Streams_g)+log2ceil(Windows_g) downto 0);
|
||||
signal IrqFifoOut : std_logic_vector(log2ceil(Streams_g)+log2ceil(Windows_g) 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);
|
||||
@@ -178,7 +182,7 @@ architecture rtl of psi_ms_daq_daq_sm is
|
||||
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(log2ceil(Streams_g)-1 downto 0);
|
||||
TfDoneCnt : std_logic_vector(StreamBits_c-1 downto 0);
|
||||
TfDoneReg : std_logic;
|
||||
HndlWinDone : std_logic;
|
||||
CtxStr_Cmd : ToCtxStr_t;
|
||||
@@ -429,7 +433,7 @@ begin
|
||||
-- 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
|
||||
v.Dma_Cmd.MaxSize := std_logic_vector(to_unsigned(MaxBurstSize_g*MemoryBusBytes_c, 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;
|
||||
@@ -681,15 +685,15 @@ begin
|
||||
|
||||
-- *** IRQ Information FIFO ***
|
||||
-- input assembly
|
||||
IrqFifoIn(log2ceil(Streams_g)-1 downto 0) <= std_logic_vector(to_unsigned(r.HndlStream, log2ceil(Streams_g)));
|
||||
IrqFifoIn(log2ceil(Streams_g)+log2ceil(Windows_g)-1 downto log2ceil(Streams_g)) <= r.HndlLastWinNr;
|
||||
IrqFifoIn(IrqFifoIn'high) <= r.HndlWinDone;
|
||||
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 => log2ceil(Streams_g)+log2ceil(Windows_g)+1,
|
||||
Depth_g => Streams_g*4,
|
||||
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"
|
||||
@@ -706,8 +710,8 @@ begin
|
||||
);
|
||||
|
||||
-- Output disassembly
|
||||
IrqFifoStream <= IrqFifoOut(log2ceil(Streams_g)-1 downto 0);
|
||||
IrqLastWinNr <= IrqFifoOut(log2ceil(Streams_g)+log2ceil(Windows_g)-1 downto log2ceil(Streams_g));
|
||||
IrqFifoStream <= IrqFifoOut(StreamBits_c-1 downto 0);
|
||||
IrqLastWinNr <= IrqFifoOut(StreamBits_c+log2ceil(Windows_g)-1 downto StreamBits_c);
|
||||
IrqFifoGenIrq <= IrqFifoOut(IrqFifoOut'high);
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ library work;
|
||||
-- $$ 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 $$
|
||||
StreamWidth_g : positive range 8 to MemoryBusWidth_c := 16; -- Must be 8 bits increments and modulo MemoryBusWidth_c $$ 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 $$
|
||||
@@ -49,6 +49,7 @@ entity psi_ms_daq_input is
|
||||
RstReg : in std_logic;
|
||||
PostTrigSpls : in std_logic_vector(31 downto 0); -- $$ proc=daq $$
|
||||
Mode : in RecMode_t; -- $$ proc=daq $$
|
||||
PreTrigDisable : in std_logic; -- $$ proc=daq $$
|
||||
Arm : in std_logic; -- $$ proc=stream $$
|
||||
IsArmed : out std_logic; -- $$ proc=stream $$
|
||||
IsRecording : out std_logic; -- $$ proc=stream $$
|
||||
@@ -81,16 +82,19 @@ architecture rtl of psi_ms_daq_input is
|
||||
|
||||
-- Constants
|
||||
constant TimeoutLimit_c : integer := integer(StreamClkFreq_g*StreamTimeout_g)-1;
|
||||
constant WconvFactor_c : positive := 64/StreamWidth_g;
|
||||
constant WconvFactor_c : positive := MemoryBusWidth_c/StreamWidth_g;
|
||||
constant TlastCntWidth_c : positive := log2ceil(StreamBuffer_g) + 1;
|
||||
|
||||
|
||||
constant BytesIncr_c : unsigned(log2(MemoryBusBytes_c)-1 downto 0)
|
||||
:= to_unsigned(StreamWidth_g/8, log2(MemoryBusBytes_c));
|
||||
-- Two process method
|
||||
type two_process_r is record
|
||||
ModeReg : RecMode_t;
|
||||
ArmReg : std_logic;
|
||||
DataSftReg : std_logic_vector(63 downto 0);
|
||||
DataSftReg : std_logic_vector(MemoryBusWidth_c-1 downto 0);
|
||||
WordCnt : unsigned(log2ceil(WconvFactor_c) downto 0);
|
||||
DataFifoBytes : unsigned(3 downto 0);
|
||||
BytesCnt : unsigned(Input2Daq_Data_Bytes_Len-1 downto 0);
|
||||
DataFifoBytes : unsigned(Input2Daq_Data_Bytes_Len-1 downto 0);
|
||||
TrigLatch : std_logic;
|
||||
DataFifoVld : std_logic;
|
||||
DataFifoIsTo : std_logic;
|
||||
@@ -104,16 +108,25 @@ architecture rtl of psi_ms_daq_input is
|
||||
HasTlastSync : std_logic_vector(0 to 1);
|
||||
IsArmed : std_logic;
|
||||
RecEna : std_logic;
|
||||
PreRecEna : std_logic;
|
||||
StrData : std_logic_vector(StreamWidth_g-1 downto 0); -- 1 clk delayed stream data
|
||||
end record;
|
||||
signal r, r_next : two_process_r;
|
||||
|
||||
-- General Instantiation signals
|
||||
signal Str_Rst : std_logic;
|
||||
|
||||
-- DataFifo contains Data, Number of Bytes and Timeout and Trig signals
|
||||
constant DataFifo_Width_c : natural := MemoryBusWidth_c+Input2Daq_Data_Bytes_Len+2;
|
||||
-- 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_InData : std_logic_vector(DataFifo_Width_c-1 downto 0);
|
||||
signal DataFifo_OutData : std_logic_vector(DataFifo_Width_c-1 downto 0);
|
||||
signal DataFifo_PlData : std_logic_vector(DataFifo_Width_c-1 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;
|
||||
@@ -135,26 +148,27 @@ architecture rtl of psi_ms_daq_input is
|
||||
-- Clock Crossing Signals
|
||||
signal PostTrigSpls_Sync : std_logic_vector(PostTrigSpls'range);
|
||||
signal Mode_Sync : RecMode_t;
|
||||
signal PreTrigDisable_Sync : std_logic;
|
||||
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;
|
||||
--------------------------------------------
|
||||
-- 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, PreTrigDisable_Sync)
|
||||
variable v : two_process_r;
|
||||
variable ProcessSample_v : boolean;
|
||||
variable TriggerSample_v : boolean;
|
||||
variable TrigMasked_v : std_logic;
|
||||
begin
|
||||
-- *** Hold variables stable ***
|
||||
v := r;
|
||||
|
||||
-- *** Simplification Variables ***
|
||||
ProcessSample_v := (DataFifo_InRdy = '1') and (Str_Vld = '1');
|
||||
@@ -165,7 +179,11 @@ begin
|
||||
v.DataFifoIsTrig := '0';
|
||||
v.ModeReg := Mode_Sync;
|
||||
v.ArmReg := Arm_Sync;
|
||||
|
||||
if ProcessSample_v then
|
||||
v.StrData := Str_Data;
|
||||
end if;
|
||||
|
||||
|
||||
-- Masking trigger according to recording mode
|
||||
case r.ModeReg is
|
||||
when RecMode_Continuous_c =>
|
||||
@@ -177,8 +195,7 @@ begin
|
||||
TrigMasked_v := r.ArmReg;
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
|
||||
|
||||
-- Keep FifoVld high until data is written
|
||||
v.DataFifoVld := r.DataFifoVld and not DataFifo_InRdy;
|
||||
|
||||
@@ -186,7 +203,7 @@ begin
|
||||
if ProcessSample_v then
|
||||
v.TrigLatch := '0';
|
||||
else
|
||||
v.TrigLatch := r.TrigLatch or TrigMasked_v;
|
||||
v.TrigLatch := r.TrigLatch or TrigMasked_v;
|
||||
end if;
|
||||
|
||||
-- Detect timestamp FIFO overflows
|
||||
@@ -212,28 +229,31 @@ begin
|
||||
end if;
|
||||
|
||||
-- Trigger handling and post trigger counter
|
||||
if ProcessSample_v and r.RecEna = '1' then
|
||||
if ProcessSample_v 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.DataFifoVld := r.DataFifoVld or r.RecEna or r.PreRecEna;
|
||||
v.RecEna := '0'; -- stop recording after frame
|
||||
v.PreRecEna := '0';
|
||||
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.DataFifoVld := r.DataFifoVld or r.RecEna or r.PreRecEna;
|
||||
v.RecEna := '0'; -- stop recording after frame
|
||||
v.PreRecEna := '0';
|
||||
else
|
||||
v.PostTrigCnt := unsigned(PostTrigSpls_Sync);
|
||||
v.RecEna := '1';
|
||||
v.PostTrigCnt := unsigned(PostTrigSpls_Sync);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Detect Timeout
|
||||
if Str_Vld = '1' then
|
||||
-- Detect Timeout (only if data is stuck in conversion)
|
||||
if Str_Vld = '1' or r.WordCnt = 0 then
|
||||
v.TimeoutCnt := 0;
|
||||
else
|
||||
if r.TimeoutCnt = TimeoutLimit_c then
|
||||
@@ -249,40 +269,41 @@ begin
|
||||
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;
|
||||
-- Write because timeout occured
|
||||
if r.Timeout = '1' then
|
||||
v.DataFifoVld := r.DataFifoVld or r.RecEna or r.PreRecEna;
|
||||
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' or r.PreRecEna = '1') then
|
||||
v.WordCnt := r.WordCnt + 1;
|
||||
v.BytesCnt := r.BytesCnt + BytesIncr_c;
|
||||
-- Write because 64-bits are ready
|
||||
if r.WordCnt = WconvFactor_c-1 then
|
||||
v.DataFifoVld := r.DataFifoVld or r.RecEna or r.PreRecEna;
|
||||
end if;
|
||||
-- If the pretrigger is disabled, use delayed data to compensate for trigger detection time
|
||||
if PreTrigDisable_Sync = '1' then
|
||||
v.DataSftReg((to_integer(r.WordCnt)+1)*StreamWidth_g-1 downto to_integer(r.WordCnt)*StreamWidth_g) := r.StrData;
|
||||
else
|
||||
v.DataSftReg((to_integer(r.WordCnt)+1)*StreamWidth_g-1 downto to_integer(r.WordCnt)*StreamWidth_g) := Str_Data;
|
||||
end if;
|
||||
end if;
|
||||
-- Reset counter if data is being written to FIFO
|
||||
if v.DataFifoVld = '1' then
|
||||
v.WordCnt := (others => '0');
|
||||
v.BytesCnt := (others => '0');
|
||||
end if;
|
||||
|
||||
-- Convert word counter to byte counter
|
||||
v.DataFifoBytes := (others => '0');
|
||||
if r.Timeout = '1' then
|
||||
AddSamples_v := 0;
|
||||
v.DataFifoBytes := r.BytesCnt;
|
||||
else
|
||||
AddSamples_v := 1;
|
||||
v.DataFifoBytes := r.BytesCnt + BytesIncr_c;
|
||||
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!
|
||||
@@ -298,17 +319,21 @@ begin
|
||||
when RecMode_Continuous_c |
|
||||
RecMode_TriggerMask_c =>
|
||||
-- always enabled
|
||||
v.RecEna := '1';
|
||||
when RecMode_SingleShot_c |
|
||||
RecMode_ManuelMode_c =>
|
||||
v.PreRecEna := not PreTrigDisable_Sync;
|
||||
when RecMode_SingleShot_c =>
|
||||
if v.ArmReg = '1' then
|
||||
v.PreRecEna := not PreTrigDisable_Sync;
|
||||
end if;
|
||||
when RecMode_ManuelMode_c =>
|
||||
-- enable on arming (disable happens after recording)
|
||||
if v.ArmReg = '1' then
|
||||
v.RecEna := '1';
|
||||
v.PreRecEna := '1';
|
||||
end if;
|
||||
when others => null;
|
||||
end case;
|
||||
if r.ModeReg /= Mode_Sync then
|
||||
v.RecEna := '0';
|
||||
v.RecEna := '0';
|
||||
v.PreRecEna := '0';
|
||||
end if;
|
||||
|
||||
-- *** Assign to signal ***
|
||||
@@ -316,33 +341,36 @@ begin
|
||||
|
||||
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;
|
||||
--------------------------------------------
|
||||
-- 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.BytesCnt <= (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.PreRecEna <= '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
|
||||
@@ -357,33 +385,50 @@ begin
|
||||
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');
|
||||
end if;
|
||||
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 (
|
||||
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
|
||||
);
|
||||
--------------------------------------------
|
||||
-- Component Instantiation
|
||||
--------------------------------------------
|
||||
-- *** Register Interface clock crossings ***
|
||||
i_cc_reg_status : entity work.psi_common_status_cc
|
||||
generic map (
|
||||
DataWidth_g => 35
|
||||
)
|
||||
port map (
|
||||
ClkA => ClkReg,
|
||||
RstInA => '0',
|
||||
DataA(31 downto 0) => PostTrigSpls,
|
||||
DataA(33 downto 32) => Mode,
|
||||
DataA(34) => PreTrigDisable,
|
||||
ClkB => Str_Clk,
|
||||
RstInB => Str_Rst,
|
||||
DataB(31 downto 0) => PostTrigSpls_Sync,
|
||||
DataB(33 downto 32) => Mode_Sync,
|
||||
DataB(34) => PreTrigDisable_Sync
|
||||
);
|
||||
|
||||
i_cc_status : entity work.psi_common_bit_cc
|
||||
generic map (
|
||||
@@ -391,7 +436,7 @@ begin
|
||||
)
|
||||
port map (
|
||||
BitsA(0) => r.IsArmed,
|
||||
BitsA(1) => r.RecEna,
|
||||
BitsA(1) => r.RecEna or r.PreRecEna,
|
||||
ClkB => ClkReg,
|
||||
BitsB(0) => IsArmed,
|
||||
BitsB(1) => IsRecording
|
||||
@@ -452,16 +497,17 @@ begin
|
||||
);
|
||||
|
||||
|
||||
-- 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;
|
||||
-- Data FIFO
|
||||
DataFifo_InData(MemoryBusWidth_c-1+2 downto 2) <= r.DataSftReg;
|
||||
DataFifo_InData(MemoryBusWidth_c+Input2Daq_Data_Bytes_Len+2-1
|
||||
downto MemoryBusWidth_c+2) <= std_logic_vector(r.DataFifoBytes);
|
||||
DataFifo_InData(0) <= r.DataFifoIsTo;
|
||||
DataFifo_InData(1) <= r.DataFifoIsTrig;
|
||||
|
||||
|
||||
i_dfifo : entity work.psi_common_async_fifo
|
||||
generic map (
|
||||
Width_g => 70,
|
||||
Width_g => DataFifo_Width_c,
|
||||
Depth_g => StreamBuffer_g,
|
||||
AlmFullOn_g => false,
|
||||
AlmEmptyOn_g => false
|
||||
@@ -474,21 +520,37 @@ begin
|
||||
InData => DataFifo_InData,
|
||||
InVld => r.DataFifoVld,
|
||||
InRdy => DataFifo_InRdy,
|
||||
OutData => DataFifo_OutData,
|
||||
OutVld => Daq_Vld_I,
|
||||
OutRdy => Daq_Rdy,
|
||||
OutLevel => Daq_Level(log2ceil(StreamBuffer_g) downto 0)
|
||||
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 => DataFifo_Width_c,
|
||||
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
|
||||
);
|
||||
Daq_Level(Daq_Level'high downto log2ceil(StreamBuffer_g)+1) <= (others => '0');
|
||||
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;
|
||||
Daq_Data_I.Data <= DataFifo_OutData(MemoryBusWidth_c-1+2 downto 2);
|
||||
Daq_Data_I.Bytes <= DataFifo_OutData(MemoryBusWidth_c+Input2Daq_Data_Bytes_Len+2-1 downto MemoryBusWidth_c+2);
|
||||
Daq_Data_I.IsTo <= DataFifo_OutData(0);
|
||||
Daq_Data_I.IsTrig <= DataFifo_OutData(1);
|
||||
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
|
||||
@@ -535,7 +597,7 @@ begin
|
||||
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;
|
||||
assert MemoryBusWidth_c mod StreamWidth_g = 0 report "###ERROR###: psi_ms_daq_input: StreamWidth_g must be modulo division of MemoryBusWidth_c" severity error;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@ library work;
|
||||
------------------------------------------------------------------------------
|
||||
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;
|
||||
constant MemoryBusWidth_c : integer := 512;
|
||||
constant MemoryBusBytes_c : integer := MemoryBusWidth_c/8;
|
||||
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 := MemoryBusWidth_c;
|
||||
|
||||
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));
|
||||
@@ -33,11 +35,12 @@ package psi_ms_daq_pkg is
|
||||
|
||||
subtype WinType_t is std_logic_vector(MaxWindowsBits_c-1 downto 0);
|
||||
type WinType_a is array (natural range <>) of WinType_t;
|
||||
|
||||
|
||||
constant Input2Daq_Data_Bytes_Len : natural := log2(MemoryBusBytes_c)+1;
|
||||
type Input2Daq_Data_t is record
|
||||
Last : std_logic;
|
||||
Data : std_logic_vector(63 downto 0);
|
||||
Bytes : std_logic_vector(3 downto 0);
|
||||
Data : std_logic_vector(MemoryBusWidth_c-1 downto 0);
|
||||
Bytes : std_logic_vector(Input2Daq_Data_Bytes_Len-1 downto 0);
|
||||
IsTo : std_logic;
|
||||
IsTrig : std_logic;
|
||||
end record;
|
||||
|
||||
@@ -77,6 +77,7 @@ entity psi_ms_daq_reg_axi is
|
||||
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);
|
||||
PreTrigDisable : out std_logic_vector(Streams_g-1 downto 0);
|
||||
IrqOut : out std_logic;
|
||||
|
||||
-- Memory Interfae Clock domain control singals
|
||||
@@ -99,22 +100,23 @@ entity psi_ms_daq_reg_axi is
|
||||
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;
|
||||
-- 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);
|
||||
Reg_Mode_PreTrigDisable : 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";
|
||||
|
||||
@@ -206,7 +208,7 @@ begin
|
||||
v.Reg_Mode_Arm := (others => '0');
|
||||
v.MaxLvlClr := (others => '0');
|
||||
if AccAddr(15 downto 9) = X"0" & "001" then
|
||||
Stream_v := to_integer(unsigned(AccAddr(8 downto 4)));
|
||||
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
|
||||
@@ -224,18 +226,20 @@ begin
|
||||
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;
|
||||
-- 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);
|
||||
v.Reg_Mode_PreTrigDisable(Stream_v) := AccWrData(2);
|
||||
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(2) := r.Reg_Mode_PreTrigDisable(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
|
||||
@@ -291,27 +295,29 @@ begin
|
||||
PostTrig <= r.Reg_PostTrig;
|
||||
Arm <= r.Reg_Mode_Arm;
|
||||
RecMode <= r.Reg_Mode_Recm;
|
||||
PreTrigDisable <= r.Reg_Mode_PreTrigDisable;
|
||||
|
||||
--------------------------------------------
|
||||
-- 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;
|
||||
--------------------------------------------
|
||||
-- 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');
|
||||
r.Reg_Mode_PreTrigDisable <= (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------
|
||||
-- Maximum Level Latching (MemClk)
|
||||
|
||||
@@ -90,6 +90,8 @@ add_sources "../tb" {
|
||||
psi_ms_daq_axi/psi_ms_daq_axi_tb_str2_pkg.vhd \
|
||||
psi_ms_daq_axi/psi_ms_daq_axi_tb_str3_pkg.vhd \
|
||||
psi_ms_daq_axi/psi_ms_daq_axi_tb.vhd \
|
||||
psi_ms_daq_axi_1s/psi_ms_daq_axi_1s_tb_str0_pkg.vhd \
|
||||
psi_ms_daq_axi_1s/psi_ms_daq_axi_1s_tb.vhd \
|
||||
} -tag tb
|
||||
|
||||
#TB Runs
|
||||
@@ -112,6 +114,9 @@ add_tb_run
|
||||
create_tb_run "psi_ms_daq_axi_tb"
|
||||
add_tb_run
|
||||
|
||||
create_tb_run "psi_ms_daq_axi_1s_tb"
|
||||
add_tb_run
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -378,7 +378,7 @@ begin
|
||||
-- *** Check end state ***
|
||||
assert Str0WinCheck >= 4 report "###ERROR###: Stream 0 checks not completed" severity error;
|
||||
assert Str1WinCheck = 1 report "###ERROR###: Stream 1 checks not completed" severity error;
|
||||
assert Str2WinCheck = 2 report "###ERROR###: Stream 2 checks not completed" severity error;
|
||||
assert Str2WinCheck >= 2 report "###ERROR###: Stream 2 checks not completed" severity error;
|
||||
assert Str3WinCheck = 2 report "###ERROR###: Stream 3 checks not completed" severity error;
|
||||
wait;
|
||||
end process;
|
||||
|
||||
393
tb/psi_ms_daq_axi_1s/psi_ms_daq_axi_1s_tb.vhd
Normal file
393
tb/psi_ms_daq_axi_1s/psi_ms_daq_axi_1s_tb.vhd
Normal file
@@ -0,0 +1,393 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- Copyright (c) 2019 by Paul Scherrer Institute, Switzerland
|
||||
-- All rights reserved.
|
||||
-- Authors: Oliver Bruendler
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Testbench generated by TbGen.py
|
||||
------------------------------------------------------------
|
||||
-- see Library/Python/TbGenerator
|
||||
|
||||
------------------------------------------------------------
|
||||
-- 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;
|
||||
|
||||
library work;
|
||||
use work.psi_tb_txt_util.all;
|
||||
use work.psi_tb_compare_pkg.all;
|
||||
use work.psi_tb_axi_pkg.all;
|
||||
use work.psi_ms_daq_axi_tb_pkg.all;
|
||||
use work.psi_ms_daq_axi_1s_tb_str0_pkg.all;
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Entity Declaration
|
||||
------------------------------------------------------------
|
||||
entity psi_ms_daq_axi_1s_tb is
|
||||
end entity;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Architecture
|
||||
------------------------------------------------------------
|
||||
architecture sim of psi_ms_daq_axi_1s_tb is
|
||||
|
||||
-- TB Control
|
||||
signal TbRunning : boolean := true;
|
||||
signal PrintIrq_c : boolean := PrintDefault_c;
|
||||
|
||||
-- Constants
|
||||
constant StrCount_c : integer := 1;
|
||||
constant ClkFreq_c : t_areal := (0=>250.0e6);
|
||||
|
||||
-- Axi Memory
|
||||
constant ID_WIDTH : integer := 1;
|
||||
constant ADDR_WIDTH : integer := 32;
|
||||
constant USER_WIDTH : integer := 1;
|
||||
constant DATA_WIDTH : integer := 64;
|
||||
constant BYTE_WIDTH : integer := DATA_WIDTH/8;
|
||||
|
||||
subtype ID_RANGE is natural range ID_WIDTH-1 downto 0;
|
||||
subtype ADDR_RANGE is natural range ADDR_WIDTH-1 downto 0;
|
||||
subtype USER_RANGE is natural range USER_WIDTH-1 downto 0;
|
||||
subtype DATA_RANGE is natural range DATA_WIDTH-1 downto 0;
|
||||
subtype BYTE_RANGE is natural range BYTE_WIDTH-1 downto 0;
|
||||
|
||||
subtype axi_ms_t is axi_ms_r ( arid(ID_RANGE), awid(ID_RANGE),
|
||||
araddr(ADDR_RANGE), awaddr(ADDR_RANGE),
|
||||
aruser(USER_RANGE), awuser(USER_RANGE), wuser(USER_RANGE),
|
||||
wdata(DATA_RANGE),
|
||||
wstrb(BYTE_RANGE));
|
||||
|
||||
subtype axi_sm_t is axi_sm_r ( rid(ID_RANGE), bid(ID_RANGE),
|
||||
ruser(USER_RANGE), buser(USER_RANGE),
|
||||
rdata(DATA_RANGE));
|
||||
|
||||
-- Axi Registers
|
||||
constant REG_ID_WIDTH : integer := 1;
|
||||
constant REG_ADDR_WIDTH : integer := 16;
|
||||
constant REG_USER_WIDTH : integer := 1;
|
||||
constant REG_DATA_WIDTH : integer := 32;
|
||||
constant REG_BYTE_WIDTH : integer := REG_DATA_WIDTH/8;
|
||||
|
||||
subtype REG_ID_RANGE is natural range REG_ID_WIDTH-1 downto 0;
|
||||
subtype REG_ADDR_RANGE is natural range REG_ADDR_WIDTH-1 downto 0;
|
||||
subtype REG_USER_RANGE is natural range REG_USER_WIDTH-1 downto 0;
|
||||
subtype REG_DATA_RANGE is natural range REG_DATA_WIDTH-1 downto 0;
|
||||
subtype REG_BYTE_RANGE is natural range REG_BYTE_WIDTH-1 downto 0;
|
||||
|
||||
subtype reg_axi_ms_t is axi_ms_r ( arid(REG_ID_RANGE), awid(REG_ID_RANGE),
|
||||
araddr(REG_ADDR_RANGE), awaddr(REG_ADDR_RANGE),
|
||||
aruser(REG_USER_RANGE), awuser(REG_USER_RANGE), wuser(REG_USER_RANGE),
|
||||
wdata(REG_DATA_RANGE),
|
||||
wstrb(REG_BYTE_RANGE));
|
||||
|
||||
subtype reg_axi_sm_t is axi_sm_r ( rid(REG_ID_RANGE), bid(REG_ID_RANGE),
|
||||
ruser(REG_USER_RANGE), buser(REG_USER_RANGE),
|
||||
rdata(REG_DATA_RANGE));
|
||||
|
||||
|
||||
-- Port signals
|
||||
signal Str_Clk : std_logic_vector(StrCount_c-1 downto 0) := (others => '0');
|
||||
signal Str0_Data : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal Timestamp : t_aslv64(StrCount_c-1 downto 0) := (others => (others => '0'));
|
||||
signal Str_Vld : std_logic_vector(StrCount_c-1 downto 0) := (others => '0');
|
||||
signal Str_Rdy : std_logic_vector(StrCount_c-1 downto 0) := (others => '0');
|
||||
signal Str_Trig : std_logic_vector(StrCount_c-1 downto 0) := (others => '0');
|
||||
signal M_Axi_Aclk : std_logic := '0';
|
||||
signal S_Axi_Aclk : std_logic := '0';
|
||||
signal M_Axi_Aresetn : std_logic := '0';
|
||||
signal S_Axi_Aresetn : std_logic := '0';
|
||||
signal Irq : std_logic := '0';
|
||||
signal axi_ms : axi_ms_t;
|
||||
signal axi_sm : axi_sm_t;
|
||||
signal reg_axi_ms : reg_axi_ms_t;
|
||||
signal reg_axi_sm : reg_axi_sm_t;
|
||||
|
||||
|
||||
procedure IrqHandler( signal clk : in std_logic;
|
||||
signal rqst : out axi_ms_r;
|
||||
signal rsp : in axi_sm_r) is
|
||||
variable v : integer;
|
||||
variable slv : std_logic_vector(31 downto 0);
|
||||
begin
|
||||
print("###################################### IRQ Detected #########################################", PrintIrq_c);
|
||||
wait until rising_edge(clk);
|
||||
AxiRead32(16#0010#, v, clk, rqst, rsp);
|
||||
slv := std_logic_vector(to_unsigned(v, 32));
|
||||
AxiWrite32(16#0010#, v, clk, rqst, rsp);
|
||||
wait until rising_edge(clk);
|
||||
for i in 0 to StrCount_c-1 loop
|
||||
if slv(i) = '1' then
|
||||
case i is
|
||||
when 0 => Str0Handler(clk, rqst, rsp);
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end loop;
|
||||
-- Delay to ensure IRQ is cleared
|
||||
for i in 0 to 5 loop
|
||||
wait until rising_edge(clk);
|
||||
end loop;
|
||||
end procedure;
|
||||
|
||||
|
||||
begin
|
||||
------------------------------------------------------------
|
||||
-- DUT Instantiation
|
||||
------------------------------------------------------------
|
||||
i_dut : entity work.psi_ms_daq_axi
|
||||
generic map (
|
||||
Streams_g => StrCount_c,
|
||||
StreamWidth_g => (0=>8),
|
||||
StreamPrio_g => (0=>1),
|
||||
StreamBuffer_g => (0=>32),
|
||||
StreamTimeout_g => (0=>5.0e-6),
|
||||
StreamClkFreq_g => (ClkFreq_c, ClkFreq_c),
|
||||
StreamTsFifoDepth_g => (0=>16, 1=>16),
|
||||
StreamUseTs_g => (0=>true, 1=>true),
|
||||
MaxWindows_g => work.psi_ms_daq_axi_tb_pkg.MaxWindows_c,
|
||||
MinBurstSize_g => 16,
|
||||
MaxBurstSize_g => 128,
|
||||
AxiFifoDepth_g => 512,
|
||||
AxiSlaveIdWidth_g => 1
|
||||
)
|
||||
port map (
|
||||
Str_Clk => Str_Clk,
|
||||
Str_Data(0)(7 downto 0) => Str0_Data,
|
||||
Str_Data(0)(63 downto 8) => (others => '0'),
|
||||
Str_Ts => Timestamp,
|
||||
Str_Vld => Str_Vld,
|
||||
Str_Rdy => Str_Rdy,
|
||||
Str_Trig => Str_Trig,
|
||||
Irq => Irq,
|
||||
S_Axi_Aclk => S_Axi_Aclk,
|
||||
S_Axi_Aresetn => S_Axi_Aresetn,
|
||||
S_Axi_ArId => reg_axi_ms.arid,
|
||||
S_Axi_ArAddr => reg_axi_ms.araddr,
|
||||
S_Axi_Arlen => reg_axi_ms.arlen,
|
||||
S_Axi_ArSize => reg_axi_ms.arsize,
|
||||
S_Axi_ArBurst => reg_axi_ms.arburst,
|
||||
S_Axi_ArLock => reg_axi_ms.arlock,
|
||||
S_Axi_ArCache => reg_axi_ms.arcache,
|
||||
S_Axi_ArProt => reg_axi_ms.arprot,
|
||||
S_Axi_ArValid => reg_axi_ms.arvalid,
|
||||
S_Axi_ArReady => reg_axi_sm.arready,
|
||||
S_Axi_RId => reg_axi_sm.rid,
|
||||
S_Axi_RData => reg_axi_sm.rdata,
|
||||
S_Axi_RResp => reg_axi_sm.rresp,
|
||||
S_Axi_RLast => reg_axi_sm.rlast,
|
||||
S_Axi_RValid => reg_axi_sm.rvalid,
|
||||
S_Axi_RReady => reg_axi_ms.rready,
|
||||
S_Axi_AwAddr => reg_axi_ms.awaddr,
|
||||
S_AXi_AwId => reg_axi_ms.awid,
|
||||
S_Axi_AwLen => reg_axi_ms.awlen,
|
||||
S_Axi_AwSize => reg_axi_ms.awsize,
|
||||
S_Axi_AwBurst => reg_axi_ms.awburst,
|
||||
S_Axi_AwLock => reg_axi_ms.awlock,
|
||||
S_Axi_AwCache => reg_axi_ms.awcache,
|
||||
S_Axi_AwProt => reg_axi_ms.awprot,
|
||||
S_Axi_AwValid => reg_axi_ms.awvalid,
|
||||
S_Axi_AwReady => reg_axi_sm.awready,
|
||||
S_Axi_WData => reg_axi_ms.wdata,
|
||||
S_Axi_WStrb => reg_axi_ms.wstrb,
|
||||
S_Axi_WLast => reg_axi_ms.wlast,
|
||||
S_Axi_WValid => reg_axi_ms.wvalid,
|
||||
S_Axi_WReady => reg_axi_sm.wready,
|
||||
S_Axi_BId => reg_axi_sm.bid,
|
||||
S_Axi_BResp => reg_axi_sm.bresp,
|
||||
S_Axi_BValid => reg_axi_sm.bvalid,
|
||||
S_Axi_BReady => reg_axi_ms.bready,
|
||||
M_Axi_Aclk => M_Axi_Aclk,
|
||||
M_Axi_Aresetn => M_Axi_Aresetn,
|
||||
M_Axi_AwAddr => axi_ms.awaddr,
|
||||
M_Axi_AwLen => axi_ms.awlen,
|
||||
M_Axi_AwSize => axi_ms.awsize,
|
||||
M_Axi_AwBurst => axi_ms.awburst,
|
||||
M_Axi_AwLock => axi_ms.awlock,
|
||||
M_Axi_AwCache => axi_ms.awcache,
|
||||
M_Axi_AwProt => axi_ms.awprot,
|
||||
M_Axi_AwValid => axi_ms.awvalid,
|
||||
M_Axi_AwReady => axi_sm.awready,
|
||||
M_Axi_WData => axi_ms.wdata,
|
||||
M_Axi_WStrb => axi_ms.wstrb,
|
||||
M_Axi_WLast => axi_ms.wlast,
|
||||
M_Axi_WValid => axi_ms.wvalid,
|
||||
M_Axi_WReady => axi_sm.wready,
|
||||
M_Axi_BResp => axi_sm.bresp,
|
||||
M_Axi_BValid => axi_sm.bvalid,
|
||||
M_Axi_BReady => axi_ms.bready,
|
||||
M_Axi_ArAddr => axi_ms.araddr,
|
||||
M_Axi_ArLen => axi_ms.arlen,
|
||||
M_Axi_ArSize => axi_ms.arsize,
|
||||
M_Axi_ArBurst => axi_ms.arburst,
|
||||
M_Axi_ArLock => axi_ms.arlock,
|
||||
M_Axi_ArCache => axi_ms.arcache,
|
||||
M_Axi_ArProt => axi_ms.arprot,
|
||||
M_Axi_ArValid => axi_ms.arvalid,
|
||||
M_Axi_ArReady => axi_sm.arready,
|
||||
M_Axi_RData => axi_sm.rdata,
|
||||
M_Axi_RResp => axi_sm.rresp,
|
||||
M_Axi_RLast => axi_sm.rlast,
|
||||
M_Axi_RValid => axi_sm.rvalid,
|
||||
M_Axi_RReady => axi_ms.rready
|
||||
);
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Emulate Memory
|
||||
------------------------------------------------------------
|
||||
p_mem : process
|
||||
variable Address_v : integer;
|
||||
variable Size_v : integer;
|
||||
begin
|
||||
axi_slave_init(axi_sm);
|
||||
wait until rising_edge(M_Axi_Aclk);
|
||||
while TbRunning loop
|
||||
axi_sm.awready <= '1';
|
||||
wait until (rising_edge(M_Axi_Aclk) and axi_ms.awvalid = '1') or (not TbRunning);
|
||||
if TbRunning then
|
||||
axi_sm.awready <= '0';
|
||||
axi_sm.wready <= '1';
|
||||
Address_v := to_integer(unsigned(axi_ms.awaddr));
|
||||
Size_v := to_integer(unsigned(axi_ms.awlen))+1;
|
||||
for qw in 0 to Size_v-1 loop
|
||||
wait until rising_edge(M_Axi_Aclk) and axi_ms.wvalid = '1';
|
||||
for byte in 0 to 7 loop
|
||||
if axi_ms.wstrb(byte) = '1' then
|
||||
Memory(Address_v+qw*8+byte) <= axi_ms.wdata(byte*8+7 downto byte*8);
|
||||
end if;
|
||||
end loop;
|
||||
end loop;
|
||||
StdlCompare(1, axi_ms.wlast, "Last not received at end of burst");
|
||||
axi_sm.wready <= '0';
|
||||
axi_sm.bresp <= xRESP_OKAY_c;
|
||||
axi_sm.bvalid <= '1';
|
||||
wait until rising_edge(M_Axi_Aclk) and axi_ms.bready = '1';
|
||||
axi_sm.bvalid <= '0';
|
||||
end if;
|
||||
end loop;
|
||||
wait;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Clocks
|
||||
------------------------------------------------------------
|
||||
|
||||
p_clk_axi_mem : process
|
||||
constant Frequency_c : real := real(200e6);
|
||||
begin
|
||||
while TbRunning loop
|
||||
wait for 0.5*(1 sec)/Frequency_c;
|
||||
M_Axi_Aclk <= not M_Axi_Aclk;
|
||||
end loop;
|
||||
wait;
|
||||
end process;
|
||||
|
||||
p_clk_axi_reg : process
|
||||
constant Frequency_c : real := real(166e6);
|
||||
begin
|
||||
while TbRunning loop
|
||||
wait for 0.5*(1 sec)/Frequency_c;
|
||||
S_Axi_Aclk <= not S_Axi_Aclk;
|
||||
end loop;
|
||||
wait;
|
||||
end process;
|
||||
|
||||
g_clk_str : for i in 0 to StrCount_c-1 generate
|
||||
p_clk_str : process
|
||||
begin
|
||||
while TbRunning loop
|
||||
wait for 0.5*(1 sec)/(ClkFreq_c(i)+0.1e6);
|
||||
Str_Clk(i) <= not Str_Clk(i);
|
||||
end loop;
|
||||
wait;
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Reg-Access Process
|
||||
------------------------------------------------------------
|
||||
p_regacc : process
|
||||
variable StartTime_v : time;
|
||||
variable Stream1Armed_v : boolean := false;
|
||||
variable Stream2Armed_v : boolean := false;
|
||||
begin
|
||||
print("*** Info ***");
|
||||
print("This testbench does not print any status information by default (only errors).");
|
||||
print("To change this behavior, change the constant PrintDefault_c in psi_ms_daq_axi_1s_tb_pkg.");
|
||||
|
||||
axi_master_init(reg_axi_ms);
|
||||
wait for 1 us;
|
||||
S_Axi_Aresetn <= '1';
|
||||
M_Axi_Aresetn <= '1';
|
||||
|
||||
-- *** Initial Configuration ***
|
||||
AxiExpect32(16#0010#, 0, S_Axi_Aclk, reg_axi_ms, reg_axi_sm, "Inital IRQVEC");
|
||||
AxiWriteAndRead32(16#0014#, 16#0001#, S_Axi_Aclk, reg_axi_ms, reg_axi_sm);
|
||||
AxiWriteAndRead32(16#0020#, 16#0001#, S_Axi_Aclk, reg_axi_ms, reg_axi_sm);
|
||||
-- Stream Setup
|
||||
Str0Setup(S_Axi_Aclk, reg_axi_ms, reg_axi_sm);
|
||||
|
||||
-- Enable
|
||||
AxiWriteAndRead32(16#0000#, 16#0101#, S_Axi_Aclk, reg_axi_ms, reg_axi_sm);
|
||||
|
||||
|
||||
-- *** Run Test ***
|
||||
StartTime_v := now;
|
||||
while now < StartTime_v+150 us loop
|
||||
wait until rising_edge(S_Axi_Aclk);
|
||||
-- IRQ Handling
|
||||
if Irq = '1' then
|
||||
IrqHandler(S_Axi_Aclk, reg_axi_ms, reg_axi_sm);
|
||||
end if;
|
||||
-- Regular actions
|
||||
Str0Update(S_Axi_Aclk, reg_axi_ms, reg_axi_sm);
|
||||
|
||||
end loop;
|
||||
TbRunning <= false;
|
||||
|
||||
-- *** Check end state ***
|
||||
assert Str0WinCheck >= 4 report "###ERROR###: Stream 0 checks not completed" severity error;
|
||||
wait;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Timestamp Processes
|
||||
------------------------------------------------------------
|
||||
g_ts : for i in 0 to StrCount_c-1 generate
|
||||
p_ts : process
|
||||
begin
|
||||
while TbRunning loop
|
||||
wait until rising_edge(Str_Clk(0));
|
||||
Timestamp(0) <= std_logic_vector(unsigned(Timestamp(0)) + 1);
|
||||
end loop;
|
||||
wait;
|
||||
end process;
|
||||
end generate;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Data Generation Processes
|
||||
------------------------------------------------------------
|
||||
p_str0 : process
|
||||
variable IrqOn : boolean := false;
|
||||
begin
|
||||
wait until rising_edge(Str_Clk(0));
|
||||
while TbRunning loop
|
||||
Str0Sample(Str_Clk(0), Str_Vld(0), Str_Trig(0), Str0_Data);
|
||||
end loop;
|
||||
wait;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Check Process
|
||||
------------------------------------------------------------
|
||||
|
||||
end;
|
||||
258
tb/psi_ms_daq_axi_1s/psi_ms_daq_axi_1s_tb_str0_pkg.vhd
Normal file
258
tb/psi_ms_daq_axi_1s/psi_ms_daq_axi_1s_tb_str0_pkg.vhd
Normal file
@@ -0,0 +1,258 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- Copyright (c) 2019 by Paul Scherrer Institute, Switzerland
|
||||
-- All rights reserved.
|
||||
-- Authors: Oliver Bruendler
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Description
|
||||
------------------------------------------------------------
|
||||
-- Stream 0 works in ringbuffer mode (without overwrite). It
|
||||
-- produces 8-bit data (modulo counter). IRQs are located at samples
|
||||
-- containing data 30, 60 and 90. IRQs are suppressed until 15 us after
|
||||
-- simulation to see if IRQ enable works correctly.
|
||||
-- The IRQ handler also sets the window sample counter to zero to ensure
|
||||
-- more data can be recorded after the IRQ.
|
||||
|
||||
------------------------------------------------------------
|
||||
-- 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;
|
||||
|
||||
library work;
|
||||
use work.psi_tb_txt_util.all;
|
||||
use work.psi_tb_compare_pkg.all;
|
||||
use work.psi_ms_daq_axi_tb_pkg.all;
|
||||
use work.psi_tb_axi_pkg.all;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Package Header
|
||||
------------------------------------------------------------
|
||||
package psi_ms_daq_axi_1s_tb_str0_pkg is
|
||||
|
||||
constant PrintStr0_c : boolean := PrintDefault_c;
|
||||
|
||||
-- Memory
|
||||
constant Str0BufStart_c : integer := 16#1000#;
|
||||
constant Str0WinSize_c : integer := 100;
|
||||
constant Str0Windows_c : integer := 3;
|
||||
alias Memory0 : t_aslv8(0 to Str0WinSize_c*Str0Windows_c) is Memory(Str0BufStart_c to Str0BufStart_c+Str0WinSize_c*Str0Windows_c);
|
||||
|
||||
--------------------------------------------------------
|
||||
-- Persistent State
|
||||
--------------------------------------------------------
|
||||
shared variable Str0NextWin : integer := 0;
|
||||
shared variable Str0WinCheck : integer := 0;
|
||||
shared variable Str0LastTs : integer;
|
||||
shared variable Str0IrqOn : boolean := false;
|
||||
shared variable Str0Disabled : boolean := false;
|
||||
|
||||
--------------------------------------------------------
|
||||
-- Data Generation
|
||||
--------------------------------------------------------
|
||||
procedure Str0Sample( signal clk : in std_logic;
|
||||
signal vld : out std_logic;
|
||||
signal trig : out std_logic;
|
||||
signal data : out std_logic_vector(7 downto 0));
|
||||
|
||||
--------------------------------------------------------
|
||||
-- IRQ Handler
|
||||
--------------------------------------------------------
|
||||
procedure Str0Handler( signal clk : in std_logic;
|
||||
signal rqst : out axi_ms_r;
|
||||
signal rsp : in axi_sm_r);
|
||||
|
||||
--------------------------------------------------------
|
||||
-- Setup
|
||||
--------------------------------------------------------
|
||||
procedure Str0Setup( signal clk : in std_logic;
|
||||
signal rqst : out axi_ms_r;
|
||||
signal rsp : in axi_sm_r);
|
||||
|
||||
--------------------------------------------------------
|
||||
-- Update
|
||||
--------------------------------------------------------
|
||||
procedure Str0Update( signal clk : in std_logic;
|
||||
signal rqst : out axi_ms_r;
|
||||
signal rsp : in axi_sm_r);
|
||||
|
||||
|
||||
end package;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- Package Body
|
||||
------------------------------------------------------------
|
||||
package body psi_ms_daq_axi_1s_tb_str0_pkg is
|
||||
|
||||
--------------------------------------------------------
|
||||
-- Data Generation
|
||||
--------------------------------------------------------
|
||||
procedure Str0Sample( signal clk : in std_logic;
|
||||
signal vld : out std_logic;
|
||||
signal trig : out std_logic;
|
||||
signal data : out std_logic_vector(7 downto 0)) is
|
||||
begin
|
||||
vld <= '1';
|
||||
if (now > 15 us) and (to_integer(unsigned(data)) = 0) then
|
||||
Str0IrqOn := true;
|
||||
end if;
|
||||
case to_integer(unsigned(data)) is
|
||||
when 30 | 60 | 90 =>
|
||||
if Str0IrqOn then
|
||||
trig <= '1';
|
||||
end if;
|
||||
when others => null;
|
||||
end case;
|
||||
wait until rising_edge(clk);
|
||||
vld <= '0';
|
||||
trig <= '0';
|
||||
data <= std_logic_vector(unsigned(data)+1);
|
||||
wait until rising_edge(clk);
|
||||
end procedure;
|
||||
|
||||
--------------------------------------------------------
|
||||
-- IRQ Handler
|
||||
--------------------------------------------------------
|
||||
procedure Str0Handler( signal clk : in std_logic;
|
||||
signal rqst : out axi_ms_r;
|
||||
signal rsp : in axi_sm_r) is
|
||||
variable v : integer;
|
||||
variable curwin : integer;
|
||||
variable lastwin : integer;
|
||||
variable wincnt : integer;
|
||||
variable winstart, winend : integer;
|
||||
variable winlast : integer;
|
||||
variable addr : integer;
|
||||
variable tslo : integer;
|
||||
variable firstLoop : boolean := true;
|
||||
variable HasTrigger : boolean;
|
||||
begin
|
||||
print("------------ Stream 0 Handler ------------", PrintStr0_c);
|
||||
HlGetMaxLvl(0, clk, rqst, rsp, v);
|
||||
print("MAXLVL: " & to_string(v), PrintStr0_c);
|
||||
HlGetCurWin(0, clk, rqst, rsp, curwin);
|
||||
print("CURWIN: " & to_string(curwin), PrintStr0_c);
|
||||
HlGetLastWin(0, clk, rqst, rsp, lastwin);
|
||||
print("LASTWIN: " & to_string(lastwin), PrintStr0_c);
|
||||
print("", PrintStr0_c);
|
||||
if Str0Disabled then
|
||||
print("Skipped, stream disabled", PrintStr0_c);
|
||||
print("", PrintStr0_c);
|
||||
else
|
||||
HlIsTrigWin(0, Str0NextWin, clk, rqst, rsp, HasTrigger);
|
||||
-- lastwin = nextwin can occur if al lwindows are filled. In all cases we only interpret windows containing triggers.
|
||||
while ((Str0NextWin /= ((lastwin+1) mod 3)) or firstLoop) and HasTrigger loop
|
||||
firstLoop := false;
|
||||
print("*** Window " & to_string(Str0NextWin) & " / Number: " & to_string(Str0WinCheck) & " ***", PrintStr0_c);
|
||||
HlGetWinCnt(0, Str0NextWin, clk, rqst, rsp, wincnt);
|
||||
print("WINCNT: " & to_string(wincnt), PrintStr0_c);
|
||||
HlClrWinCnt(0, Str0NextWin, clk, rqst, rsp);
|
||||
HlGetWinLast(0, Str0NextWin, clk, rqst, rsp, winlast);
|
||||
print("WINLAST: " & to_string(winlast), PrintStr0_c);
|
||||
HlGetTsLo(0, Str0NextWin, clk, rqst, rsp, tslo);
|
||||
print("WINTSLO: " & to_string(tslo), PrintStr0_c);
|
||||
HlGetTsHi(0, Str0NextWin, clk, rqst, rsp, v);
|
||||
print("WINTSHI: " & to_string(v), PrintStr0_c);
|
||||
winstart := Str0BufStart_c + Str0NextWin*Str0WinSize_c;
|
||||
winend := winstart + Str0WinSize_c - 1;
|
||||
case Str0WinCheck is
|
||||
when 0 =>
|
||||
-- Windows full because dat received for quite some time
|
||||
IntCompare(Str0WinSize_c, wincnt, "Stream0: WINCNT wrong");
|
||||
-- Check Values
|
||||
addr := winlast;
|
||||
|
||||
for i in 256+30+3-99 to 256+30+3 loop
|
||||
if addr = winend then
|
||||
addr := winstart;
|
||||
else
|
||||
addr := addr + 1;
|
||||
end if;
|
||||
StdlvCompareInt (i mod 256, Memory(addr), "Stream0: Wrong value at 0x" & to_hstring(to_unsigned(addr,32)), false);
|
||||
end loop;
|
||||
|
||||
when 1 =>
|
||||
-- Trigger following each other with 30 samples difference
|
||||
IntCompare(30, wincnt, "Stream0: WINCNT wrong");
|
||||
IntCompare(30*2, tslo-Str0LastTs, "Stream0: TS difference wrong");
|
||||
-- Check Values
|
||||
addr := winstart;
|
||||
for i in 34 to 63 loop
|
||||
StdlvCompareInt (i, Memory(addr), "Stream0: Wrong value", false);
|
||||
addr := addr + 1; -- does never wrap
|
||||
end loop;
|
||||
|
||||
when 2 =>
|
||||
-- Trigger following each other with 30 samples difference
|
||||
IntCompare(30, wincnt, "Stream0: WINCNT wrong");
|
||||
IntCompare(30*2, tslo-Str0LastTs, "Stream0: TS difference wrong");
|
||||
-- Check Values
|
||||
addr := winstart;
|
||||
for i in 64 to 93 loop
|
||||
StdlvCompareInt (i, Memory(addr), "Stream0: Wrong value", false);
|
||||
addr := addr + 1; -- does never wrap
|
||||
end loop;
|
||||
when 3 =>
|
||||
-- Full buffer recorded after emptying first buffer
|
||||
IntCompare(100, wincnt, "Stream0: WINCNT wrong");
|
||||
IntCompare((256-2*30)*2, tslo-Str0LastTs, "Stream0: TS difference wrong");
|
||||
-- Disable stream IRQ
|
||||
AxiRead32(REG_CONF_IRQENA_ADDR, v, clk, rqst, rsp);
|
||||
v := IntAnd(v, 16#0FE#);
|
||||
AxiWrite32(REG_CONF_IRQENA_ADDR, v, clk, rqst, rsp);
|
||||
AxiRead32(REG_CONF_STRENA_ADDR, v, clk, rqst, rsp);
|
||||
v := IntAnd(v, 16#0FE#);
|
||||
AxiWrite32(REG_CONF_STRENA_ADDR, v, clk, rqst, rsp);
|
||||
Str0Disabled := true;
|
||||
-- Check Values
|
||||
addr := winlast + 1;
|
||||
for i in 256+30+3-99 to 256+30+3 loop
|
||||
StdlvCompareInt (i mod 256, Memory(addr), "Stream0: Wrong value", false);
|
||||
if addr = winend then
|
||||
addr := winstart;
|
||||
else
|
||||
addr := addr + 1;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
when others => null;
|
||||
end case;
|
||||
print("", PrintStr0_c);
|
||||
Str0LastTs := tslo;
|
||||
Str0NextWin := (Str0NextWin + 1) mod 3;
|
||||
Str0WinCheck := Str0WinCheck + 1;
|
||||
end loop;
|
||||
end if;
|
||||
end procedure;
|
||||
|
||||
--------------------------------------------------------
|
||||
-- Setup
|
||||
--------------------------------------------------------
|
||||
procedure Str0Setup( signal clk : in std_logic;
|
||||
signal rqst : out axi_ms_r;
|
||||
signal rsp : in axi_sm_r) is
|
||||
begin
|
||||
HlCheckMaxLvl(0, 0, clk, rqst, rsp);
|
||||
HlSetPostTrig(0, 3, clk, rqst, rsp);
|
||||
HlSetMode(0, VAL_MODE_RECM_CONT, clk, rqst, rsp);
|
||||
HlConfStream( str => 0, bufstart => Str0BufStart_c, ringbuf => true, overwrite => false, wincnt => Str0Windows_c, winsize => Str0WinSize_c,
|
||||
clk => clk, rqst => rqst, rsp => rsp);
|
||||
end procedure;
|
||||
|
||||
--------------------------------------------------------
|
||||
-- Update
|
||||
--------------------------------------------------------
|
||||
procedure Str0Update( signal clk : in std_logic;
|
||||
signal rqst : out axi_ms_r;
|
||||
signal rsp : in axi_sm_r) is
|
||||
begin
|
||||
end;
|
||||
|
||||
end;
|
||||
Reference in New Issue
Block a user