URL
https://opencores.org/ocsvn/t48/t48/trunk
Subversion Repositories t48
Compare Revisions
- This comparison shows the changes necessary to convert path
/t48/tags/rel_0_1_beta/bench/vhdl
- from Rev 251 to Rev 292
- ↔ Reverse comparison
Rev 251 → Rev 292
/tb.vhd
0,0 → 1,401
------------------------------------------------------------------------------- |
-- |
-- The testbench for t48_core. |
-- |
-- $Id: tb.vhd,v 1.8 2004-04-25 20:41:48 arniml Exp $ |
-- |
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved |
-- |
-- Redistribution and use in source and synthezised forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- |
-- Redistributions of source code must retain the above copyright notice, |
-- this list of conditions and the following disclaimer. |
-- |
-- Redistributions in synthesized form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution. |
-- |
-- Neither the name of the author nor the names of other contributors may |
-- be used to endorse or promote products derived from this software without |
-- specific prior written permission. |
-- |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-- POSSIBILITY OF SUCH DAMAGE. |
-- |
-- Please report bugs to the author, but before you do so, please |
-- make sure that this is not a derivative work and that |
-- you have the latest version of this file. |
-- |
-- The latest version of this file can be found at: |
-- http://www.opencores.org/cvsweb.shtml/t48/ |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
entity tb is |
|
end tb; |
|
|
use work.t48_core_comp_pack.all; |
|
use work.t48_tb_pack.all; |
|
architecture behav of tb is |
|
-- clock period, 11 MHz |
constant period_c : time := 90 ns; |
|
component if_timing |
port( |
xtal_i : in std_logic; |
ale_i : in std_logic; |
psen_n_i : in std_logic; |
rd_n_i : in std_logic; |
wr_n_i : in std_logic; |
prog_n_i : in std_logic; |
db_bus_i : in std_logic_vector(7 downto 0); |
p2_i : in std_logic_vector(7 downto 0) |
); |
end component; |
|
signal xtal_s : std_logic; |
signal xtal_n_s : std_logic; |
signal res_n_s : std_logic; |
signal xtal3_s : std_logic; |
signal int_n_s : std_logic; |
signal ale_s : std_logic; |
signal rom_addr_s : std_logic_vector(11 downto 0); |
signal rom_data_s : std_logic_vector( 7 downto 0); |
signal ram_data_to_s : std_logic_vector( 7 downto 0); |
signal ram_data_from_s : std_logic_vector( 7 downto 0); |
signal ram_addr_s : std_logic_vector( 7 downto 0); |
signal ram_we_s : std_logic; |
|
signal p1_s : std_logic_vector( 7 downto 0); |
signal t48_p1_s : std_logic_vector( 7 downto 0); |
signal p1_low_imp_s : std_logic; |
signal p2_s : std_logic_vector( 7 downto 0); |
signal t48_p2_s : std_logic_vector( 7 downto 0); |
signal p2_low_imp_s : std_logic; |
signal psen_n_s : std_logic; |
signal prog_n_s : std_logic; |
|
signal bus_s : std_logic_vector( 7 downto 0); |
signal t48_bus_s : std_logic_vector( 7 downto 0); |
signal bus_dir_s : std_logic; |
|
signal ext_ram_addr_s : std_logic_vector( 7 downto 0); |
signal ext_ram_data_from_s : std_logic_vector( 7 downto 0); |
signal ext_ram_we_s : std_logic; |
signal rd_n_s : std_logic; |
signal wr_n_s : std_logic; |
|
signal zero_s : std_logic; |
signal one_s : std_logic; |
signal zero_byte_s : std_logic_vector( 7 downto 0); |
|
begin |
|
zero_s <= '0'; |
one_s <= '1'; |
zero_byte_s <= (others => '0'); |
|
rom_4k : syn_rom |
generic map ( |
address_width_g => 12 |
) |
port map ( |
clk_i => xtal_s, |
rom_addr_i => rom_addr_s, |
rom_data_o => rom_data_s |
); |
|
ram_256 : syn_ram |
generic map ( |
address_width_g => 8 |
) |
port map ( |
clk_i => xtal_s, |
res_i => res_n_s, |
ram_addr_i => ram_addr_s, |
ram_data_i => ram_data_to_s, |
ram_we_i => ram_we_s, |
ram_data_o => ram_data_from_s |
); |
|
ext_ram_b : syn_ram |
generic map ( |
address_width_g => 8 |
) |
port map ( |
clk_i => xtal_s, |
res_i => res_n_s, |
ram_addr_i => ext_ram_addr_s, |
ram_data_i => bus_s, |
ram_we_i => ext_ram_we_s, |
ram_data_o => ext_ram_data_from_s |
); |
|
t48_core_b : t48_core |
generic map ( |
xtal_div_3_g => 1, |
register_mnemonic_g => 1, |
include_port1_g => 1, |
include_port2_g => 1, |
include_bus_g => 1, |
include_timer_g => 1, |
sample_t1_state_g => 4 |
) |
port map ( |
xtal_i => xtal_s, |
reset_i => res_n_s, |
t0_i => p1_s(0), |
t0_o => open, |
t0_dir_o => open, |
int_n_i => int_n_s, |
ea_i => zero_s, |
rd_n_o => rd_n_s, |
psen_n_o => psen_n_s, |
wr_n_o => wr_n_s, |
ale_o => ale_s, |
db_i => bus_s, |
db_o => t48_bus_s, |
db_dir_o => bus_dir_s, |
t1_i => p1_s(1), |
p2_i => p2_s, |
p2_o => t48_p2_s, |
p2_low_imp_o => p2_low_imp_s, |
p1_i => p1_s, |
p1_o => t48_p1_s, |
p1_low_imp_o => p1_low_imp_s, |
prog_n_o => prog_n_s, |
clk_i => xtal_s, |
en_clk_i => xtal3_s, |
xtal3_o => xtal3_s, |
dmem_addr_o => ram_addr_s, |
dmem_we_o => ram_we_s, |
dmem_data_i => ram_data_from_s, |
dmem_data_o => ram_data_to_s, |
pmem_addr_o => rom_addr_s, |
pmem_data_i => rom_data_s |
); |
|
if_timing_b : if_timing |
port map ( |
xtal_i => xtal_s, |
ale_i => ale_s, |
psen_n_i => psen_n_s, |
rd_n_i => rd_n_s, |
wr_n_i => wr_n_s, |
prog_n_i => prog_n_s, |
db_bus_i => bus_s, |
p2_i => t48_p2_s |
); |
|
|
----------------------------------------------------------------------------- |
-- Port logic |
-- |
ports: process (t48_p1_s, |
p1_low_imp_s, |
t48_p2_s, |
p2_low_imp_s) |
function t48_port_f(t48_p : std_logic_vector(7 downto 0); |
low_imp : std_logic) return std_logic_vector is |
variable p_v : std_logic_vector(7 downto 0); |
begin |
if low_imp = '1' then |
p_v := t48_p; |
|
else |
for i in p_v'range loop |
if t48_p(i) = '1' then |
p_v(i) := 'H'; |
else |
p_v(i) := t48_p(i); |
end if; |
end loop; |
|
end if; |
|
return p_v; |
end; |
|
begin |
|
p1_s <= t48_port_f(t48_p => t48_p1_s, |
low_imp => p1_low_imp_s); |
|
p2_s <= t48_port_f(t48_p => t48_p2_s, |
low_imp => p2_low_imp_s); |
|
end process ports; |
-- |
----------------------------------------------------------------------------- |
|
bus_s <= t48_bus_s |
when bus_dir_s = '1' else |
(others => 'Z'); |
|
bus_s <= ext_ram_data_from_s |
when rd_n_s = '0' else |
(others => 'Z'); |
|
|
----------------------------------------------------------------------------- |
-- External RAM access signals |
-- |
ext_ram: process (wr_n_s, |
ext_ram_addr_s, |
ale_s, |
bus_s, |
xtal_s) |
begin |
if ale_s'event and ale_s = '0' then |
if not is_X(bus_s) then |
ext_ram_addr_s <= bus_s; |
else |
ext_ram_addr_s <= (others => '0'); |
end if; |
end if; |
|
if wr_n_s'event and wr_n_s = '1' then |
ext_ram_we_s <= '1'; |
end if; |
|
if xtal_s'event and xtal_s = '1' then |
ext_ram_we_s <= '0'; |
end if; |
|
end process ext_ram; |
-- |
----------------------------------------------------------------------------- |
|
xtal_n_s <= not xtal_s; |
|
----------------------------------------------------------------------------- |
-- The clock generator |
-- |
clk_gen: process |
begin |
xtal_s <= '0'; |
wait for period_c/2; |
xtal_s <= '1'; |
wait for period_c/2; |
end process clk_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- The reset generator |
-- |
res_gen: process |
begin |
res_n_s <= '0'; |
wait for 5 * period_c; |
res_n_s <= '1'; |
wait; |
end process res_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- The interrupt generator |
-- |
int_gen: process |
begin |
int_n_s <= '1'; |
wait for 750 * period_c; |
int_n_s <= '0'; |
wait for 45 * period_c; |
end process int_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- End of simulation detection |
-- |
eos: process |
begin |
|
outer: loop |
wait on tb_accu_s; |
if tb_accu_s = "10101010" then |
wait on tb_accu_s; |
if tb_accu_s = "01010101" then |
wait on tb_accu_s; |
if tb_accu_s = "00000001" then |
-- wait for instruction strobe of this move |
wait until tb_istrobe_s'event and tb_istrobe_s = '1'; |
-- wait for next strobe |
wait until tb_istrobe_s'event and tb_istrobe_s = '1'; |
assert false |
report "Simulation Result: PASS." |
severity note; |
else |
assert false |
report "Simulation Result: FAIL." |
severity note; |
end if; |
|
assert false |
report "End of simulation reached." |
severity failure; |
|
end if; |
end if; |
end loop; |
|
end process eos; |
-- |
----------------------------------------------------------------------------- |
|
end behav; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.7 2004/04/25 16:23:21 arniml |
-- added if_timing |
-- |
-- Revision 1.6 2004/04/14 20:57:44 arniml |
-- wait for instruction strobe after final end-of-simulation detection |
-- this ensures that the last mov instruction is part of the dump and |
-- enables 100% matching with i8039 simulator |
-- |
-- Revision 1.5 2004/03/29 19:45:15 arniml |
-- rename pX_limp to pX_low_imp |
-- |
-- Revision 1.4 2004/03/28 21:30:25 arniml |
-- connect prog_n_o |
-- |
-- Revision 1.3 2004/03/26 22:39:28 arniml |
-- enhance simulation result string |
-- |
-- Revision 1.2 2004/03/24 23:22:35 arniml |
-- put ext_ram on falling clock edge to sample the write enable properly |
-- |
-- Revision 1.1 2004/03/24 21:42:10 arniml |
-- initial check-in |
-- |
------------------------------------------------------------------------------- |
/if_timing.vhd
0,0 → 1,537
------------------------------------------------------------------------------- |
-- |
-- Interface Timing Checker. |
-- |
-- $Id: if_timing.vhd,v 1.2 2004-04-25 20:40:58 arniml Exp $ |
-- |
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved |
-- |
-- Redistribution and use in source and synthezised forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- |
-- Redistributions of source code must retain the above copyright notice, |
-- this list of conditions and the following disclaimer. |
-- |
-- Redistributions in synthesized form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution. |
-- |
-- Neither the name of the author nor the names of other contributors may |
-- be used to endorse or promote products derived from this software without |
-- specific prior written permission. |
-- |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-- POSSIBILITY OF SUCH DAMAGE. |
-- |
-- Please report bugs to the author, but before you do so, please |
-- make sure that this is not a derivative work and that |
-- you have the latest version of this file. |
-- |
-- The latest version of this file can be found at: |
-- http://www.opencores.org/cvsweb.shtml/t48/ |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
entity if_timing is |
|
port ( |
xtal_i : in std_logic; |
ale_i : in std_logic; |
psen_n_i : in std_logic; |
rd_n_i : in std_logic; |
wr_n_i : in std_logic; |
prog_n_i : in std_logic; |
db_bus_i : in std_logic_vector(7 downto 0); |
p2_i : in std_logic_vector(7 downto 0) |
); |
|
end if_timing; |
|
|
|
architecture behav of if_timing is |
|
signal last_xtal_rise_s : time; |
signal period_s : time; |
|
signal last_ale_rise_s, |
last_ale_fall_s : time; |
|
signal last_psen_n_rise_s, |
last_psen_n_fall_s : time; |
|
signal last_rd_n_rise_s, |
last_rd_n_fall_s : time; |
|
signal last_wr_n_rise_s, |
last_wr_n_fall_s : time; |
|
signal last_prog_n_rise_s, |
last_prog_n_fall_s : time; |
|
signal last_bus_change_s, |
bus_change_ale_s : time; |
signal last_p2_change_s : time; |
|
signal t_CY : time; |
|
begin |
|
t_CY <= 15 * period_s; |
|
----------------------------------------------------------------------------- |
-- Check RD |
-- |
rd_check: process (rd_n_i) |
begin |
case rd_n_i is |
-- RD active |
when '0' => |
-- tLAFC1: ALE to Control RD |
assert (now - last_ale_fall_s) > (t_CY / 5 - 75 ns) |
report "Timing violation of tLAFC1 on RD!" |
severity error; |
|
-- tAFC1: Addr Float to RD |
assert (now - last_bus_change_s) > (t_CY * 2/15 - 40 ns) |
report "Timing violation of tAFC1 on RD!" |
severity error; |
|
-- RD inactive |
when '1' => |
-- tCC1: Control Pulse Width RD |
assert (now - last_rd_n_fall_s) > (t_CY / 2 - 200 ns) |
report "Timing violation of tCC1 on RD!" |
severity error; |
|
when others => |
null; |
end case; |
|
end process rd_check; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Check WR |
-- |
wr_check: process (wr_n_i) |
begin |
case wr_n_i is |
-- WR active |
when '0' => |
-- tLAFC1: ALE to Control WR |
assert (now - last_ale_fall_s) > (t_CY / 5 - 75 ns) |
report "Timing violation of tLAFC1 on WR!" |
severity error; |
|
-- tAW: Addr Setup to WR |
assert (now - bus_change_ale_s) > (t_CY / 3 - 150 ns) |
report "Timing violation of tAW on WR!" |
severity error; |
|
-- tAW sanity check |
assert (now - bus_change_ale_s) < t_CY |
report "Timing relation between BUS and WR inconsistent!" |
severity error; |
|
-- WR inactive |
when '1' => |
-- tCC1: Control Pulse Width WR |
assert (now - last_wr_n_fall_s) > (t_CY / 2 - 200 ns) |
report "Timing violation of tCC1 on WR!" |
severity error; |
|
-- tDW: Data Setup before WR |
assert (now - last_bus_change_s) > (t_CY * 13/30 - 200 ns) |
report "Timing violation of tDW on WR!" |
severity error; |
|
when others => |
null; |
end case; |
|
end process wr_check; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Check BUS |
-- |
bus_check: process (db_bus_i) |
begin |
-- RD access |
-- tAD1 and tRD1 are not checked as they are constraints for the |
-- external memory, not the t48! |
|
-- WR access |
if wr_n_i = '0' then |
-- tDW: Data Hold after WR |
assert (now - last_wr_n_rise_s) > (t_CY / 15 - 50 ns) |
report "Timing violation of tDW on BUS vs. WR!" |
severity error; |
|
end if; |
|
-- Address strobe |
if ale_i = '0' then |
-- tLA: Addr Hold from ALE |
assert (now - last_ale_fall_s) > (t_CY / 15 - 40 ns) |
report "Timing violation of tLA on BUS vs. ALE!" |
severity error; |
end if; |
|
end process bus_check; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Check ALE |
-- |
ale_check: process (ale_i) |
variable t_CA1 : time; |
variable t_AL : time; |
begin |
case ale_i is |
when '0' => |
t_AL := t_CY * 2/15 - 110 ns; |
|
-- tAL: Addr Setup to ALE |
assert (now - last_bus_change_s) > t_AL |
report "Timing violation of tAL on BUS vs. ALE!" |
severity error; |
assert (now - last_p2_change_s) > t_AL |
report "Timing violation of tAL on P2 vs. ALE!" |
severity error; |
|
when '1' => |
-- tCA1: Control to ALE (RD, WR, PROG) |
t_CA1 := t_CY / 15 - 40 ns; |
|
assert (now - last_rd_n_rise_s) > t_CA1 |
report "Timing violation of tCA1 on RD vs. ALE!" |
severity error; |
assert (now - last_wr_n_rise_s) > t_CA1 |
report "Timing violation of tCA1 on WR vs. ALE!" |
severity error; |
assert (now - last_prog_n_rise_s) > t_CA1 |
report "Timing violation of tCA1 on PROG vs. ALE!" |
severity error; |
|
-- tCA2: Control to ALE (PSEN) |
assert (now - last_psen_n_rise_s) > (t_CY * 4/15 - 40 ns) |
report "Timing violation of tCA2 on PSEN vs. ALE!" |
severity error; |
|
-- tPL: Port 2 I/O Setup to ALE |
assert (now - last_p2_change_s) > (t_CY * 4/15 - 200 ns) |
report "Timing violation of tPL on P2 vs. ALE!" |
severity error; |
|
when others => |
null; |
|
end case; |
|
end process ale_check; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Check P2 |
-- |
p2_check: process (p2_i) |
begin |
case ale_i is |
when '0' => |
-- tLA: Addr Hold from ALE |
assert ((now - last_ale_fall_s) > (t_CY / 15 - 40 ns)) or |
now = 0 ns |
report "Timing violation of tLA on P2 vs. ALE!" |
severity error; |
|
if last_ale_fall_s < last_ale_rise_s then |
-- tPV: Port Output from ALE |
assert (now - last_ale_fall_s) < (t_CY * 3/10 + 100 ns) |
report "Timing violation of tPV on P2 vs. ALE!" |
severity error; |
end if; |
|
if prog_n_i = '1' then |
-- tPD: Output Data Hold |
assert ((now - last_prog_n_rise_s) > (t_CY / 10 - 50 ns)) or |
now = 0 ns |
report "Timing violation of tPD on P2 vs. PROG!" |
severity error; |
|
end if; |
|
when '1' => |
-- tLP: Port 2 I/O to ALE |
assert (now - last_ale_rise_s) > (t_CY / 30 - 30 ns) |
report "Timing violation of tLP on P2 vs. ALE!" |
severity error; |
|
when others => |
null; |
|
end case; |
|
end process p2_check; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Check PROG |
-- |
prog_check: process (prog_n_i) |
begin |
case prog_n_i is |
when '1' => |
-- tPP: PROG Pulse Width |
assert (now - last_prog_n_fall_s) > (t_CY * 7/10 - 250 ns) |
report "Timing violation of tPP!" |
severity error; |
|
-- tDP: Output Data Setup |
assert (now - last_p2_change_s) > (t_CY * 2/5 - 150 ns) |
report "Timing violation of tDP on P2 vs. PROG!" |
severity error; |
|
when others => |
null; |
end case; |
|
end process prog_check; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Monitor XTAL |
-- |
xtal_mon: process |
begin |
last_xtal_rise_s <= 0 ns; |
period_s <= 90 ns; |
|
while true loop |
wait on xtal_i; |
|
if xtal_i = '1' then |
period_s <= now - last_xtal_rise_s; |
last_xtal_rise_s <= now; |
end if; |
|
end loop; |
|
end process xtal_mon; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Monitor ALE |
-- |
ale_mon: process |
begin |
last_ale_rise_s <= 0 ns; |
last_ale_fall_s <= 0 ns; |
|
while true loop |
wait on ale_i; |
|
case ale_i is |
when '0' => |
last_ale_fall_s <= now; |
when '1' => |
last_ale_rise_s <= now; |
when others => |
null; |
end case; |
|
end loop; |
|
end process ale_mon; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Monitor PSEN |
-- |
psen_mon: process |
begin |
last_psen_n_rise_s <= 0 ns; |
last_psen_n_fall_s <= 0 ns; |
|
while true loop |
wait on psen_n_i; |
|
case psen_n_i is |
when '0' => |
last_psen_n_fall_s <= now; |
when '1' => |
last_psen_n_rise_s <= now; |
when others => |
null; |
end case; |
|
end loop; |
|
end process psen_mon; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Monitor RD |
-- |
rd_mon: process |
begin |
last_rd_n_rise_s <= 0 ns; |
last_rd_n_fall_s <= 0 ns; |
|
while true loop |
wait on rd_n_i; |
|
case rd_n_i is |
when '0' => |
last_rd_n_fall_s <= now; |
when '1' => |
last_rd_n_rise_s <= now; |
when others => |
null; |
end case; |
|
end loop; |
|
end process rd_mon; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Monitor WR |
-- |
wr_mon: process |
begin |
last_wr_n_rise_s <= 0 ns; |
last_wr_n_fall_s <= 0 ns; |
|
while true loop |
wait on wr_n_i; |
|
case wr_n_i is |
when '0' => |
last_wr_n_fall_s <= now; |
when '1' => |
last_wr_n_rise_s <= now; |
when others => |
null; |
end case; |
|
end loop; |
|
end process wr_mon; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Monitor PROG |
-- |
prog_mon: process |
begin |
last_prog_n_rise_s <= 0 ns; |
last_prog_n_fall_s <= 0 ns; |
|
while true loop |
wait on prog_n_i; |
|
case prog_n_i is |
when '0' => |
last_prog_n_fall_s <= now; |
when '1' => |
last_prog_n_rise_s <= now; |
when others => |
null; |
end case; |
|
end loop; |
|
end process prog_mon; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Monitor BUS |
-- |
bus_mon: process |
begin |
last_bus_change_s <= 0 ns; |
bus_change_ale_s <= 0 ns; |
|
while true loop |
wait on db_bus_i; |
|
last_bus_change_s <= now; |
|
if ale_i = '1' then |
bus_change_ale_s <= now; |
end if; |
end loop; |
|
end process bus_mon; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- Monitor P2 |
-- |
p2_mon: process |
begin |
last_p2_change_s <= 0 ns; |
|
while true loop |
wait on p2_i; |
|
last_p2_change_s <= now; |
end loop; |
|
end process p2_mon; |
-- |
----------------------------------------------------------------------------- |
|
end behav; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.1 2004/04/25 16:24:10 arniml |
-- initial check-in |
-- |
------------------------------------------------------------------------------- |
/if_timing-c.vhd
0,0 → 1,25
------------------------------------------------------------------------------- |
-- |
-- The Interface Timing Checker. |
-- |
-- $Id: if_timing-c.vhd,v 1.1 2004-04-25 16:24:10 arniml Exp $ |
-- |
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved |
-- |
------------------------------------------------------------------------------- |
|
configuration if_timing_behav_c0 of if_timing is |
|
for behav |
end for; |
|
end if_timing_behav_c0; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
------------------------------------------------------------------------------- |
/tb-c.vhd
0,0 → 1,49
------------------------------------------------------------------------------- |
-- |
-- The testbench for t48_core. |
-- |
-- $Id: tb-c.vhd,v 1.2 2004-04-25 16:23:21 arniml Exp $ |
-- |
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_behav_c0 of tb is |
|
for behav |
|
for rom_4k : syn_rom |
use configuration work.syn_rom_lpm_c0; |
end for; |
|
for ram_256 : syn_ram |
use configuration work.syn_ram_lpm_c0; |
end for; |
|
for ext_ram_b : syn_ram |
use configuration work.syn_ram_lpm_c0; |
end for; |
|
for t48_core_b : t48_core |
use configuration work.t48_core_struct_c0; |
end for; |
|
for if_timing_b : if_timing |
use configuration work.if_timing_behav_c0; |
end for; |
|
end for; |
|
end tb_behav_c0; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.1 2004/03/24 21:42:10 arniml |
-- initial check-in |
-- |
------------------------------------------------------------------------------- |
/tb_t8048.vhd
0,0 → 1,273
------------------------------------------------------------------------------- |
-- |
-- The testbench for t8048. |
-- |
-- $Id: tb_t8048.vhd,v 1.4 2004-04-18 19:00:58 arniml Exp $ |
-- |
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved |
-- |
-- Redistribution and use in source and synthezised forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- |
-- Redistributions of source code must retain the above copyright notice, |
-- this list of conditions and the following disclaimer. |
-- |
-- Redistributions in synthesized form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution. |
-- |
-- Neither the name of the author nor the names of other contributors may |
-- be used to endorse or promote products derived from this software without |
-- specific prior written permission. |
-- |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-- POSSIBILITY OF SUCH DAMAGE. |
-- |
-- Please report bugs to the author, but before you do so, please |
-- make sure that this is not a derivative work and that |
-- you have the latest version of this file. |
-- |
-- The latest version of this file can be found at: |
-- http://www.opencores.org/cvsweb.shtml/t48/ |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
entity tb_t8048 is |
|
end tb_t8048; |
|
use work.t48_core_comp_pack.syn_ram; |
|
use work.t48_tb_pack.all; |
|
architecture behav of tb_t8048 is |
|
-- clock period, 11 MHz |
constant period_c : time := 90 ns; |
|
component t8048 |
port ( |
xtal_i : in std_logic; |
reset_n_i : in std_logic; |
t0_b : inout std_logic; |
int_n_i : in std_logic; |
ea_i : in std_logic; |
rd_n_o : out std_logic; |
psen_n_o : out std_logic; |
wr_n_o : out std_logic; |
ale_o : out std_logic; |
db_b : inout std_logic_vector( 7 downto 0); |
t1_i : in std_logic; |
p2_b : inout std_logic_vector( 7 downto 0); |
p1_b : inout std_logic_vector( 7 downto 0); |
prog_n_o : out std_logic |
); |
end component; |
|
signal xtal_s : std_logic; |
signal res_n_s : std_logic; |
signal int_n_s : std_logic; |
signal ale_s : std_logic; |
signal psen_n_s : std_logic; |
signal prog_n_s : std_logic; |
signal rom_addr_s : std_logic_vector(11 downto 0); |
signal rom_data_s : std_logic_vector( 7 downto 0); |
signal ram_data_to_s : std_logic_vector( 7 downto 0); |
signal ram_data_from_s : std_logic_vector( 7 downto 0); |
signal ram_addr_s : std_logic_vector( 7 downto 0); |
signal ram_we_s : std_logic; |
|
signal p1_b : std_logic_vector( 7 downto 0); |
signal p2_b : std_logic_vector( 7 downto 0); |
|
signal db_b : std_logic_vector( 7 downto 0); |
signal ext_ram_addr_s : std_logic_vector( 7 downto 0); |
signal ext_ram_data_from_s : std_logic_vector( 7 downto 0); |
signal ext_ram_we_s : std_logic; |
signal rd_n_s : std_logic; |
signal wr_n_s : std_logic; |
|
signal zero_s : std_logic; |
signal one_s : std_logic; |
|
begin |
|
zero_s <= '0'; |
one_s <= '1'; |
|
p2_b <= (others => 'H'); |
p1_b <= (others => 'H'); |
|
ext_ram_b : syn_ram |
generic map ( |
address_width_g => 8 |
) |
port map ( |
clk_i => zero_s, |
res_i => res_n_s, |
ram_addr_i => ext_ram_addr_s, |
ram_data_i => db_b, |
ram_we_i => ext_ram_we_s, |
ram_data_o => ext_ram_data_from_s |
); |
|
t8048_b : t8048 |
port map ( |
xtal_i => xtal_s, |
reset_n_i => res_n_s, |
t0_b => p1_b(0), |
int_n_i => int_n_s, |
ea_i => zero_s, |
rd_n_o => rd_n_s, |
psen_n_o => psen_n_s, |
wr_n_o => wr_n_s, |
ale_o => ale_s, |
db_b => db_b, |
t1_i => p1_b(1), |
p2_b => p2_b, |
p1_b => p1_b, |
prog_n_o => prog_n_s |
); |
|
|
|
----------------------------------------------------------------------------- |
-- External RAM access signals |
-- |
ext_ram: process (wr_n_s, |
ale_s, |
db_b) |
begin |
if ale_s'event and ale_s = '0' then |
if not is_X(db_b) then |
ext_ram_addr_s <= db_b; |
else |
ext_ram_addr_s <= (others => '0'); |
end if; |
end if; |
|
if wr_n_s'event and wr_n_s = '1' then |
ext_ram_we_s <= '1'; |
end if; |
|
-- if clk_s'event then |
-- ext_ram_we_s <= '0'; |
-- end if; |
|
end process ext_ram; |
-- |
----------------------------------------------------------------------------- |
|
----------------------------------------------------------------------------- |
-- The clock generator |
-- |
clk_gen: process |
begin |
xtal_s <= '0'; |
wait for period_c/2; |
xtal_s <= '1'; |
wait for period_c/2; |
end process clk_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- The reset generator |
-- |
res_gen: process |
begin |
res_n_s <= '0'; |
wait for 5 * period_c; |
res_n_s <= '1'; |
wait; |
end process res_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- The interrupt generator |
-- |
int_gen: process |
begin |
int_n_s <= '1'; |
wait for 750 * period_c; |
int_n_s <= '0'; |
wait for 45 * period_c; |
end process int_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- End of simulation detection |
-- |
eos: process |
begin |
|
outer: loop |
wait on tb_accu_s; |
if tb_accu_s = "10101010" then |
wait on tb_accu_s; |
if tb_accu_s = "01010101" then |
wait on tb_accu_s; |
if tb_accu_s = "00000001" then |
-- wait for instruction strobe of this move |
wait until tb_istrobe_s'event and tb_istrobe_s = '1'; |
-- wait for next strobe |
wait until tb_istrobe_s'event and tb_istrobe_s = '1'; |
assert false |
report "Simulation Result: PASS." |
severity note; |
else |
assert false |
report "Simulation Result: FAIL." |
severity note; |
end if; |
|
assert false |
report "End of simulation reached." |
severity failure; |
|
end if; |
end if; |
end loop; |
|
end process eos; |
-- |
----------------------------------------------------------------------------- |
|
end behav; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.3 2004/04/14 20:57:44 arniml |
-- wait for instruction strobe after final end-of-simulation detection |
-- this ensures that the last mov instruction is part of the dump and |
-- enables 100% matching with i8039 simulator |
-- |
-- Revision 1.2 2004/03/26 22:39:28 arniml |
-- enhance simulation result string |
-- |
-- Revision 1.1 2004/03/24 21:42:10 arniml |
-- initial check-in |
-- |
------------------------------------------------------------------------------- |
/tb_t8039-c.vhd
0,0 → 1,38
------------------------------------------------------------------------------- |
-- |
-- The testbench for t8039. |
-- |
-- $Id: tb_t8039-c.vhd,v 1.1 2004-04-18 19:00:07 arniml Exp $ |
-- |
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_t8039_behav_c0 of tb_t8039 is |
|
for behav |
|
for ext_ram_b : syn_ram |
use configuration work.syn_ram_lpm_c0; |
end for; |
|
for ext_rom_b : syn_rom |
use configuration work.syn_rom_lpm_c0; |
end for; |
|
for t8039_b : t8039 |
use configuration work.t8039_struct_c0; |
end for; |
|
end for; |
|
end tb_t8039_behav_c0; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
------------------------------------------------------------------------------- |
/tb_t8039.vhd
0,0 → 1,289
------------------------------------------------------------------------------- |
-- |
-- The testbench for t8039. |
-- |
-- $Id: tb_t8039.vhd,v 1.1 2004-04-18 19:00:07 arniml Exp $ |
-- |
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved |
-- |
-- Redistribution and use in source and synthezised forms, with or without |
-- modification, are permitted provided that the following conditions are met: |
-- |
-- Redistributions of source code must retain the above copyright notice, |
-- this list of conditions and the following disclaimer. |
-- |
-- Redistributions in synthesized form must reproduce the above copyright |
-- notice, this list of conditions and the following disclaimer in the |
-- documentation and/or other materials provided with the distribution. |
-- |
-- Neither the name of the author nor the names of other contributors may |
-- be used to endorse or promote products derived from this software without |
-- specific prior written permission. |
-- |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE |
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
-- POSSIBILITY OF SUCH DAMAGE. |
-- |
-- Please report bugs to the author, but before you do so, please |
-- make sure that this is not a derivative work and that |
-- you have the latest version of this file. |
-- |
-- The latest version of this file can be found at: |
-- http://www.opencores.org/cvsweb.shtml/t48/ |
-- |
------------------------------------------------------------------------------- |
|
library ieee; |
use ieee.std_logic_1164.all; |
|
entity tb_t8039 is |
|
end tb_t8039; |
|
use work.t48_core_comp_pack.syn_ram; |
use work.t48_core_comp_pack.syn_rom; |
|
use work.t48_tb_pack.all; |
|
architecture behav of tb_t8039 is |
|
-- clock period, 11 MHz |
constant period_c : time := 90 ns; |
|
component t8039 |
port ( |
xtal_i : in std_logic; |
reset_n_i : in std_logic; |
t0_b : inout std_logic; |
int_n_i : in std_logic; |
ea_i : in std_logic; |
rd_n_o : out std_logic; |
psen_n_o : out std_logic; |
wr_n_o : out std_logic; |
ale_o : out std_logic; |
db_b : inout std_logic_vector( 7 downto 0); |
t1_i : in std_logic; |
p2_b : inout std_logic_vector( 7 downto 0); |
p1_b : inout std_logic_vector( 7 downto 0); |
prog_n_o : out std_logic |
); |
end component; |
|
signal xtal_s : std_logic; |
signal res_n_s : std_logic; |
signal int_n_s : std_logic; |
signal ale_s : std_logic; |
signal psen_n_s : std_logic; |
signal prog_n_s : std_logic; |
signal rom_addr_s : std_logic_vector(11 downto 0); |
signal rom_data_s : std_logic_vector( 7 downto 0); |
signal ram_data_to_s : std_logic_vector( 7 downto 0); |
signal ram_data_from_s : std_logic_vector( 7 downto 0); |
signal ram_addr_s : std_logic_vector( 7 downto 0); |
signal ram_we_s : std_logic; |
|
signal p1_b : std_logic_vector( 7 downto 0); |
signal p2_b : std_logic_vector( 7 downto 0); |
|
signal db_b : std_logic_vector( 7 downto 0); |
signal ext_mem_addr_s : std_logic_vector(11 downto 0); |
signal ext_ram_data_from_s : std_logic_vector( 7 downto 0); |
signal ext_ram_we_s : std_logic; |
signal ext_rom_data_s : std_logic_vector( 7 downto 0); |
signal rd_n_s : std_logic; |
signal wr_n_s : std_logic; |
|
signal zero_s : std_logic; |
signal one_s : std_logic; |
|
begin |
|
zero_s <= '0'; |
one_s <= '1'; |
|
p2_b <= (others => 'H'); |
p1_b <= (others => 'H'); |
|
ext_rom_b : syn_rom |
generic map ( |
address_width_g => 12 |
) |
port map ( |
clk_i => xtal_s, |
rom_addr_i => ext_mem_addr_s, |
rom_data_o => ext_rom_data_s |
); |
|
ext_ram_b : syn_ram |
generic map ( |
address_width_g => 8 |
) |
port map ( |
clk_i => zero_s, |
res_i => res_n_s, |
ram_addr_i => ext_mem_addr_s(7 downto 0), |
ram_data_i => db_b, |
ram_we_i => ext_ram_we_s, |
ram_data_o => ext_ram_data_from_s |
); |
|
t8039_b : t8039 |
port map ( |
xtal_i => xtal_s, |
reset_n_i => res_n_s, |
t0_b => p1_b(0), |
int_n_i => int_n_s, |
ea_i => one_s, |
rd_n_o => rd_n_s, |
psen_n_o => psen_n_s, |
wr_n_o => wr_n_s, |
ale_o => ale_s, |
db_b => db_b, |
t1_i => p1_b(1), |
p2_b => p2_b, |
p1_b => p1_b, |
prog_n_o => prog_n_s |
); |
|
|
----------------------------------------------------------------------------- |
-- Read from external memory |
-- |
db_b <= ext_rom_data_s |
when psen_n_s = '0' else |
(others => 'Z'); |
db_b <= ext_ram_data_from_s |
when rd_n_s = '0' else |
(others => 'Z'); |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- External memory access signals |
-- |
ext_mem: process (wr_n_s, |
ale_s, |
p2_b, |
db_b) |
begin |
ext_mem_addr_s(11 downto 8) <= p2_b(3 downto 0); |
|
if ale_s = '1' then |
if not is_X(db_b) then |
ext_mem_addr_s(7 downto 0) <= db_b; |
else |
ext_mem_addr_s(7 downto 0) <= (others => '0'); |
end if; |
end if; |
|
if wr_n_s'event and wr_n_s = '1' then |
ext_ram_we_s <= '1'; |
end if; |
|
-- if clk_s'event then |
-- ext_ram_we_s <= '0'; |
-- end if; |
|
end process ext_mem; |
-- |
----------------------------------------------------------------------------- |
|
----------------------------------------------------------------------------- |
-- The clock generator |
-- |
clk_gen: process |
begin |
xtal_s <= '0'; |
wait for period_c/2; |
xtal_s <= '1'; |
wait for period_c/2; |
end process clk_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- The reset generator |
-- |
res_gen: process |
begin |
res_n_s <= '0'; |
wait for 5 * period_c; |
res_n_s <= '1'; |
wait; |
end process res_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- The interrupt generator |
-- |
int_gen: process |
begin |
int_n_s <= '1'; |
wait for 750 * period_c; |
int_n_s <= '0'; |
wait for 45 * period_c; |
end process int_gen; |
-- |
----------------------------------------------------------------------------- |
|
|
----------------------------------------------------------------------------- |
-- End of simulation detection |
-- |
eos: process |
begin |
|
outer: loop |
wait on tb_accu_s; |
if tb_accu_s = "10101010" then |
wait on tb_accu_s; |
if tb_accu_s = "01010101" then |
wait on tb_accu_s; |
if tb_accu_s = "00000001" then |
-- wait for instruction strobe of this move |
wait until tb_istrobe_s'event and tb_istrobe_s = '1'; |
-- wait for next strobe |
wait until tb_istrobe_s'event and tb_istrobe_s = '1'; |
assert false |
report "Simulation Result: PASS." |
severity note; |
else |
assert false |
report "Simulation Result: FAIL." |
severity note; |
end if; |
|
assert false |
report "End of simulation reached." |
severity failure; |
|
end if; |
end if; |
end loop; |
|
end process eos; |
-- |
----------------------------------------------------------------------------- |
|
end behav; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
------------------------------------------------------------------------------- |
/tb_t8048-c.vhd
0,0 → 1,34
------------------------------------------------------------------------------- |
-- |
-- The testbench for t8048. |
-- |
-- $Id: tb_t8048-c.vhd,v 1.1 2004-03-24 21:42:10 arniml Exp $ |
-- |
-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org) |
-- |
-- All rights reserved |
-- |
------------------------------------------------------------------------------- |
|
configuration tb_t8048_behav_c0 of tb_t8048 is |
|
for behav |
|
for ext_ram_b : syn_ram |
use configuration work.syn_ram_lpm_c0; |
end for; |
|
for t8048_b : t8048 |
use configuration work.t8048_struct_c0; |
end for; |
|
end for; |
|
end tb_t8048_behav_c0; |
|
|
------------------------------------------------------------------------------- |
-- File History: |
-- |
-- $Log: not supported by cvs2svn $ |
------------------------------------------------------------------------------- |