📄 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_UNSIGNED.ALL;
ENTITY i2c_master_byte_ctrl IS
PORT(
Clk : IN STD_LOGIC;
-- rst : IN STD_LOGIC; -- synchronous active high reset (WISHBONE compatible)
Reset_n : IN STD_LOGIC; -- asynchornous active low reset (FPGA compatible)
ena : IN STD_LOGIC; -- core enable signal
clk_cnt : IN STD_LOGIC_VECTOR(15 DOWNTO 0); -- 4x SCL
-- input signals
start : IN STD_LOGIC;
stop : IN STD_LOGIC;
read_en : IN STD_LOGIC;
write_en : IN STD_LOGIC;
ack_in : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
-- output signals
cmd_ack : OUT STD_LOGIC;
ack_out : OUT STD_LOGIC;
i2c_busy : OUT STD_LOGIC;
-- i2c_al : OUT STD_LOGIC;
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;
Reset_n : IN STD_LOGIC;
ena : IN STD_LOGIC; -- core enable signal
clk_cnt : IN STD_LOGIC_VECTOR(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 : STD_LOGIC_VECTOR(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,
Reset_n => Reset_n,
ena => ena,
clk_cnt => clk_cnt,
cmd => core_cmd,
cmd_ack => core_ack,
busy => i2c_busy,
-- 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_en OR write_en OR stop) AND (NOT host_ack);
-- assign Dout output to shift-register
dout <= sr;--????
-- generate shift register
shift_register: PROCESS(Clk, Reset_n)
BEGIN
IF (Reset_n = '0') THEN
sr <= (OTHERS => '0');
ELSIF (Clk'EVENT AND Clk = '1') THEN
IF (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, Reset_n)
BEGIN
IF (Reset_n = '0') THEN
dcnt <= (OTHERS => '0');
ELSIF (Clk'EVENT AND Clk = '1') THEN
IF (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, Reset_n)
BEGIN
IF (Reset_n = '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 (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_en = '1') THEN
c_state <= st_read;
core_cmd <= I2C_CMD_READ;
ELSIF (write_en = '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_en = '1') THEN--start and read
c_state <= st_read;
core_cmd <= I2C_CMD_READ;
ELSE--else start and write
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 + -