- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello.
I want to use Wishbone I2C core from OpenCores in my Nios project. Trying to send a byte, i write 0xA2 byte to TxR and set STA and WR bits, the TIP flag asserts high and then never negates until reset. The problem as i see might be in custom Wishbone to Avalon-MM wrapper i use with the following assignments:
signal scl_i,scl_o,sda_i,sda_o,scl_oen,sda_oen:std_logic;
signal s_clock,s_reset_n,s_waitrequest_n,s_irq,s_chipselect,s_write,s_read:std_logic;
signal s_address:std_logic_vector(2 downto 0);
signal s_readdata,s_writedata:std_logic_vector(7 downto 0);
begin
SDA<=sda_o when sda_oen='0' else sda_i;
SCL<=scl_o when scl_oen='0' else scl_i;
s_clock<=clock;
s_reset_n<=reset_n;
waitrequest_n<=s_waitrequest_n;
s_chipselect<=chipselect;
irq<=s_irq;
s_write<=write;
s_read<=read;
s_address<=address;
readdata<=s_readdata;
s_writedata<=writedata;
l1:i2c_master_top
port map(
wb_clk_i=>s_clock,
wb_rst_i=>'0',
arst_i=>s_reset_n,
wb_adr_i=>s_address,
wb_dat_i=>s_writedata,
wb_dat_o=>s_readdata,
wb_we_i=>s_write and (not s_read),
wb_stb_i=>s_chipselect,
wb_cyc_i=>s_write or s_read,
wb_ack_o=>s_waitrequest_n,
wb_inta_o=>s_irq,
scl_pad_i=>scl_i,
scl_pad_o=>scl_o,
scl_padoen_o=>scl_oen,
sda_pad_i=>sda_i,
sda_pad_o=>sda_o,
sda_padoen_o=>sda_oen
);
end architecture;
According to wikipedia http://en.wikipedia.org/wiki/wishbone_(computer_bus) it should be ok. Is that I2C core bug or me doing somthing wrong?
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Should the SDA and SCL be driven with 'Z' in the else condition? Looks pretty straight forward otherwise. I've used that core in the past without any problems but not hooked up to Nios.
The only thing that was a little strange to me before was how you set the clock rate. IIRC it was a generic. Is your clock the same as the default clock the core is expecting?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm using the OpenCores block with a Nios. The only thing that was required was to combine read and write to make the wb_stb signal and inverting wb_ack as the waitreq.
The problem is more likely that the I2C signals should be tristated when output enable negates or else the core will never see the ack from the slave device.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
you can get this component premade in the nios linux git repo.
git clone git://sopc.et.ntust.edu.tw/git/openip.git- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
skaneta,
clock rate iss not a generic; it's programmed into a configuration register -- you configure the division factor. CosworthRS, as other have pointed out, you have the SDA and SCL signals wrong. First, you should take the sda_i, sda_o and sda_oen signals to the FPGA top level. Common practice is not to have internal tri-state signals in FPGA designs. Secondly, the correct way to handle it is: sda_i <= SDA; SDA <= '0' when sda_o = '0' and sda_oen = '0' else 'Z'; Rinse and repeat for SCL. This will get Quartus to infer an open drain configuration for the SDA and SCL pins.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It seem to solve the tip latching problem, but still there are some arbitration issues. The piece of schematic:
http://i41.tinypic.com/2h3a32d.png And the code:
int i2c_init(int prescaler,void* isr,int BASE,int IRQ,int IRQ_ICID){
int res=1;
IOWR_16DIRECT(BASE,OC_I2C_PRER_LO,prescaler);
if(IORD_16DIRECT(BASE,OC_I2C_PRER_LO)==prescaler){
IOWR_8DIRECT(BASE,OC_I2C_CTR,0xC0);
if(IORD_8DIRECT(BASE,OC_I2C_CTR)==0xC0){
if(alt_ic_isr_register(IRQ_ICID,IRQ,isr,NULL,NULL)==0){
res=0;
}
}
}
return res;
}
static void i2c_isr(void *context){
printf("Status register: %d\n",IORD_8DIRECT(I2C_BASE,OC_I2C_SR));
IOWR_8DIRECT(I2C_BASE,OC_I2C_CR,0x01);
}
int main()
{
if(i2c_init(PreSC,(void*)i2c_isr,I2C_BASE,I2C_IRQ,I2C_IRQ_INTERRUPT_CONTROLLER_ID)==0){
IOWR_8DIRECT(I2C_BASE,OC_I2C_TXR,0x80); //write slave address+write bit
IOWR_8DIRECT(I2C_BASE,OC_I2C_CR,0x90); //set STA, set WR
IOWR_8DIRECT(I2C_BASE,OC_I2C_TXR,0x02); //write subaddr
IOWR_8DIRECT(I2C_BASE,OC_I2C_CR,0x10); //set WR
IOWR_8DIRECT(I2C_BASE,OC_I2C_TXR,0x81); //write addr+read bit
IOWR_8DIRECT(I2C_BASE,OC_I2C_CR,0x90); //set WR, set STA
IOWR_8DIRECT(I2C_BASE,OC_I2C_CR,0x68); //set NACK, set STO, SET RD
printf("RxD=%d\n",IORD_8DIRECT(I2C_BASE,OC_I2C_RXR));
}else{
printf("I2C init fail!\n");
}
return 0;
}
Right after i register the ISR, the arbitration lost occures (once). Then not a single acknowledgement from slave (ADV7180) proceed.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page