daisyzari
Junior Member level 3
We were able to write a data to our slave which is an EEPROM atmel 24C04 but we can't seem to read from it.
Please help
Thank You.. :smile:
This is our code
Ignore the comments. It's quite confusing because i fail to change some of it when i edited some of the codes. :razz:
Please help
Thank You.. :smile:
This is our code
Code:
--
--
-- State machine for reading data from EEPROM
--
-- Testsystem for i2c controller
--
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.i2c.all;
entity I2C_TOP is
port (
clk : in std_logic;
nReset : in std_logic;
-- data from EEPROM
Dprom : out std_logic_vector(7 downto 0); -- out from interface; in to i2c
error : out std_logic; -- no correct ack received
SCL : inout std_logic;
SDA : inout std_logic
);
end entity I2C_TOP;
architecture structural of I2C_TOP is
constant SLAVE_ADDR : std_logic_vector(6 downto 0) := "1010001";
constant PROM_HBYT : std_logic_vector(7 downto 0) := x"01";
constant PROM_LBYT : std_logic_vector(7 downto 0) := x"AB";
constant PROM_HBYT_R : std_logic_vector(7 downto 0) := x"00";
constant PROM_LBYT_R : std_logic_vector(7 downto 0) := x"FF";
constant CLK_CNT : unsigned(7 downto 0) := conv_unsigned(100, 8); --28 binary
signal cmd_ack : std_logic;
signal D : std_logic_vector(7 downto 0);
signal lack : std_logic;
signal start, RDRF, TDRE, ack, stop : std_logic;
signal i2c_dout : std_logic_vector(7 downto 0);
begin
-- instantiate to i2c_statemachine
u1: i2c_statemachine port map (clk => clk, ena => '1', clk_cnt => clk_cnt, nReset => nReset,
RDRF => RDRF, TDRE => TDRE, start => start, stop => stop, ack_in => ack, cmd_ack => cmd_ack,
Din => D, Dout => i2c_dout, ack_out => lack, SCL => SCL, SDA => SDA);
interface : block -- grouping,organizing
type states_w is (i1, i2, i3, i4, i5);
type states_r is (t1, t2, t3, t4, t5, t6, t7);
type states_all is (a1, a2);
signal state_write : states_w;
signal state_read : states_r;
signal state_all : states_all;
begin
state_decoder: process(clk, nReset, state_write, state_read, state_all)
variable nxt_state_w : states_w;
variable nxt_state_r : states_r;
variable nxt_state_all : states_all;
variable iD : std_logic_vector(7 downto 0);
variable ierr : std_logic;
variable istart, iread, iwrite, iack, istop : std_logic;
--variable istore_dout : std_logic;
begin
nxt_state_w := state_write;
nxt_state_r := state_read;
nxt_state_all := state_all;
ierr := '0';
istart := start;
iread := RDRF;
iwrite := TDRE;
iack := ack;
istop := stop;
iD := D;
case (state_all) is
when a1 => --write
case (state_write) is
when i1 => -- send start condition, sent slave address + write
istart := '1';
iread := '0';
iwrite := '1';
iack := '0'; -- means acknowledged
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
istop := '1';
nxt_state_w := i2;
when i2 => -- send start condition, sent slave address + write
if (cmd_ack = '1') then
nxt_state_w := i3;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received, acknowledge is always 0
end if;
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
end if;
-- send PROM highbit
when i3 =>
if (cmd_ack = '1') then
nxt_state_w := i4;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := PROM_HBYT;
end if;
-- send PROM lowbit
when i4 =>
if (cmd_ack = '1') then
nxt_state_w := i5;
-- check aknowledge bit
if (lack = '1') then
ierr := '1';
-- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := PROM_LBYT;
end if;
when i5 =>
if (cmd_ack = '1') then
nxt_state_all :=a2;
if (lack = '1') then
ierr := '1';
-- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '1';
iD := x"55";
end if;
end case;
when a2 => -- read
case(state_read) is
when t1 => -- send start condition, sent slave address + write
if (cmd_ack = '1') then
nxt_state_r := t2;
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '1';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
end if;
when t2 => -- send start condition, sent slave address + write
if (cmd_ack = '1') then
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '0'); -- write to slave (R/W = '0')
nxt_state_r := t3;
end if;
when t3 => -- send PROM highbit
if (cmd_ack = '1') then
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := PROM_HBYT_R;
nxt_state_r := t4;
end if;
when t4 => -- send PROM lowbit
if (cmd_ack = '1') then
-- check aknowledge bit
if (lack = '1') then
ierr := '1';
-- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := PROM_LBYT_R;
nxt_state_r := t5;
end if;
when t5 => -- send (repeated) start condition, send slave address + read
if (cmd_ack = '1') then
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received, expected ACK
end if;
istart := '1';
iread := '0';
iwrite := '1';
iack := '0';
istop := '0';
iD := (slave_addr & '1'); -- read from slave (R/W = '1')
nxt_state_r := t6;
end if;
when t6 => -- read MSB (hi-byte), send acknowledge
if (cmd_ack = '1') then
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '1';
iwrite := '0';
iack := '1'; --NACK
istop := '1';
nxt_state_r := t7;
end if;
when t7 => -- read MSB (hi-byte), send acknowledge
if (cmd_ack = '1') then
-- check aknowledge bit
if (lack = '1') then
ierr := '1'; -- no acknowledge received from last command, expected ACK
end if;
istart := '0';
iread := '0';
iwrite := '0';
iack := '0'; --NACK
istop := '0';
iD := x"00";
end if;
end case;
end case;
-- genregs
if (nReset = '0') then
state_all <= a1;
state_write <=i1;
state_read <=t1;
error <= '0';
start <= '0';
RDRF <= '0';
TDRE <= '0';
ack <= '0';
stop <= '0';
D <= (others => '0');
elsif (clk'event and clk = '1') then
state_all <= nxt_state_all;
state_write <= nxt_state_w;
state_read <= nxt_state_r;
error <= ierr;
start <= istart;
RDRF <= iread;
TDRE <= iwrite;
ack <= iack;
stop <= istop;
D <= iD;
end if;
end process state_decoder;
end block interface;
end architecture structural;
--Note: 8bits per data + 1 bit extra new command after 9th bit
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
--for easier access
package I2C is
component i2c_statemachine is
port (
clk : in std_logic;
ena : in std_logic;
nReset : in std_logic;
clk_cnt : in unsigned(7 downto 0); -- 4x SCL
-- input signals
start,
stop,
RDRF,
TDRE,
ack_in : std_logic;
Din : in std_logic_vector(7 downto 0);
-- output signals
cmd_ack : out std_logic;
ack_out : out std_logic;
Dout : out std_logic_vector(7 downto 0);
-- i2c signals
SCL : inout std_logic;
SDA : inout std_logic
);
end component i2c_statemachine;
end package I2C;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity i2c_statemachine is
port (
clk : in std_logic;
ena : in std_logic;
nReset : in std_logic;
clk_cnt : in unsigned(7 downto 0); -- 4x SCL 128 CLK 32 SCL
-- input signals
start,
stop,
RDRF, -- signal for read
TDRE, -- Transmit Data Register Empty; '1' = empty means start writing
ack_in : std_logic;
Din : in std_logic_vector(7 downto 0);
-- output signals
cmd_ack : out std_logic;
ack_out : out std_logic;
Dout : out std_logic_vector(7 downto 0);
-- i2c signals
SCL : inout std_logic;
SDA : inout std_logic
);
end entity i2c_statemachine;
architecture structural of i2c_statemachine is
component i2c_base is
port (
clk : in std_logic;
nReset : in std_logic;
clk_cnt : in unsigned(7 downto 0); -- 4x SCL 128 CLK 32 SCL
cmd_act : in std_logic_vector(2 downto 0); --command for action
act_ack : out std_logic; --acknowledgement for action
Din : in std_logic;
Dout : out std_logic;
SCL : inout std_logic;
SDA : inout std_logic
);
end component i2c_base;
--important actions/commands for i2c base
constant act_no_op : std_logic_vector(2 downto 0) := "000";
constant act_start: std_logic_vector(2 downto 0) := "010";
constant act_write : std_logic_vector(2 downto 0) := "011";
constant act_read : std_logic_vector(2 downto 0) := "100";
constant act_idle : std_logic_vector(2 downto 0) := "101";-- SDA is high when idle
constant act_stop : std_logic_vector(2 downto 0) := "110";
-- signals for i2c_controller_base
signal core_cmd : std_logic_vector(2 downto 0);
signal core_ack, core_trans, core_rcve : std_logic;
-- signals for shift register
signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
signal shift, load : std_logic;
-- signals for state machine
signal en_act, master_ack : std_logic;
begin
-- instantiation to i2c_base
u1: i2c_base port map (clk, nReset, clk_cnt, core_cmd, core_ack, core_trans, core_rcve, SCL, SDA);
-- generate command-acknowledge on
cmd_ack <= master_ack;
-- assign ack_out output to core_rcve: should be equal to zero
ack_out <= core_rcve;
-- generate data register with+shift register
data_reg : block
--signals for data register
signal dr: std_logic_vector(7 downto 0);
begin
data_register: process(clk)
variable iempty :std_logic_vector(7 downto 0):= "00000000";
begin
if (clk'event and clk = '1') then
if (TDRE = '1') then
dr <=iempty;
dr <= Din;
end if;
if (load = '1') then
sr <= dr;
elsif (shift = '1') then
sr <= (sr(6 downto 0) & core_rcve); --last rcved bit :research
end if;
end if;
-- shift-register to Dout
Dout <= sr;
end process data_register;
end block data_reg;
-- grouping of state machine using black statement
statuscontrol_reg : block
type states is (st_no_op, st_start, st_read, st_write, st_ack, st_stop);
signal state : states;
signal dcnt : unsigned(2 downto 0);
begin
-- enable before startup
en_act <= (RDRF or TDRE) and not master_ack;
status_control: process(clk, nReset, state)
variable nxt_state : states;
variable idcnt : unsigned(2 downto 0);
variable imaster_ack : std_logic; --host acknowledge
variable icore_cmd : std_logic_vector(2 downto 0);
variable icore_trans : std_logic;
variable ishift, iload : std_logic;
begin
-- 8 databits (1byte) of data to shift-in/out
idcnt := dcnt;
-- no acknowledge (until command complete)
imaster_ack := '0';
icore_trans := core_trans;
icore_cmd := core_cmd;
-- no shifting or loading of shift-register
ishift := '0';
iload := '0';
-- keep current state;
nxt_state := state;
case state is
when st_no_op =>
if (en_act = '1') then
if (start = '1') then
nxt_state := st_start;
icore_cmd := act_start;
elsif (RDRF = '1') then
nxt_state := st_read;
icore_cmd := act_read;
idcnt := "111";
else
nxt_state := st_write;
icore_cmd := act_write;
idcnt := "111";
iload := '1';
end if;
end if;
when st_start =>
if (core_ack = '1') then
if (RDRF = '1') then
nxt_state := st_read;
icore_cmd := act_read;
idcnt := "111";
else
nxt_state := st_write;
icore_cmd := act_write;
idcnt := "111";
iload := '1';
end if;
end if;
when st_write =>
if (core_ack = '1') then
idcnt := dcnt -1; -- count down Data_counter
icore_trans := sr(7);
if (dcnt = 0) then
nxt_state := st_ack;
icore_cmd := act_idle;
else
ishift := '1';
-- icore_trans := sr(7);
end if;
end if;
when st_read =>
if (core_ack = '1') then
idcnt := dcnt -1; -- count down Data_counter
ishift := '1';
if (dcnt = 0) then
nxt_state := st_ack;
icore_cmd := act_idle;
icore_trans := ack_in;
end if;
end if;
when st_ack =>
if (core_ack = '1') then
-- generate command acknowledge signal
imaster_ack := '1';
-- Perform an additional shift, needed for 'read' (store last received bit in shift register)
ishift := '1';
-- check for stop; Should a STOP command be generated ?
if (stop = '1') then
nxt_state := st_stop;
icore_cmd := act_stop;
else
nxt_state := st_no_op;
icore_cmd := act_no_op;
end if;
end if;
when st_stop =>
if (core_ack = '1') then
nxt_state := st_no_op;
icore_cmd := act_no_op;
end if;
when others => -- illegal states
nxt_state := st_no_op;
icore_cmd := act_no_op;
end case;
-- generate registers
if (nReset = '0') then
core_cmd <= act_no_op;
core_trans <= '0';
shift <= '0';
load <= '0';
dcnt <= "111";
master_ack <= '0';
state <= st_no_op;
elsif (clk'event and clk = '1') then
if (ena = '1') then
state <= nxt_state;
dcnt <= idcnt;
shift <= ishift;
load <= iload;
core_cmd <= icore_cmd;
core_trans <= icore_trans;
master_ack <= imaster_ack;
end if;
end if;
end process status_control;
end block statuscontrol_reg;
end architecture structural;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity i2c_base is
port (
clk : in std_logic;
nReset : in std_logic;
clk_cnt : in unsigned(7 downto 0); -- 4x SCL 128 CLK 32 SCL
cmd_act : in std_logic_vector(2 downto 0); --command for action
act_ack : out std_logic; --acknowledgement for action
Din : in std_logic;
Dout : out std_logic;
SCL : inout std_logic;
SDA : inout std_logic
);
end entity i2c_base;
architecture structural of i2c_base is
--important actions/commands
constant act_no_op : std_logic_vector(2 downto 0) := "000";
constant act_start: std_logic_vector(2 downto 0) := "010";
constant act_write : std_logic_vector(2 downto 0) := "011";
constant act_read : std_logic_vector(2 downto 0) := "100";
constant act_idle : std_logic_vector(2 downto 0) := "101"; -- when idle sda is high
constant act_stop : std_logic_vector(2 downto 0) := "110";
type action is (no_op, idle_a, idle_b, idle_c, idle_d, start_a, start_b, start_c, start_d, start_e, start_f, stop_a, stop_b, stop_c, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);
signal state : action;
signal SDAo, SCLo : std_logic;
signal txd : std_logic;
signal clk_en, slave_wait :std_logic;
signal cnt : unsigned(7 downto 0) := clk_cnt;
begin
-- whenever the slave is not ready it can delay the cycle by pulling SCL low
slave_wait <= '1' when ((SCLo = '1') and (SCL = '0')) else '0';
-- clk_enable signal
gen_clken: process(clk, nReset)
begin
if (nReset = '0') then
cnt <= (others => '0');
clk_en <= '1'; --'0';
elsif (clk'event and clk = '1') then
if (cnt = 0) then
clk_en <= '1';
cnt <= clk_cnt; -- loading of clk_cnt when clk_en is disabled
else
if (slave_wait = '0') then
cnt <= cnt -1;
end if;
clk_en <= '0';
end if;
end if;
end process gen_clken;
-- statemachine for i2c_base
state_decoder : process (clk, nReset, state, cmd_act, SDA)
variable nxt_state : action;
variable iact_ack : std_logic;
variable itxd : std_logic;
begin
nxt_state := state;
iact_ack := '0'; -- default no acknowledge
itxd := txd;
case (state) is
-- no operation
when no_op =>
case (cmd_act) is
when act_start =>
nxt_state := start_a;
iact_ack := '1'; -- command completed
when act_stop =>
nxt_state := stop_a;
iact_ack := '1'; -- command completed
when act_write =>
nxt_state := wr_a;
iact_ack := '1'; -- command completed
itxd := Din;
when act_read =>
nxt_state := rd_a;
iact_ack := '1'; -- command completed
when act_idle=>
nxt_state := idle_a;
iact_ack := '1';
when others =>
nxt_state := no_op;
end case;
-- start
when start_a =>
nxt_state := start_b;
when start_b =>
nxt_state := start_c;
when start_c =>
nxt_state := start_d;
when start_d =>
nxt_state := start_e;
when start_e =>
nxt_state := start_f;
when start_f =>
nxt_state := no_op;
-- stop
when stop_a =>
nxt_state := stop_b;
when stop_b =>
nxt_state := stop_c;
when stop_c =>
-- nxt_state := stop_d;
-- when stop_d =>
nxt_state := no_op;
-- read
when rd_a =>
nxt_state := rd_b;
when rd_b =>
nxt_state := rd_c;
when rd_c =>
nxt_state := rd_d;
when rd_d =>
nxt_state := no_op;
-- write
when wr_a =>
nxt_state := wr_b;
when wr_b =>
nxt_state := wr_c;
when wr_c =>
nxt_state := wr_d;
when wr_d =>
nxt_state := no_op;
--idle
when idle_a =>
nxt_state := idle_b;
when idle_b =>
nxt_state := idle_c;
when idle_c =>
nxt_state := idle_d;
when idle_d =>
nxt_state := no_op;
end case;
-- Resetting
if (nReset = '0') then
state <= no_op;
act_ack <= '0';
txd <= '0';
Dout <= '0';
elsif (clk'event and clk = '1') then
if (clk_en = '1') then
state <= nxt_state;
txd <= itxd;
end if;
act_ack <= iact_ack and clk_en;--go back '0'
end if;
end process state_decoder;
--
-- convert states to SCL and SDA signals
--
output_decoder: process (clk, nReset, state)
variable iscl, isda : std_logic;
begin
case (state) is
--idle with spike
when no_op =>
iscl := SCLo; -- keep SCL in same state
isda := SDAo; -- keep SDA in same state
when idle_a =>
iscl := '0'; -- keep SCL low
-- isda := txd; -- set SDA
isda := '0';
when idle_b =>
iscl := '1'; -- set SCL high
isda := '0';
when idle_c =>
iscl := '1'; -- keep SCL high
-- isda := txd; -- set SDA
isda := '0';
when idle_d =>
iscl := '0'; -- set SCL low
isda := '1';
-- start
when start_a =>
iscl := SCLo; -- keep SCL in same state (for repeated start)
isda := '1'; -- set SDA high
when start_b =>
iscl := '1'; -- set SCL high
isda := '1'; -- keep SDA high
when start_c =>
iscl := '1'; -- keep SCL high
isda := '1'; -- sel SDA low
when start_d =>
iscl := '1'; -- set SCL low
isda := '0'; -- keep SDA low
when start_e =>
iscl := '1'; -- set SCL low
isda := '0'; -- keep SDA low
when start_f =>
iscl := '0'; -- set SCL low
isda := '0'; -- keep SDA low
-- stop
when stop_a =>
iscl := '0'; -- keep SCL disabled
isda := '0'; -- set SDA low
when stop_b =>
iscl := '1'; -- set SCL high
isda := '0'; -- keep SDA low
when stop_c =>
iscl := '1'; -- keep SCL high
isda := '1'; -- set SDA high
-- write
when wr_a =>
iscl := '0'; -- keep SCL low
-- isda := txd; -- set SDA
isda := Din;
when wr_b =>
iscl := '1'; -- set SCL high
-- isda := txd; -- set SDA
isda := Din;
when wr_c =>
iscl := '1'; -- keep SCL high
-- isda := txd; -- set SDA
isda := Din;
when wr_d =>
iscl := '0'; -- set SCL low
-- isda := txd; -- set SDA
isda := Din;
-- read
when rd_a =>
iscl := '0'; -- keep SCL low
isda := '1'; -- tri-state SDA
when rd_b =>
iscl := '1'; -- set SCL high
isda := '1'; -- tri-state SDA
when rd_c =>
iscl := '1'; -- keep SCL high
isda := '1'; -- tri-state SDA
when rd_d =>
iscl := '0'; -- set SCL low
isda := '1'; -- tri-state SDA
end case;
-- generate registers
if (nReset = '0') then
SCLo <= '1';
SDAo <= '1';
elsif (clk'event and clk = '1') then
if (clk_en = '1') then
SCLo <= iscl;
SDAo <= isda;
end if;
end if;
end process output_decoder;
SCL <= '0' when (SCLo = '0') else 'Z'; -- since SCL is externally pulled-up convert a '1' to a 'Z'(tri-state)
SDA <= '0' when (SDAo = '0') else 'Z'; -- since SDA is externally pulled-up convert a '1' to a 'Z'(tri-state)
-- SCL <= SCLo;
-- SDA <= SDAo;
end architecture structural;
Ignore the comments. It's quite confusing because i fail to change some of it when i edited some of the codes. :razz: