📄 i2c_master_bit_ctrl.vhd
字号:
ELSIF (Clk'EVENT AND Clk = '1') THEN
sta_condition <= ((NOT sSDA) AND dSDA) AND sSCL;--hold '1' for 1 clock
sto_condition <= (sSDA AND (NOT dSDA)) AND sSCL;--Slave release the bus
END IF;
END PROCESS detect_sta_sto;
-- generate i2c-bus busy signal
gen_busy: process(Clk, Reset_n)
BEGIN
IF (Reset_n = '0') THEN
ibusy <= '0';
ELSIF (Clk'EVENT AND Clk = '1') THEN
ibusy <= (sta_condition OR ibusy) AND (NOT sto_condition);
END IF;
END PROCESS gen_busy;
busy <= ibusy;
-- generate arbitration lost signal
-- aribitration lost when:
-- 1) master drives SDA high, but the i2c bus is low
-- 2) stop detected while not requested (detect during 'idle' state)
-- gen_al: PROCESS(Clk, Reset_n)
-- BEGIN
-- IF (Reset_n = '0') THEN
-- cmd_stop <= '0';
-- ial <= '0';
-- ELSIF (Clk'EVENT AND Clk = '1') THEN
-- IF (clk_en = '1') THEN
-- IF (cmd = I2C_CMD_STOP) THEN
-- cmd_stop <= '1';
-- ELSE
-- cmd_stop <= '0';
-- END IF;
-- END IF;
-- IF (c_state = idle) THEN
-- ial <= (sda_chk AND (NOT sSDA) AND isda_oen);
-- ELSE
-- ial <= (sda_chk AND (NOT sSDA) AND isda_oen) OR (sto_condition AND (NOT cmd_stop));
-- END IF;
-- END IF;
-- END PROCESS gen_al;
-- al <= ial;
-- generate dout signal, store dout on rising edge of SCL
gen_dout: PROCESS(Clk)
BEGIN
IF (Clk'EVENT AND Clk = '1') THEN
IF (sSCL = '1' AND dSCL = '0') THEN
dout <= sSDA;
ELSE
Null;
END IF;
END IF;
END PROCESS gen_dout;
END BLOCK bus_status_ctrl;
-- generate statemachine
nxt_state_decoder : PROCESS (Clk, Reset_n, c_state, cmd)
BEGIN
IF (Reset_n = '0') THEN
c_state <= idle;
cmd_ack <= '0';---
--iscl_oen <= '0';---
isda_oen <= '0';---
iscl_o <= '1';--- reset '1';
isda_o <= '1';---
-- sda_chk <= '0';
ELSIF (Clk'EVENT AND Clk = '1') THEN
-- IF (ial = '1') THEN
-- c_state <= idle;
-- cmd_ack <= '0';
-- iscl_oen <= '1';
-- isda_oen <= '1';
-- sda_chk <= '0';
-- ELSE
cmd_ack <= '0'; -- default no acknowledge
IF (clk_en = '1') THEN
CASE (c_state) IS
-- idle
WHEN idle =>
CASE cmd IS
WHEN I2C_CMD_START => c_state <= start_a;
WHEN I2C_CMD_STOP => c_state <= stop_a;
WHEN I2C_CMD_WRITE => c_state <= wr_a;
WHEN I2C_CMD_READ => c_state <= rd_a;
WHEN others => c_state <= idle; -- NOP command
END CASE;
--iscl_oen <= iscl_oen; -- keep SCL in same state
isda_oen <= isda_oen; -- keep SDA in same state
iscl_o <= iscl_o;---
isda_o <= isda_o;---
-- sda_chk <= '0'; -- don't check SDA
-- start
WHEN start_a =>
c_state <= start_b;
--iscl_oen <= '0';
isda_oen <= '0';
iscl_o <= iscl_o; -- keep SCL in same state (for repeated start)
isda_o <= '1'; -- set SDA high
-- sda_chk <= '0'; -- don't check SDA
WHEN start_b =>
c_state <= start_c;
--iscl_oen <= '0'; -- set SCL high
isda_oen <= '0'; -- keep SDA high
iscl_o <= '1';
isda_o <= '1';
-- sda_chk <= '0'; -- don't check SDA
WHEN start_c =>
c_state <= start_d;
--iscl_oen <= '0'; -- keep SCL high
isda_oen <= '0'; -- set SDA low
iscl_o <= '1';
isda_o <= '0';
-- sda_chk <= '0'; -- don't check SDA
WHEN start_d =>
c_state <= start_e;
--iscl_oen <= '0'; -- keep SCL high
isda_oen <= '0'; -- keep SDA low
iscl_o <= '1';
isda_o <= '0';
-- sda_chk <= '0'; -- don't check SDA
WHEN start_e =>
c_state <= idle;
cmd_ack <= '1'; -- command completed
--iscl_oen <= '0'; -- set SCL low
isda_oen <= '0'; -- keep SDA low
iscl_o <= '0';
isda_o <= '0';
-- sda_chk <= '0'; -- don't check SDA
-- stop
WHEN stop_a =>
c_state <= stop_b;
--iscl_oen <= '0'; -- keep SCL low
isda_oen <= '0'; -- set SDA low
iscl_o <= '0';
isda_o <= '0';
-- sda_chk <= '0'; -- don't check SDA
WHEN stop_b =>
c_state <= stop_c;
--iscl_oen <= '0'; -- set SCL high
isda_oen <= '0'; -- keep SDA low
iscl_o <= '1';
isda_o <= '0';
-- sda_chk <= '0'; -- don't check SDA
WHEN stop_c =>
c_state <= stop_d;
--iscl_oen <= '0'; -- keep SCL high
isda_oen <= '0'; -- keep SDA low
iscl_o <= '1';
isda_o <= '0';
-- sda_chk <= '0'; -- don't check SDA
WHEN stop_d =>
c_state <= idle;
cmd_ack <= '1'; -- command completed
--iscl_oen <= '0'; -- keep SCL high
isda_oen <= '0'; -- set SDA high
iscl_o <= '1';
isda_o <= '1';
-- sda_chk <= '0'; -- don't check SDA
-- read
WHEN rd_a =>
c_state <= rd_b;
--iscl_oen <= '0'; -- keep SCL low
isda_oen <= '1'; -- tri-state SDA
iscl_o <= '0';
-- sda_chk <= '0'; -- don't check SDA
WHEN rd_b =>
c_state <= rd_c;
--iscl_oen <= '0'; -- set SCL high
isda_oen <= '1'; -- tri-state SDA
iscl_o <= '1';
-- sda_chk <= '0'; -- don't check SDA
WHEN rd_c =>
c_state <= rd_d;
--iscl_oen <= '0'; -- keep SCL high
isda_oen <= '1'; -- tri-state SDA
iscl_o <= '1';
-- sda_chk <= '0'; -- don't check SDA
WHEN rd_d =>
c_state <= idle;
cmd_ack <= '1'; -- command completed
--iscl_oen <= '0'; -- set SCL low
isda_oen <= '1'; -- tri-state SDA
iscl_o <= '0';
-- sda_chk <= '0'; -- don't check SDA
-- write
WHEN wr_a =>
c_state <= wr_b;
--iscl_oen <= '0'; -- keep SCL low
isda_oen <= '0'; -- set SDA
iscl_o <= '0';
isda_o <= din;
-- sda_chk <= '0'; -- don't check SDA (SCL low)
WHEN wr_b =>
c_state <= wr_c;
--iscl_oen <= '0'; -- set SCL high
isda_oen <= '0'; -- keep SDA
iscl_o <= '1';
isda_o <= din;
-- sda_chk <= '1'; -- check SDA
WHEN wr_c =>
c_state <= wr_d;
--iscl_oen <= '0'; -- keep SCL high
isda_oen <= '0'; -- keep SDA
iscl_o <= '1';
isda_o <= din;
-- sda_chk <= '1'; -- check SDA
WHEN wr_d =>
c_state <= idle;
cmd_ack <= '1'; -- command completed
--iscl_oen <= '0'; -- set SCL low
isda_oen <= '0'; -- keep SDA
iscl_o <= '0';
isda_o <= din;
-- sda_chk <= '0'; -- don't check SDA (SCL low)
WHEN OTHERS => NULL;
END CASE;
END IF;
-- END IF;
END IF;
END PROCESS nxt_state_decoder;
-- assign outputs
scl_o <= iscl_o;
-- scl_oen <= iscl_oen;
sda_o <= isda_o;
sda_oen <= isda_oen;
END ARCHITECTURE structural;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -