Revision 982
Added by markw over 5 years ago
| common/components/I2C_regs.vhd | ||
|---|---|---|
| 
     	 bits : integer := 1
 
   | 
||
| 
       );
 
   | 
||
| 
       port (
 
   | 
||
| 
         scl              : inout std_logic;
 
   | 
||
| 
         sda              : inout std_logic;
 
   | 
||
| 
         scl_in           : in std_logic;
 
   | 
||
| 
         sda_in           : in std_logic;
 
   | 
||
| 
     	 scl_wen          : out std_logic;
 
   | 
||
| 
     	 sda_wen          : out std_logic;
 
   | 
||
| 
     | 
||
| 
         clk              : in    std_logic;
 
   | 
||
| 
         rst              : in    std_logic;
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     		SLAVE_ADDR => SLAVE_ADDR
 
   | 
||
| 
     	)
 
   | 
||
| 
     	port map (
 
   | 
||
| 
     		scl => scl,
 
   | 
||
| 
     		sda => sda,
 
   | 
||
| 
     		scl_in => scl_in,
 
   | 
||
| 
     		sda_in => sda_in,		
 
   | 
||
| 
     		scl_wen => scl_wen,
 
   | 
||
| 
     		sda_wen => sda_wen,				
 
   | 
||
| 
     | 
||
| 
     		clk => clk,
 
   | 
||
| 
     		rst => rst,
 
   | 
||
| 
     | 
||
| common/components/I2C_slave.vhd | ||
|---|---|---|
| 
     ------------------------------------------------------------
 
   | 
||
| 
     -- Copyright (c) 2016 Peter Samarin
 
   | 
||
| 
     ------------------------------------------------------------
 
   | 
||
| 
     -- Mark Watson 2020 - modified to not use inout, for simpler in fpga use
 
   | 
||
| 
     ------------------------------------------------------------
 
   | 
||
| 
     library ieee;
 
   | 
||
| 
     use ieee.std_logic_1164.all;
 
   | 
||
| 
     use ieee.numeric_std.all;
 
   | 
||
| ... | ... | |
| 
       generic (
 
   | 
||
| 
         SLAVE_ADDR : std_logic_vector(6 downto 0));
 
   | 
||
| 
       port (
 
   | 
||
| 
         scl              : inout std_logic;
 
   | 
||
| 
         sda              : inout std_logic;
 
   | 
||
| 
         scl_in           : in std_logic;
 
   | 
||
| 
         sda_in           : in std_logic;
 
   | 
||
| 
     	 scl_wen          : out std_logic;
 
   | 
||
| 
     	 sda_wen          : out std_logic;
 
   | 
||
| 
     | 
||
| 
         clk              : in    std_logic;
 
   | 
||
| 
         rst              : in    std_logic;
 
   | 
||
| 
         -- User interface
 
   | 
||
| ... | ... | |
| 
       begin
 
   | 
||
| 
         if rising_edge(clk) then
 
   | 
||
| 
           -- save SCL in registers that are used for debouncing
 
   | 
||
| 
           scl_reg <= scl;
 
   | 
||
| 
           sda_reg <= sda;
 
   | 
||
| 
           scl_reg <= scl_in;
 
   | 
||
| 
           sda_reg <= sda_in;
 
   | 
||
| 
     | 
||
| 
           -- Delay debounced SCL and SDA by 1 clock cycle
 
   | 
||
| 
           scl_prev_reg   <= scl_debounced;
 
   | 
||
| ... | ... | |
| 
       ----------------------------------------------------------
 
   | 
||
| 
       -- I2C interface
 
   | 
||
| 
       ----------------------------------------------------------
 
   | 
||
| 
       sda <= sda_o_reg when sda_wen_reg = '1' else
 
   | 
||
| 
              'Z';
 
   | 
||
| 
       scl <= scl_o_reg when scl_wen_reg = '1' else
 
   | 
||
| 
              'Z';
 
   | 
||
| 
       scl_wen <= scl_wen_reg and not(scl_o_reg);  
 
   | 
||
| 
       sda_wen <= sda_wen_reg and not(sda_o_reg);
 
   | 
||
| 
       ----------------------------------------------------------
 
   | 
||
| 
       -- User interface
 
   | 
||
| 
       ----------------------------------------------------------
 
   | 
||
| common/components/i2c_master.vhd | ||
|---|---|---|
| 
     --     Adjusted timing of SCL during start and stop conditions
 
   | 
||
| 
     --   Version 2.2 02/05/2015 Scott Larson
 
   | 
||
| 
     --     Corrected small SDA glitch introduced in version 2.1
 
   | 
||
| 
     --   2020 Mark Watson
 
   | 
||
| 
     --     Modified to use in/out instead of inout
 
   | 
||
| 
     -- 
 
   | 
||
| 
     --------------------------------------------------------------------------------
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
         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
 
   | 
||
| 
     | 
||
| 
         scl_in           : in std_logic;
 
   | 
||
| 
         sda_in           : in std_logic;
 
   | 
||
| 
     	 scl_wen          : out std_logic;
 
   | 
||
| 
     	 sda_wen          : out std_logic
 
   | 
||
| 
     | 
||
| 
     );                   --serial clock output of i2c bus
 
   | 
||
| 
     END i2c_master;
 
   | 
||
| 
     | 
||
| 
     ARCHITECTURE logic OF i2c_master IS
 
   | 
||
| ... | ... | |
| 
               data_clk <= '1';
 
   | 
||
| 
             WHEN divider*2 TO divider*3-1 =>  --third 1/4 cycle of clocking
 
   | 
||
| 
               scl_clk <= '1';                 --release scl
 
   | 
||
| 
               IF(scl = '0') THEN              --detect if slave is stretching clock
 
   | 
||
| 
               IF(scl_in = '0') THEN              --detect if slave is stretching clock
 
   | 
||
| 
                 stretch <= '1';
 
   | 
||
| 
               ELSE
 
   | 
||
| 
                 stretch <= '0';
 
   | 
||
| ... | ... | |
| 
                   ack_error <= '0';                     --reset acknowledge error output
 
   | 
||
| 
                 END IF;
 
   | 
||
| 
               WHEN slv_ack1 =>                          --receiving slave acknowledge (command)
 
   | 
||
| 
                 IF(sda /= '0' OR ack_error = '1') THEN  --no-acknowledge or previous no-acknowledge
 
   | 
||
| 
                 IF(sda_in /= '0' OR ack_error = '1') THEN  --no-acknowledge or previous no-acknowledge
 
   | 
||
| 
                   ack_error <= '1';                     --set error output if no-acknowledge
 
   | 
||
| 
                 END IF;
 
   | 
||
| 
               WHEN rd =>                                --receiving slave data
 
   | 
||
| 
                 data_rx(bit_cnt) <= sda;                --receive current slave data bit
 
   | 
||
| 
                 data_rx(bit_cnt) <= sda_in;                --receive current slave data bit
 
   | 
||
| 
               WHEN slv_ack2 =>                          --receiving slave acknowledge (write)
 
   | 
||
| 
                 IF(sda /= '0' OR ack_error = '1') THEN  --no-acknowledge or previous no-acknowledge
 
   | 
||
| 
                 IF(sda_in /= '0' OR ack_error = '1') THEN  --no-acknowledge or previous no-acknowledge
 
   | 
||
| 
                   ack_error <= '1';                     --set error output if no-acknowledge
 
   | 
||
| 
                 END IF;
 
   | 
||
| 
               WHEN stop =>
 
   | 
||
| ... | ... | |
| 
                      NOT data_clk_prev WHEN stop,  --generate stop condition
 
   | 
||
| 
                      sda_int WHEN OTHERS;          --set to internal sda signal    
 
   | 
||
| 
     | 
||
| 
       --set scl and sda outputs
 
   | 
||
| 
       scl <= '0' WHEN (scl_ena = '1' AND scl_clk = '0') ELSE 'Z';
 
   | 
||
| 
       sda <= '0' WHEN sda_ena_n = '0' ELSE 'Z';
 
   | 
||
| 
     | 
||
| 
       --set scl and sda outputs  
 
   | 
||
| 
       sda_wen <= not(sda_ena_n);
 
   | 
||
| 
       scl_wen <= scl_ena AND not(scl_clk);
 
   | 
||
| 
     | 
||
| 
     END logic;
 
   | 
||
| common/zpu/zpu_config_regs.vhdl | ||
|---|---|---|
| 
     	USBWireOE_n :out std_logic_vector(usb-1 downto 0);
 
   | 
||
| 
     | 
||
| 
     	-- I2C (400k)
 
   | 
||
| 
     	i2c0_sda : inout std_logic;
 
   | 
||
| 
     	i2c0_scl : inout std_logic;
 
   | 
||
| 
     	i2c1_sda : inout std_logic;
 
   | 
||
| 
     	i2c1_scl : inout std_logic
 
   | 
||
| 
     	i2c0_sda_in : in std_logic;
 
   | 
||
| 
     	i2c0_scl_in : in std_logic;
 
   | 
||
| 
     	i2c0_sda_wen : out std_logic;
 
   | 
||
| 
     	i2c0_scl_wen : out std_logic;
 
   | 
||
| 
     | 
||
| 
     	i2c1_sda_in : in std_logic;
 
   | 
||
| 
     	i2c1_scl_in : in std_logic;
 
   | 
||
| 
     	i2c1_sda_wen : out std_logic;
 
   | 
||
| 
     	i2c1_scl_wen : out std_logic		
 
   | 
||
| 
     );
 
   | 
