I2C core


Guest Blue12

Recommended Posts

Guest Blue12

So is there a current project working to get an I2c module together to simulate the one on the atmega103 or should I just make my own and write some vhdl to connect it to one of the eight bit ports of the processor?

If there is current work being done I would rather help/follow along with that so that it can be used with the IDE without having to make special functions myself to write to ports.

Anyways I was just wondering what was going on with that.

Link to comment
Share on other sites

Hello,

 

  Its probably not required to write a VHDL module for I2C if you just want to get up and running quickly.

 

  Without really digging into the details it looks like there are a couple  of I2C libraries for the Arduino that should be easy to make work.

  http://www.arduino.cc/en/Reference/Wire

  http://www.arduino.cc/playground/Learning/I2C

 

  I also saw somewhere that SMBus is related to I2C and we already have an  SMBus core that works with Ruslan's AVR128 project. It might be  possible to adapt the SMBus core to work with I2C also?

 

  I'm attaching the SMbus core if you want to look at it.

 

  Jack.

 

smbus_mod.zip

Link to comment
Share on other sites

Guest Blue12

I thought that the i2c libraries used the i2c hardware functionality of the chip? I looked at those examples and the functions did not seem to allow for specification of what pin will be used. It says pin 4 and pin 5 on the Arduino. How would I set what pins to use in the fpga?

Link to comment
Share on other sites

Ok, sorry, you are right. I quickly looked at the Atmega103 and Atmega128 datasheets and did not see any I2C functionality so I thought that the Arduino code was a software based solution. I should have been looking at the Atmega168 datasheet instead.

It looks like I2C bus will need to be implemented with VHDL or Verilog code. But according to wikipedia it looks like SMBus and I2C are very close so it might be easy to adapt the SMBus core.

I also see 5 different I2C implementations on OpenCores.com so we shouldn't have to start from scratch.

Jack.

Link to comment
Share on other sites

Guest Blue12

Sounds like an interesting task....Ohh thats funny, I just looked at the data sheet for the atmega 103 and it does not have i2c hardware functionality like the atmega 168 and 328 that are commonly found on arduino boards. So I guess that means we would not be able to stay consistent with the gcc compiler anyways, so adding the core to any place would be fine i guess...I still don't know how much this core relies on the gcc compiler(I mean the SFR positions and stuff) so I don't really know.

I was just trying think of the best way to implement the i2c core. For consistency I would think that would mean emulating the atmega 103 registers, but since the atmega 103 does not have those I2c registers perhaps it would be better to emulated the registers found in the 168 or 328...Since the atmega found on the arduino has special function registers at certain ram addresses. Since we won't be able to stay compatable with gcc anyways since the 103 does not have these registers I guess keeping the addresses in the same place would not be very important....but for instance....

the 328 has

TWBR - TWI Bit Rate Register @ 0xB8

TWCR - TWI Control Register @ 0xBC

TWSR - TWI Status Register @ 0xB9

TWDR - TWI Data Register @ 0xBB

TWAR - TWI Slave Address Register @ 0xBA

TWAMR - TWI Slave Address Mask Register @ 0xBD

So if we wanted similar functionality we would have to make some registers like that I guess...

Or perhaps it would be better to improve on their ic2 core and maybe make some fifos for sending out and receiving data...I don't really know I am new to this but it seems interesting. Ok I am going to stop rambling now.

Link to comment
Share on other sites

I think the best approach here is to make a core that implements all the  registers and functionality of the 2 wire peripheral defined in the Atmega168 datasheet. The registers don't need to be in the exact same locations as the registers are in the Atmega168, as long as the same registers are defined and they function in the same manner then we are fine.

Once we have this core defined then we can implement the core in the User I/O space and then make definitions in the Papilio header files in the Arduino IDE. These definitions will point to the registers in the User I/O space instead of the traditional Atmega168 locations. The end result is that any existing I2C code will behave in the same way as it would on an Atmega168.

BTW, I'm interviewing some VHDL coders since I'm swamped with business related tasks right now. The first task I'm asking them to do is to write this core. So if all goes well there may be a core defined soon.

Jack.

Link to comment
Share on other sites

BTW, I'm interviewing some VHDL coders since I'm swamped with business  related tasks right now. The first task I'm asking them to do is to  write this core. So if all goes well there may be a core defined soon.

