\r
entity I2C_GSTART 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
+ 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;\r
\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
+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
-- 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
+ 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
-- 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
+ 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
+ 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
+ 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
entity i2c_sendb 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
+ 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_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
-- 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
+ 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
-- 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
+ 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
-- 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
+ 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
+ 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
+ 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
-- 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
+ 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
+ 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
+ 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
+ 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
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
+ DIRECT_IN : in std_logic; -- '0' -> normal access, '1' -> direct read\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
SCL_IN : in std_logic;\r
SCL_OUT : out std_logic;\r
-- Debug\r
- BSM_OUT : out std_logic_vector(4 downto 0)\r
+ BSM_OUT : out std_logic_vector(3 downto 0)\r
);\r
end entity i2c_slim2;\r
\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 bsm : std_logic_vector(3 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 load_dh : std_logic;\r
signal load_dl_x : std_logic;\r
signal load_dl : std_logic;\r
+signal clr_data_x : std_logic;\r
+signal clr_data : std_logic;\r
\r
signal sdone : std_logic; -- acknowledge signal from GenStart module\r
signal sok : std_logic; -- status signal from GenStart module\r
end process THE_SYNC_PROC;\r
\r
-- lower limit of speed\r
-i2c_speed <= i2c_speed_in & "000";\r
+i2c_speed <= i2c_speed_in & b"010";\r
\r
-- Read phase indicator\r
THE_PHASE_PROC: process( CLOCK )\r
if( rising_edge(CLOCK) ) then\r
if( RESET = '1' ) then\r
phase <= '0';\r
- elsif( CURRENT_STATE = INC ) then\r
+ elsif( (CURRENT_STATE = INC) ) then\r
phase <= '1';\r
elsif( (CURRENT_STATE = DONE) or (CURRENT_STATE = SLEEP) ) then\r
phase <= '0';\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
+ clr_data <= '1';\r
valid <= '0';\r
+ i2c_done <= '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
+ clr_data <= clr_data_x;\r
valid <= valid_x;\r
+ i2c_done <= i2c_done_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
+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
+ clr_data_x <= '0';\r
valid_x <= '0';\r
+ i2c_done_x <= '0';\r
errors_x <= x"00";\r
save_x <= '0';\r
case CURRENT_STATE is\r
when SLEEP => \r
- if( i2c_go_in = '1' ) then\r
+ if( I2C_GO_IN = '1' ) then\r
NEXT_STATE <= LOADA;\r
save_x <= '1';\r
+ clr_data_x <= '1';\r
else\r
NEXT_STATE <= SLEEP;\r
running_x <= '0';\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
+ if ( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') and (DIRECT_IN = '0') ) then\r
+ NEXT_STATE <= LOADC; -- I2C normal write\r
+ elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (DIRECT_IN = '0') and (phase = '0') ) then\r
+ NEXT_STATE <= LOADC; -- I2C normal read, address stage (same for byte and word)\r
+ elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (phase = '1') and (WORD_IN = '0') ) then\r
+ NEXT_STATE <= LOADD2; -- I2C normal read (byte), data stage\r
+ elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (phase = '1') and (WORD_IN = '1') ) then\r
+ NEXT_STATE <= LOADD; -- I2C normal read (word), data stage\r
+ elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') and (DIRECT_IN = '1') and (WORD_IN = '0') ) then\r
+ NEXT_STATE <= LOADD2; -- I2C direct write (byte)\r
+ elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') and (DIRECT_IN = '1') and (WORD_IN = '1') ) then\r
+ NEXT_STATE <= LOADD; -- I2C direct write (word)\r
+ elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (DIRECT_IN = '1') and (WORD_IN = '0') ) then\r
+ NEXT_STATE <= LOADD2; -- I2C direct read (byte)\r
+ elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (DIRECT_IN = '1') and (WORD_IN = '1') ) then\r
+ NEXT_STATE <= LOADD; -- I2C direct read (word)\r
elsif( (bdone = '1') and (bok = '0') and (phase = '0') ) then\r
NEXT_STATE <= FAILED; -- first address phase failed\r
errors_x <= x"20";\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
+ 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
+ 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
+ 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
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
+ if ( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') ) then\r
+ NEXT_STATE <= LOADD2; -- I2C write, word access, last byte to send\r
+ elsif( (bdone = '1') and (ACTION_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
+ elsif( (bdone = '1') and (bok = '0') and (ACTION_IN = '0') ) then\r
NEXT_STATE <= FAILED; -- I2C write, first data phase failed\r
errors_x <= x"04";\r
save_x <= '1';\r
when LOADD2 => \r
NEXT_STATE <= SENDD2;\r
when SENDD2 => \r
- if ( (bdone = '1') and (bok = '1') and (action_in = '0') ) then\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
+ 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
+ elsif( (bdone = '1') and (bok = '0') and (ACTION_IN = '0') ) then\r
NEXT_STATE <= FAILED; -- I2C write, data phase failed\r
errors_x <= x"02";\r
save_x <= '1';\r
dobyte_x <= '1';\r
end if;\r
when GSTOP => \r
- if ( (sdone = '1') and (action_in = '0') ) then\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
+ 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
+ elsif( (sdone = '1') and (ACTION_IN = '1') and (phase = '0') and (DIRECT_IN = '0') ) then\r
NEXT_STATE <= INC;\r
+ elsif( (sdone = '1') and (ACTION_IN = '1') and (DIRECT_IN = '1') ) then\r
+ NEXT_STATE <= DONE;\r
+ i2c_done_x <= '1';\r
+ valid_x <= '1';\r
else\r
NEXT_STATE <= GSTOP;\r
dostart_x <= '1';\r
when INC => \r
NEXT_STATE <= LOADA;\r
when FAILED => \r
+ -- emergency STOP condition to correctly free the bus\r
if( sdone = '1' ) then\r
NEXT_STATE <= DONE;\r
i2c_done_x <= '1';\r
end if;\r
end process THE_ERROR_PROC;\r
\r
+---- DONE bit: set by FSM completion, cleared by start of FSM\r
+--THE_DONE_PROC: process( CLOCK )\r
+--begin\r
+-- if( rising_edge(CLOCK) ) then\r
+-- if ( RESET = '1' ) then\r
+-- i2c_done <= '0';\r
+-- elsif( CURRENT_STATE = LOADA ) then\r
+-- i2c_done <= '0';\r
+-- elsif( CURRENT_STATE = DONE ) then\r
+-- i2c_done <= '1';\r
+-- end if;\r
+-- end if;\r
+--end process THE_DONE_PROC;\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
+ when SLEEP => bsm <= b"0000"; -- 0\r
+ when LOADA => bsm <= b"0001"; -- 1\r
+ when GSTART => bsm <= b"0010"; -- 2\r
+ when SENDA => bsm <= b"0011"; -- 3\r
+ when LOADC => bsm <= b"0100"; -- 4\r
+ when SENDC => bsm <= b"0101"; -- 5\r
+ when LOADD => bsm <= b"0110"; -- 6\r
+ when SENDD => bsm <= b"0111"; -- 7\r
+ when GSTOP => bsm <= b"1000"; -- 8\r
+ when INC => bsm <= b"1001"; -- 9\r
+ when FAILED => bsm <= b"1010"; -- a\r
+ when DONE => bsm <= b"1011"; -- b\r
+ when LOADD2 => bsm <= b"1100"; -- c\r
+ when SENDD2 => bsm <= b"1101"; -- d\r
+ when others => bsm <= b"1111"; -- f\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
+ elsif( (CURRENT_STATE = LOADA) and (phase = '0') and (DIRECT_IN = '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 = '0') and (DIRECT_IN = '1') and (ACTION_IN = '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 = '0') and (DIRECT_IN = '1') and (ACTION_IN = '1') ) then\r
+ i2c_byte <= i2c_addr_in(7 downto 1) & '1' & '1'; -- send read 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
+ elsif( (CURRENT_STATE = LOADC) ) then\r
+ i2c_byte <= i2c_cmd_in(7 downto 0) & '1'; -- send command byte (read/write), 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
+ 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
+ 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
+ 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
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
+ if ( clr_data = '1' ) then\r
+ i2c_drw(15 downto 8) <= (others => '1');\r
elsif( rising_edge(CLOCK) ) then\r
if( load_dh = '1' ) then\r
i2c_drw(15 downto 8) <= i2c_dr(8 downto 1);\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
+ if ( clr_data = '1' ) then\r
+ i2c_drw(7 downto 0) <= (others => '1');\r
elsif( rising_edge(CLOCK) ) then\r
if( load_dl = '1' ) then\r
i2c_drw(7 downto 0) <= i2c_dr(8 downto 1);\r