||
| 
     END zpu_config_regs;
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     	 -- TODO: Use real clk freq... Not that important since only used on eclaire for now anyway.
 
   | 
||
| 
     	 i2c_master0 : entity work.i2c_master
 
   | 
||
| 
     	 	generic map(input_clk=>58_000_000, bus_clk=>400_000)
 
   | 
||
| 
     		port map (clk=>clk,reset_n=>reset_n,ena=>i2c0_write_reg,addr=>i2c0_write_data_reg(15 downto 9),rw=>i2c0_write_data_reg(8),data_wr=>i2c0_write_data_reg(7 downto 0),busy=>i2c0_busy_next,data_rd=>i2c0_read_data,ack_error=>i2c0_error,sda=>i2c0_sda,scl=>i2c0_scl);
 
   | 
||
| 
     		port map (clk=>clk,reset_n=>reset_n,ena=>i2c0_write_reg,addr=>i2c0_write_data_reg(15 downto 9),rw=>i2c0_write_data_reg(8),data_wr=>i2c0_write_data_reg(7 downto 0),busy=>i2c0_busy_next,data_rd=>i2c0_read_data,ack_error=>i2c0_error,
 
   | 
||
| 
     		sda_in=>i2c0_sda_in,scl_in=>i2c0_scl_in,sda_wen=>i2c0_sda_wen,scl_wen=>i2c0_scl_wen);
 
   | 
