Bare Bones I2C Master Writer


Recommended Posts

My design only requires me to perform some I2C writes to initialize a couple of devices. After trying several different methods and being new to FPGA in general I found that this solution was even simpler than implementing PicoBlaze.

Customizing

To define the I2C writes performed look inside SimpleI2CCore.vhd where you will find an array called seq:


constant seq: seqT:= (
-- RESET CAM
(idle, x"00"),
(start, x"00"),
(const, TCM_DEV_ADDR & '0'),
(const, TCM_REG_SLEEP),
(const, TCM_SOFT_RESET),
(stop, x"00"),

.
.
.

(start, x"00"),
(const, VIDEO_ENCODER_ADDR & '0'),
(const, VIDEO_CONTROL_5),
(const, x"60"),
(stop, x"00"),
-- end
(idle, x"00")
);

Change the const values to the appropriate ones for your device(s). In the attached project there are several writes defined for two different devices, you can remove/add as many as you like just always ensure your last value is idle so that it releases the SCL and SDA lines. Also note the device address constants are 7 bits.

Remember to modify the top boundary of the array here:


type seqT is array(0 to 41) of i2cT;

With a 24Mhz input clock, it produces a 100KHz I2C clock. The additional DCM in the attached project that provides 27MHz is only to drive the external I2C devices and can be removed or modified as needed.

Live output from Papilio:

simplei2c.jpg

Hopefully others will find this as useful as I did :)

This post has been promoted to an article

post-29506-0-68722300-1349883293_thumb.j

SimpleI2C.zip

Link to comment
Share on other sites

I see that you plan to use (or are using) a TCM8230 camera module and a video encoder, what is your project goal ?

Currently I have the camera feeding live video data into a dual port RAMB based SRAM frame buffer. The output side of the frame buffer is read by the the video encoder whose output I am feeding to a wireless video transmitter. The contents of the frame buffer also can be sent over serial to acquire snapshots. Plans to add character generator for external sensor reading text overlays and some digital processing of the raw data coming from the camera for tracking.

The need to use as much RAMB for video data processing as possible and only needing to perform I2C writes on power up/reset is what drove me to find the smallest I2C solution I could find as my initial use of the AVR8 softcore (and even later PicoBlaze) turned out to be too much overhead.

I posted about my initial experimentation with the camera here at SparkFun.

Analyzing a snapshot taken with the camera to develop a color map for segmentation and tracking

WME%20-%20Vision%20Color%20Mapping%20Cyl%20and%20Cube.jpg

Link to comment
Share on other sites

Nice coding style indeed! Very clean.

One thing you could do to avoid changing the seqT type when you add/remove I2C commands from your constant is define the type as:

[tt]    type seqT is array(natural range <>) of i2cT;[/tt]

then the type is unconstrained and the the constant [tt]seq[/tt] can vary in length.

You need to change the index signal to:

[tt]    signal  idxSeq:        integer range seq'range;[/tt]

and change all the [tt]seqT'low[/tt] to [tt]seq'left[/tt] and the [tt]seqT'high[/tt] to [tt]seq'right[/tt].

I ran your testbench with these changes and it looked like it worked fine.  And, it got through XST without error.

That's the great thing about VHDL: lots of ways to do the same thing (and its the bad thing about VHDL, also.  ;D ).

-vn

Link to comment
Share on other sites

  • 4 months later...
  • 4 weeks later...

Hi,

could you please repost your SimpleI2c.zip files. I cannot unzip the ones already posted above by using winzip or 7z. I get a message from winzip saying that the file is missing 7193 bytes.

thanks

pp

The attachments are fixed you can download them now

Link to comment
Share on other sites

  • 10 months later...

Nice coding style indeed! Very clean.

One thing you could do to avoid changing the seqT type when you add/remove I2C commands from your constant is define the type as:

[tt]    type seqT is array(natural range <>) of i2cT;[/tt]

then the type is unconstrained and the the constant [tt]seq[/tt] can vary in length.

You need to change the index signal to:

[tt]    signal  idxSeq:        integer range seq'range;[/tt]

and change all the [tt]seqT'low[/tt] to [tt]seq'left[/tt] and the [tt]seqT'high[/tt] to [tt]seq'right[/tt].

I ran your testbench with these changes and it looked like it worked fine.  And, it got through XST without error.

That's the great thing about VHDL: lots of ways to do the same thing (and its the bad thing about VHDL, also.  ;D ).

-vn

 

seq'low and seq'high will also work.

 

----------------

re: original post

I noticed in your simulation you specified the clock period to be 10 ps.  I don't understand why you would do that, as the simulation does not represent the real world signaling.  In simulations, you should always specify the expected clock period. 

 

-- Clock period definitions

constant clk24_freq : real := 24.0; -- MHz

constant clk24_period : time := (1000.0/clk24_freq) * 1 ns;

 

-----------  like this ^^ ----------

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.