mirror of
https://github.com/wfjm/w11.git
synced 2026-01-12 00:43:01 +00:00
- add fifo_simple_dram: simple fifo with CE/WE interface, dram based - add test benches for fifo_simple_dram, fifo_2c_dram, and fifo_2c_dram2 - add simclkv: test bench clock generator with variable period
341 lines
10 KiB
VHDL
341 lines
10 KiB
VHDL
-- $Id: tb_fifo_2c_dram.vhd 984 2018-01-02 20:56:27Z mueller $
|
|
--
|
|
-- Copyright 2007-2011 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
|
--
|
|
-- This program is free software; you may redistribute and/or modify it under
|
|
-- the terms of the GNU General Public License as published by the Free
|
|
-- Software Foundation, either version 3, or (at your option) any later version.
|
|
--
|
|
-- This program is distributed in the hope that it will be useful, but
|
|
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
-- for complete details.
|
|
--
|
|
------------------------------------------------------------------------------
|
|
-- Module Name: tb_fifo_2c_dram - sim
|
|
-- Description: Test bench for fifo_2c_dram
|
|
--
|
|
-- Dependencies: simlib/simclkv
|
|
-- simlib/simclkvcnt
|
|
-- tbd_fifo_2c_dram [UUT]
|
|
--
|
|
-- To test: fifo_2c_dram
|
|
--
|
|
-- Target Devices: generic
|
|
-- Tool versions: xst 8.2, 9.1, 9.2, 11.3, 13.1; ghdl 0.18-0.29
|
|
-- Revision History:
|
|
-- Date Rev Version Comment
|
|
-- 2011-12-23 444 1.1 use new simclk/simclkcnt
|
|
-- 2011-11-07 421 1.0.5 now numeric_std clean
|
|
-- 2010-06-03 299 1.0.4 use sv_ prefix for shared variables
|
|
-- 2010-04-17 277 1.0.3 use direct instantiation of tbd_
|
|
-- 2009-11-22 252 1.0.2 CLK*_CYCLE now 31 bits
|
|
-- 2007-12-28 107 1.0.1 add reset and check handling
|
|
-- 2007-12-28 106 1.0 Initial version
|
|
------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
use ieee.std_logic_textio.all;
|
|
use std.textio.all;
|
|
|
|
use work.slvtypes.all;
|
|
use work.simlib.all;
|
|
|
|
entity tb_fifo_2c_dram is
|
|
end tb_fifo_2c_dram;
|
|
|
|
architecture sim of tb_fifo_2c_dram is
|
|
|
|
signal CLKW : slbit := '0';
|
|
signal CLKR : slbit := '0';
|
|
signal RESETW : slbit := '0';
|
|
signal RESETR : slbit := '0';
|
|
signal DI : slv16 := (others=>'0');
|
|
signal ENA : slbit := '0';
|
|
signal BUSY : slbit := '0';
|
|
signal DO : slv16 := (others=>'0');
|
|
signal VAL : slbit := '0';
|
|
signal SIZEW : slv4 := (others=>'0');
|
|
signal SIZER : slv4 := (others=>'0');
|
|
|
|
signal N_HOLD : slbit := '0';
|
|
signal R_HOLD : slbit := '0';
|
|
|
|
signal CLKW_PERIOD : Delay_length := 20 ns;
|
|
signal CLKR_PERIOD : Delay_length := 20 ns;
|
|
signal CLK_HOLD : slbit := '1';
|
|
signal CLK_STOP : slbit := '0';
|
|
signal CLKW_CYCLE : integer := 0;
|
|
signal CLKR_CYCLE : integer := 0;
|
|
|
|
signal CLKR_C2OUT : Delay_length := 10 ns;
|
|
|
|
shared variable sv_nrstr : integer := 0;
|
|
shared variable sv_ndatar : integer := 0; -- data counter (fifo data output)
|
|
|
|
begin
|
|
|
|
CLKWGEN : simclkv
|
|
port map (
|
|
CLK => CLKW,
|
|
CLK_PERIOD => CLKW_PERIOD,
|
|
CLK_HOLD => CLK_HOLD,
|
|
CLK_STOP => CLK_STOP
|
|
);
|
|
|
|
CLKWCNT : simclkcnt port map (CLK => CLKW, CLK_CYCLE => CLKW_CYCLE);
|
|
|
|
CLKRGEN : simclkv
|
|
port map (
|
|
CLK => CLKR,
|
|
CLK_PERIOD => CLKR_PERIOD,
|
|
CLK_HOLD => CLK_HOLD,
|
|
CLK_STOP => CLK_STOP
|
|
);
|
|
|
|
CLKRCNT : simclkcnt port map (CLK => CLKR, CLK_CYCLE => CLKR_CYCLE);
|
|
|
|
UUT : entity work.tbd_fifo_2c_dram
|
|
port map (
|
|
CLKW => CLKW,
|
|
CLKR => CLKR,
|
|
RESETW => RESETW,
|
|
RESETR => RESETR,
|
|
DI => DI,
|
|
ENA => ENA,
|
|
BUSY => BUSY,
|
|
DO => DO,
|
|
VAL => VAL,
|
|
HOLD => R_HOLD,
|
|
SIZEW => SIZEW,
|
|
SIZER => SIZER
|
|
);
|
|
|
|
|
|
proc_stim: process
|
|
file fstim : text open read_mode is "tb_fifo_2c_dram_stim";
|
|
variable iline : line;
|
|
variable oline : line;
|
|
variable dname : string(1 to 6) := (others=>' ');
|
|
variable ok : boolean;
|
|
variable dtime : Delay_length := 0 ns;
|
|
variable nwait : integer := 0; --
|
|
variable nword : integer := 0; --
|
|
variable nbusy : integer := 0; -- number of busy before accept
|
|
variable idi : slv16 := (others=>'0');
|
|
|
|
variable ndataw : integer := 0; -- data counter (fifo data input)
|
|
|
|
variable iclkw_period : Delay_length := 20 ns;
|
|
variable iclkw_setup : Delay_length := 5 ns;
|
|
variable iclkr_period : Delay_length := 20 ns;
|
|
variable iclkr_c2out : Delay_length := 10 ns;
|
|
|
|
begin
|
|
|
|
file_loop: while not endfile(fstim) loop
|
|
|
|
readline (fstim, iline);
|
|
|
|
readcomment(iline, ok);
|
|
next file_loop when ok;
|
|
|
|
readword(iline, dname, ok);
|
|
|
|
if ok then
|
|
case dname is
|
|
when ".chold" => -- .chold time
|
|
write(oline, string'(".chold"));
|
|
writeline(output, oline);
|
|
read_ea(iline, dtime);
|
|
CLK_HOLD <= '1';
|
|
wait for dtime;
|
|
CLK_HOLD <= '0';
|
|
wait until rising_edge(CLKW);
|
|
wait for iclkw_period-iclkw_setup;
|
|
|
|
when ".cdef " => -- .cdef wper wset rper rout
|
|
write(oline, string'(".cdef "));
|
|
writeline(output, oline);
|
|
read_ea(iline, iclkw_period);
|
|
read_ea(iline, iclkw_setup);
|
|
read_ea(iline, iclkr_period);
|
|
read_ea(iline, iclkr_c2out);
|
|
CLKW_PERIOD <= iclkw_period;
|
|
CLKR_PERIOD <= iclkr_period;
|
|
CLKR_C2OUT <= iclkr_c2out;
|
|
if CLK_HOLD = '0' then
|
|
wait until rising_edge(CLKW);
|
|
wait for iclkw_period-iclkw_setup;
|
|
end if;
|
|
|
|
when ".ndata" => -- .ndata num
|
|
read_ea(iline, ndataw);
|
|
sv_ndatar := ndataw;
|
|
|
|
when ".hold " => -- .hold time
|
|
read_ea(iline, dtime);
|
|
if dtime > 0 ns then
|
|
N_HOLD <= '1', '0' after dtime;
|
|
else -- allow hold abort with 0ns
|
|
N_HOLD <= '0';
|
|
end if;
|
|
|
|
when ".wait " => -- .wait ncyc
|
|
read_ea(iline, nwait);
|
|
wait for nwait*iclkw_period;
|
|
|
|
when "resetw" => -- resetw ncyc
|
|
read_ea(iline, nwait);
|
|
RESETW <= '1';
|
|
wait for nwait*iclkw_period;
|
|
RESETW <= '0';
|
|
|
|
when "resetr" => -- resetr ncyc
|
|
read_ea(iline, nwait);
|
|
sv_nrstr := nwait;
|
|
|
|
when "send " => -- send nw nd
|
|
read_ea(iline, nwait);
|
|
read_ea(iline, nword);
|
|
for i in 1 to nword loop
|
|
wait for nwait*iclkw_period;
|
|
|
|
idi := slv(to_unsigned(ndataw, 16));
|
|
ndataw := ndataw + 1;
|
|
DI <= idi;
|
|
ENA <= '1';
|
|
nbusy := 0;
|
|
|
|
while BUSY='1' loop
|
|
nbusy := nbusy + 1;
|
|
wait for iclkw_period;
|
|
end loop;
|
|
|
|
writetimestamp(oline, CLKW_CYCLE, ": stim ");
|
|
write(oline, idi, right, 18);
|
|
write(oline, SIZEW, right, 7);
|
|
write(oline, string'(" ("));
|
|
write(oline, to_integer(unsigned(idi)), right, 5);
|
|
write(oline, string'(","));
|
|
write(oline, to_integer(unsigned(SIZEW)), right, 2);
|
|
write(oline, string'(")"));
|
|
if nbusy > 0 then
|
|
write(oline, string'(" nbusy="));
|
|
write(oline, nbusy, right, 2);
|
|
end if;
|
|
writeline(output, oline);
|
|
|
|
wait for iclkw_period;
|
|
ENA <= '0';
|
|
|
|
end loop; -- i
|
|
|
|
when others => -- bad directive
|
|
write(oline, string'("?? unknown command: "));
|
|
write(oline, dname);
|
|
writeline(output, oline);
|
|
report "aborting" severity failure;
|
|
end case;
|
|
|
|
else
|
|
report "failed to find command" severity failure;
|
|
end if;
|
|
|
|
testempty_ea(iline);
|
|
|
|
end loop; -- file_loop:
|
|
|
|
if N_HOLD = '1' then
|
|
wait until N_HOLD='0';
|
|
end if;
|
|
wait for 20*(iclkw_period+iclkr_period);
|
|
CLK_STOP <= '1';
|
|
|
|
writetimestamp(oline, CLKW_CYCLE, ": DONE-w ");
|
|
writeline(output, oline);
|
|
writetimestamp(oline, CLKR_CYCLE, ": DONE-r ");
|
|
writeline(output, oline);
|
|
|
|
wait; -- suspend proc_stim forever
|
|
-- clock is stopped, sim will end
|
|
end process proc_stim;
|
|
|
|
|
|
proc_moni: process
|
|
variable oline : line;
|
|
variable nhold : integer := 0; -- number of hold cycles before accept
|
|
variable isizer_last : slv4 := (others=>'0');
|
|
variable ido : slv16 := (others=>'0');
|
|
begin
|
|
|
|
loop
|
|
wait until rising_edge(CLKR);
|
|
wait for CLKR_C2OUT;
|
|
|
|
if VAL = '1' then
|
|
if R_HOLD = '1' then
|
|
nhold := nhold + 1;
|
|
else
|
|
ido := slv(to_unsigned(sv_ndatar, 16));
|
|
sv_ndatar := sv_ndatar + 1;
|
|
|
|
writetimestamp(oline, CLKR_CYCLE, ": moni ");
|
|
write(oline, DO, right, 18);
|
|
write(oline, SIZER, right, 7);
|
|
write(oline, string'(" ("));
|
|
write(oline, to_integer(unsigned(DO)), right, 5);
|
|
write(oline, string'(","));
|
|
write(oline, to_integer(unsigned(SIZER)), right, 2);
|
|
write(oline, string'(")"));
|
|
if nhold > 0 then
|
|
write(oline, string'(" nhold="));
|
|
write(oline, nhold, right, 2);
|
|
end if;
|
|
|
|
if DO = ido then
|
|
write(oline, string'(" OK"));
|
|
else
|
|
write(oline, string'(" FAIL, exp="));
|
|
write(oline, ido, right, 18);
|
|
end if;
|
|
|
|
writeline(output, oline);
|
|
nhold := 0;
|
|
end if;
|
|
else
|
|
if SIZER /= isizer_last then
|
|
writetimestamp(oline, CLKR_CYCLE, ": moni ");
|
|
write(oline, string'(" "));
|
|
write(oline, SIZER, right, 7);
|
|
write(oline, string'(" ("));
|
|
write(oline, to_integer(unsigned(SIZER)), right, 2);
|
|
write(oline, string'(")"));
|
|
writeline(output, oline);
|
|
end if;
|
|
end if;
|
|
|
|
isizer_last := SIZER;
|
|
|
|
end loop;
|
|
|
|
end process proc_moni;
|
|
|
|
proc_clkr: process (CLKR)
|
|
begin
|
|
if rising_edge(CLKR) then
|
|
R_HOLD <= N_HOLD;
|
|
|
|
if sv_nrstr > 0 then
|
|
RESETR <= '1';
|
|
sv_nrstr := sv_nrstr - 1;
|
|
else
|
|
RESETR <= '0';
|
|
end if;
|
|
end if;
|
|
end process proc_clkr;
|
|
|
|
end sim;
|