--- /dev/null
+library IEEE;\r
+use IEEE.STD_LOGIC_1164.ALL;\r
+use IEEE.STD_LOGIC_ARITH.ALL;\r
+use IEEE.STD_LOGIC_UNSIGNED.ALL;\r
+\r
+entity i2c_gstart2 is\r
+port(\r
+ CLK_IN : in std_logic;\r
+ RESET_IN : in std_logic;\r
+ START_IN : in std_logic;\r
+ DOSTART_IN : in std_logic;\r
+ I2C_SPEED_IN : in std_logic_vector(8 downto 0);\r
+ SDONE_OUT : out std_logic;\r
+ SOK_OUT : out std_logic;\r
+ SDA_IN : in std_logic;\r
+ SCL_IN : in std_logic;\r
+ R_SCL_OUT : out std_logic;\r
+ S_SCL_OUT : out std_logic;\r
+ R_SDA_OUT : out std_logic;\r
+ S_SDA_OUT : out std_logic;\r
+ BSM_OUT : out std_logic_vector(3 downto 0)\r
+);\r
+end entity i2c_gstart2;\r
+\r
+architecture Behavioral of i2c_gstart2 is\r
+\r
+-- Signals\r
+type STATES is (SLEEP,P_SCL,WCTR0,P_SDA,WCTR1,P_CHK,S_CHK0,RS_SDA,S_CHK1,ERROR,DONE,WCTR2);\r
+signal CURRENT_STATE, NEXT_STATE: STATES;\r
+\r
+signal bsm : std_logic_vector(3 downto 0);\r
+signal cctr : std_logic_vector(8 downto 0); -- counter for bit length\r
+\r
+signal cycdone_x : std_logic;\r
+signal cycdone : std_logic; -- one counter period done\r
+\r
+signal load_cyc_x : std_logic;\r
+signal load_cyc : std_logic;\r
+signal dec_cyc_x : std_logic;\r
+signal dec_cyc : std_logic;\r
+signal sdone_x : std_logic;\r
+signal sdone : std_logic; -- Start/Stop done\r
+signal sok_x : std_logic;\r
+signal sok : std_logic; -- Start/Stop OK\r
+\r
+signal r_scl_x : std_logic;\r
+signal r_scl : std_logic;\r
+signal s_scl_x : std_logic;\r
+signal s_scl : std_logic;\r
+signal r_sda_x : std_logic;\r
+signal r_sda : std_logic;\r
+signal s_sda_x : std_logic;\r
+signal s_sda : std_logic;\r
+\r
+-- Moduls\r
+\r
+begin\r
+\r
+-- Countdown for one half of SCL (adjustable clock width)\r
+THE_CYC_CTR_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if( reset_in = '1' ) then\r
+ cctr <= (others => '0');\r
+ elsif( load_cyc = '1' ) then\r
+ cctr <= i2c_speed_in;\r
+ elsif( dec_cyc = '1' ) then\r
+ cctr <= cctr - 1;\r
+ end if;\r
+ end if;\r
+end process THE_CYC_CTR_PROC;\r
+\r
+-- end of cycle recognition\r
+cycdone_x <= '1' when (cctr = x"00") else '0';\r
+\r
+-- The main state machine\r
+-- State memory process\r
+STATE_MEM: process( clk_in )\r
+begin\r
+ if ( rising_edge(clk_in) ) then\r
+ if( reset_in = '1' ) then\r
+ CURRENT_STATE <= SLEEP;\r
+ load_cyc <= '0';\r
+ dec_cyc <= '0';\r
+ sdone <= '0';\r
+ sok <= '0';\r
+ cycdone <= '0';\r
+ r_scl <= '0';\r
+ s_scl <= '0';\r
+ r_sda <= '0';\r
+ s_sda <= '0';\r
+ else\r
+ CURRENT_STATE <= NEXT_STATE;\r
+ load_cyc <= load_cyc_x;\r
+ dec_cyc <= dec_cyc_x;\r
+ sdone <= sdone_x;\r
+ sok <= sok_x;\r
+ cycdone <= cycdone_x;\r
+ r_scl <= r_scl_x;\r
+ s_scl <= s_scl_x;\r
+ r_sda <= r_sda_x;\r
+ s_sda <= s_sda_x;\r
+ end if;\r
+ end if;\r
+end process STATE_MEM;\r
+\r
+-- Transition matrix\r
+TRANSFORM: process(CURRENT_STATE, dostart_in, start_in, sda_in, scl_in, cycdone)\r
+begin\r
+ NEXT_STATE <= SLEEP;\r
+ load_cyc_x <= '0';\r
+ dec_cyc_x <= '0';\r
+ sdone_x <= '0';\r
+ sok_x <= '1';\r
+ r_sda_x <= '0';\r
+ s_sda_x <= '0';\r
+ r_scl_x <= '0';\r
+ s_scl_x <= '0';\r
+ case CURRENT_STATE is\r
+ when SLEEP => \r
+ if ( (dostart_in = '1') and (start_in = '1') ) then\r
+ NEXT_STATE <= S_CHK0; -- generate a start condition\r
+ load_cyc_x <= '1';\r
+ elsif( (dostart_in = '1') and (start_in = '0') ) then\r
+ NEXT_STATE <= WCTR2; -- generate a stop condition\r
+ load_cyc_x <= '1';\r
+ else\r
+ NEXT_STATE <= SLEEP;\r
+-- load_cyc_x <= '1';\r
+ end if;\r
+ when WCTR2 =>\r
+ if( (cycdone = '1') ) then\r
+ NEXT_STATE <= P_SCL;\r
+ load_cyc_x <= '1';\r
+ s_scl_x <= '1';\r
+ else\r
+ NEXT_STATE <= WCTR2;\r
+ dec_cyc_x <= '1';\r
+ end if;\r
+ when P_SCL => \r
+ NEXT_STATE <= WCTR0;\r
+ dec_cyc_x <= '1';\r
+ when S_CHK0 =>\r
+ if( (sda_in = '1') and (scl_in = '1') ) then\r
+ NEXT_STATE <= RS_SDA;\r
+ r_sda_x <= '1';\r
+ else\r
+ NEXT_STATE <= ERROR;\r
+ sok_x <= '0';\r
+ end if;\r
+ when RS_SDA =>\r
+ NEXT_STATE <= WCTR0;\r
+ dec_cyc_x <= '1';\r
+ when WCTR0 =>\r
+ if ( (cycdone = '1') and (start_in = '1') ) then\r
+ NEXT_STATE <= S_CHK1;\r
+ elsif( (cycdone = '1') and (start_in = '0') ) then\r
+ NEXT_STATE <= P_SDA;\r
+ load_cyc_x <= '1';\r
+ s_sda_x <= '1';\r
+ else\r
+ NEXT_STATE <= WCTR0;\r
+ dec_cyc_x <= '1';\r
+ end if;\r
+ when S_CHK1 =>\r
+ if( (sda_in = '0') and (scl_in = '1') ) then\r
+ NEXT_STATE <= DONE;\r
+ else\r
+ NEXT_STATE <= ERROR;\r
+ sok_x <= '0';\r
+ end if;\r
+ when P_SDA =>\r
+ NEXT_STATE <= WCTR1;\r
+ dec_cyc_x <= '1';\r
+ when WCTR1 =>\r
+ if( (cycdone = '1') ) then\r
+ NEXT_STATE <= P_CHK;\r
+ else\r
+ NEXT_STATE <= WCTR1;\r
+ dec_cyc_x <= '1';\r
+ end if;\r
+ when P_CHK =>\r
+ if( (sda_in = '1') and (scl_in = '1') ) then\r
+ NEXT_STATE <= DONE;\r
+ sdone_x <= '1';\r
+ else\r
+ NEXT_STATE <= ERROR;\r
+ sok_x <= '0';\r
+ end if;\r
+ when ERROR =>\r
+ if( dostart_in = '0' ) then\r
+ NEXT_STATE <= SLEEP;\r
+ else\r
+ NEXT_STATE <= ERROR;\r
+ sdone_x <= '1';\r
+ sok_x <= '0';\r
+ end if;\r
+ when DONE =>\r
+ if( dostart_in = '0' ) then\r
+ NEXT_STATE <= SLEEP;\r
+ else\r
+ NEXT_STATE <= DONE;\r
+ sdone_x <= '1';\r
+ end if;\r
+ when others =>\r
+ NEXT_STATE <= SLEEP;\r
+ end case;\r
+end process TRANSFORM;\r
+\r
+-- Output decoding\r
+DECODE: process(CURRENT_STATE)\r
+begin\r
+ case CURRENT_STATE is\r
+ when SLEEP => bsm <= x"0";\r
+ when S_CHK0 => bsm <= x"1";\r
+ when RS_SDA => bsm <= x"2";\r
+ when P_SCL => bsm <= x"3";\r
+ when WCTR0 => bsm <= x"4";\r
+ when S_CHK1 => bsm <= x"5";\r
+ when P_SDA => bsm <= x"6";\r
+ when WCTR1 => bsm <= x"7";\r
+ when P_CHK => bsm <= x"8";\r
+ when DONE => bsm <= x"9";\r
+ when WCTR2 => bsm <= x"a";\r
+ when ERROR => bsm <= x"e";\r
+ when others => bsm <= x"f";\r
+ end case;\r
+end process DECODE;\r
+\r
+-- Outputs\r
+r_scl_out <= r_scl;\r
+s_scl_out <= s_scl;\r
+r_sda_out <= r_sda;\r
+s_sda_out <= s_sda;\r
+sdone_out <= sdone;\r
+sok_out <= sok;\r
+\r
+-- Debug\r
+bsm_out <= bsm;\r
+\r
+end Behavioral;\r
--- /dev/null
+library IEEE;\r
+use IEEE.STD_LOGIC_1164.ALL;\r
+use IEEE.STD_LOGIC_ARITH.ALL;\r
+use IEEE.STD_LOGIC_UNSIGNED.ALL;\r
+\r
+entity i2c_sendb2 is\r
+port(\r
+ CLK_IN : in std_logic;\r
+ RESET_IN : in std_logic;\r
+ DOBYTE_IN : in std_logic;\r
+ I2C_SPEED_IN : in std_logic_vector(8 downto 0);\r
+ I2C_BYTE_IN : in std_logic_vector(8 downto 0);\r
+ I2C_BACK_OUT : out std_logic_vector(8 downto 0);\r
+ SDA_IN : in std_logic;\r
+ R_SDA_OUT : out std_logic;\r
+ S_SDA_OUT : out std_logic;\r
+-- SCL_IN : in std_logic;\r
+ R_SCL_OUT : out std_logic;\r
+ S_SCL_OUT : out std_logic;\r
+ BDONE_OUT : out std_logic;\r
+ BOK_OUT : out std_logic;\r
+ BSM_OUT : out std_logic_vector(3 downto 0)\r
+);\r
+end entity;\r
+\r
+architecture Behavioral of i2c_sendb2 is\r
+\r
+-- Signals\r
+type STATES is (SLEEP,LCL,WCL,LCH,WCH,FREE,DONE);\r
+signal CURRENT_STATE, NEXT_STATE: STATES;\r
+\r
+signal bsm : std_logic_vector( 3 downto 0 );\r
+\r
+signal inc_bit_x : std_logic;\r
+signal inc_bit : std_logic; -- increment bit counter for byte to send\r
+signal rst_bit_x : std_logic;\r
+signal rst_bit : std_logic; -- reset bit counter for byte to send\r
+signal load_cyc_x : std_logic;\r
+signal load_cyc : std_logic; -- load cycle counter (SCL length)\r
+signal dec_cyc_x : std_logic;\r
+signal dec_cyc : std_logic; -- decrement cycle counter (SCL length)\r
+signal load_sr_x : std_logic;\r
+signal load_sr : std_logic; -- load output shift register\r
+signal shift_o_x : std_logic;\r
+signal shift_o : std_logic; -- output shift register control\r
+signal shift_i_x : std_logic;\r
+signal shift_i : std_logic; -- input shift register control\r
+signal bdone_x : std_logic;\r
+signal bdone : std_logic;\r
+signal r_scl_x : std_logic;\r
+signal r_scl : std_logic; -- output for SCL\r
+signal s_scl_x : std_logic;\r
+signal s_scl : std_logic; -- output for SCL\r
+\r
+signal bctr : std_logic_vector(3 downto 0); -- bit counter (1...9)\r
+signal cctr : std_logic_vector(8 downto 0); -- counter for bit length\r
+signal bok : std_logic;\r
+signal cycdone : std_logic; -- one counter period done\r
+signal bytedone : std_logic; -- all bits sents\r
+signal in_sr : std_logic_vector(8 downto 0); -- shift register for byte in\r
+signal out_sr : std_logic_vector(8 downto 0); -- shift register for byte out\r
+signal i2c_back : std_logic_vector(8 downto 0); -- shift register for byte in\r
+signal r_sda : std_logic; -- output for SDA\r
+signal s_sda : std_logic; -- output for SDA\r
+signal load : std_logic; -- delay register\r
+signal i2c_d : std_logic; -- auxiliary register\r
+\r
+-- Moduls\r
+\r
+begin\r
+\r
+-- Bit counter (for byte to send)\r
+THE_BIT_CTR_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if( reset_in = '1' ) then\r
+ bctr <= (others => '0');\r
+ elsif( rst_bit = '1' ) then\r
+ bctr <= (others => '0');\r
+ elsif( inc_bit = '1' ) then\r
+ bctr <= bctr + 1;\r
+ end if;\r
+ end if;\r
+end process THE_BIT_CTR_PROC;\r
+\r
+-- end of byte recognition\r
+bytedone <= '1' when (bctr = x"9") else '0';\r
+\r
+-- Countdown for one half of SCL (adjustable clock width)\r
+THE_CYC_CTR_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if( reset_in = '1' ) then\r
+ cctr <= (others => '0');\r
+ elsif( load_cyc = '1' ) then\r
+ cctr <= i2c_speed_in;\r
+ elsif( dec_cyc = '1' ) then\r
+ cctr <= cctr - 1;\r
+ end if;\r
+ end if;\r
+end process THE_CYC_CTR_PROC;\r
+\r
+-- end of cycle recognition\r
+cycdone <= '1' when (cctr = x"00") else '0';\r
+\r
+-- Bit output\r
+THE_BIT_OUT_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if( reset_in = '1' ) then\r
+ out_sr <= (others => '0');\r
+ i2c_d <= '1';\r
+ elsif( load_sr = '1' ) then\r
+ out_sr <= i2c_byte_in;\r
+ i2c_d <= '1';\r
+ elsif( shift_o = '1' ) then\r
+ i2c_d <= out_sr(8);\r
+ out_sr(8 downto 0) <= out_sr(7 downto 0) & '0';\r
+ end if;\r
+ end if;\r
+end process THE_BIT_OUT_PROC;\r
+\r
+-- Bit input\r
+THE_BIT_IN_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if ( reset_in = '1' ) then\r
+ in_sr <= (others => '1');\r
+ elsif( shift_o = '1' ) then\r
+ in_sr(8 downto 1) <= in_sr(7 downto 0);\r
+ in_sr(0) <= sda_in;\r
+ end if;\r
+ end if;\r
+end process THE_BIT_IN_PROC;\r
+\r
+-- Output register for readback data (could be reduced to SR_IN_INT)\r
+THE_I2C_BACK_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if( reset_in = '1' ) then\r
+ i2c_back <= (others => '1');\r
+ elsif( shift_i = '1' ) then\r
+ i2c_back(8 downto 1) <= in_sr(7 downto 0);\r
+ i2c_back(0) <= sda_in;\r
+ end if;\r
+ end if;\r
+end process THE_I2C_BACK_PROC;\r
+\r
+-- ByteOK is the inverted ACK bit from readback data.\r
+bok <= not i2c_back(0); -- BUG\r
+\r
+-- The main state machine\r
+-- State memory process\r
+STATE_MEM: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if( reset_in = '1') then\r
+ CURRENT_STATE <= SLEEP;\r
+ inc_bit <= '0';\r
+ rst_bit <= '0';\r
+ load_cyc <= '0';\r
+ dec_cyc <= '0';\r
+ load_sr <= '0';\r
+ shift_o <= '0';\r
+ shift_i <= '0';\r
+ bdone <= '0';\r
+ r_scl <= '0';\r
+ s_scl <= '0';\r
+ else\r
+ CURRENT_STATE <= NEXT_STATE;\r
+ inc_bit <= inc_bit_x;\r
+ rst_bit <= rst_bit_x;\r
+ load_cyc <= load_cyc_x;\r
+ dec_cyc <= dec_cyc_x;\r
+ load_sr <= load_sr_x;\r
+ shift_o <= shift_o_x;\r
+ shift_i <= shift_i_x;\r
+ bdone <= bdone_x;\r
+ r_scl <= r_scl_x;\r
+ s_scl <= s_scl_x;\r
+ end if;\r
+ end if;\r
+end process STATE_MEM;\r
+\r
+-- Transition matrix\r
+TRANSFORM: process(CURRENT_STATE, dobyte_in, cycdone, bytedone)\r
+begin\r
+ NEXT_STATE <= SLEEP;\r
+ inc_bit_x <= '0';\r
+ rst_bit_x <= '0';\r
+ load_cyc_x <= '0';\r
+ dec_cyc_x <= '0';\r
+ load_sr_x <= '0';\r
+ shift_o_x <= '0';\r
+ shift_i_x <= '0';\r
+ bdone_x <= '0';\r
+ r_scl_x <= '0';\r
+ s_scl_x <= '0';\r
+ case CURRENT_STATE is\r
+ when SLEEP => if( dobyte_in = '1' ) then\r
+ NEXT_STATE <= LCL;\r
+ inc_bit_x <= '1';\r
+ load_cyc_x <= '1';\r
+ shift_o_x <= '1';\r
+ r_scl_x <= '1';\r
+ else\r
+ NEXT_STATE <= SLEEP;\r
+ load_sr_x <= '1';\r
+ end if;\r
+ when LCL => NEXT_STATE <= WCL;\r
+ dec_cyc_x <= '1';\r
+ when WCL => if( cycdone = '1' ) then\r
+ NEXT_STATE <= LCH;\r
+ load_cyc_x <= '1';\r
+ s_scl_x <= '1';\r
+ else\r
+ NEXT_STATE <= WCL;\r
+ dec_cyc_x <= '1';\r
+ end if;\r
+ when LCH => NEXT_STATE <= WCH;\r
+ dec_cyc_x <= '1';\r
+ when WCH => if ( (cycdone = '1') and (bytedone = '0') ) then\r
+ NEXT_STATE <= LCL;\r
+ inc_bit_x <= '1';\r
+ load_cyc_x <= '1';\r
+ shift_o_x <= '1';\r
+ r_scl_x <= '1';\r
+ elsif( (cycdone = '1') and (bytedone = '1') ) then\r
+ NEXT_STATE <= FREE;\r
+ shift_o_x <= '1';\r
+ shift_i_x <= '1';\r
+ r_scl_x <= '1';\r
+ else\r
+ NEXT_STATE <= WCH;\r
+ dec_cyc_x <= '1';\r
+ end if;\r
+ when FREE => NEXT_STATE <= DONE;\r
+ rst_bit_x <= '1';\r
+ bdone_x <= '1';\r
+ when DONE => if( dobyte_in = '0' ) then\r
+ NEXT_STATE <= SLEEP;\r
+ else\r
+ NEXT_STATE <= DONE;\r
+ rst_bit_x <= '1';\r
+ bdone_x <= '1';\r
+ end if;\r
+ -- Just in case...\r
+ when others => NEXT_STATE <= SLEEP;\r
+ end case;\r
+end process TRANSFORM;\r
+\r
+-- Output decoding\r
+DECODE: process(CURRENT_STATE)\r
+begin\r
+ case CURRENT_STATE is\r
+ when SLEEP => bsm <= x"0";\r
+ when LCL => bsm <= x"1";\r
+ when WCL => bsm <= x"2";\r
+ when LCH => bsm <= x"3";\r
+ when WCH => bsm <= x"4";\r
+ when FREE => bsm <= x"5";\r
+ when DONE => bsm <= x"6";\r
+ when others => bsm <= x"f";\r
+ end case;\r
+end process DECODE;\r
+\r
+-- SCL and SDA output pulses\r
+THE_SDA_OUT_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if( reset_in = '1' ) then\r
+ load <= '0'; -- was a bug, found 081008\r
+ r_sda <= '0';\r
+ s_sda <= '0';\r
+ else\r
+ load <= shift_o;\r
+ r_sda <= load and not i2c_d;\r
+ s_sda <= load and i2c_d;\r
+ end if;\r
+ end if;\r
+end process THE_SDA_OUT_PROC;\r
+\r
+-- Outputs\r
+r_scl_out <= r_scl;\r
+s_scl_out <= s_scl;\r
+r_sda_out <= r_sda;\r
+s_sda_out <= s_sda;\r
+\r
+i2c_back_out <= i2c_back;\r
+\r
+bdone_out <= bdone;\r
+bok_out <= bok;\r
+\r
+-- Debugging\r
+bsm_out <= bsm;\r
+\r
+end Behavioral;\r
--- /dev/null
+library IEEE;\r
+use IEEE.STD_LOGIC_1164.ALL;\r
+use IEEE.STD_LOGIC_ARITH.ALL;\r
+use IEEE.STD_LOGIC_UNSIGNED.ALL;\r
+\r
+entity i2c_slim2 is\r
+port(\r
+ CLOCK : in std_logic;\r
+ RESET : in std_logic;\r
+ -- I2C command / setup\r
+ I2C_GO_IN : in std_logic; -- startbit to trigger I2C actions\r
+ ACTION_IN : in std_logic; -- '0' -> write, '1' -> read\r
+ WORD_IN : in std_logic; -- '0' -> byte, '1' -> word\r
+ I2C_SPEED_IN : in std_logic_vector(5 downto 0); -- speed adjustment (to be defined)\r
+ I2C_ADDR_IN : in std_logic_vector(7 downto 0); -- I2C address byte (R/W bit is ignored)\r
+ I2C_CMD_IN : in std_logic_vector(7 downto 0); -- I2C command byte (sent after address byte)\r
+ I2C_DW_IN : in std_logic_vector(15 downto 0); -- data word for write command\r
+ I2C_DR_OUT : out std_logic_vector(15 downto 0); -- data word from read command\r
+ STATUS_OUT : out std_logic_vector(7 downto 0); -- status and error bits\r
+ VALID_OUT : out std_logic;\r
+ I2C_BUSY_OUT : out std_logic;\r
+ I2C_DONE_OUT : out std_logic;\r
+ -- I2C connections\r
+ SDA_IN : in std_logic; \r
+ SDA_OUT : out std_logic;\r
+ SCL_IN : in std_logic;\r
+ SCL_OUT : out std_logic;\r
+ -- Debug\r
+ BSM_OUT : out std_logic_vector(4 downto 0)\r
+);\r
+end entity i2c_slim2;\r
+\r
+architecture Behavioral of i2c_slim2 is\r
+\r
+-- Signals\r
+type STATES is (SLEEP, LOADA, GSTART, SENDA, LOADC, SENDC, LOADD, SENDD, \r
+ GSTOP, INC, DONE, FAILED, LOADD2, SENDD2);\r
+signal CURRENT_STATE, NEXT_STATE: STATES;\r
+\r
+signal bsm : std_logic_vector( 4 downto 0 );\r
+signal phase : std_logic; -- '0' => first phase, '1' => second phase of read cycle\r
+\r
+signal start_x : std_logic;\r
+signal start : std_logic; -- '0' => generate STOP, '1' => generate START\r
+signal dostart_x : std_logic;\r
+signal dostart : std_logic; -- trigger the GenStart module\r
+signal dobyte_x : std_logic;\r
+signal dobyte : std_logic; -- trigger the ByteSend module\r
+signal i2c_done_x : std_logic;\r
+signal i2c_done : std_logic; -- acknowledge signal to the outside world\r
+signal running_x : std_logic;\r
+signal running : std_logic; -- legacy\r
+signal valid_x : std_logic; \r
+signal valid : std_logic;\r
+\r
+signal load_dh_x : std_logic;\r
+signal load_dh : std_logic;\r
+signal load_dl_x : std_logic;\r
+signal load_dl : std_logic;\r
+\r
+signal sdone : std_logic; -- acknowledge signal from GenStart module\r
+signal sok : std_logic; -- status signal from GenStart module\r
+signal bdone : std_logic; -- acknowledge signal from SendByte module\r
+signal bok : std_logic; -- status signal from SendByte module\r
+signal i2c_byte : std_logic_vector(8 downto 0);\r
+signal i2c_dr : std_logic_vector(8 downto 0);\r
+\r
+signal i2c_drw : std_logic_vector(15 downto 0);\r
+\r
+signal s_scl : std_logic;\r
+signal r_scl : std_logic;\r
+signal s_sda : std_logic;\r
+signal r_sda : std_logic;\r
+signal r_scl_gs : std_logic;\r
+signal s_scl_gs : std_logic;\r
+signal r_sda_gs : std_logic;\r
+signal s_sda_gs : std_logic;\r
+signal r_scl_sb : std_logic;\r
+signal s_scl_sb : std_logic;\r
+signal r_sda_sb : std_logic;\r
+signal s_sda_sb : std_logic;\r
+\r
+signal scl_q : std_logic_vector(2 downto 0);\r
+signal sda_q : std_logic_vector(2 downto 0);\r
+\r
+signal i2c_speed : std_logic_vector(8 downto 0);\r
+\r
+signal error_bits : std_logic_vector(7 downto 0);\r
+\r
+-- Components\r
+component i2c_gstart2 is\r
+port( \r
+ CLK_IN : in std_logic;\r
+ RESET_IN : in std_logic;\r
+ START_IN : in std_logic;\r
+ DOSTART_IN : in std_logic;\r
+ I2C_SPEED_IN : in std_logic_vector(8 downto 0);\r
+ SDONE_OUT : out std_logic;\r
+ SOK_OUT : out std_logic;\r
+ SDA_IN : in std_logic;\r
+ SCL_IN : in std_logic;\r
+ R_SCL_OUT : out std_logic;\r
+ S_SCL_OUT : out std_logic;\r
+ R_SDA_OUT : out std_logic;\r
+ S_SDA_OUT : out std_logic;\r
+ BSM_OUT : out std_logic_vector(3 downto 0)\r
+);\r
+end component i2c_gstart2;\r
+\r
+component i2c_sendb2 is\r
+port( \r
+ CLK_IN : in std_logic;\r
+ RESET_IN : in std_logic;\r
+ DOBYTE_IN : in std_logic;\r
+ I2C_SPEED_IN : in std_logic_vector(8 downto 0);\r
+ I2C_BYTE_IN : in std_logic_vector(8 downto 0);\r
+ I2C_BACK_OUT : out std_logic_vector(8 downto 0);\r
+ SDA_IN : in std_logic;\r
+ R_SDA_OUT : out std_logic;\r
+ S_SDA_OUT : out std_logic;\r
+-- SCL_IN : in std_logic;\r
+ R_SCL_OUT : out std_logic;\r
+ S_SCL_OUT : out std_logic;\r
+ BDONE_OUT : out std_logic;\r
+ BOK_OUT : out std_logic;\r
+ BSM_OUT : out std_logic_vector(3 downto 0)\r
+);\r
+end component i2c_sendb2;\r
+\r
+begin\r
+\r
+THE_SYNC_PROC: process( CLOCK )\r
+begin\r
+ if( rising_edge(CLOCK) ) then\r
+ sda_q(2 downto 0) <= sda_q(1 downto 0) & SDA_IN;\r
+ scl_q(2 downto 0) <= scl_q(1 downto 0) & SCL_IN; \r
+ end if;\r
+end process THE_SYNC_PROC;\r
+\r
+-- lower limit of speed\r
+i2c_speed <= i2c_speed_in & "000";\r
+\r
+-- Read phase indicator\r
+THE_PHASE_PROC: process( CLOCK )\r
+begin\r
+ if( rising_edge(CLOCK) ) then\r
+ if( RESET = '1' ) then\r
+ phase <= '0';\r
+ elsif( CURRENT_STATE = INC ) then\r
+ phase <= '1';\r
+ elsif( (CURRENT_STATE = DONE) or (CURRENT_STATE = SLEEP) ) then\r
+ phase <= '0';\r
+ end if;\r
+ end if;\r
+end process THE_PHASE_PROC;\r
+\r
+-- The main state machine\r
+-- State memory process\r
+STATE_MEM: process( CLOCK )\r
+begin\r
+ if( rising_edge(CLOCK) ) then\r
+ if( RESET = '1' ) then\r
+ CURRENT_STATE <= SLEEP;\r
+ start <= '0';\r
+ dostart <= '0';\r
+ dobyte <= '0';\r
+ i2c_done <= '0';\r
+ running <= '0';\r
+ load_dh <= '0';\r
+ load_dl <= '0';\r
+ valid <= '0';\r
+ else\r
+ CURRENT_STATE <= NEXT_STATE;\r
+ start <= start_x;\r
+ dostart <= dostart_x;\r
+ dobyte <= dobyte_x;\r
+ i2c_done <= i2c_done_x;\r
+ running <= running_x;\r
+ load_dh <= load_dh_x;\r
+ load_dl <= load_dl_x;\r
+ valid <= valid_x;\r
+ end if;\r
+ end if;\r
+end process STATE_MEM;\r
+\r
+-- Transition matrix\r
+TRANSFORM: process(CURRENT_STATE, i2c_go_in, sdone, sok, phase, bdone, bok, action_in, word_in)\r
+begin\r
+ NEXT_STATE <= SLEEP;\r
+ start_x <= '0';\r
+ dostart_x <= '0';\r
+ dobyte_x <= '0';\r
+ i2c_done_x <= '0';\r
+ running_x <= '1';\r
+ load_dh_x <= '0';\r
+ load_dl_x <= '0';\r
+ valid_x <= '0';\r
+ case CURRENT_STATE is\r
+ when SLEEP => \r
+ if( i2c_go_in = '1' ) then\r
+ NEXT_STATE <= LOADA;\r
+ error_bits <= x"00";\r
+ else\r
+ NEXT_STATE <= SLEEP;\r
+ running_x <= '0';\r
+ end if;\r
+ when LOADA => \r
+ NEXT_STATE <= GSTART;\r
+ start_x <= '1';\r
+ dostart_x <= '1';\r
+ when GSTART => \r
+ if ( (sdone = '1') and (sok = '1') ) then\r
+ NEXT_STATE <= SENDA; -- generating START did succeed\r
+ dobyte_x <= '1';\r
+ elsif( (sdone = '1') and (sok = '0') and (phase = '0') ) then\r
+ NEXT_STATE <= FAILED; -- first START condition failed\r
+ error_bits <= x"80";\r
+ dostart_x <= '1';\r
+ elsif( (sdone = '1') and (sok = '0') and (phase = '1') ) then\r
+ NEXT_STATE <= FAILED; -- second START condition failed\r
+ error_bits <= x"40";\r
+ dostart_x <= '1';\r
+ else\r
+ NEXT_STATE <= GSTART; -- wait for START generation ending\r
+ start_x <= '1';\r
+ dostart_x <= '1';\r
+ end if;\r
+ when SENDA => \r
+ if ( (bdone = '1') and (bok = '1') and (action_in = '0') ) then\r
+ NEXT_STATE <= LOADC; -- I2C write, send command\r
+ elsif( (bdone = '1') and (bok = '1') and (action_in = '1') and (phase = '0') ) then\r
+ NEXT_STATE <= LOADC; -- I2C read, send command\r
+ elsif( (bdone = '1') and (bok = '1') and (action_in = '1') and (phase = '1') ) then\r
+ NEXT_STATE <= LOADD; -- I2C read, send 0xff dummy byte\r
+ elsif( (bdone = '1') and (bok = '0') and (phase = '0') ) then\r
+ NEXT_STATE <= FAILED; -- first address phase failed\r
+ error_bits <= x"20";\r
+ dostart_x <= '1';\r
+ elsif( (bdone = '1') and (bok = '0') and (phase = '1') ) then\r
+ NEXT_STATE <= FAILED; -- second address phase failed\r
+ error_bits <= x"10";\r
+ dostart_x <= '1';\r
+ else\r
+ NEXT_STATE <= SENDA; -- wait for send address ending\r
+ dobyte_x <= '1';\r
+ end if;\r
+ when LOADC => \r
+ NEXT_STATE <= SENDC;\r
+ when SENDC => \r
+ if ( (bdone = '1') and (bok = '1') and (action_in = '0') and (word_in = '0') ) then\r
+ NEXT_STATE <= LOADD2; -- I2C byte write, prepare data\r
+ elsif( (bdone = '1') and (bok = '1') and (action_in = '0') and (word_in = '1') ) then\r
+ NEXT_STATE <= LOADD; -- I2C word write, prepare data\r
+ elsif( (bdone = '1') and (bok = '1') and (action_in = '1') ) then\r
+ NEXT_STATE <= GSTOP; -- I2C read, first phase ends\r
+ dostart_x <= '1';\r
+ elsif( (bdone = '1') and (bok = '0') ) then\r
+ NEXT_STATE <= FAILED; -- command phase failed\r
+ error_bits <= x"08";\r
+ dostart_x <= '1';\r
+ else\r
+ NEXT_STATE <= SENDC; -- wait for send command ending\r
+ dobyte_x <= '1';\r
+ end if;\r
+ when LOADD => \r
+ NEXT_STATE <= SENDD;\r
+ when SENDD => \r
+ if ( (bdone = '1') and (bok = '1') and (action_in = '0') and (word_in = '0') ) then\r
+ NEXT_STATE <= GSTOP; -- I2C write, byte access, done\r
+ dostart_x <= '1';\r
+ elsif( (bdone = '1') and (bok = '1') and (action_in = '0') and (word_in = '1') ) then\r
+ NEXT_STATE <= LOADD2; -- I2C write, word access, last byte to send\r
+ elsif( (bdone = '1') and (action_in = '1') and (word_in = '0') ) then\r
+ NEXT_STATE <= GSTOP; -- I2C read, byte access, data phase\r
+ dostart_x <= '1';\r
+ load_dl_x <= '1';\r
+ elsif( (bdone = '1') and (action_in = '1') and (word_in = '1') ) then\r
+ NEXT_STATE <= LOADD2; -- I2C read, word access, last byte to receive\r
+ load_dh_x <= '1';\r
+ elsif( (bdone = '1') and (bok = '0') and (action_in = '0') ) then\r
+ NEXT_STATE <= FAILED; -- I2C write, first data phase failed\r
+ error_bits <= x"04";\r
+ dostart_x <= '1';\r
+ else\r
+ NEXT_STATE <= SENDD; -- wait for send data ending\r
+ dobyte_x <= '1';\r
+ end if;\r
+ when LOADD2 => \r
+ NEXT_STATE <= SENDD2;\r
+ when SENDD2 => \r
+ if ( (bdone = '1') and (bok = '1') and (action_in = '0') ) then\r
+ NEXT_STATE <= GSTOP; -- I2C write, done\r
+ dostart_x <= '1';\r
+ elsif( (bdone = '1') and (action_in = '1') ) then\r
+ NEXT_STATE <= GSTOP; -- I2C read, data phase\r
+ dostart_x <= '1';\r
+ load_dl_x <= '1';\r
+ elsif( (bdone = '1') and (bok = '0') and (action_in = '0') ) then\r
+ NEXT_STATE <= FAILED; -- I2C write, data phase failed\r
+ error_bits <= x"02";\r
+ dostart_x <= '1';\r
+ else\r
+ NEXT_STATE <= SENDD2;\r
+ dobyte_x <= '1';\r
+ end if;\r
+ when GSTOP => \r
+ if ( (sdone = '1') and (action_in = '0') ) then\r
+ NEXT_STATE <= DONE;\r
+ i2c_done_x <= '1';\r
+ valid_x <= '1';\r
+ elsif( (sdone = '1') and (action_in = '1') and (phase = '1') ) then\r
+ NEXT_STATE <= DONE;\r
+ i2c_done_x <= '1';\r
+ valid_x <= '1';\r
+ elsif( (sdone = '1') and (action_in = '1') and (phase = '0') ) then\r
+ NEXT_STATE <= INC;\r
+ else\r
+ NEXT_STATE <= GSTOP;\r
+ dostart_x <= '1';\r
+ end if;\r
+ when INC => \r
+ NEXT_STATE <= LOADA;\r
+ when FAILED => \r
+ if( sdone = '1' ) then\r
+ NEXT_STATE <= DONE;\r
+ i2c_done_x <= '1';\r
+ running_x <= '0';\r
+ else\r
+ NEXT_STATE <= FAILED;\r
+ dostart_x <= '1';\r
+ end if;\r
+ when DONE => \r
+ if( i2c_go_in = '1' ) then\r
+ NEXT_STATE <= DONE;\r
+ i2c_done_x <= '1';\r
+ running_x <= '0';\r
+ else\r
+ NEXT_STATE <= SLEEP;\r
+ running_x <= '0';\r
+ end if;\r
+ -- Just in case...\r
+ when others => \r
+ NEXT_STATE <= SLEEP;\r
+ end case;\r
+end process TRANSFORM;\r
+\r
+-- Output decoding\r
+DECODE: process(CURRENT_STATE)\r
+begin\r
+ case CURRENT_STATE is\r
+ when SLEEP => bsm <= b"00000"; -- 00\r
+ when LOADA => bsm <= b"00001"; -- 01\r
+ when GSTART => bsm <= b"00010"; -- 02\r
+ when SENDA => bsm <= b"00011"; -- 03\r
+ when LOADC => bsm <= b"00100"; -- 04\r
+ when SENDC => bsm <= b"00101"; -- 05\r
+ when LOADD => bsm <= b"00110"; -- 06\r
+ when SENDD => bsm <= b"00111"; -- 07\r
+ when GSTOP => bsm <= b"01000"; -- 08\r
+ when INC => bsm <= b"01001"; -- 09\r
+ when FAILED => bsm <= b"01010"; -- 0a\r
+ when DONE => bsm <= b"01011"; -- 0b\r
+ when LOADD2 => bsm <= b"01100"; -- 0c\r
+ when SENDD2 => bsm <= b"01101"; -- 0d\r
+ when others => bsm <= b"11111"; -- 1f\r
+ end case;\r
+end process DECODE;\r
+\r
+-- We need to load different data sets\r
+--LOAD_DATA_PROC: process( CLOCK, RESET, CURRENT_STATE, action_in, phase)\r
+LOAD_DATA_PROC: process( CLOCK )\r
+begin\r
+ if( rising_edge(CLOCK) ) then\r
+ if ( RESET = '1' ) then\r
+ i2c_byte <= (others => '1');\r
+ elsif( (CURRENT_STATE = LOADA) and (phase = '0') ) then\r
+ i2c_byte <= i2c_addr_in(7 downto 1) & '0' & '1'; -- send write address, receive ACK\r
+ elsif( (CURRENT_STATE = LOADA) and (phase = '1') ) then\r
+ i2c_byte <= i2c_addr_in(7 downto 1) & '1' & '1'; -- send read address, receive ACK\r
+ elsif( (CURRENT_STATE = LOADC) and (action_in = '0') ) then\r
+ i2c_byte <= i2c_cmd_in(7 downto 0) & '1'; -- send command byte (WRITE), receive ACK\r
+ elsif( (CURRENT_STATE = LOADC) and (action_in = '1') ) then\r
+ i2c_byte <= i2c_cmd_in(7 downto 0) & '1'; -- send command byte (READ), receive ACK\r
+ elsif( (CURRENT_STATE = LOADD) and (action_in = '0') ) then\r
+ i2c_byte <= i2c_dw_in(15 downto 8) & '1'; -- send data byte, receive ACK\r
+ elsif( (CURRENT_STATE = LOADD2) and (action_in = '0') ) then\r
+ i2c_byte <= i2c_dw_in(7 downto 0) & '1'; -- send data byte, receive ACK\r
+ elsif( (CURRENT_STATE = LOADD) and (action_in = '1') ) then\r
+ i2c_byte <= x"ff" & '0'; -- send 0xff byte, send ACK\r
+ elsif( (CURRENT_STATE = LOADD2) and (action_in = '1') ) then\r
+ i2c_byte <= x"ff" & '1'; -- send 0xff byte, send NACK\r
+ end if;\r
+ end if;\r
+end process LOAD_DATA_PROC;\r
+\r
+-- The SendByte module\r
+THE_I2C_SENDB: i2c_sendb2\r
+port map(\r
+ CLK_IN => CLOCK,\r
+ RESET_IN => RESET,\r
+ DOBYTE_IN => dobyte,\r
+ I2C_SPEED_IN => i2c_speed,\r
+ I2C_BYTE_IN => i2c_byte,\r
+ I2C_BACK_OUT => i2c_dr,\r
+ SDA_IN => sda_q(2), -- changed\r
+ R_SDA_OUT => r_sda_sb,\r
+ S_SDA_OUT => s_sda_sb,\r
+-- SCL_IN => scl_q(2), -- changes\r
+ R_SCL_OUT => r_scl_sb,\r
+ S_SCL_OUT => s_scl_sb,\r
+ BDONE_OUT => bdone,\r
+ BOK_OUT => bok,\r
+ BSM_OUT => open\r
+);\r
+\r
+-- The GenStart module\r
+THE_I2C_GSTART: i2c_gstart2\r
+port map(\r
+ CLK_IN => CLOCK,\r
+ RESET_IN => RESET,\r
+ START_IN => start,\r
+ DOSTART_IN => dostart,\r
+ I2C_SPEED_IN => i2c_speed,\r
+ SDONE_OUT => sdone,\r
+ SOK_OUT => sok,\r
+ SDA_IN => sda_q(2), -- changed\r
+ SCL_IN => scl_q(2), -- changed\r
+ R_SCL_OUT => r_scl_gs,\r
+ S_SCL_OUT => s_scl_gs,\r
+ R_SDA_OUT => r_sda_gs,\r
+ S_SDA_OUT => s_sda_gs,\r
+ BSM_OUT => open\r
+);\r
+\r
+r_scl <= r_scl_gs or r_scl_sb;\r
+s_scl <= s_scl_gs or s_scl_sb;\r
+r_sda <= r_sda_gs or r_sda_sb;\r
+s_sda <= s_sda_gs or s_sda_sb;\r
+\r
+-- Output flipflop for SCL line\r
+THE_SCL_PROC: process( CLOCK )\r
+begin\r
+ if( rising_edge(CLOCK) ) then\r
+ if( RESET = '1' ) then\r
+ SCL_OUT <= '1';\r
+ elsif( (r_scl = '1') and (s_scl = '0') ) then\r
+ SCL_OUT <= '0';\r
+ elsif( (r_scl = '0') and (s_scl = '1') ) then\r
+ SCL_OUT <= '1';\r
+ end if;\r
+ end if;\r
+end process THE_SCL_PROC;\r
+\r
+-- Output flipflop for SDA line\r
+THE_SDA_PROC: process( CLOCK )\r
+begin\r
+ if( rising_edge(CLOCK) ) then\r
+ if( RESET = '1' ) then\r
+ SDA_OUT <= '1';\r
+ elsif( (r_sda = '1') and (s_sda = '0') ) then\r
+ SDA_OUT <= '0';\r
+ elsif( (r_sda = '0') and (s_sda = '1') ) then\r
+ SDA_OUT <= '1';\r
+ end if;\r
+ end if;\r
+end process THE_SDA_PROC;\r
+\r
+-- store data read from I2C (high byte)\r
+THE_STORE_READ_H_PROC: process( CLOCK ) \r
+begin\r
+ if( rising_edge(CLOCK) ) then\r
+ if ( RESET = '1' ) then\r
+ i2c_drw(15 downto 8) <= (others => '0');\r
+ elsif( rising_edge(CLOCK) ) then\r
+ if( load_dh = '1' ) then\r
+ i2c_drw(15 downto 8) <= i2c_dr(8 downto 1);\r
+ end if;\r
+ end if;\r
+ end if;\r
+end process THE_STORE_READ_H_PROC;\r
+\r
+-- store data read from I2C (low byte)\r
+THE_STORE_READ_L_PROC: process( CLOCK ) \r
+begin\r
+ if( rising_edge(CLOCK) ) then\r
+ if ( RESET = '1' ) then\r
+ i2c_drw(7 downto 0) <= (others => '0');\r
+ elsif( rising_edge(CLOCK) ) then\r
+ if( load_dl = '1' ) then\r
+ i2c_drw(7 downto 0) <= i2c_dr(8 downto 1);\r
+ end if;\r
+ end if;\r
+ end if;\r
+end process THE_STORE_READ_L_PROC;\r
+\r
+-- Status output\r
+status_out <= error_bits;\r
+\r
+-- Outputs\r
+I2C_DR_OUT <= i2c_drw;\r
+I2C_BUSY_OUT <= running;\r
+I2C_DONE_OUT <= i2c_done;\r
+VALID_OUT <= valid;\r
+BSM_OUT <= bsm;\r
+\r
+end Behavioral;\r