From f34ac31f3badd4c646243b21c58e513886a9a4a8 Mon Sep 17 00:00:00 2001 From: Christian Svensson Date: Sun, 6 Oct 2019 14:28:04 +0200 Subject: [PATCH] I2C SFP port working --- Makefile | 2 +- README.md | 1 + fejkon_sfp.tcl | 6 ++-- ip/sfp_port/sfp_port.sv | 58 ++++++++++++++++++------------------- ip/sfp_port/sfp_port_hw.tcl | 21 ++++++++++++-- 5 files changed, 53 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 4ba0a83..dcd9c19 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ clean: rm -f fejkon.sof rm -fr gen -fejkon.sof: ip/altera_fc_phy/fc_phy.qip fejkon.qsys de5net.sdc de5net.tcl +fejkon.sof: ip/altera_fc_phy/fc_phy.qip fejkon.qsys de5net.sdc de5net.tcl $(wildcard ip/*/*.sv) (mkdir -p gen; cd gen; $(QPATH)/bin/quartus_sh -t ../quartus.tcl) cp gen/output_files/fejkon.sof $@ diff --git a/README.md b/README.md index 7ed2633..530f64b 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ Accesses need to be 4 byte wide. | 2 | Read only | TX Fault | | 3 | Read/Write | TX Disable | | 4:5 | Read/Write | Rate Select | +| 6 | Read/Write | I2C Reset | ### MSI Interrupts diff --git a/fejkon_sfp.tcl b/fejkon_sfp.tcl index ce48291..9df1006 100644 --- a/fejkon_sfp.tcl +++ b/fejkon_sfp.tcl @@ -14,7 +14,7 @@ set_instance_parameter_value clk {EXPLICIT_CLOCK_RATE} {0.0} set_instance_parameter_value clk {NUM_CLOCK_OUTPUTS} {1} add_instance i2c altera_avalon_i2c 19.1 -set_instance_parameter_value i2c {FIFO_DEPTH} {4} +set_instance_parameter_value i2c {FIFO_DEPTH} {64} set_instance_parameter_value i2c {USE_AV_ST} {0} add_instance mm altera_avalon_mm_bridge 19.1 @@ -76,12 +76,12 @@ set_connection_parameter_value mm.m0/sfp.mm arbitrationPriority {1} set_connection_parameter_value mm.m0/sfp.mm baseAddress {0x0000} set_connection_parameter_value mm.m0/sfp.mm defaultConnection {0} -add_connection reset.out_reset i2c.reset_sink - add_connection reset.out_reset mm.reset add_connection reset.out_reset sfp.reset +add_connection sfp.i2c_reset i2c.reset_sink + # interconnect requirements set_interconnect_requirement {$system} {qsys_mm.clockCrossingAdapter} {HANDSHAKE} set_interconnect_requirement {$system} {qsys_mm.enableEccProtection} {FALSE} diff --git a/ip/sfp_port/sfp_port.sv b/ip/sfp_port/sfp_port.sv index 78451eb..cbb4306 100644 --- a/ip/sfp_port/sfp_port.sv +++ b/ip/sfp_port/sfp_port.sv @@ -18,6 +18,7 @@ module sfp_port ( input wire clk, // clk.clk input wire reset, // reset.reset + output wire i2c_reset, // i2c_reset.reset input wire los, // sfp.los input wire mod0_prsnt_n, // .prsnt_n output wire tx_disable, // .txdis @@ -39,44 +40,28 @@ module sfp_port ( input wire scl_oe ); - reg [7:0] rd_data; - reg [1:0] rd_response; + wire [7:0] rd_data; + wire [1:0] rd_response; - reg [1:0] wr_response; + wire [1:0] wr_response; reg tx_disable_r; reg [1:0] ratesel_r; + reg i2c_reset_r; + reg mod0_prsnt_n_r; // Reader - always @(posedge clk or posedge reset) - begin - if (reset) - begin - rd_data <= 8'b0; - rd_response <= 2'b10; - end - else if (mm_read) - begin - // Status register - // TODO(bluecmd): Seems to be some delay here where state - // transitions lag one clock cycle, probably due to Avalon needing - // the data the same clock cycle or something? - if (mm_address == 4'h0) - begin - rd_data <= {2'b00, ratesel, tx_disable_r, tx_fault, los, ~mod0_prsnt_n}; - rd_response <= 2'b00; - end - else - rd_response <= 2'b11; - end - end + assign rd_data = {1'b0, i2c_reset_r, ratesel, tx_disable_r, tx_fault, los, ~mod0_prsnt_n}; + assign rd_response = mm_address == 4'h0 ? 2'b00 : 2'b11; // Writer always @(posedge clk or posedge reset) begin if (reset) begin - wr_response <= 2'b10; + tx_disable_r <= 1; + ratesel_r <= 2'b00; + i2c_reset_r <= 0; end else if (mm_write) begin @@ -85,19 +70,34 @@ module sfp_port ( begin tx_disable_r <= mm_writedata[3]; ratesel_r <= mm_writedata[5:4]; - wr_response <= 2'b00; + i2c_reset_r <= mm_writedata[6]; end - else - wr_response <= 2'b11; end + else + begin + // Only reset for one clock cycle + i2c_reset_r <= 0; + end end + always @(posedge clk) + begin + mod0_prsnt_n_r <= mod0_prsnt_n; + end + + assign wr_response = mm_address == 4'h0 ? 2'b00 : 2'b11; + assign ratesel = ratesel_r; assign tx_disable = tx_disable_r; assign mm_response = mm_read ? rd_response : wr_response ; assign mm_readdata = rd_data; + // Reset the I2C core when: + // - the host tells us to (i2c_reset_r) + // - the system is being reset (rest) + // - a SFP module was just plugged in (mod0_prsnt_n 1->0) + assign i2c_reset = i2c_reset_r | reset | (~mod0_prsnt_n & mod0_prsnt_n_r); // Altera I2C master bus driver assign scl_in = mod1_scl; diff --git a/ip/sfp_port/sfp_port_hw.tcl b/ip/sfp_port/sfp_port_hw.tcl index fdb079f..e93854f 100644 --- a/ip/sfp_port/sfp_port_hw.tcl +++ b/ip/sfp_port/sfp_port_hw.tcl @@ -1,11 +1,11 @@ # TCL File Generated by Component Editor 19.1 -# Thu Oct 03 22:48:40 CEST 2019 +# Sun Oct 06 14:02:46 CEST 2019 # DO NOT MODIFY # # sfp_port "SFP Port" v1.0 -# bluecmd 2019.10.03.22:48:40 +# bluecmd 2019.10.06.14:02:46 # # @@ -158,3 +158,20 @@ add_interface_port i2c sda_oe sda_oe Input 1 add_interface_port i2c scl_in scl_in Output 1 add_interface_port i2c scl_oe scl_oe Input 1 + +# +# connection point i2c_reset +# +add_interface i2c_reset reset start +set_interface_property i2c_reset associatedClock clk +set_interface_property i2c_reset associatedDirectReset "" +set_interface_property i2c_reset associatedResetSinks "" +set_interface_property i2c_reset synchronousEdges DEASSERT +set_interface_property i2c_reset ENABLED true +set_interface_property i2c_reset EXPORT_OF "" +set_interface_property i2c_reset PORT_NAME_MAP "" +set_interface_property i2c_reset CMSIS_SVD_VARIABLES "" +set_interface_property i2c_reset SVD_ADDRESS_GROUP "" + +add_interface_port i2c_reset i2c_reset reset Output 1 +