📄 i2c_master_byte_ctrl.vhd
字号:
------------------------------------------------------------------------- -------- WISHBONE revB2 compl. I2C Master Core; byte-controller -------- -------- -------- Author: Richard Herveille -------- richard@asics.ws -------- www.asics.ws -------- -------- Downloaded from: http://www.opencores.org/projects/i2c/ -------- ----------------------------------------------------------------------------- -------- Copyright (C) 2000 Richard Herveille -------- richard@asics.ws -------- -------- This source file may be used and distributed without -------- restriction provided that this copyright statement is not -------- removed from the file and that any derivative work contains -------- the original copyright notice and the associated disclaimer.-------- -------- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY -------- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -------- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -------- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR -------- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -------- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -------- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -------- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -------- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -------- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -------- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -------- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -------- POSSIBILITY OF SUCH DAMAGE. -------- --------------------------------------------------------------------------- CVS Log---- $Id: i2c_master_byte_ctrl.vhd,v 1.5 2004/02/18 11:41:48 rherveille Exp $---- $Date: 2004/02/18 11:41:48 $-- $Revision: 1.5 $-- $Author: rherveille $-- $Locker: $-- $State: Exp $---- Change History:-- $Log: i2c_master_byte_ctrl.vhd,v $-- Revision 1.5 2004/02/18 11:41:48 rherveille-- Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command.---- Revision 1.4 2003/08/09 07:01:13 rherveille-- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.-- Fixed a potential bug in the byte controller's host-acknowledge generation.---- Revision 1.3 2002/12/26 16:05:47 rherveille-- Core is now a Multimaster I2C controller.---- Revision 1.2 2002/11/30 22:24:37 rherveille-- Cleaned up code---- Revision 1.1 2001/11/05 12:02:33 rherveille-- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version.-- Code updated, is now up-to-date to doc. rev.0.4.-- Added headers.------------------------------------------------ Byte controller section--------------------------------------------library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;entity i2c_master_byte_ctrl is port ( clk : in std_logic; rst : in std_logic; -- synchronous active high reset (WISHBONE compatible) nReset : in std_logic; -- asynchornous active low reset (FPGA compatible) ena : in std_logic; -- core enable signal clk_cnt : in unsigned(15 downto 0); -- 4x SCL -- input signals start, stop, read, write, ack_in : std_logic; din : in std_logic_vector(7 downto 0); -- output signals cmd_ack : out std_logic; -- command done ack_out : out std_logic; i2c_busy : out std_logic; -- arbitration lost i2c_al : out std_logic; -- i2c bus busy dout : out std_logic_vector(7 downto 0); -- i2c lines scl_i : in std_logic; -- i2c clock line input scl_o : out std_logic; -- i2c clock line output scl_oen : out std_logic; -- i2c clock line output enable, active low sda_i : in std_logic; -- i2c data line input sda_o : out std_logic; -- i2c data line output sda_oen : out std_logic -- i2c data line output enable, active low );end entity i2c_master_byte_ctrl;architecture structural of i2c_master_byte_ctrl is component i2c_master_bit_ctrl is port ( clk : in std_logic; rst : in std_logic; nReset : in std_logic; ena : in std_logic; -- core enable signal clk_cnt : in unsigned(15 downto 0); -- clock prescale value cmd : in std_logic_vector(3 downto 0); cmd_ack : out std_logic; -- command done busy : out std_logic; -- i2c bus busy al : out std_logic; -- arbitration lost din : in std_logic; dout : out std_logic; -- i2c lines scl_i : in std_logic; -- i2c clock line input scl_o : out std_logic; -- i2c clock line output scl_oen : out std_logic; -- i2c clock line output enable, active low sda_i : in std_logic; -- i2c data line input sda_o : out std_logic; -- i2c data line output sda_oen : out std_logic -- i2c data line output enable, active low ); end component i2c_master_bit_ctrl; -- commands for bit_controller block constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000"; constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001"; constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010"; constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100"; constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000"; -- signals for bit_controller signal core_cmd : std_logic_vector(3 downto 0); signal core_ack, core_txd, core_rxd : std_logic; signal al : std_logic; -- signals for shift register signal sr : std_logic_vector(7 downto 0); -- 8bit shift register signal shift, ld : std_logic; -- signals for state machine signal go, host_ack : std_logic; signal dcnt : unsigned(2 downto 0); -- data counter signal cnt_done : std_logic;begin -- hookup bit_controller bit_ctrl: i2c_master_bit_ctrl port map( clk => clk, rst => rst, nReset => nReset, ena => ena, clk_cnt => clk_cnt, cmd => core_cmd, cmd_ack => core_ack, busy => i2c_busy, al => al, din => core_txd, dout => core_rxd, scl_i => scl_i, scl_o => scl_o, scl_oen => scl_oen, sda_i => sda_i, sda_o => sda_o, sda_oen => sda_oen ); i2c_al <= al; -- generate host-command-acknowledge cmd_ack <= host_ack; -- generate go-signal go <= (read or write or stop) and not host_ack; -- assign Dout output to shift-register dout <= sr; -- generate shift register shift_register: process(clk, nReset) begin if (nReset = '0') then sr <= (others => '0'); elsif (clk'event and clk = '1') then if (rst = '1') then sr <= (others => '0'); elsif (ld = '1') then sr <= din; elsif (shift = '1') then sr <= (sr(6 downto 0) & core_rxd); end if; end if; end process shift_register; -- generate data-counter data_cnt: process(clk, nReset) begin if (nReset = '0') then dcnt <= (others => '0'); elsif (clk'event and clk = '1') then if (rst = '1') then dcnt <= (others => '0'); elsif (ld = '1') then dcnt <= (others => '1'); -- load counter with 7 elsif (shift = '1') then dcnt <= dcnt -1; end if; end if; end process data_cnt; cnt_done <= '1' when (dcnt = 0) else '0'; -- -- state machine -- statemachine : block type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop); signal c_state : states; begin -- -- command interpreter, translate complex commands into simpler I2C commands -- nxt_state_decoder: process(clk, nReset) begin if (nReset = '0') then core_cmd <= I2C_CMD_NOP; core_txd <= '0'; shift <= '0'; ld <= '0'; host_ack <= '0'; c_state <= st_idle; ack_out <= '0'; elsif (clk'event and clk = '1') then if (rst = '1' or al = '1') then core_cmd <= I2C_CMD_NOP; core_txd <= '0'; shift <= '0'; ld <= '0'; host_ack <= '0'; c_state <= st_idle; ack_out <= '0'; else -- initialy reset all signal core_txd <= sr(7); shift <= '0'; ld <= '0'; host_ack <= '0'; case c_state is when st_idle => if (go = '1') then if (start = '1') then c_state <= st_start; core_cmd <= I2C_CMD_START; elsif (read = '1') then c_state <= st_read; core_cmd <= I2C_CMD_READ; elsif (write = '1') then c_state <= st_write; core_cmd <= I2C_CMD_WRITE; else -- stop c_state <= st_stop; core_cmd <= I2C_CMD_STOP; end if; ld <= '1'; end if; when st_start => if (core_ack = '1') then if (read = '1') then c_state <= st_read; core_cmd <= I2C_CMD_READ; else c_state <= st_write; core_cmd <= I2C_CMD_WRITE; end if; ld <= '1'; end if; when st_write => if (core_ack = '1') then if (cnt_done = '1') then c_state <= st_ack; core_cmd <= I2C_CMD_READ; else c_state <= st_write; -- stay in same state core_cmd <= I2C_CMD_WRITE; -- write next bit shift <= '1'; end if; end if; when st_read => if (core_ack = '1') then if (cnt_done = '1') then c_state <= st_ack; core_cmd <= I2C_CMD_WRITE; else c_state <= st_read; -- stay in same state core_cmd <= I2C_CMD_READ; -- read next bit end if; shift <= '1'; core_txd <= ack_in; end if; when st_ack => if (core_ack = '1') then -- check for stop; Should a STOP command be generated ? if (stop = '1') then c_state <= st_stop; core_cmd <= I2C_CMD_STOP; else c_state <= st_idle; core_cmd <= I2C_CMD_NOP; -- generate command acknowledge signal host_ack <= '1'; end if; -- assign ack_out output to core_rxd (contains last received bit) ack_out <= core_rxd; core_txd <= '1'; else core_txd <= ack_in; end if; when st_stop => if (core_ack = '1') then c_state <= st_idle; core_cmd <= I2C_CMD_NOP; -- generate command acknowledge signal host_ack <= '1'; end if; when others => -- illegal states c_state <= st_idle; core_cmd <= I2C_CMD_NOP; report ("Byte controller entered illegal state."); end case; end if; end if; end process nxt_state_decoder; end block statemachine;end architecture structural;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -