How to simulate the connection of to bidir ports ?

Guest
A question which I ran across:

Asume that I have two components.
For easier description lets assume that one is a CPU and the other one
is a RAM.

Usually the dataBus pins which connect the CPU to the RAM are
bi-directional.

Now if I want to build a testbench which contains the CPU component and
the RAM
component I have the following component declarations:


--------------------
.....
component cpu is
port (
....
dataBus : inout STD_LOGIC_VECTOR(7 downto 0); -- 8 Bit data bus
for example
...
);
end component;

component ram is
port (
....
dataBus : inout STD_LOGIC_VECTOR(7 downto 0); -- 8 Bit data bus
....
);
end component;

-- dataBus connection between cpu and ram
signal dataBus : STD_LOGIC_VECTOR(7 downto 0);
--------------------

I further assume that the cpu and ram components are completely
functional
models without any explicit delays in them.

now in the architecture body of my testbench I could use the following:

--------------------
cCpu : cpu
port map (
...
dataBus => dataBus
...
);
cRam : ram
port map (
...
dataBus => dataBus
...
);
------------------

This is ok as long as I don't want to simulate delays.

But what do I do if I want to add delays from the port of the cpu and
ram
components to the data bus in my testbench, without changing the
"cpu" or "ram" entities ?

I mean I could do something like this

--------------------------------------------
....
signal dataCpu : STD_LOGIC_VECTOR(7 downto 0);
signal dataRam: STD_LOGIC_VECTOR(7 downto 0);

begin
cCpu : cpu
port map (
...
dataBus => dataCpu
...
);
cRam : ram
port map (
...
dataBus => dataRam
...
);
dataRam <= dataCpu after 5 ns;
dataCpu <= dataRam after 5 ns;

-------------------------------------------------------

But this (of course) doesn't work.

Any ideas ?

so long
lundril
 
You're going to need to build a model for the PCB traces. Something
like:

pcb_trace (
cpu_end : inout std_logic,
mem_end : inout std_logic
)

case mem_end is
when '1' => cpu_end <= 'H' after 5 ns;
when '0' => cpu_end <= 'L' after 5ns;
when others => cpu_end <= 'Z' after 5 ns;
end case;

The 'H' and 'L' will allow the other end to over-ride the signal.

You may want the others case to be cpu_end instead of 'Z'; this will
create an RS latch that simulates bus hold.

Alternatevely, you can model the wire with two HiZ buffers back to
back. In this case you would need to extract the direction information
from one of the cpu or ram models. (Or both, and look for contention.)

I haven't tried either; do let me know how it goes.
 
I further assume that the cpu and ram components are completely
functional
models without any explicit delays in them.


This is ok as long as I don't want to simulate delays.

But what do I do if I want to add delays from the port of the cpu and
ram
components to the data bus in my testbench, without changing the
"cpu" or "ram" entities ?
In a sense what you're modelling then is the PCB trace that connects the CPU
to the RAM. For each signal that you want to delay connect the RAM (i.e.
dataRam from your example) and CPU (i.e. dataCpu from your example) to
either the 'A' or 'B' ports of the 'Generic_Bidir_Delay_Line' component
(code below). It has independent generics for the delays in each direction.

I've used this to model PCB trace delays so it's been 'tested' and works.

KJ

-------------- Start of code --------------
entity Generic_Bidir_Delay_Line is generic(
A2B_Delay_Time: in time := 1 ns;
B2A_Delay_Time: in time := 1 ns);
port(
A: inout std_logic;
B: inout std_logic);
end Generic_Bidir_Delay_Line;
architecture RTL of Generic_Bidir_Delay_Line is
signal Ignore_A_Event_Time: time := B2A_Delay_Time;
signal Ignore_B_Event_Time: time := A2B_Delay_Time;
begin
assert A2B_Delay_Time > 0 ns
report "Generic_Bidir_Delay_Line must have an A2B delay time greater than
0 ns"
severity FAILURE;
assert B2A_Delay_Time > 0 ns
report "Generic_Bidir_Delay_Line must have a B2A delay time greater than 0
ns"
severity FAILURE;

------------------------------------------------------------------------------- -- The bi-directional delay line waits for events on each port andtransfers -- the result to the other port after the specified time. Since this will -- then cause a subsequent event on the other port we need to keep track ofthe -- time of the expected event and then prevent that event from propogating -- backwards to the original port that had the event ------------------------------------------------------------------------------- A2B : process begin if (now = 0 ns) then B <= A; wait for A2B_Delay_Time; else wait until not(A'stable) and (now /= Ignore_A_Event_Time); B <= transport A after A2B_Delay_Time; Ignore_B_Event_Time <= transport (now + A2B_Delay_Time) afterA2B_Delay_Time; end if; end process; B2A : process begin if (now = 0 ns) then A <= 'L'; wait for B2A_Delay_Time; else wait until not(B'stable) and (now /= Ignore_B_Event_Time); A <= transport B after B2A_Delay_Time; Ignore_A_Event_Time <= transport (now + B2A_Delay_Time) afterB2A_Delay_Time; end if; end process;end RTL;-------------- End of code --------------
 

Welcome to EDABoard.com

Sponsor

Back
Top