Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
17268 Discussions

implement i2c with vhdl

Altera_Forum
Honored Contributor II
2,357 Views

Hello, 

I am beginner with vhdl and i have to implement an I2C master controller. I found this code to generate I2C clock but i didn't understand why the cycle is devided into for parts and how it assigns values to scl_clk and data_clk. 

ENTITY i2c_master IS GENERIC( input_clk : INTEGER := 50_000_000; --input clock speed from user logic in Hz bus_clk : INTEGER := 400_000); --speed the i2c bus (scl) will run at in Hz PORT( clk : IN STD_LOGIC; --system clock reset_n : IN STD_LOGIC; --active low reset ena : IN STD_LOGIC; --latch in command addr : IN STD_LOGIC_VECTOR(6 DOWNTO 0); --address of target slave rw : IN STD_LOGIC; --'0' is write, '1' is read data_wr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); --data to write to slave busy : OUT STD_LOGIC; --indicates transaction in progress data_rd : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --data read from slave ack_error : BUFFER STD_LOGIC; --flag if improper acknowledge from slave sda : INOUT STD_LOGIC; --serial data output of i2c bus scl : INOUT STD_LOGIC); --serial clock output of i2c bus END i2c_master; ARCHITECTURE logic OF i2c_master IS CONSTANT divider : INTEGER := (input_clk/bus_clk)/4; --number of clocks in 1/4 cycle of scl TYPE machine IS(ready, start, command, slv_ack1, wr, rd, slv_ack2, mstr_ack, stop); --needed states SIGNAL state : machine; --state machine SIGNAL data_clk : STD_LOGIC; --clock edges for sda SIGNAL scl_clk : STD_LOGIC; --constantly running internal scl SIGNAL scl_ena : STD_LOGIC := '0'; --enables internal scl to output SIGNAL sda_int : STD_LOGIC := '1'; --internal sda SIGNAL sda_ena_n : STD_LOGIC; --enables internal sda to output SIGNAL addr_rw : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in address and read/write SIGNAL data_tx : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in data to write to slave SIGNAL data_rx : STD_LOGIC_VECTOR(7 DOWNTO 0); --data received from slave SIGNAL bit_cnt : INTEGER RANGE 0 TO 7 := 7; --tracks bit number in transaction SIGNAL stretch : STD_LOGIC := '0'; --identifies if slave is stretching scl BEGIN --generate the timing for the bus clock (scl_clk) and the data clock (data_clk) PROCESS(clk, reset_n) VARIABLE count : INTEGER RANGE 0 TO divider*4; --timing for clock generation BEGIN IF(reset_n = '0') THEN --reset asserted --stretch <= '0'; count := 0; ELSIF(clk'EVENT AND clk = '1') THEN IF(count = divider*4-1) THEN --end of timing cycle count := 0; --reset timer ELSIF(stretch = '0') THEN --clock stretching from slave not detected count := count + 1; --continue clock generation timing END IF; CASE count IS WHEN 0 TO divider-1 => --first 1/4 cycle of clocking scl=0 et sda=0 start sequence scl_clk <= '0'; data_clk <= '0'; WHEN divider TO divider*2-1 => --second 1/4 cycle of clocking scl=0 et sda=1 lecture scl_clk <= '0'; data_clk <= '1'; WHEN divider*2 TO divider*3-1 => --third 1/4 cycle of clocking ecriture ???? scl_clk <= 'Z'; --release scl IF(scl = '0') THEN --detect if slave is stretching clock stretch <= '1'; ELSE stretch <= '0'; END IF; data_clk <= '1'; WHEN OTHERS => --last 1/4 cycle of clocking sda =0 donc stop sequence scl_clk <= 'Z'; data_clk <= '0'; END CASE; END IF; END PROCESS; 

I search for that but i didn't find an explaination so please help me it's urgent :cry:  

Thanks in advance
0 Kudos
2 Replies
Altera_Forum
Honored Contributor II
1,399 Views

Did you run a testbench to see how it works?

0 Kudos
Altera_Forum
Honored Contributor II
1,399 Views

 

--- Quote Start ---  

Did you run a testbench to see how it works? 

--- Quote End ---  

 

 

thanks for your response. 

No i did not run a test bench because i think that it 's I2C's clock behavor and data_clk will be the sensibility for the FSM process to wich i will run a test bench. 

i just want to understand why data clock and scl_clk are generated in that way.
0 Kudos
Reply