1
0
mirror of https://github.com/wfjm/w11.git synced 2026-02-17 13:27:33 +00:00
Files
wfjm.w11/rtl/vlib/simlib/simbididly.vhd

125 lines
4.1 KiB
VHDL

-- $Id: simbididly.vhd 984 2018-01-02 20:56:27Z mueller $
--
-- Copyright 2016- 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: simbididly - sim
-- Description: Bi-directional bus delay for test benches
--
-- Dependencies: -
-- Test bench: tb_simbididly
-- Target Devices: generic
-- Tool versions: xst 14.7; viv 2016.2; ghdl 0.33
-- Revision History:
-- Date Rev Version Comment
-- 2016-07-23 793 1.0.1 ensure non-zero DELAY
-- 2016-07-17 789 1.0 Initial version (use separate driver regs now)
-- 2016-07-16 787 0.1 First draft
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.slvtypes.all;
entity simbididly is -- test bench bi-directional bus delay
generic (
DELAY : Delay_length; -- transport delay between A and B (>0ns!)
DWIDTH : positive := 16); -- data port width
port (
A : inout slv(DWIDTH-1 downto 0); -- port A
B : inout slv(DWIDTH-1 downto 0) -- port B
);
end entity simbididly;
architecture sim of simbididly is
type state_type is (
s_idle, -- s_idle: both ports high-z
s_a2b, -- s_a2b: A drives, B listens
s_b2a -- s_b2a: B drives, A listens
);
constant all_z : slv(DWIDTH-1 downto 0) := (others=>'Z');
signal R_STATE : state_type := s_idle;
signal R_A : slv(DWIDTH-1 downto 0) := (others=>'Z');
signal R_B : slv(DWIDTH-1 downto 0) := (others=>'Z');
begin
process
variable istate : state_type := s_idle;
begin
-- the delay model can enter into a delta cycle oszillation mode
-- when DELAY is 0 ns. So ensure the delay is non-zero
assert DELAY > 0 ns report "DELAY > 0 ns" severity failure;
while true loop
-- if idle check whether A or B port starts to drive bus
-- Note: both signal R_STATE and variable istate is updated
-- istate is needed to control the driver section below in the
-- same delta cycle based on the most recent state state
istate := R_STATE;
if now > 0 ns then -- to avoid startup problems
if R_STATE = s_idle then
if A /= all_z then
R_STATE <= s_a2b;
istate := s_a2b;
elsif B /= all_z then
R_STATE <= s_b2a;
istate := s_b2a;
end if;
end if;
end if;
case istate is
when s_a2b =>
R_B <= transport A after DELAY;
if A = all_z then R_STATE <= s_idle after DELAY; end if;
when s_b2a =>
R_A <= transport B after DELAY;
if B = all_z then R_STATE <= s_idle after DELAY; end if;
when others => null;
end case;
-- Note: the driver clash check is done by comparing an internal signal
-- with the external signal. If they differ this indicates a clash.
-- Just checking for 'x' gives false alarms when the bus is driven
-- with 'x', which can for example come from a memory model before
-- valid data is available.
if now > 0 ns then -- to avoid startup problems
case istate is
when s_a2b =>
assert B = R_B report "driver clash B port" severity error;
when s_b2a =>
assert A = R_A report "driver clash A port" severity error;
when others => null;
end case;
end if;
wait on A,B;
end loop;
end process;
A <= R_A;
B <= R_B;
end sim;