Wanna hire me ? :P

That was just a joke. I do this for beer.  8)

Álvaro

Link to comment
Share on other sites

Guest Blue12

That sounds nice. I think that would be a good way to make it more compatible, I would like to be better at this so I can help more, but right now I am limited to small changes. Hopefully I can get better at this and make  some contributions. Thanks again this is a great project.

Link to comment
Share on other sites

  • 2 weeks later...

Blue12,

Good news, we have been working furiously on the ZPUino and AVR8 processors. Alvaro has added Wishbone to the ZPUino and Shielou has added Wishbone to the AVR8. So we are nicely positioned to quickly add new cores going forward.

Shielou even added a Wishbone I2C core into the AVR8, its all checked into github if you want to give it a test drive. Unfortunately I don't have any I2C chips to test with so we have not been able to do any real world verification yet. The core that Shielou implemented is: http://opencores.org/project,i2c

And the updated AVR8 is available on github at:

https://github.com/shielou/Arduino-Soft-Core

There should be a new tag for V1.5.1

Please be patient with us if there are any problems, there is a lot to get right here and it might take a few more updates.

Jack.

Link to comment
Share on other sites

Guest Blue12

I have some i2c chips to test this with...Sorry I am confused on how to write the code to access the hardware i2c. Do I just write the code like I am writing for a normal arduino, or do I need to write to a special memory address, like when using the custom core? Thanks again.

Link to comment
Share on other sites

I have some i2c chips to test this with...Sorry I am confused on how to write the code to access the hardware i2c. Do I just write the code like I am writing for a normal arduino, or do I need to write to a special memory address, like when using the custom core? Thanks again.

Hi Blue12,

Unfortunately we cannot use the normal Arduino libraries (e.g. Wire library) for the OpenCores I2C core since the registers and addresses are different from the Arduino/ATmega's I2C controller registers.

So we need to program it like the custom core. I've configured the base address of the OpenCores I2C as 0x1A00. You can then find the registers (and corresponding address offset) in the core's datasheet (see attached pdf). The sequence of register programming is also in the datasheet.

Let me know if you need further help. I've not yet started writing Arduino code for this I2C core. So it would be great if we could make it work.  :)

Lou

i2c_specs.pdf

Link to comment
Share on other sites

Guest Blue12

Well I guess I have a couple questions sorry if some of them are obvious...

1.What pins are scl and sda mapped to...I can't figure it out

2. How did you specify that the base address is 0x1A00? I don't see it in the vhdl like it is in the custom core?...and if I am not mistaken that is out of the ram space which ends at 0x1000(4kbytes)...well now I am second guessing myself...I just remember that jack had to move the custom core to address 0xFE0 for some reason...(edit...even FE0 is out of the data memory ram block 4kbytes is 0xFA0 in hex...so FE0 is higher than that....so I am not really sure why it was put there I assume that was a just vacant ram address outside of the ram blocks...it looks like the ram address bus in the avr8 core is 16 bit so I think that means that a custom core could be connected to any ram address up to 0xFFFF if I am not mistaken???Which I probably am).

I think I found the base address list (page 4)is it do I have this right?

PRERlo  0x00  8 RW Clock Prescale register lo-byte  =====>  0x1A00?

PRERhi  0x01  8 RW Clock Prescale register hi-byte  =====>  0x1A01?

CTR      0x02      8 RW Control register                  =====>  0x1A02?

TXR      0x03      8 W Transmit register                  =====>  0x1A03?

RXR      0x03    8 R Receive register                    =====>  0x1A03?

CR        0x04      8 W Command register                =====>  0x1A04?

SR        0x04      8 R Status register                      =====>  0x1A04?

It looks like 3 and 4 have different meanings depending on what mode it is in read/write.

I guess I should make another post for this question but....

I am also a bit confused on the wishbone bus...is it transparent to the processor or do I need to set some bits for it in the processor then set the bits and bytes for the i2c core as well?

Anyways Just let me know what is going on with those and I will try this thing out...I will keep reading in the mean time perhaps I have missed some things...thanks again!

Link to comment
Share on other sites

Guest Blue12

