bluecmd / fejkon

Fibre Channel / FICON HBA implemented on FPGA
GNU General Public License v3.0
36 stars 2 forks source link

FC<->Ethernet mode #30

Open bluecmd opened 4 years ago

bluecmd commented 4 years ago

If PCIe continues to be a hassle it might be worth to figure out how to get the CDCM61001 clock up and running.

That would allow another clock source for use for Ethernet. For a 156.25 MHz clock (10GigE) it seems driving PR1=1, PR0=0 , OD0=1, OD1=1, OD2=0 will do the trick.

After specifying the desired output frequency in the parallel interface, developers must assert the output enable pin CE and control the RSTN pin to generate a rising signal to start the PLL Recalibration process. In the FPGA board, the required output type is LVDS, so always set OS0 and SO1 to 0 and 1, respectively.

Likely this is going to be the clock pin: U53 SFP1G_REFCLK_p 125.0 MHz LVDS PIN_AH6 which we will obviously call something else.

The clock config pins are configured by the MAX II, so there is likely going to be some need to talk to it:

CDCM61001 (U53)
PLL_SCL 2.5-V PIN_AF32
PLL_SDA 2.5-V PIN_AG32
I2C bus, connected with MAX II CPLD

Something like this (generated from builder):


//=======================================================
//  CDCM61001/CDCM61004 External PLL Configuration 
//      Configure CDCM61001 as 156.25 MHz
//      Configure CDCM61004 as Disabled
//=======================================================

//  Signal declarations
wire [ 3: 0] clk1_set_wr, clk2_set_wr, clk3_set_wr;
wire         rstn;
wire         conf_ready;
wire         counter_max;
wire  [7:0]  counter_inc;
reg   [7:0]  auto_set_counter;
reg          conf_wr;

//  Structural coding
assign clk1_set_wr = 4'd7; //156.25 MHz
assign clk2_set_wr = 4'd1; //Disabled
assign clk3_set_wr = 4'd0; //Unchange

assign rstn = CPU_RESET_n;
assign counter_max = &auto_set_counter;
assign counter_inc = auto_set_counter + 1'b1;

always @(posedge OSC_50_B3B or negedge rstn)
    if(!rstn)
    begin
        auto_set_counter <= 0;
        conf_wr <= 0;
    end 
    else if (counter_max)
        conf_wr <= 1;
    else
        auto_set_counter <= counter_inc;

ext_pll_ctrl ext_pll_ctrl_Inst(
    .osc_50(OSC_50_B3B), //50MHZ
    .rstn(rstn),

    // device 1 (SFP1G_REFCLK_p)
    .clk1_set_wr(clk1_set_wr),
    .clk1_set_rd(),

    // device 2 (SATA_HOST_REFCLK_p/SATA_DEVICE_REFCLK_p)
    .clk2_set_wr(clk2_set_wr),
    .clk2_set_rd(),

    // device 3 (reserved)
    .clk3_set_wr(clk3_set_wr),
    .clk3_set_rd(),

    // setting trigger
    .conf_wr(conf_wr), // 1T 50MHz 
    .conf_rd(), // 1T 50MHz

    // status 
    .conf_ready(conf_ready),

    // 2-wire interface 
    .max_sclk(PLL_SCL),
    .max_sdat(PLL_SDA)

);

endmodule

The values for both clk1 and clk2 seems to align. Other known values are:

0 = Unchanged 1 = Disabled 2 = 62.5 MHz 3 = 75 MHz 4 = 100 MHz 5 = 125 MHz 6 = 150 MHz 7 = 156.25 MHz 8 = 187.50 MHz 9 = 200 MHz 10 = 250 MHz 11 = 312.5 MHz 12 = 625 MHz

Creating an IP core for configuring the two clocks seems like the best thing to do.

bluecmd commented 4 years ago

image

PLL for generating the needed 66/64 clock seems to be happy with a 312.5 MHz and 156.25 MHz input.

bluecmd commented 4 years ago

On the PHY side I think this should work:

image

And the MAC: image

There seems to be need a converter between XGMII DC and Standard, see "XGMII Mapping to Standard SDR XGMII Data" in the Transceiver guide.

The MAC code seems to be fine for usage in Qsys directly while the PHY needs to be core-ized.