Closed lk-davidegironi closed 2 years ago
I2C is open-drain, somewhat slow, and slave devices are allowed to hold the clock low (clock stretching), so the core will wait until it sees the expected levels on the I2C interface. But the idle state of I2C is high, since nothing is pulling it down. So, why are probe17/probe18 reading low?
Thanks for your reply!
I don't know why probe17/probe18 are low. In the snapshot above probe17/probe18 are connected straight to output from fpga_core, not external port involved.
I've made further tests, enabled the full tristate, but again nothing out from SCL or SDA. I can not attach inout ports using System ILA, so I've to assign it to output port.
In the snapshot below probe20/probe21 are connected to monitor_i2c_scl/monitor_i2c_sda and i2c_scl/i2c_sda to i2c_0_scl_io/i2c_0_sda_io constraints
The main fpga_core I2C zone looks like this
inout wire i2c_scl,
inout wire i2c_sda,
output wire monitor_i2c_scl,
output wire monitor_i2c_sda,
A few lines below in the core.
wire i2c_scl_i;
wire i2c_scl_o;
wire i2c_scl_t;
wire i2c_sda_i;
wire i2c_sda_o;
wire i2c_sda_t;
assign i2c_scl_i = i2c_scl;
assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o;
assign i2c_sda_i = i2c_sda;
assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o;
assign monitor_i2c_scl = i2c_scl;
assign monitor_i2c_sda = i2c_sda;
xfcp_mod_i2c_master #(
.XFCP_ID_STR("XFCP I2C Master"),
.DEFAULT_PRESCALE(125000000/(400000*4))
)
i2c_master_inst (
.clk(clk),
.rst(rst),
.up_xfcp_in_tdata(xfcp_switch_port_3_down_tdata),
.up_xfcp_in_tvalid(xfcp_switch_port_3_down_tvalid),
.up_xfcp_in_tready(xfcp_switch_port_3_down_tready),
.up_xfcp_in_tlast(xfcp_switch_port_3_down_tlast),
.up_xfcp_in_tuser(xfcp_switch_port_3_down_tuser),
.up_xfcp_out_tdata(xfcp_switch_port_3_up_tdata),
.up_xfcp_out_tvalid(xfcp_switch_port_3_up_tvalid),
.up_xfcp_out_tready(xfcp_switch_port_3_up_tready),
.up_xfcp_out_tlast(xfcp_switch_port_3_up_tlast),
.up_xfcp_out_tuser(xfcp_switch_port_3_up_tuser),
.i2c_scl_i(i2c_scl_i),
.i2c_scl_o(i2c_scl_o),
.i2c_scl_t(i2c_scl_t),
.i2c_sda_i(i2c_sda_i),
.i2c_sda_o(i2c_sda_o),
.i2c_sda_t(i2c_sda_t)
);
And constrainst
set_property IOSTANDARD LVCMOS18 [get_ports i2c_0_scl_io]
set_property IOSTANDARD LVCMOS18 [get_ports i2c_0_sda_io]
set_property PACKAGE_PIN B20 [get_ports i2c_0_scl_io]
set_property PACKAGE_PIN C20 [get_ports i2c_0_sda_io]
set_property PULLUP true [get_ports i2c_0_scl_io]
set_property PULLUP true [get_ports i2c_0_sda_io]
Hardware side there's a 24C256 connected to B20 and C20.
Vivado version is 2021, xfcp is at latest version
2
I recommend probing the _i, _o, and _t signals. Anyway, I suspect a board - level issue. Did you forget the pull - up resistors? Or maybe the pin constraints are incorrect?
Really sorry to bother you, I do have a blog and release opensource too - although i'm not as expertise as you :) -, I know helps other people takes time and often it's for "dumb" things.
PIN B20 and C20 are ok if tested with blinking IP (tested on scope). 24C256 is tested ok on micro (STM32) at 3.3V (attached the board I'm using). I've renamed pins and double checked it.
fpga_gpio_0 is attached to SCL with 4.7 pullup of 24C256, operating at 3.3V, fpga_gpio_1 is attached to SDA.
There's for sure a mistake somewhere, I can't find it where. Attached the latest ILA screenshot, with _i, _o, _t monitored like in the code below. For the probe just numbered: probe20 -> monitor_i2c_scl probe21 -> monitor_i2c_sda probe22 -> monitor_i2c_scl_i probe25 -> monitor_i2c_sda_i
set_property IOSTANDARD LVCMOS18 [get_ports fpga_gpio_0]
set_property PACKAGE_PIN C20 [get_ports fpga_gpio_0]
set_property IOSTANDARD LVCMOS18 [get_ports fpga_gpio_1]
set_property PACKAGE_PIN B20 [get_ports fpga_gpio_1]
set_property PULLUP true [get_ports fpga_gpio_0]
set_property PULLUP true [get_ports fpga_gpio_1]
For consistency, code below
...
inout wire i2c_scl,
inout wire i2c_sda,
output wire monitor_i2c_scl,
output wire monitor_i2c_sda,
output wire monitor_i2c_scl_i,
output wire monitor_i2c_scl_o,
output wire monitor_i2c_scl_t,
output wire monitor_i2c_sda_i,
output wire monitor_i2c_sda_o,
output wire monitor_i2c_sda_t,
...
wire i2c_scl_i;
wire i2c_scl_o;
wire i2c_scl_t;
wire i2c_sda_i;
wire i2c_sda_o;
wire i2c_sda_t;
assign i2c_scl_i = i2c_scl;
assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o;
assign i2c_sda_i = i2c_sda;
assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o;
assign monitor_i2c_scl = i2c_scl;
assign monitor_i2c_sda = i2c_sda;
assign monitor_i2c_scl_i = i2c_scl_i;
assign monitor_i2c_scl_o = i2c_scl_o;
assign monitor_i2c_scl_t = i2c_scl_t;
assign monitor_i2c_sda_i = i2c_sda_i;
assign monitor_i2c_sda_o = i2c_sda_o;
assign monitor_i2c_sda_t = i2c_sda_t;
xfcp_mod_i2c_master #(
...
.i2c_scl_i(i2c_scl_i),
.i2c_scl_o(i2c_scl_o),
.i2c_scl_t(i2c_scl_t),
.i2c_sda_i(i2c_sda_i),
.i2c_sda_o(i2c_sda_o),
.i2c_sda_t(i2c_sda_t)
...
My board is the MIYR MYD-Y7Z010 Development Board http://www.myirtech.com/list.asp?id=580
Solved Yesterday I had time to investigate this problem, turn out it was my tristate implementation. It's a newbie problem I know. I'm now using IOBUF.
My wiring for the I2C node below, just in case, for other people.
// XFCP I2C Master
wire i2c_scl_i;
wire i2c_scl_o;
wire i2c_scl_t;
wire i2c_sda_i;
wire i2c_sda_o;
wire i2c_sda_t;
IOBUF sda_iobuf (
.I(i2c_sda_o),
.O(i2c_sda_i),
.T(i2c_sda_t),
.IO(i2c_sda)
);
IOBUF scl_iobuf (
.I(i2c_scl_o),
.O(i2c_scl_i),
.T(i2c_scl_t),
.IO(i2c_scl)
);
xfcp_mod_i2c_master #
(
.XFCP_ID_STR("XFCP I2C Master"),
.DEFAULT_PRESCALE(125000000/(100000*4))
)
i2c_master_inst (
.clk(clk),
.rst(rst),
.up_xfcp_in_tdata(xfcp_switch_port_2_down_tdata),
.up_xfcp_in_tvalid(xfcp_switch_port_2_down_tvalid),
.up_xfcp_in_tready(xfcp_switch_port_2_down_tready),
.up_xfcp_in_tlast(xfcp_switch_port_2_down_tlast),
.up_xfcp_in_tuser(xfcp_switch_port_2_down_tuser),
.up_xfcp_out_tdata(xfcp_switch_port_2_up_tdata),
.up_xfcp_out_tvalid(xfcp_switch_port_2_up_tvalid),
.up_xfcp_out_tready(xfcp_switch_port_2_up_tready),
.up_xfcp_out_tlast(xfcp_switch_port_2_up_tlast),
.up_xfcp_out_tuser(xfcp_switch_port_2_up_tuser),
.i2c_scl_i(i2c_scl_i),
.i2c_scl_o(i2c_scl_o),
.i2c_scl_t(i2c_scl_t),
.i2c_sda_i(i2c_sda_i),
.i2c_sda_o(i2c_sda_o),
.i2c_sda_t(i2c_sda_t)
);
My constraints for the wiring (on MIYR MYD-Y7Z010)
inout wire _i2cscl connected to pin _gpio1 inout wire _i2csda connected to pin _gpio0
set_property IOSTANDARD LVCMOS18 [get_ports gpio_0]
set_property PACKAGE_PIN L17 [get_ports gpio_0]
set_property IOSTANDARD LVCMOS18 [get_ports gpio_1]
set_property PACKAGE_PIN L16 [get_ports gpio_1]
set_property PULLUP true [get_ports gpio_0]
set_property PULLUP true [get_ports gpio_1]
To read my 24C256 EEPROM I've to assert a write to point the address to read. So just for test I've changed xfcp_ctrl.py read_i2c function to call _write_readi2c instead of _readi2c
Hello Alex, first of all I would like to thank you for sharing your code, I'm already using your verilog-ethernet library on which I've implemented a Ethernet RAW reader/writer for a device I'm working on, it works like a charm. I'm working on a ZYNQ-7010 board. In my design I've added your fpga_core, RAM works fine, but I've a problem with I2C. Clock is 125Mhz. Whenever I try to query/write/read on I2C module, all the core stops working. No output on the SDA and SCL pins. You can find attached an ILA screenshoot. I think the problem is that the TLAST line stays on. An help to your side will be appreciated, I'm sure I'm missing something.
Below the wire you can find in the screenshot (probe 17 and 18 are SCL and SDA)
If I'll be able to make all the things works, I'll translate the python library to C#, cause main project uses this language. If you are interested I can post it. I've other few questions but I don't want to bother you, so I'll try to solve this by myself before asking :) I'm pretty new to FPGA world, so excuse me if questions may sounds dumb.
Thanks
!