You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
467 lines
19 KiB
VHDL
467 lines
19 KiB
VHDL
-- © IBM Corp. 2020
|
|
-- Licensed under the Apache License, Version 2.0 (the "License"), as modified by
|
|
-- the terms below; you may not use the files in this repository except in
|
|
-- compliance with the License as modified.
|
|
-- You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
--
|
|
-- Modified Terms:
|
|
--
|
|
-- 1) For the purpose of the patent license granted to you in Section 3 of the
|
|
-- License, the "Work" hereby includes implementations of the work of authorship
|
|
-- in physical form.
|
|
--
|
|
-- 2) Notwithstanding any terms to the contrary in the License, any licenses
|
|
-- necessary for implementation of the Work that are available from OpenPOWER
|
|
-- via the Power ISA End User License Agreement (EULA) are explicitly excluded
|
|
-- hereunder, and may be obtained from OpenPOWER under the terms and conditions
|
|
-- of the EULA.
|
|
--
|
|
-- Unless required by applicable law or agreed to in writing, the reference design
|
|
-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
|
-- for the specific language governing permissions and limitations under the License.
|
|
--
|
|
-- Additional rights, including the ability to physically implement a softcore that
|
|
-- is compliant with the required sections of the Power ISA Specification, are
|
|
-- available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be
|
|
-- obtained (along with the Power ISA) here: https://openpowerfoundation.org.
|
|
|
|
library ieee; use ieee.std_logic_1164.all;
|
|
library support;
|
|
use support.power_logic_pkg.all;
|
|
library ibm;
|
|
use ibm.std_ulogic_support.all ;
|
|
use ibm.std_ulogic_function_support.all;
|
|
library tri; use tri.tri_latches_pkg.all;
|
|
|
|
entity tri_128x16_1r1w_1 is
|
|
generic (addressable_ports : positive := 128;
|
|
addressbus_width : positive := 7;
|
|
port_bitwidth : positive := 16;
|
|
ways : positive := 1;
|
|
expand_type : integer := 1);
|
|
port (
|
|
vdd : INOUT power_logic;
|
|
vcs : INOUT power_logic;
|
|
gnd : INOUT power_logic;
|
|
|
|
nclk : IN clk_logic;
|
|
|
|
rd_act : IN std_ulogic;
|
|
wr_act : IN std_ulogic;
|
|
|
|
lcb_d_mode_dc : IN std_ulogic;
|
|
lcb_clkoff_dc_b : IN std_ulogic;
|
|
lcb_mpw1_dc_b : IN std_ulogic_vector(0 TO 4);
|
|
lcb_mpw2_dc_b : IN std_ulogic;
|
|
lcb_delay_lclkr_dc : IN std_ulogic_vector(0 TO 4);
|
|
|
|
ccflush_dc : IN std_ulogic;
|
|
scan_dis_dc_b : IN std_ulogic;
|
|
scan_diag_dc : IN std_ulogic;
|
|
func_scan_in : IN std_ulogic;
|
|
func_scan_out : OUT std_ulogic;
|
|
|
|
lcb_sg_0 : IN std_ulogic;
|
|
lcb_sl_thold_0_b : IN std_ulogic;
|
|
lcb_time_sl_thold_0 : IN std_ulogic;
|
|
lcb_abst_sl_thold_0 : IN std_ulogic;
|
|
lcb_ary_nsl_thold_0 : IN std_ulogic;
|
|
lcb_repr_sl_thold_0 : IN std_ulogic;
|
|
time_scan_in : IN std_ulogic;
|
|
time_scan_out : OUT std_ulogic;
|
|
abst_scan_in : IN std_ulogic;
|
|
abst_scan_out : OUT std_ulogic;
|
|
repr_scan_in : IN std_ulogic;
|
|
repr_scan_out : OUT std_ulogic;
|
|
|
|
abist_di : IN std_ulogic_vector(0 TO 3);
|
|
abist_bw_odd : IN std_ulogic;
|
|
abist_bw_even : IN std_ulogic;
|
|
abist_wr_adr : IN std_ulogic_vector(0 TO 6);
|
|
wr_abst_act : IN std_ulogic;
|
|
abist_rd0_adr : IN std_ulogic_vector(0 TO 6);
|
|
rd0_abst_act : IN std_ulogic;
|
|
tc_lbist_ary_wrt_thru_dc : IN std_ulogic;
|
|
abist_ena_1 : IN std_ulogic;
|
|
abist_g8t_rd0_comp_ena : IN std_ulogic;
|
|
abist_raw_dc_b : IN std_ulogic;
|
|
obs0_abist_cmp : IN std_ulogic_vector(0 TO 3);
|
|
|
|
lcb_bolt_sl_thold_0 : in std_ulogic;
|
|
pc_bo_enable_2 : in std_ulogic;
|
|
pc_bo_reset : in std_ulogic;
|
|
pc_bo_unload : in std_ulogic;
|
|
pc_bo_repair : in std_ulogic;
|
|
pc_bo_shdata : in std_ulogic;
|
|
pc_bo_select : in std_ulogic;
|
|
bo_pc_failout : out std_ulogic;
|
|
bo_pc_diagloop : out std_ulogic;
|
|
tri_lcb_mpw1_dc_b : in std_ulogic;
|
|
tri_lcb_mpw2_dc_b : in std_ulogic;
|
|
tri_lcb_delay_lclkr_dc : in std_ulogic;
|
|
tri_lcb_clkoff_dc_b : in std_ulogic;
|
|
tri_lcb_act_dis_dc : in std_ulogic;
|
|
|
|
bw : IN std_ulogic_vector( 0 TO 15 );
|
|
wr_adr : IN std_ulogic_vector( 0 TO 6 );
|
|
rd_adr : IN std_ulogic_vector( 0 TO 6 );
|
|
di : IN std_ulogic_vector( 0 TO 15 );
|
|
do : OUT std_ulogic_vector( 0 TO 15 )
|
|
|
|
);
|
|
|
|
-- synopsys translate_off
|
|
-- synopsys translate_on
|
|
|
|
end entity tri_128x16_1r1w_1;
|
|
|
|
architecture tri_128x16_1r1w_1 of tri_128x16_1r1w_1 is
|
|
|
|
begin
|
|
|
|
-- synopsys translate_off
|
|
um: if expand_type = 0 generate
|
|
|
|
constant rd_addr_offset : natural := 0;
|
|
constant wr_addr_offset : natural := rd_addr_offset + addressbus_width;
|
|
constant write_enable_offset : natural := wr_addr_offset + addressbus_width;
|
|
constant data_in_offset : natural := write_enable_offset + port_bitwidth;
|
|
constant data_out_offset : natural := data_in_offset + port_bitwidth;
|
|
constant array_offset : natural := data_out_offset + port_bitwidth;
|
|
constant scan_right : natural := array_offset + addressable_ports*port_bitwidth*ways - 1;
|
|
|
|
signal tiup : std_ulogic;
|
|
signal tidn : std_ulogic;
|
|
|
|
signal rd_addr_l2 : std_ulogic_vector (0 TO addressbus_width-1);
|
|
signal wr_addr_l2 : std_ulogic_vector (0 TO addressbus_width-1);
|
|
signal write_enable_d : std_ulogic_vector(0 to port_bitwidth-1);
|
|
signal write_enable_l2 : std_ulogic_vector(0 to port_bitwidth-1);
|
|
signal data_in_l2 : std_ulogic_vector(0 to port_bitwidth-1);
|
|
signal data_out_d : std_ulogic_vector(0 to port_bitwidth-1);
|
|
signal data_out_l2 : std_ulogic_vector(0 to port_bitwidth-1);
|
|
signal array_d : std_ulogic_vector(0 to addressable_ports*port_bitwidth*ways-1);
|
|
signal array_l2 : std_ulogic_vector(0 to addressable_ports*port_bitwidth*ways-1);
|
|
signal siv : std_ulogic_vector(0 to scan_right);
|
|
signal sov : std_ulogic_vector(0 to scan_right);
|
|
begin
|
|
tiup <= '1';
|
|
tidn <= '0';
|
|
|
|
rd_addr_latch: tri_rlmreg_p
|
|
generic map (width => rd_adr'length, init => 0, expand_type => expand_type)
|
|
port map (vd => vdd,
|
|
gd => gnd,
|
|
nclk => nclk,
|
|
act => rd_act,
|
|
scin => siv(rd_addr_offset to rd_addr_offset+rd_addr_l2'length-1),
|
|
scout => sov(rd_addr_offset to rd_addr_offset+rd_addr_l2'length-1),
|
|
din => rd_adr,
|
|
dout => rd_addr_l2 );
|
|
|
|
wr_addr_latch: tri_rlmreg_p
|
|
generic map (width => wr_adr'length, init => 0, expand_type => expand_type)
|
|
port map (vd => vdd,
|
|
gd => gnd,
|
|
nclk => nclk,
|
|
act => wr_act,
|
|
scin => siv(wr_addr_offset to wr_addr_offset+wr_addr_l2'length-1),
|
|
scout => sov(wr_addr_offset to wr_addr_offset+wr_addr_l2'length-1),
|
|
din => wr_adr,
|
|
dout => wr_addr_l2 );
|
|
|
|
|
|
|
|
write_enable_latch: tri_rlmreg_p
|
|
generic map (width => port_bitwidth, init => 0, expand_type => expand_type)
|
|
port map (vd => vdd,
|
|
gd => gnd,
|
|
nclk => nclk,
|
|
act => wr_act,
|
|
scin => siv(write_enable_offset to write_enable_offset+write_enable_l2'length-1),
|
|
scout => sov(write_enable_offset to write_enable_offset+write_enable_l2'length-1),
|
|
din => write_enable_d,
|
|
dout => write_enable_l2 );
|
|
|
|
data_in_latch: tri_rlmreg_p
|
|
generic map (width => port_bitwidth, init => 0, expand_type => expand_type)
|
|
port map (vd => vdd,
|
|
gd => gnd,
|
|
nclk => nclk,
|
|
act => wr_act,
|
|
scin => siv(data_in_offset to data_in_offset+data_in_l2'length-1),
|
|
scout => sov(data_in_offset to data_in_offset+data_in_l2'length-1),
|
|
din => di,
|
|
dout => data_in_l2 );
|
|
|
|
data_out_latch: tri_rlmreg_p
|
|
generic map (width => port_bitwidth, init => 0, expand_type => expand_type)
|
|
port map (vd => vdd,
|
|
gd => gnd,
|
|
nclk => nclk,
|
|
act => wr_act,
|
|
scin => siv(data_out_offset to data_out_offset+data_out_l2'length-1),
|
|
scout => sov(data_out_offset to data_out_offset+data_out_l2'length-1),
|
|
din => data_out_d,
|
|
dout => data_out_l2 );
|
|
|
|
array_latch: tri_rlmreg_p
|
|
generic map (width => addressable_ports*port_bitwidth*ways, init => 0, expand_type => expand_type)
|
|
port map (vd => vdd,
|
|
gd => gnd,
|
|
nclk => nclk,
|
|
act => tiup,
|
|
scin => siv(array_offset to array_offset+array_l2'length-1),
|
|
scout => sov(array_offset to array_offset+array_l2'length-1),
|
|
din => array_d,
|
|
dout => array_l2 );
|
|
|
|
write_enable_d <= bw when wr_act='1' else (others => '0');
|
|
|
|
ww: for w in 0 to ways-1 generate
|
|
begin
|
|
wy: for y in 0 to addressable_ports-1 generate
|
|
begin
|
|
wx: for x in 0 to port_bitwidth-1 generate
|
|
begin
|
|
array_d(y*port_bitwidth*ways+w*port_bitwidth+x) <=
|
|
data_in_l2(x) when ( write_enable_l2(x)='1' and wr_addr_l2 = tconv(y, addressbus_width))
|
|
else array_l2(y*port_bitwidth*ways+w*port_bitwidth+x);
|
|
|
|
end generate wx;
|
|
end generate wy;
|
|
end generate ww;
|
|
|
|
data_out_d(0) <= array_l2( tconv(rd_addr_l2)*port_bitwidth);
|
|
data_out_d(1) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+1);
|
|
data_out_d(2) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+2);
|
|
data_out_d(3) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+3);
|
|
data_out_d(4) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+4);
|
|
data_out_d(5) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+5);
|
|
data_out_d(6) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+6);
|
|
data_out_d(7) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+7);
|
|
data_out_d(8) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+8);
|
|
data_out_d(9) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+9);
|
|
data_out_d(10) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+10);
|
|
data_out_d(11) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+11);
|
|
data_out_d(12) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+12);
|
|
data_out_d(13) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+13);
|
|
data_out_d(14) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+14);
|
|
data_out_d(15) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+15);
|
|
|
|
do(0) <= array_l2( tconv(rd_addr_l2)*port_bitwidth);
|
|
do(1) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+1);
|
|
do(2) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+2);
|
|
do(3) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+3);
|
|
do(4) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+4);
|
|
do(5) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+5);
|
|
do(6) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+6);
|
|
do(7) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+7);
|
|
do(8) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+8);
|
|
do(9) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+9);
|
|
do(10) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+10);
|
|
do(11) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+11);
|
|
do(12) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+12);
|
|
do(13) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+13);
|
|
do(14) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+14);
|
|
do(15) <= array_l2( tconv(rd_addr_l2)*port_bitwidth+15);
|
|
|
|
siv(0 to scan_right) <= sov(1 to scan_right) & func_scan_in;
|
|
func_scan_out <= sov(0);
|
|
|
|
time_scan_out <= time_scan_in;
|
|
abst_scan_out <= abst_scan_in;
|
|
repr_scan_out <= repr_scan_in;
|
|
|
|
bo_pc_failout <= '0';
|
|
bo_pc_diagloop <= '0';
|
|
|
|
end generate um;
|
|
-- synopsys translate_on
|
|
|
|
|
|
a : if expand_type = 1 generate
|
|
|
|
component RAMB16_S36_S36
|
|
-- pragma translate_off
|
|
generic(
|
|
SIM_COLLISION_CHECK : string := "none");
|
|
-- pragma translate_on
|
|
port(
|
|
DOA : out std_logic_vector(31 downto 0);
|
|
DOB : out std_logic_vector(31 downto 0);
|
|
DOPA : out std_logic_vector(3 downto 0);
|
|
DOPB : out std_logic_vector(3 downto 0);
|
|
ADDRA : in std_logic_vector(8 downto 0);
|
|
ADDRB : in std_logic_vector(8 downto 0);
|
|
CLKA : in std_ulogic;
|
|
CLKB : in std_ulogic;
|
|
DIA : in std_logic_vector(31 downto 0);
|
|
DIB : in std_logic_vector(31 downto 0);
|
|
DIPA : in std_logic_vector(3 downto 0);
|
|
DIPB : in std_logic_vector(3 downto 0);
|
|
ENA : in std_ulogic;
|
|
ENB : in std_ulogic;
|
|
SSRA : in std_ulogic;
|
|
SSRB : in std_ulogic;
|
|
WEA : in std_ulogic;
|
|
WEB : in std_ulogic);
|
|
end component;
|
|
|
|
|
|
|
|
-- pragma translate_off
|
|
-- pragma translate_on
|
|
|
|
|
|
|
|
signal clk,clk2x : std_ulogic;
|
|
signal b0addra, b0addrb : std_ulogic_vector(0 to 8);
|
|
signal wea, web : std_ulogic;
|
|
signal wren_a : std_ulogic;
|
|
signal reset_q : std_ulogic;
|
|
signal gate_fq, gate_d : std_ulogic;
|
|
signal r_data_out_1_d, r_data_out_1_fq : std_ulogic_vector(0 to 35);
|
|
signal w_data_in_0 : std_ulogic_vector(0 to 35);
|
|
|
|
signal r_data_out_0_bram : std_logic_vector(0 to 35);
|
|
signal r_data_out_1_bram : std_logic_vector(0 to 35);
|
|
|
|
signal toggle_d : std_ulogic;
|
|
signal toggle_q : std_ulogic;
|
|
signal toggle2x_d : std_ulogic;
|
|
signal toggle2x_q : std_ulogic;
|
|
|
|
signal unused : std_ulogic;
|
|
-- synopsys translate_off
|
|
-- synopsys translate_on
|
|
|
|
begin
|
|
|
|
clk <= nclk.clk;
|
|
clk2x <= nclk.clk2x;
|
|
|
|
rlatch: process (clk) begin
|
|
if(rising_edge(clk)) then
|
|
reset_q <= nclk.sreset;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
tlatch: process (nclk.clk,reset_q)
|
|
begin
|
|
if(rising_edge(nclk.clk)) then
|
|
if (reset_q = '1') then
|
|
toggle_q <= '1';
|
|
else
|
|
toggle_q <= toggle_d;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
flatch: process (nclk.clk2x)
|
|
begin
|
|
if(rising_edge(nclk.clk2x)) then
|
|
toggle2x_q <= toggle2x_d;
|
|
gate_fq <= gate_d;
|
|
r_data_out_1_fq <= r_data_out_1_d;
|
|
end if;
|
|
end process;
|
|
|
|
toggle_d <= not toggle_q;
|
|
toggle2x_d <= toggle_q;
|
|
|
|
gate_d <= not(toggle_q xor toggle2x_q);
|
|
|
|
|
|
|
|
|
|
|
|
b0addra(2 to 8) <= wr_adr;
|
|
b0addrb(2 to 8) <= rd_adr;
|
|
|
|
b0addra(0 to 1) <= "00";
|
|
b0addrb(0 to 1) <= "00";
|
|
|
|
|
|
|
|
wren_a <= '1' when bw /= "0000000000000000" else '0';
|
|
wea <= wren_a and not(gate_fq);
|
|
web <= '0';
|
|
w_data_in_0(0) <= di(0) when bw(0)='1' else r_data_out_0_bram(0);
|
|
w_data_in_0(1) <= di(1) when bw(1)='1' else r_data_out_0_bram(1);
|
|
w_data_in_0(2) <= di(2) when bw(2)='1' else r_data_out_0_bram(2);
|
|
w_data_in_0(3) <= di(3) when bw(3)='1' else r_data_out_0_bram(3);
|
|
w_data_in_0(4) <= di(4) when bw(4)='1' else r_data_out_0_bram(4);
|
|
w_data_in_0(5) <= di(5) when bw(5)='1' else r_data_out_0_bram(5);
|
|
w_data_in_0(6) <= di(6) when bw(6)='1' else r_data_out_0_bram(6);
|
|
w_data_in_0(7) <= di(7) when bw(7)='1' else r_data_out_0_bram(7);
|
|
w_data_in_0(8) <= di(8) when bw(8)='1' else r_data_out_0_bram(8);
|
|
w_data_in_0(9) <= di(9) when bw(9)='1' else r_data_out_0_bram(9);
|
|
w_data_in_0(10) <= di(10) when bw(10)='1' else r_data_out_0_bram(10);
|
|
w_data_in_0(11) <= di(11) when bw(11)='1' else r_data_out_0_bram(11);
|
|
w_data_in_0(12) <= di(12) when bw(12)='1' else r_data_out_0_bram(12);
|
|
w_data_in_0(13) <= di(13) when bw(13)='1' else r_data_out_0_bram(13);
|
|
w_data_in_0(14) <= di(14) when bw(14)='1' else r_data_out_0_bram(14);
|
|
w_data_in_0(15) <= di(15) when bw(15)='1' else r_data_out_0_bram(15);
|
|
w_data_in_0(16 to 35) <= (others => '0');
|
|
|
|
r_data_out_1_d <= std_ulogic_vector(r_data_out_1_bram);
|
|
|
|
bram0a : ramb16_s36_s36
|
|
-- pragma translate_off
|
|
generic map(
|
|
sim_collision_check => "none")
|
|
-- pragma translate_on
|
|
port map(
|
|
clka => clk2x,
|
|
clkb => clk2x,
|
|
ssra => reset_q,
|
|
ssrb => reset_q,
|
|
addra => std_logic_vector(b0addra),
|
|
addrb => std_logic_vector(b0addrb),
|
|
dia => std_logic_vector(w_data_in_0(0 to 31)),
|
|
dib => (others => '0'),
|
|
doa => r_data_out_0_bram(0 to 31),
|
|
dob => r_data_out_1_bram(0 to 31),
|
|
dopa => r_data_out_0_bram(32 to 35),
|
|
dopb => r_data_out_1_bram(32 to 35),
|
|
dipa => std_logic_vector(w_data_in_0(32 to 35)),
|
|
dipb => (others => '0'),
|
|
ena => '1',
|
|
enb => '1',
|
|
wea => wea,
|
|
web => web
|
|
);
|
|
|
|
|
|
do <= r_data_out_1_fq(0 to 15);
|
|
|
|
func_scan_out <= func_scan_in;
|
|
time_scan_out <= time_scan_in;
|
|
abst_scan_out <= abst_scan_in;
|
|
repr_scan_out <= repr_scan_in;
|
|
|
|
bo_pc_failout <= '0';
|
|
bo_pc_diagloop <= '0';
|
|
|
|
unused <= or_reduce( std_ulogic_vector(r_data_out_0_bram(16 to 35)) & rd_act & wr_act
|
|
& lcb_d_mode_dc & lcb_clkoff_dc_b & lcb_mpw1_dc_b & lcb_mpw2_dc_b
|
|
& lcb_delay_lclkr_dc & ccflush_dc & scan_dis_dc_b & scan_diag_dc
|
|
& lcb_sg_0 & lcb_sl_thold_0_b & lcb_time_sl_thold_0 & lcb_abst_sl_thold_0
|
|
& lcb_ary_nsl_thold_0 & lcb_repr_sl_thold_0 & abist_di & abist_bw_odd
|
|
& abist_bw_even & abist_wr_adr & wr_abst_act & abist_rd0_adr & rd0_abst_act
|
|
& tc_lbist_ary_wrt_thru_dc & abist_ena_1 & abist_g8t_rd0_comp_ena
|
|
& abist_raw_dc_b & obs0_abist_cmp & lcb_bolt_sl_thold_0 & pc_bo_enable_2
|
|
& pc_bo_reset & pc_bo_unload & pc_bo_repair & pc_bo_shdata & pc_bo_select
|
|
& tri_lcb_mpw1_dc_b & tri_lcb_mpw2_dc_b & tri_lcb_delay_lclkr_dc
|
|
& tri_lcb_clkoff_dc_b & tri_lcb_act_dis_dc );
|
|
|
|
end generate a;
|
|
|
|
|
|
end architecture tri_128x16_1r1w_1;
|
|
|
|
|