BUGFIX: Made design working for 1 stream
This commit is contained in:
@ -68,15 +68,19 @@ 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);
|
||||
|
||||
|
||||
-- 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);
|
||||
@ -95,7 +99,7 @@ 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);
|
||||
@ -300,7 +304,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 +326,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"
|
||||
)
|
||||
@ -366,7 +370,7 @@ begin
|
||||
-- *** Remaining Data RAM ***
|
||||
i_remram : entity work.psi_common_sdp_ram
|
||||
generic map (
|
||||
Depth_g => Streams_g,
|
||||
Depth_g => 2**StreamBits_c,
|
||||
Width_g => 1+1+3+64,
|
||||
IsAsync_g => false,
|
||||
RamStyle_g => "distributed",
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
|
||||
|
||||
|
@ -206,7 +206,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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
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