DEVEL: Top level TB works for stream 0

This commit is contained in:
Oliver Bruendler
2018-09-03 14:21:16 +02:00
parent e96dddc623
commit befcc9f36b
6 changed files with 376 additions and 88 deletions

View File

@ -202,7 +202,6 @@ begin
--------------------------------------------
i_statemachine : entity work.psi_ms_daq_daq_sm
generic map (
Simulation_g => false,
Streams_g => Streams_g,
StreamPrio_g => StreamPrio_g,
StreamWidth_g => StreamWidth_g,

View File

@ -24,7 +24,6 @@ library work;
-- $$ tbpkg=work.psi_tb_txt_util,work.psi_tb_compare_pkg $$
entity psi_ms_daq_daq_sm is
generic (
Simulation_g : boolean := false; -- $$ constant=true $$
Streams_g : positive range 1 to 32 := 4; -- $$ constant=4 $$
StreamPrio_g : t_ainteger := (1, 2, 3, 1); -- $$ constant=(1, 2, 3, 1) $$
StreamWidth_g : t_ainteger := (8, 16, 32, 64); -- $$ constant=(8, 16, 32, 64) $$
@ -166,7 +165,7 @@ architecture rtl of psi_ms_daq_daq_sm is
Dma_Cmd_Vld : std_logic;
Dma_Resp_Rdy : std_logic;
Ts_Rdy : std_logic_vector(Streams_g-1 downto 0);
SimDelCnt : integer range 0 to 4;
ArbDelCnt : integer range 0 to 4;
IrqFifoWrite : std_logic;
IrqFifoRead : std_logic;
StrIrq : std_logic_vector(Streams_g-1 downto 0);
@ -241,13 +240,11 @@ begin
v.HndlAfterCtxt := CalcAccess0_s;
end if;
-- Delay arbitration in simulation to allow TB to react
if Simulation_g then
if r.SimDelCnt /= 4 then
v.State := Idle_s;
v.SimDelCnt := r.SimDelCnt + 1;
else
v.SimDelCnt := 0;
end if;
if r.ArbDelCnt /= 4 then
v.State := Idle_s;
v.ArbDelCnt := r.ArbDelCnt + 1;
else
v.ArbDelCnt := 0;
end if;
-- *** Check for next stream to handle ***
@ -291,7 +288,7 @@ begin
v.State := CheckResp_s;
v.WinProtected := (others => '0'); -- No bursts where available on any stream, so all of them were checked and we can retry whether SW emptied a window.
for idx in 0 to Streams_g-1 loop
if r.HasLastReg(idx) = '1' then
if (r.HasLastReg(idx) = '1') and (r.OpenCommand(idx) = '0') then
v.State := ReadCtxStr_s;
v.HndlStream := idx;
end if;
@ -572,9 +569,7 @@ begin
if rising_edge(Clk) then
r <= r_next;
if Rst = '1' then
if Simulation_g then
r.SimDelCnt <= 0;
end if;
r.ArbDelCnt <= 0;
r.InpDataAvail <= (others => '0');
r.DataAvailArbIn <= (others => '0');
r.HndlStream <= 0;

View File

@ -106,77 +106,81 @@ begin
-- *** General Register Accesses ***
v.RegRdval := (others => '0');
case TmemRqst.ADD is
-- GCFG / GSTAT
when X"000000" =>
-- GCFG
if TmemRqst.WE(0) = '1' then
v.Reg_Gcfg_Ena := TmemRqst.DATW(0);
end if;
if TmemRqst.WE(1) = '1' then
v.Reg_Gcfg_Ena := TmemRqst.DATW(8);
end if;
v.RegRdval(0) := r.Reg_Gcfg_Ena;
v.RegRdval(8) := r.Reg_Gcfg_IrqEna;
-- IRQVEC / IRQENA
when X"000010" =>
-- IRQVEC
if TmemRqst.WE(WeLow_c) = DwWrite_c then
v.Reg_IrqVec := r.Reg_IrqVec and (not TmemRqst.DATW(Streams_g-1 downto 0));
end if;
v.RegRdval(Streams_g-1 downto 0) := r.Reg_IrqVec;
-- IRQENA
if TmemRqst.WE(WeHigh_c) = DwWrite_c then
v.Reg_IrqEna := TmemRqst.DATW(Streams_g+32-1 downto 32);
end if;
v.RegRdval(Streams_g+32-1 downto 32) := r.Reg_IrqEna;
-- STRENA
when X"000020" =>
-- STRENA
if TmemRqst.WE(WeLow_c) = DwWrite_c then
v.Reg_StrEna := TmemRqst.DATW(Streams_g-1 downto 0);
end if;
v.RegRdval(Streams_g-1 downto 0) := r.Reg_StrEna;
-- others clause
when others => null;
if TmemRqst.ENA = '1' then
case TmemRqst.ADD is
-- GCFG / GSTAT
when X"000000" =>
-- GCFG
if TmemRqst.WE(0) = '1' then
v.Reg_Gcfg_Ena := TmemRqst.DATW(0);
end if;
if TmemRqst.WE(1) = '1' then
v.Reg_Gcfg_IrqEna := TmemRqst.DATW(8);
end if;
v.RegRdval(0) := r.Reg_Gcfg_Ena;
v.RegRdval(8) := r.Reg_Gcfg_IrqEna;
end case;
-- IRQVEC / IRQENA
when X"000010" =>
-- IRQVEC
if TmemRqst.WE(WeLow_c) = DwWrite_c then
v.Reg_IrqVec := r.Reg_IrqVec and (not TmemRqst.DATW(Streams_g-1 downto 0));
end if;
v.RegRdval(Streams_g-1 downto 0) := r.Reg_IrqVec;
-- IRQENA
if TmemRqst.WE(WeHigh_c) = DwWrite_c then
v.Reg_IrqEna := TmemRqst.DATW(Streams_g+32-1 downto 32);
end if;
v.RegRdval(Streams_g+32-1 downto 32) := r.Reg_IrqEna;
-- STRENA
when X"000020" =>
-- STRENA
if TmemRqst.WE(WeLow_c) = DwWrite_c then
v.Reg_StrEna := TmemRqst.DATW(Streams_g-1 downto 0);
end if;
v.RegRdval(Streams_g-1 downto 0) := r.Reg_StrEna;
-- others clause
when others => null;
end case;
end if;
-- *** Stream Register Accesses ***
v.Reg_Mode_Arm := (others => '0');
if TmemRqst.ADD(23 downto 9) = X"000" & "001" then
Stream_v := to_integer(unsigned(TmemRqst.ADD(8 downto 4)));
-- MAXLVLn / POSTTRIGn
if TmemRqst.ADD(3 downto 0) = X"0" then
-- MAXLVLn
if TmemRqst.WE(WeLow_c) = DwWrite_c then
v.Reg_MaxLvl(Stream_v) := (others => '0');
if TmemRqst.ENA = '1' then
if TmemRqst.ADD(23 downto 9) = X"000" & "001" then
Stream_v := to_integer(unsigned(TmemRqst.ADD(8 downto 4)));
-- MAXLVLn / POSTTRIGn
if TmemRqst.ADD(3 downto 0) = X"0" then
-- MAXLVLn
if TmemRqst.WE(WeLow_c) = DwWrite_c then
v.Reg_MaxLvl(Stream_v) := (others => '0');
end if;
v.RegRdval(15 downto 0) := r.Reg_MaxLvl(Stream_v);
-- POSTTRIGn
if TmemRqst.WE(WeHigh_c) = DwWrite_c then
v.Reg_PostTrig(Stream_v) := TmemRqst.DATW(63 downto 32);
end if;
v.RegRdval(63 downto 32) := r.Reg_PostTrig(Stream_v);
end if;
v.RegRdval(15 downto 0) := r.Reg_MaxLvl(Stream_v);
-- POSTTRIGn
if TmemRqst.WE(WeHigh_c) = DwWrite_c then
v.Reg_PostTrig(Stream_v) := TmemRqst.DATW(63 downto 32);
end if;
v.RegRdval(63 downto 32) := r.Reg_PostTrig(Stream_v);
end if;
-- MODEn
if TmemRqst.ADD(3 downto 0) = X"8" then
-- MODEn
if TmemRqst.WE(0) = '1' then
v.Reg_Mode_Recm(Stream_v) := TmemRqst.DATW(1 downto 0);
if TmemRqst.ADD(3 downto 0) = X"8" then
-- MODEn
if TmemRqst.WE(0) = '1' then
v.Reg_Mode_Recm(Stream_v) := TmemRqst.DATW(1 downto 0);
end if;
if TmemRqst.WE(1) = '1' then
v.Reg_Mode_Arm(Stream_v) := TmemRqst.DATW(8);
end if;
v.RegRdval(1 downto 0) := r.Reg_Mode_Recm(Stream_v);
v.RegRdval(8) := IsArmed(Stream_v);
end if;
if TmemRqst.WE(1) = '1' then
v.Reg_Mode_Arm(Stream_v) := TmemRqst.DATW(8);
end if;
v.RegRdval(1 downto 0) := r.Reg_Mode_Recm(Stream_v);
v.RegRdval(8) := IsArmed(Stream_v);
end if;
end if;
-- *** Read Data MUX ***
@ -249,8 +253,8 @@ begin
-- *** Stream Context Memory ***
-- Signal Assembly
AddrCtxStr <= TmemRqst.ADD(23 downto 12) = X"001";
CtxStr_WeLo <= '1' when TmemRqst.WE(WeLow_c) = DwWrite_c and AddrCtxStr else '0';
CtxStr_WeHi <= '1' when TmemRqst.WE(WeHigh_c) = DwWrite_c and AddrCtxStr else '0';
CtxStr_WeLo <= '1' when TmemRqst.WE(WeLow_c) = DwWrite_c and AddrCtxStr and TmemRqst.ENA = '1' else '0';
CtxStr_WeHi <= '1' when TmemRqst.WE(WeHigh_c) = DwWrite_c and AddrCtxStr and TmemRqst.ENA = '1' else '0';
CtxStr_AddrB <= std_logic_vector(to_unsigned(CtxStr_Cmd.Stream, log2ceil(Streams_g))) & CtxStr_Cmd.Sel;
-- Low DWORD memory
@ -294,8 +298,8 @@ begin
-- *** Window Context Memory ***
-- Signal Assembly
AddrCtxWin <= TmemRqst.ADD(23 downto 14) = X"00" & "01";
CtxWin_WeLo <= '1' when TmemRqst.WE(WeLow_c) = DwWrite_c and AddrCtxWin else '0';
CtxWin_WeHi <= '1' when TmemRqst.WE(WeHigh_c) = DwWrite_c and AddrCtxWin else '0';
CtxWin_WeLo <= '1' when TmemRqst.WE(WeLow_c) = DwWrite_c and AddrCtxWin and TmemRqst.ENA = '1' else '0';
CtxWin_WeHi <= '1' when TmemRqst.WE(WeHigh_c) = DwWrite_c and AddrCtxWin and TmemRqst.ENA = '1'else '0';
CtxWin_AddrB <= std_logic_vector(to_unsigned(CtxWin_Cmd.Stream, log2ceil(Streams_g))) &
std_logic_vector(to_unsigned(CtxWin_Cmd.Window, log2ceil(MaxWindows_g))) &
CtxWin_Cmd.Sel;

View File

@ -91,6 +91,9 @@ add_tb_run
create_tb_run "psi_ms_daq_daq_dma_tb"
add_tb_run
create_tb_run "psi_ms_daq_tb"
add_tb_run

View File

@ -37,8 +37,8 @@ architecture sim of psi_ms_daq_tb is
-- Constants
constant StrCount_c : integer := 4;
constant ClkFreq_c : t_areal := (0=>250.0e6, 1=>125.0e-6, 2=>80.0e-6, 3=>200.0e-6);
constant MemSize_c : integer := 2**16;
constant ClkFreq_c : t_areal := (0=>250.0e6, 1=>125.0e6, 2=>80.0e6, 3=>200.0e6);
constant MemSize_c : integer := 16#10000#;
-- Port signals
signal Str_Clk : std_logic_vector(StrCount_c-1 downto 0) := (others => '0');
@ -60,7 +60,217 @@ architecture sim of psi_ms_daq_tb is
signal Irq : std_logic := '0';
-- Memory
shared variable Memory_v : t_aslv8(0 to MemSize_c-1);
signal Memory : t_aslv8(0 to MemSize_c-1);
alias Memory0 : t_aslv8(0 to 16#0FFF#) is Memory(16#1000# to 16#1FFF#);
function IntAnd( int : in integer;
op : in integer) return integer is
variable intu, opu : unsigned(31 downto 0);
begin
intu := to_unsigned(int, 32);
opu := to_unsigned(op, 32);
return to_integer(intu and opu);
end function;
-- *** TMEM Procedures ***
procedure TmemWrite32( address : in integer;
value : in integer;
signal clk : in std_logic;
signal rqst : out TmemRqst_t;
signal rsp : in TmemResp_t) is
begin
wait until rising_edge(clk);
rqst.ADD <= std_logic_vector(to_unsigned(address, 24)) and X"FFFFF8";
rqst.ENA <= '1';
rqst.DATW <= (others => '0');
rqst.WE <= (others => '0');
if address mod 8 = 0 then
rqst.DATW(31 downto 0) <= std_logic_vector(to_unsigned(value, 32));
rqst.WE(3 downto 0) <= (others => '1');
else
rqst.DATW(63 downto 32) <= std_logic_vector(to_unsigned(value, 32));
rqst.WE(7 downto 4) <= (others => '1');
end if;
wait until rising_edge(clk);
rqst.ENA <= '0';
rqst.WE <= (others => '0');
end procedure;
procedure TmemRead32( address : in integer;
value : out integer;
signal clk : in std_logic;
signal rqst : out TmemRqst_t;
signal rsp : in TmemResp_t) is
begin
wait until rising_edge(clk);
rqst.ADD <= std_logic_vector(to_unsigned(address, 24)) and X"FFFFF8";
rqst.ENA <= '1';
wait until rising_edge(clk);
wait until rising_edge(clk);
wait until rising_edge(clk);
if address mod 8 = 0 then
value := to_integer(unsigned(rsp.DATR(31 downto 0)));
else
value := to_integer(unsigned(rsp.DATR(63 downto 32)));
end if;
rqst.ENA <= '0';
end procedure;
procedure TmemExpect32( address : in integer;
value : in integer;
signal clk : in std_logic;
signal rqst : out TmemRqst_t;
signal rsp : in TmemResp_t) is
variable readVal : integer;
begin
TmemRead32(address, readVal, clk, rqst, rsp);
IntCompare(value, readVal, "Unexpected value at address 0x" & to_hstring(to_unsigned(address, 32)));
end procedure;
procedure TmemWriteAndRead32( address : in integer;
value : in integer;
signal clk : in std_logic;
signal rqst : out TmemRqst_t;
signal rsp : in TmemResp_t) is
begin
TmemWrite32(address, value, clk, rqst, rsp);
TmemExpect32(address, value, clk, rqst, rsp);
end procedure;
-- *** IRQ Handling ***
shared variable Str0NextWin : integer := 0;
shared variable Str0WinCheck : integer := 0;
shared variable Str0LastTs : integer;
procedure Str0Handler( signal clk : in std_logic;
signal rqst : out TmemRqst_t;
signal rsp : in TmemResp_t) is
variable v : integer;
variable curwin : integer;
variable wincnt : integer;
variable winstart, winend : integer;
variable winlast : integer;
variable addr : integer;
variable tslo : integer;
begin
print("------------ Stream 0 Handler ------------");
TmemRead32(16#0200#, v, clk, rqst, rsp);
print("MAXLVL: " & to_string(v));
TmemRead32(16#1000#, v, clk, rqst, rsp);
curwin := v/(2**24);
print("CURWIN: " & to_string(curwin));
print("");
while Str0NextWin /= curwin loop
print("*** Window " & to_string(Str0NextWin) & " / Number: " & to_string(Str0WinCheck) & " ***");
TmemRead32(16#4000#+Str0NextWin*16#10#, wincnt, clk, rqst, rsp);
print("WINCNT: " & to_string(wincnt));
TmemWrite32(16#4000#+Str0NextWin*16#10#, 0, clk, rqst, rsp); -- reset window counter
TmemRead32(16#4004#+Str0NextWin*16#10#, winlast, clk, rqst, rsp);
print("WINLAST: " & to_string(winlast));
TmemRead32(16#4008#+Str0NextWin*16#10#, tslo, clk, rqst, rsp);
print("WINTSLO: " & to_string(tslo));
TmemRead32(16#400C#+Str0NextWin*16#10#, v, clk, rqst, rsp);
print("WINTSHI: " & to_string(v));
winstart := 16#1000# + Str0NextWin*100;
winend := winstart + 99;
case Str0WinCheck is
when 0 =>
-- Windows full because dat received for quite some time
IntCompare(100, wincnt, "WINCNT wrong");
-- Check Values
addr := winlast + 1;
for i in 256+30+3-99 to 256+30+3 loop
StdlvCompareInt (i mod 256, Memory(addr), "Wrong value", false);
if addr = winend then
addr := winstart;
else
addr := addr + 1;
end if;
end loop;
when 1 =>
-- Trigger following each other with 30 samples difference
IntCompare(30, wincnt, "WINCNT wrong");
IntCompare(30*2, tslo-Str0LastTs, "TS difference wrong");
-- Check Values
addr := winstart;
for i in 34 to 63 loop
StdlvCompareInt (i, Memory(addr), "Wrong value", false);
addr := addr + 1; -- does never wrap
end loop;
when 2 =>
-- Trigger following each other with 30 samples difference
IntCompare(30, wincnt, "WINCNT wrong");
print(to_string(tslo) & " " & to_string(Str0LastTs));
IntCompare(30*2, tslo-Str0LastTs, "TS difference wrong");
-- Check Values
addr := winstart;
for i in 64 to 93 loop
StdlvCompareInt (i, Memory(addr), "Wrong value", false);
addr := addr + 1; -- does never wrap
end loop;
when 3 =>
-- Full buffer recorded after emptying first buffer
IntCompare(100, wincnt, "WINCNT wrong");
IntCompare((256-2*30)*2, tslo-Str0LastTs, "TS difference wrong");
-- Disable stream IRQ
TmemRead32(16#0014#, v, clk, rqst, rsp);
v := IntAnd(v, 16#0FE#);
TmemWrite32(16#0014#, v, clk, rqst, rsp);
TmemRead32(16#0020#, v, clk, rqst, rsp);
v := IntAnd(v, 16#0FE#);
TmemWrite32(16#0020#, v, clk, rqst, rsp);
-- Check Values
addr := winlast + 1;
for i in 256+30+3-99 to 256+30+3 loop
StdlvCompareInt (i mod 256, Memory(addr), "Wrong value", false);
if addr = winend then
addr := winstart;
else
addr := addr + 1;
end if;
end loop;
when others => null;
end case;
print("");
Str0LastTs := tslo;
Str0NextWin := (Str0NextWin + 1) mod 3;
Str0WinCheck := Str0WinCheck + 1;
end loop;
end procedure;
procedure IrqHandler( signal clk : in std_logic;
signal rqst : out TmemRqst_t;
signal rsp : in TmemResp_t) is
variable v : integer;
variable slv : std_logic_vector(31 downto 0);
begin
print("###################################### IRQ Detected #########################################");
wait until rising_edge(clk);
TmemRead32(16#0010#, v, clk, rqst, rsp);
slv := std_logic_vector(to_unsigned(v, 32));
TmemWrite32(16#0010#, v, clk, rqst, rsp);
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;
wait until rising_edge(clk);
end procedure;
begin
------------------------------------------------------------
@ -130,7 +340,7 @@ begin
wait until rising_edge(Tosca_Clk);
for byte in 0 to 7 loop
if AcqSmem.WBE(byte) = '1' then
Memory_v(Address_v+qw*8+byte) := AcqSmem.WDAT(byte*8+7 downto byte*8);
Memory(Address_v+qw*8+byte) <= AcqSmem.WDAT(byte*8+7 downto byte*8);
end if;
end loop;
end loop;
@ -160,7 +370,7 @@ begin
begin
while TbRunning loop
wait for 0.5*(1 sec)/(ClkFreq_c(i)+0.1e6);
Tosca_Clk <= not Tosca_Clk;
Str_Clk(i) <= not Str_Clk(i);
end loop;
wait;
end process;
@ -171,14 +381,92 @@ begin
------------------------------------------------------------
-- No influence when disabled
-- Disable / re-enable
-- Disable during transfer
-- Version register!
-- RINGBUF (OK), LINEAR (TODO)
-- OVERWRITE (TODO), STOP (OK)
-- Mode: CONTINUOUS (OK), SINGLE(TODO), MASK(TODO), MANUAL (TODO)
------------------------------------------------------------
-- TMEM Process
------------------------------------------------------------
p_tmem : process
variable StartTime_v : time;
begin
wait for 1 us;
Tmem_Rst <= '0';
Smem_Rst <= '0';
-- *** Initial Configuration ***
TmemExpect32(16#0010#, 0, Tosca_Clk, TmemAcq, AcqTmem);
TmemWriteAndRead32(16#0014#, 16#000F#, Tosca_Clk, TmemAcq, AcqTmem);
TmemWriteAndRead32(16#0020#, 16#000F#, Tosca_Clk, TmemAcq, AcqTmem);
-- Stream 0 (Continuous Recording, 3 Window, Ringbuffer, 0x1000-0x2000)
TmemExpect32(16#0200#, 0, Tosca_Clk, TmemAcq, AcqTmem);
TmemWriteAndRead32(16#0204#, 3, Tosca_Clk, TmemAcq, AcqTmem);
TmemWriteAndRead32(16#0208#, 16#0000#, Tosca_Clk, TmemAcq, AcqTmem);
TmemWriteAndRead32(16#1000#, 16#00020001#, Tosca_Clk, TmemAcq, AcqTmem);
TmemWriteAndRead32(16#1004#, 16#1000#, Tosca_Clk, TmemAcq, AcqTmem);
TmemWriteAndRead32(16#1008#, 100, Tosca_Clk, TmemAcq, AcqTmem);
-- Enable
TmemWriteAndRead32(16#0000#, 16#0101#, Tosca_Clk, TmemAcq, AcqTmem);
-- *** Run Test ***
StartTime_v := now;
while now < StartTime_v+100 us loop
wait until rising_edge(Tosca_Clk);
if Irq = '1' then
IrqHandler(Tosca_Clk, TmemAcq, AcqTmem);
end if;
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
Str_Vld(0) <= '1';
if (now > 15 us) and (to_integer(unsigned(Str0_Data)) = 0) then
IrqOn := true;
end if;
case to_integer(unsigned(Str0_Data)) is
when 30 | 60 | 90 =>
if IrqOn then
Str_Trig(0) <= '1';
end if;
when others => null;
end case;
wait until rising_edge(Str_Clk(0));
Str_Vld(0) <= '0';
Str_Trig(0) <= '0';
Str0_Data <= std_logic_vector(unsigned(Str0_Data)+1);
wait until rising_edge(Str_Clk(0));
end loop;
end process;
------------------------------------------------------------
-- Check Process

View File

@ -93,7 +93,6 @@ begin
------------------------------------------------------------
i_dut : entity work.psi_ms_daq_daq_sm
generic map (
Simulation_g => true,
Streams_g => Streams_g,
StreamPrio_g => StreamPrio_g,
StreamWidth_g => StreamWidth_g,