---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 15:01:01 07/27/2011 -- Design Name: -- Module Name: I2C - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.std_logic_misc.all; use work.amc13_pack.all; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. library UNISIM; use UNISIM.VComponents.all; Library UNIMACRO; use UNIMACRO.vcomponents.all; entity I2C is Port ( clk : in STD_LOGIC; -- DRPclk 50MHz ipb_clk : in STD_LOGIC; reset : in STD_LOGIC; -- ns2500 : in STD_LOGIC; addr: in STD_LOGIC_VECTOR(31 downto 0); rdata : out STD_LOGIC_VECTOR(31 downto 0); CLK_rdy : out STD_LOGIC; CLK_SCL : out STD_LOGIC; CLK_SDA : inout STD_LOGIC; SFP_ABS : in STD_LOGIC_VECTOR(3 downto 0); SFP_LOS : in STD_LOGIC_VECTOR(2 downto 0); SFP_SCL : out STD_LOGIC_VECTOR(3 downto 0); SFP_SDA : inout STD_LOGIC_VECTOR(3 downto 0)); end I2C; architecture Behavioral of I2C is signal clk_div : std_logic_vector(7 downto 0) := (others => '0'); signal SFP_ABSq : std_logic_vector(7 downto 0) := (others =>'0'); signal SFP : std_logic_vector(1 downto 0) := (others =>'0'); signal SFP_DATA : std_logic_vector(3 downto 0) := (others =>'0'); signal we_SFP : std_logic := '0'; signal set_we_SFP : std_logic := '0'; type state is (Idle,Debouce,S,D,A,W,P); signal SM : state := Idle; signal t_SDA : std_logic_vector(3 downto 0) := (others => '1'); signal Si5338Cntr : std_logic_vector(7 downto 0) := (others => '1'); signal t_CLK_SDA : std_logic := '1'; signal t_CLK_SDA_q : std_logic := '1'; signal Si5338Done : std_logic := '0'; signal ce_CLK_rdy : std_logic := '0'; signal ACK : std_logic := '0'; signal done : std_logic := '0'; signal data : std_logic := '0'; signal SFPROM_data : std_logic := '0'; signal SCL_phase : std_logic_vector(1 downto 0) := (others => '0'); signal SM_cntr : std_logic_vector(10 downto 0) := (others => '0'); signal Debouce_cntr : std_logic_vector(17 downto 0) := (others => '0'); signal SFP_ADDR : std_logic_vector(9 downto 0) := (others => '0'); signal we_rdata : std_logic := '0'; --type RAM16384X1 is array(0 to 16383) of std_logic; --signal I2C_buf : RAM16384X1 := (others => '0'); signal rdata_ra : std_logic_vector(8 downto 0) := (others =>'1'); signal rdata_wa : std_logic_vector(13 downto 0) := (others =>'1'); signal DIBDI : std_logic_vector(0 downto 0) := (others =>'0'); signal resetSyncRegs : std_logic_vector(2 downto 0) := (others => '0'); begin CLK_SDA <= '0' when t_CLK_SDA_q = '0' else 'Z'; SFP_SDA(3) <= '0' when t_SDA(3) = '0' else 'Z'; SFP_SDA(2) <= '0' when t_SDA(2) = '0' else 'Z'; SFP_SDA(1) <= '0' when t_SDA(1) = '0' else 'Z'; SFP_SDA(0) <= '0' when t_SDA(0) = '0' else 'Z'; i_CLK_rdy : SRLC32E generic map ( INIT => X"00000000") port map ( Q => CLK_rdy, -- SRL data output Q31 => open, -- SRL cascade output pin A => "11111", -- 5-bit shift depth select input CE => ce_CLK_rdy, -- Clock enable input CLK => clk, -- Clock input D => Si5338Done -- SRL data input ); ce_CLK_rdy <= '1' when clk_div(7) = '1' and SCL_phase = "11" else '0'; process(clk,reset) begin if(reset = '1')then resetSyncRegs <= (others => '1'); elsif(clk'event and clk = '1')then resetSyncRegs <= resetSyncRegs(1 downto 0) & '0'; end if; end process; process(clk) begin if(clk'event and clk = '1')then if(resetSyncRegs(2) = '1' or clk_div(7) = '1')then -- 400 KHz clk_div <= x"04"; else clk_div <= clk_div + 1; end if; if(resetSyncRegs(2) = '1')then SCL_phase <= "00"; elsif(clk_div(7) = '1')then SCL_phase <= SCL_phase + 1; end if; if(resetSyncRegs(2) = '1')then SFP_ABSq <= (others => '1'); SM <= Idle; t_sda <= x"f"; elsif(clk_div(7) = '1' and SCL_phase = "11")then case SM is when Idle => SM_cntr <= "11111101000"; SFP_ABSq <= SFP_ABSq(3 downto 0) & SFP_ABS; if(SFP_ABSq(7 downto 4) /= SFP_ABSq(3 downto 0))then SM <= Debouce; end if; t_SDA <= x"f"; Debouce_cntr <= (others => '0'); when Debouce => SFP_ABSq <= SFP_ABSq(3 downto 0) & SFP_ABS; Debouce_cntr <= Debouce_cntr + 1; if(Debouce_cntr(17) = '1')then SM <= S; end if; when S => SM <= D; t_SDA <= SFP_ABSq(7 downto 4); when D => if(SM_cntr(2 downto 0) = "111")then SM <= A; end if; SM_cntr <= SM_cntr + 1; if(SM_cntr(10 downto 9) = "11" and data = '0')then t_SDA <= SFP_ABSq(7 downto 4); else t_SDA <= x"f"; end if; ACK <= not SM_cntr(10); when A => if(SM_cntr(10 downto 9) = "10" or (SM_cntr(10 downto 9) = "11" and SM_cntr(4 downto 3) = "11"))then SM <= W; else Sm <= D; end if; if(ACK = '1' and SM_cntr(10 downto 9) /= "10")then t_SDA <= SFP_ABSq(7 downto 4); else t_SDA <= x"f"; end if; when W => if(SM_cntr(10 downto 9) = "10")then SM <= P; else SM <= S; end if; when P => SM <= Idle; t_SDA <= SFP_ABSq(7 downto 4); when others => SM <= Idle; end case; end if; t_CLK_SDA_q <= t_CLK_SDA; if(resetSyncRegs(2) = '1')then Si5338Done <= '0'; elsif(clk_div(7) = '1' and SCL_phase(1) = '1' and Si5338Cntr = x"72")then Si5338Done <= '1'; end if; if(resetSyncRegs(2) = '1' or Si5338Done = '1')then CLK_SCL <= '1'; elsif(clk_div(7) = '1' and SCL_phase(0) = '1')then if(SCL_phase(1) = '0')then CLK_SCL <= '1'; elsif(Si5338Cntr /= x"e2" and Si5338Cntr /= x"8f")then CLK_SCL <= '0'; end if; end if; if(resetSyncRegs(2) = '1' or Si5338Done = '1')then Si5338Cntr <= (others => '1'); elsif(clk_div(7) = '1')then if(SCL_phase = "00")then Si5338Cntr <= Si5338Cntr - 1; end if; end if; rdata_wa(12 downto 0) <= '0' & not SFP & SFP_ADDR; we_rdata <= we_SFP; DIBDI(0) <= SFP_DATA(3); if(we_SFP = '0')then SFP <= "00"; SFP_DATA <= SFP_SDA and not SFP_ABSq(7 downto 4); else SFP(1) <= SFP(1) xor SFP(0); SFP(0) <= not SFP(0); SFP_DATA <= SFP_DATA(2 downto 0) & '0'; end if; if(SFPROM_data = '1' and SCL_phase = "01" and clk_div(7) = '1')then set_we_SFP <= '1'; else set_we_SFP <= '0'; end if; if(set_we_SFP = '1')then we_SFP <= '1'; elsif(SFP = "11")then we_SFP <= '0'; end if; if(clk_div(7) = '1')then if(SM = S or SM = Idle or SM = Debouce or SCL_phase(1) = '0')then SFP_SCL <= x"f"; else SFP_SCL <= SFP_ABSq(7 downto 4); end if; if(SCL_phase = "11")then SFP_ADDR <= SM_cntr(9 downto 3) & not SM_cntr(2 downto 0); if(SM = D and SM_cntr(10) = '0')then SFPROM_data <= '1'; else SFPROM_data <= '0'; end if; end if; end if; end if; end process; i_I2C_buf : BRAM_SDP_MACRO generic map ( BRAM_SIZE => "18Kb", -- Target BRAM, "18Kb" or "36Kb" DEVICE => "7SERIES", -- Target device: "VIRTEX5", "VIRTEX6", "7SERIES", "SPARTAN6" WRITE_WIDTH => 1, -- Valid values are 1-72 (37-72 only valid when BRAM_SIZE="36Kb") READ_WIDTH => 32, -- Valid values are 1-72 (37-72 only valid when BRAM_SIZE="36Kb") DO_REG => 0, -- Optional output register (0 or 1) SIM_COLLISION_CHECK => "NONE", -- Collision check enable "ALL", "WARNING_ONLY", -- "GENERATE_X_ONLY" or "NONE" WRITE_MODE => "WRITE_FIRST", -- Specify "READ_FIRST" for same clock or synchronous clocks -- Specify "WRITE_FIRST for asynchrononous clocks on ports INIT => X"000000000000000000") -- Initial values on output port port map ( DO => rdata, -- Output read data port, width defined by READ_WIDTH parameter DI => DIBDI, -- Input write data port, width defined by WRITE_WIDTH parameter RDADDR => rdata_ra, -- Input read address, width defined by read port depth RDCLK => ipb_clk, -- 1-bit input read clock RDEN => '1', -- 1-bit input read port enable REGCE => '1', -- 1-bit input read output register enable RST => '0', -- 1-bit input reset WE => "1", -- Input write enable, width defined by write port depth WRADDR => rdata_wa, -- Input write address, width defined by write port depth WRCLK => clk, -- 1-bit input write clock WREN => we_rdata -- 1-bit input write port enable ); --process(clk) --begin -- if(clk'event and clk = '1')then -- if(we_rdata = '1')then -- I2C_buf(conv_integer(rdata_wa)) <= DIBDI(0); -- end if; -- end if; --end process; --process(ipb_clk) --begin -- if(ipb_clk'event and ipb_clk = '1')then -- for i in 0 to 31 loop -- rdata(i) <= I2C_buf(conv_integer(rdata_ra & conv_std_logic_vector(i,5))); -- end loop; -- end if; --end process; rdata_wa(13) <= '1'; rdata_ra(7 downto 0) <= addr(7 downto 0); rdata_ra(8) <= '1' when addr(15 downto 8) = I2C_addr(15 downto 8) else '0'; i_data : ROM32X1 generic map ( INIT => X"85000500") port map ( O => data, -- ROM output A0 => SM_cntr(0), -- ROM address[0] A1 => SM_cntr(1), -- ROM address[1] A2 => SM_cntr(2), -- ROM address[2] A3 => SM_cntr(3), -- ROM address[3] A4 => SM_cntr(4) -- ROM address[4] ); i_Si5338ROM : ROM256X1 generic map ( -- INIT => X"b83cd08dc156a041201008040205b83cd0080000000000000000000000000000") INIT => X"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") port map ( O => t_CLK_SDA, -- ROM output A0 => Si5338Cntr(0), -- ROM address[0] A1 => Si5338Cntr(1), -- ROM address[1] A2 => Si5338Cntr(2), -- ROM address[2] A3 => Si5338Cntr(3), -- ROM address[3] A4 => Si5338Cntr(4), -- ROM address[4] A5 => Si5338Cntr(5), -- ROM address[5] A6 => Si5338Cntr(6), -- ROM address[6] A7 => Si5338Cntr(7) -- ROM address[7] ); end Behavioral;