Synthron

i2c_master_wip

Jun 23rd, 2020
1,653
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- I2C-Master for FPGA
  2. -- Work in Progress!
  3. -- Do not use!
  4.  
  5. -- Workings of the read/write cycles:
  6. -- currently only 2 byte write is supported. After writing, the master will send the stop bit.
  7. -- It is supported to read up to 8 bytes of data in one go, as long as the slave sends ACKs.
  8. -- -- after the 8th byte the master will send a stop bit disregarding the state of ACK or NACK
  9.  
  10. library  ieee;
  11. use  IEEE.std_logic_1164.all;
  12. use  IEEE.numeric_std.all;
  13.  
  14. entity i2c_master is
  15.     port (
  16.         clock : in std_logic;
  17.         start : in std_logic;
  18.         --reset : in std_logic;                         -- seserved for later
  19.  
  20.         flag_rw : in std_logic;
  21.         flag_busy : out std_logic;
  22.  
  23.         slave_adress : in  std_logic_vector(6 downto 0);
  24.         data_write   : in  std_logic_vector(15 downto 0);
  25.         data_read    : out std_logic_vector(63 downto 0); -- supports up to 8 byte block read
  26.  
  27.         sda : inout std_logic;
  28.         scl : out std_logic
  29.     );
  30. end entity;
  31.  
  32. architecture RTL of i2c_master is
  33.     constant bitrate : integer := 100_000;
  34.     constant clockrate : integer := 25_000_000;
  35.     constant clockdiv : integer := (clockrate/bitrate);
  36.     signal clockcount : integer range 0 to clockdiv;
  37.  
  38.  
  39.     signal clk_state : std_logic_vector(3 downto 0);
  40.     signal r_start : std_logic := '0';
  41.  
  42.     signal r_data : std_logic_vector(7 downto 0) := (others=>'0');
  43.  
  44.     signal r_read_data : std_logic_vector(63 downto 0) := (others=>'0');
  45.  
  46.     signal r_adress : std_logic_vector(6 downto 0);
  47.     signal rw : std_logic;
  48.     signal adr_count : integer range 0 to 7;
  49.     signal cycle_count : integer range 0 to 8;
  50.     signal byte_count : integer range 0 to 7;
  51.  
  52.     signal write_register : std_logic := '0';
  53.     signal write_done : std_logic := '0';
  54.  
  55.     type protocol_state is (idle, p_start, p_stop, adress, ack, write_byte, read_byte);
  56.  
  57.     signal protocol : protocol_state;
  58.    
  59. begin
  60.  
  61.     count : process(clock, data_write, flag_rw, r_start, slave_adress, clockcount, start) is
  62.     begin
  63.         -- count up and create timing, also clock in the start bit
  64.         if rising_edge(clock) then
  65.             clockcount <= clockcount + 1;
  66.             r_start <= start;
  67.         end if;
  68.  
  69.         -- count 4 state steps used for timing
  70.         case clockcount is
  71.             when (clockdiv/4) =>
  72.                 clk_state <= B"0001";
  73.             when (clockdiv/2) =>
  74.                 clk_state <= B"0010";
  75.             when (3*clockdiv/4) =>
  76.                 clk_state <= B"0100";
  77.             when clockdiv =>
  78.                 clk_state <= B"1000";
  79.             when others =>
  80.                 clk_state <= B"0000";
  81.         end case;
  82.  
  83.         -- detect starting signal and setting relevant registers
  84.         if (r_start = '0' and start = '1') then
  85.             protocol <= p_start;
  86.             clockcount <= 0;
  87.             clk_state <= X"0";
  88.             sda <= 'Z';
  89.             scl <= 'Z';
  90.             flag_busy <= '1';
  91.             rw <= flag_rw;
  92.             r_adress <= slave_adress;
  93.             if (flag_rw = '0') then
  94.                 r_data <= data_write;
  95.             end if ;
  96.             adr_count <= 7;
  97.             cycle_count <= 0;
  98.             byte_count <= 0;
  99.             write_done <= '0';
  100.             write_register <= '0';
  101.         end if;
  102.     end process;
  103.  
  104.    
  105.  
  106.     i2c_protocol : process (clock) is
  107.     begin
  108.         if rising_edge(clock) then
  109.            
  110.             case protocol is
  111.                 -- senging start-bit
  112.                 when start =>
  113.                     if (clk_state(0) = '1') then
  114.                         sda <= '0';
  115.                     elsif (clk_state(2) = '1') then
  116.                         scl <= '0';
  117.                         protocol <= adress;
  118.                         adr_count <= 6;
  119.                     end if;
  120.                 -- sending slave adress and R/W-Bit
  121.                 when adress =>
  122.                     if (clk_state(0) = '1') then            -- apply data bit
  123.                         if (adr_count > 0) then               -- check if adress is not fully sent
  124.                             sda <= r_adress(adr_count-1);
  125.                         else                                -- if adress fully sent, send RW-bit
  126.                             sda <= rw;
  127.                         end if ;
  128.                     elsif (clk_state(1) = '1') then         -- set SCL high (high Z)
  129.                         scl <= 'Z';
  130.                     elsif (clk_state(3) = '1') then         -- set SCL low
  131.                         scl <= '0';
  132.                         if adr_count > 0 then               -- if not finished, send more bits
  133.                             adr_count <= adr_count - 1;
  134.                         else                                -- set SDA high-Z and goto Acknowledge sensing
  135.                             sda <= 'Z';
  136.                             protocol <= ack;
  137.                         end if;
  138.                     end if ;
  139.                 -- read and check the first Acknowledge bit
  140.                 when ack =>
  141.                     if (clk_state(1) = '1') then            -- set SCL high
  142.                         scl <= 'Z';
  143.                     elsif (clk_state(2) = '1') then        
  144.                         if(sda = '1') then
  145.                             protocol <= p_stop;             -- goto stop-bit if NACK
  146.                         else
  147.                             if rw = '1' then                -- Else read or write data according to RW-Bit
  148.                                 if (byte_count = 7) then
  149.                                     protocol <= p_stop;
  150.                                 else
  151.                                     protocol <= read_byte;
  152.                                 end if ;
  153.                             else
  154.                                 if (write_done = '1') then
  155.                                     protocol <= p_stop;
  156.                                 else
  157.                                     protocol <= write_byte;
  158.                                 end if ;
  159.                                
  160.                             end if ;
  161.                             cycle_count <= 8;
  162.                         end if;
  163.                     elsif (clk_state(3) = '1') then         -- set SCL low
  164.                         scl <= '0';
  165.                     end if;
  166.                 -- send 1 byte of data
  167.                 when write_byte =>
  168.                     if (clk_state(0) = '1') then            -- set SDA to data bit, starting with MSB, going to LSB
  169.                         sda <= r_data(cycle_count-1);
  170.                     elsif(clk_state(1) = '1') then          -- set SCL high and decrement cycle_count
  171.                         scl <= 'Z';
  172.                         cycle_count <= cycle_count - 1;
  173.                     elsif (clk_state(3) = '1') then         -- set SCL low and check if data or ACK comes next
  174.                         scl <= '0';
  175.                         if (cycle_count = 0) then
  176.                             if (write_register = '0') then
  177.                                 write_register <= '1';
  178.                             else
  179.                                 write_done <= '1';    
  180.                             end if ;
  181.                             protocol <= ack;
  182.                         end if;
  183.                     end if;
  184.                 -- read 1 byte of data
  185.                 when read_byte =>
  186.                     if (clk_state(1) = '1') then            -- set SCL high, decrement cycle_count
  187.                         scl <= 'Z';
  188.                         cycle_count <= cycle_count - 1;
  189.                     elsif (clk_state(2) = '1') then         -- read MSB of data byte
  190.                         r_read_data((8*byte_count+cycle_count)) <= sda;
  191.                     elsif (clk_state(3) = '1') then         -- set SCL low, increment byte count if cycleclount = 0;
  192.                         scl <= '1';
  193.                         if (cycle_count = 0) then
  194.                             byte_count <= byte_count + 1;
  195.                             protocol <= ack;
  196.                         end if ;
  197.                     end if ;
  198.                 -- sending stop-bit and clearing busy-flag
  199.                 when p_stop =>
  200.                     if (clk_state(1) = '1') then
  201.                         scl <= 'Z';
  202.                     elsif (clk_state(3) = '1') then
  203.                         sda <= 'Z';
  204.                     end if;
  205.                     flag_busy <= '0';
  206.                     data_read <= r_read_data;
  207.             end case;
  208.         end if ;
  209.     end process;
  210.  
  211.  
  212. end architecture;
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×