EmbDev.net

Forum: FPGA, VHDL & Verilog Can Someone Help Me Write an I2C Controller


Author: Joe Daddy (paparit432)
Posted on:

Rate this post
0 useful
not useful
It should be a an I2C Controller than can perform a single byte write. 
Compensation may be considered

Author: PittyJ (Guest)
Posted on:

Rate this post
0 useful
not useful
Tell us, what you already know and have.
How far are you with your current code?
What is the problem in detail?

Author: Martin (Guest)
Posted on:

Rate this post
0 useful
not useful
Do you have to write it on your own?
Otherwise have a look at: http://opencores.org/project,i2c

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Joe Daddy wrote:
> It should be a an I2C Controller than can perform a single byte write.
I have one written in Assembler, runing on a NEC uPD78017663A.
Will that be ok?

Author: Joe Daddy (paparit432)
Posted on:

Rate this post
0 useful
not useful
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY i2c_master IS
  GENERIC(
    input_clk : INTEGER := 50_000_000; --input clock speed from user logic in Hz
    bus_clk   : INTEGER := 400_000);   --speed the i2c bus (scl) will run at in Hz
  PORT(
    clk       : IN     STD_LOGIC;                    --system clock
    reset_n   : IN     STD_LOGIC;                    --active low reset
    ena       : IN     STD_LOGIC;                    --latch in command
    addr      : IN     STD_LOGIC_VECTOR(6 DOWNTO 0); --address of target slave
    rw        : IN     STD_LOGIC;                    --'0' is write, '1' is read
    data_wr   : IN     STD_LOGIC_VECTOR(7 DOWNTO 0); --data to write to slave
    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
END i2c_master;

ARCHITECTURE logic OF i2c_master IS
  CONSTANT divider  :  INTEGER := (input_clk/bus_clk)/4; --number of clocks in 1/4 cycle of scl
  TYPE machine IS(ready, start, command, slv_ack1, wr, rd, slv_ack2, mstr_ack, stop); --needed states
  SIGNAL  state     :  machine;                          --state machine
  SIGNAL  data_clk  :  STD_LOGIC;                        --clock edges for sda
  SIGNAL  scl_clk   :  STD_LOGIC;                        --constantly running internal scl
  SIGNAL  scl_ena   :  STD_LOGIC := '0';                 --enables internal scl to output
  SIGNAL  sda_int   :  STD_LOGIC := '1';                 --internal sda
  SIGNAL  sda_ena_n :  STD_LOGIC;                        --enables internal sda to output
  SIGNAL  addr_rw   :  STD_LOGIC_VECTOR(7 DOWNTO 0);     --latched in address and read/write
  SIGNAL  data_tx   :  STD_LOGIC_VECTOR(7 DOWNTO 0);     --latched in data to write to slave
  SIGNAL  data_rx   :  STD_LOGIC_VECTOR(7 DOWNTO 0);     --data received from slave
  SIGNAL  bit_cnt   :  INTEGER RANGE 0 TO 7 := 7;        --tracks bit number in transaction
  SIGNAL  stretch   :  STD_LOGIC := '0';                 --identifies if slave is stretching scl
BEGIN

  --generate the timing for the bus clock (scl_clk) and the data clock (data_clk)
  PROCESS(clk, reset_n)
    VARIABLE count : INTEGER RANGE 0 TO divider*4; --timing for clock generation
  BEGIN
    IF(reset_n = '0') THEN               --reset asserted
      stretch <= '0';
      count := 0;
    ELSIF(clk'EVENT AND clk = '1') THEN
      IF(count = divider*4-1) THEN       --end of timing cycle
        count := 0;                      --reset timer
      ELSIF(stretch = '0') THEN          --clock stretching from slave not detected
        count := count + 1;              --continue clock generation timing
      END IF;
      CASE count IS
        WHEN 0 TO divider-1 =>           --first 1/4 cycle of clocking
          scl_clk <= '0';
          data_clk <= '0';
        WHEN divider TO divider*2-1 =>   --second 1/4 cycle of clocking
          scl_clk <= '0';
          data_clk <= '1';
        WHEN divider*2 TO divider*3-1 => --third 1/4 cycle of clocking
          scl_clk <= 'Z';                --release scl
          IF(scl = '0') THEN             --detect if slave is stretching clock
            stretch <= '1';
          ELSE
            stretch <= '0';
          END IF;
          data_clk <= '1';
        WHEN OTHERS =>                   --last 1/4 cycle of clocking
          scl_clk <= 'Z';
          data_clk <= '0';
      END CASE;
    END IF;
  END PROCESS;

Author: Joe Daddy (paparit432)
Posted on:

Rate this post
0 useful
not useful
The above code is what I have so far. I know it is incomplete, but I 
need the I2c to perform a single byte write and a single byte read. At 
this point I am confused on where to go from here.

Author: Duke Scarring (Guest)
Posted on:

Rate this post
0 useful
not useful
Do you have a testbench?
Without testbench simulation is not possible. Test on hardware Without 
simulation is like Russian roulette...

Duke

Author: Manni (Guest)
Posted on:

Rate this post
0 useful
not useful
>Russian roulette...
You mean, we all can die from a bad coding?

I have a question about this subject: Does anybody know about I2C 
patents a license issues? I recently was told I2C was under protection 
and has to b licensed for commercial use.

Author: Max (Guest)
Posted on:

Rate this post
0 useful
not useful
Atmel showed how to bypass the License, just call it twi :-)

Author: Joe Daddy (paparit432)
Posted on:

Rate this post
0 useful
not useful
I am willing to compensate anyone who is willing to assist me

Author: Tom (Guest)
Posted on:

Rate this post
0 useful
not useful
Do you have a requirement SPEC?
Hourly Rates for such projects are around €60,-

Author: Fitzebutze (Guest)
Posted on:

Rate this post
0 useful
not useful
Hi,

I've got an i2c single master-only engine ready, but it kinda requires a 
soft CPU to be useful. Basically it is a module of a System on Chip 
design.

Example access (from the soft CPU core firmware):
int i2c_write16(unsigned int addr, unsigned int data)
{
  MMR(I2C_Ctrl)      = 1-1; // One byte per transaction
  MMR(I2C_SlaveAddr) = (addr >> 15) & ~1; // Write address
  MMR(I2C_WData)     = (addr >> 8) & 0xff;
  wait_ready();
  MMR(I2C_WData)     = addr & 0xff;
  wait_ready();
  MMR(I2C_WData)     = data >> 8;
  wait_ready();
  MMR(I2C_WData)     = data;
  wait_ready();

  while ((MMR(I2C_Stat) & INACK)); // wait until stop phase reached
  if (MMR(I2C_Stat) & NAK) return -1; 

  return 0;
}

In order to draft some pecuniary house numbers of the support expenses, 
you might have to post more about the requirements (what HW it should 
support, what soft core you'd be using, etc. )
BTW: No need to worry about any licensing issues, the patent has expired 
a while ago.

Greetings,

Butze

Author: Joe Daddy (paparit432)
Posted on:

Rate this post
0 useful
not useful
To Fitzebutze,

Can you send me an email to paparit432@yahoo.com? I wanna discuss the 
I2C controller further in depth and I also want to send you additional 
documents regarding this as well?

Author: Joe Daddy (paparit432)
Posted on:

Rate this post
0 useful
not useful
Tom wrote:
> Do you have a requirement SPEC?
> Hourly Rates for such projects are around €60,-

Yes.

Send me a personal message @ paparit432@yahoo.com and we can talk 
further.

Author: fpgaengineer (Guest)
Posted on:

Rate this post
0 useful
not useful
is this project still open? i could provide you with a working scalable 
iwc controller offering a dynamic number of inputs and outputs 
configurable by genererics, data is stored in brams

it comes complete with testbench and implementation example for both 
xilinx and altera devices

Author: Joe Daddy (paparit432)
Posted on:

Rate this post
0 useful
not useful
fpgaengineer wrote:
> is this project still open? i could provide you with a working scalable
> iwc controller offering a dynamic number of inputs and outputs
> configurable by genererics, data is stored in brams
>
> it comes complete with testbench and implementation example for both
> xilinx and altera devices

Please email me at paparit432@yahoo.com

Author: Wayne Gretzky (Guest)
Posted on:

Rate this post
0 useful
not useful
You want to pay for a simple i2C?  For a fex lines of code?
Why not using OS?

Author: Anush Kompally (Guest)
Posted on:

Rate this post
0 useful
not useful
Hello there,

Can you tell me why the divider in the code is set to 
"(input_clk/bus_clk)/4".

Author: anynomous (Guest)
Posted on:

Rate this post
0 useful
not useful
because it takes various operarion frequencies into account

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.