||
| 
     	 i2c_master1 : entity work.i2c_master
 
   | 
||
| 
     	 	generic map(input_clk=>58_000_000, bus_clk=>400_000)
 
   | 
||
| 
     		port map (clk=>clk,reset_n=>reset_n,ena=>i2c1_write_reg,addr=>i2c1_write_data_reg(15 downto 9),rw=>i2c1_write_data_reg(8),data_wr=>i2c1_write_data_reg(7 downto 0),busy=>i2c1_busy_next,data_rd=>i2c1_read_data,ack_error=>i2c1_error,sda=>i2c1_sda,scl=>i2c1_scl);
 
   | 
||
| 
     		port map (clk=>clk,reset_n=>reset_n,ena=>i2c1_write_reg,addr=>i2c1_write_data_reg(15 downto 9),rw=>i2c1_write_data_reg(8),data_wr=>i2c1_write_data_reg(7 downto 0),busy=>i2c1_busy_next,data_rd=>i2c1_read_data,ack_error=>i2c1_error,
 
   | 
||
| 
     		sda_in=>i2c1_sda_in,scl_in=>i2c1_scl_in,sda_wen=>i2c1_sda_wen,scl_wen=>i2c1_scl_wen);
 
   | 
||
| 
     | 
||
| 
     	-- device decode
 
   | 
||
| 
     	-- 0x000 - own regs (0)
 
   | 
||
| common/zpu/zpucore.vhd | ||
|---|---|---|
| 
     		USBWireOE_n :out std_logic_vector(usb-1 downto 0);
 
   | 
||
| 
     | 
||
| 
     		-- I2C (400k)
 
   | 
||
| 
     		i2c0_sda : inout std_logic;
 
   | 
||
| 
     		i2c0_scl : inout std_logic;
 
   | 
||
| 
     		i2c1_sda : inout std_logic;
 
   | 
||
| 
     		i2c1_scl : inout std_logic
 
   | 
||
| 
     		i2c0_sda_in : in std_logic := '1';
 
   | 
||
| 
     		i2c0_scl_in : in std_logic := '1';
 
   | 
||
| 
     		i2c0_sda_wen : out std_logic;
 
   | 
||
| 
     		i2c0_scl_wen : out std_logic;
 
   | 
||
| 
     | 
||
| 
     		i2c1_sda_in : in std_logic := '1';
 
   | 
||
| 
     		i2c1_scl_in : in std_logic := '1';
 
   | 
||
| 
     		i2c1_sda_wen : out std_logic;
 
   | 
||
| 
     		i2c1_scl_wen : out std_logic		
 
   | 
||
| 
     	);
 
   | 
||
| 
     END zpucore;
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     	USBWireVMout => USBWireVMout,
 
   | 
||
| 
     	USBWireOE_n => USBWireOE_n,
 
   | 
||
| 
     | 
||
| 
     	i2c0_sda => i2c0_sda,
 
   | 
||
| 
     	i2c0_scl => i2c0_scl,
 
   | 
||
| 
     	i2c1_sda => i2c1_sda,
 
   | 
||
| 
     	i2c1_scl => i2c1_scl
 
   | 
||
| 
     	i2c0_sda_in => i2c0_sda_in,
 
   | 
||
| 
     	i2c0_scl_in => i2c0_scl_in,
 
   | 
||
| 
     	i2c0_sda_wen => i2c0_sda_wen,
 
   | 
||
| 
     	i2c0_scl_wen => i2c0_scl_wen,
 
   | 
||
| 
     	i2c1_sda_in => i2c1_sda_in,
 
   | 
||
| 
     	i2c1_scl_in => i2c1_scl_in,
 
   | 
||
| 
     	i2c1_sda_wen => i2c1_sda_wen,
 
   | 
||
| 
     	i2c1_scl_wen => i2c1_scl_wen	
 
   | 
||
| 
     	);
 
   | 
||
| 
     | 
||
| 
     decode_addr1 : entity work.complete_address_decoder
 
   | 
||
Split inout into in and out for i2c, better for internal use in fpga