Since I don't really know how the wishbone bus works, I currently feel like it would almost be easier just to remove the wishbone interface and just use the i2c core mapped to ram addresses, and possibly run the data ready bit to one of the interrupt vectors available on the avr8 core...but I do not know enough about it to say that would be better or anything.

Link to comment
Share on other sites

Blue 12,

<1.What pins are scl and sda mapped to...I can't figure it out>

I haven't done this also, but I think you need to add the SCL and SDA pins in the sources/Papilio_One.ucf

Found this info in http://papilio.cc/index.php?n=Papilio.WorkingWithArduinoCore

Example mapping SCL/SDA to Wing1 pins:

# Wing1 Column A

NET "scl" LOC = "P18" | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 8 ;    #A0

NET "sda" LOC = "P23" | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 8 ;      #A1

<2. How did you specify that the base address is 0x1A00? I don't see it in the vhdl like it is in the custom core?...and if I am not mistaken that is out of the ram space which ends at 1000...well now I am second guessing myself...I just remember that jack had to move the custom core to address 0xFE0 for some reason to do with ram addressing...>

We're trying to define 0x1000 to 0xFFFF to be the IO address space. But it seems that we'll need to change something in the AVR8 core itself to make this happen, due to limitations like the ram address space you mentioned. As a temporary solution, maybe you can try moving the I2C core base address to 0x0A00.

Modify sources/CommonPacks/AVRuCPackage.vhd line 24. Change AVRIOMASK to 0000. AVRIOMASK is used in sources/uC/Addr_Decoder.vhd. Addr_Decoder module generates the iore and iowe for each IO device based on AVR adr[11:8] (only if adr[15:12] = AVRIOMASK)

  constant AVRIOMASK : std_logic_vector(3 downto 0) := "0000"; 

<I think I found the base address list (page 4)is it do I have this right?>

Yes that's right. Only this time the addresses will be 0x0A00, 0x0A01, etc

<It looks like 3 and 4 have different meanings depending on what mode it is in read/write.>

Yes that's right too.

<I am also a bit confused on the wishbone bus...is it transparent to the processor or do I need to set some bits for it in the processor then set the bits and bytes for the i2c core as well?>

Yes the Wishbone bus is transparent to the processor. I just added the module AVR2Wishbone_Bridge to map the processor signals to Wishbone signals. One thing that I would like to check is the timing of the I2C core's wb_ack_o during processor reads (i.e. iore = 1). Is it asynchronous (i.e. same cycle as wb_stb_i and wb_cyc_i) or registered. It seems that AVR8 only supports asynchronous read timing.

Additional info

1. I connected the raw clock input "clk" to the I2C core clock input. If the I2C input clock is 32MHz then

you can just set the prescale register to 0x3F just like in the datasheet.

2. You need pull up resistors for the SCL and SDA pins. You can add that in the I2C slave chip's board.

Can you also give the name of the I2C slave chip that you plan to use? So I can check also if it will work with the OpenCores I2C core.

Goodluck

Lou

Link to comment
Share on other sites

Since I don't really know how the wishbone bus works, I currently feel like it would almost be easier just to remove the wishbone interface and just use the i2c core mapped to ram addresses, and possibly run the data ready bit to one of the interrupt vectors available on the avr8 core...but I do not know enough about it to say that would be better or anything.

I understand what you would like to do with this idea.

I think the solution in my previous post would achieve the same purpose

Link to comment
Share on other sites

Guest Blue12

I have one of these sitting around,

http://www.newhavendisplay.com/index.php?main_page=product_info&cPath=253&products_id=445

I have used it with a couple micros, so I would probably test the i2c core with that first since I have experience with it, but I like i2c because there are a bunch of sensors that use the interface.

I will try those changes when I get a chance.

Link to comment
Share on other sites

I have one of these sitting around,

http://www.newhavendisplay.com/index.php?main_page=product_info&cPath=253&products_id=445

I have used it with a couple micros, so I would probably test the i2c core with that first since I have experience with it, but I like i2c because there are a bunch of sensors that use the interface.

I will try those changes when I get a chance.

Looks like the OpenCores I2C is ok with that. It will run up to 100KHz and it already has pull up resistors. You just need to short/jumper the R1 terminals.  :)

Link to comment
Share on other sites

Archived

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