library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

--tim_bits = (log(time)/log(2)) +1

entity onew is 
	generic(time_600:  integer:= 750; tim_bits_600: integer:= 10;  --600us
		time_90:   integer:=  84; tim_bits_90:  integer:=  7;  --67us
		time_10:   integer:=  12; tim_bits_10:  integer:=  4;  --10us
		time_60:   integer:= 100; tim_bits_60:  integer:=  7;  --80new--60us
		time_5:    integer:=   6;  tim_bits_5:  integer:=  3;  --5 us
                time_7:    integer:=   8;  tim_bits_7:  integer:=  4); --7 us
	port (
	clk, reset, etr, enw: in std_logic;
	add: in std_logic_vector(1 downto 0);
	grp: in std_logic_vector(4 downto 0);
	db_in: in std_logic_vector (7 downto 0);
	db_out: out std_logic_vector(7 downto 0);
--	r_reg_p, w_reg_p: out std_logic;
	tdio: inout std_logic
	);
end onew ;

architecture arch of onew is

signal w_reg, r_reg, c_reg: std_logic;
signal init, init_start, init_read: std_logic;
signal write, write_start: std_logic;
signal read, read_start, read_read: std_logic;
signal ck_slow, ck_slow_q: std_logic;
signal ckdiv: std_logic_vector(4 downto 0); --period 0.8 us
signal crc_reg: std_logic_vector(7 downto 0);
signal shift_crc, read_read_q: std_logic;

component owinit 
	generic(time_600:   integer:= 6; tim_bits_600:   integer:= 3;  --600us
		time_90:   integer:= 3; tim_bits_90:   integer:= 2);  --50us
	port (
	clk, ck_slow, start: in std_logic;
	init_p, read: out std_logic
	);
end component ;

component owwrite
          generic (time_10: integer:=10;  tim_bits_10: integer:=4;
                   time_60: integer:=60;  tim_bits_60: integer:=6);
	  port (
	  clk, ck_slow, start, w_reg: in std_logic;
	  write: out std_logic);
end component;

component owread
          generic (time_5: integer:=5;  tim_bits_5:  integer:=3;
                   time_7: integer:=7;  tim_bits_7:  integer:=3);
	  port (
	  clk, ck_slow, start: in std_logic;
	  read, read_read: out std_logic);
end component;

component owcrc
	  port (clk, input, shift, reset, enw: in std_logic;
	  db_in: in std_logic_vector (7 downto 0);
	  add: in std_logic_vector (1 downto 0);
	  grp: in std_logic_vector(4 downto 0);
	  crc_p: out std_logic_vector (7 downto 0) );
end component ;

component BUFG
      port (I : in STD_LOGIC; O : out std_logic);
end component;

begin

CK1: BUFG port map (I=>ck_slow_q, O=>ck_slow);
U1: owinit generic map(time_600, tim_bits_600, time_90, tim_bits_90)
	   port map(
	   clk=>clk, ck_slow=>ck_slow, start=>init_start, --: in std_logic;
	   init_p=>init, read=>init_read); --: out std_logic
U2: owwrite generic map(time_10, tim_bits_10, time_60, tim_bits_60)
	   port map(
	   clk=>clk, ck_slow=>ck_slow, start=>write_start, w_reg=>w_reg, --: in std_logic;
	   write=>write); --: out std_logic
U3: owread generic map(time_5, tim_bits_5, time_7, tim_bits_7)
	   port map(
	   clk=>clk, ck_slow=>ck_slow, start=>read_start, --: in std_logic;
	   read=>read, read_read=>read_read); --: out std_logic);
U4: owcrc  port map(
	  clk=>clk, input=>r_reg, shift=>shift_crc, reset=>init_read, enw=>enw, --: in std_logic;
	  db_in=>db_in, --: in std_logic_vector (7 downto 0);
	  add=>add, --: in std_logic_vector (1 downto 0);
	  grp=>grp, --: in std_logic_vector (4 downto 0);
	  crc_p=>crc_reg); --: out std_logic_vector (7 downto 0) );
tdio <= '0' when init='1' or 
                 write='1' or
                 read='1'
                 else 'Z';

db_out(0) <= w_reg when etr='0' and grp(4)='1' and add=0 else 'Z'; --16
db_out(0) <= r_reg when etr='0' and grp(4)='1' and add=1 else 'Z'; --17
db_out  <= crc_reg when etr='0' and grp(4)='1' and add=3 else (others=>'Z'); --19
--r_reg_p <= r_reg;
--w_reg_p <= w_reg;

--write register
process (clk, reset)
begin
	if reset='1' then
	  w_reg <= '0';
	elsif clk'event and clk='1' then
	  if enw='1' and grp(4)='1' and add=0 then --16
	    w_reg <= db_in(0);
	  end if;
	end if;
end process;

--control register
init_start  <= db_in(0) when enw='1' and grp(4)='1' and add=2 else '0'; --18
write_start <= db_in(1) when enw='1' and grp(4)='1' and add=2 else '0'; --18
read_start  <= db_in(2) when enw='1' and grp(4)='1' and add=2 else '0'; --18
	  
--read register
process (clk, reset)
begin
	if reset='1' then
	  r_reg <= '0';
	elsif clk'event and clk='1' then
	  if init_read='1' or read_read='1' then
	    r_reg <= tdio;
	  end if;
	end if;
end process;

--crc register
shift_crc <= read_read_q and not read_read;
process (clk, reset)
begin
	if reset='1' then
	  read_read_q <= '0';
	elsif clk'event and clk='1' then
	  read_read_q <= read_read;
	end if;
end process;

--slow clock
ck_slow_q <= ckdiv(ckdiv'high);
process (clk, reset)
begin
	if reset='1' then
	  ckdiv <= (others => '0');
	elsif clk'event and clk='1' then
	  ckdiv <= ckdiv + 1;
	end if;
end process;

end arch;
	
