dakies/OSS_Verilog huggingface dataset:
module user_module_341519170869920338(
  input [7:0] io_in,
  output [7:0] io_out
);
  wire net1 = io_in[7];
  wire net2;
  wire net3;
  wire net4;
  wire net5;
  wire net6 = 1'b1;
  wire net7 = 1'b1;
  wire net8;
  wire net9;
  wire net10;
  wire net11;
  wire net12;
  wire net13;
  wire net14;
  wire net15;
  wire net16;
  wire net17;
  wire net18;
  wire net19;
  wire net20;
  wire net21;
  wire net22;
  wire net23;
  wire net24 = 1'b0;

  assign io_out[0] = net2;
  assign io_out[1] = net3;
  assign io_out[2] = net4;
  assign io_out[3] = net5;

  not_cell not2 (

  );
  not_cell not3 (

  );
  not_cell not4 (

  );
  and_cell gate1 (

  );
  or_cell gate2 (

  );
  xor_cell gate3 (

  );
  nand_cell gate4 (

  );
  buffer_cell gate6 (

  );
  mux_cell mux1 (

  );
  dff_cell flipflop1 (
    .d (net8),
    .clk (net1),
    .q (net5),
    .notq (net8)
  );
  dff_cell flipflop2 (
    .d (net9),
    .clk (net1),
    .q (net4),
    .notq (net10)
  );
  dff_cell flipflop3 (
    .d (net11),
    .clk (net1),
    .q (net3),
    .notq (net12)
  );
  dff_cell flipflop4 (
    .d (net13),
    .clk (net1),
    .q (net2),
    .notq (net14)
  );
  and_cell gate7 (
    .a (net4),
    .b (net8),
    .out (net15)
  );
  and_cell gate8 (
    .a (net14),
    .b (net10),
    .out (net16)
  );
  and_cell gate9 (
    .a (net16),
    .b (net5),
    .out (net17)
  );
  or_cell gate10 (
    .a (net17),
    .b (net15),
    .out (net9)
  );
  or_cell gate11 (
    .a (net8),
    .b (net10),
    .out (net18)
  );
  and_cell gate12 (
    .a (net3),
    .b (net18),
    .out (net19)
  );
  or_cell gate13 (
    .a (net19),
    .b (net20),
    .out (net11)
  );
  and_cell gate14 (
    .a (net5),
    .b (net4),
    .out (net21)
  );
  and_cell gate15 (
    .a (net21),
    .b (net12),
    .out (net20)
  );
  and_cell gate16 (
    .a (net8),
    .b (net2),
    .out (net22)
  );
  or_cell gate17 (
    .a (net22),
    .b (net23),
    .out (net13)
  );
  and_cell gate18 (
    .a (net21),
    .b (net3),
    .out (net23)
  );
endmodule
module scan_controller_tb;
    initial begin
        // change to suit your project
        $dumpfile ("scan_controller_tb.vcd");
        $dumpvars (0, scan_controller_tb);
        #1;
    end

    reg clk;
    reg RSTB;
    reg power1, power2;
    reg power3, power4;

    wire gpio;
    wire [37:0] mprj_io;

    ///// convenience signals that match what the cocotb test modules are looking for
    // change to suit your project. Here's how we can make some nicer named signals for inputs & outputs

    // outputs
    wire [7:0] outputs = mprj_io[36:29];
    wire ready = mprj_io[37];
    wire slow_clk = mprj_io[10];
    wire fw_ready = mprj_io[7];

    // inputs
    wire [7:0] inputs;
    wire [1:0] driver_sel;
    wire [8:0] active_sel;
    wire set_clk_div;
    assign mprj_io[28:21] = inputs;
    assign mprj_io[9:8] = driver_sel;
    assign mprj_io[20:12] = active_sel;
    assign mprj_io[11] = set_clk_div;
    

    wire flash_csb;
    wire flash_clk;
    wire flash_io0;
    wire flash_io1;

    wire VDD3V3 = power1;
    wire VDD1V8 = power2;
    wire USER_VDD3V3 = power3;
    wire USER_VDD1V8 = power4;
    wire VSS = 1'b0;

    caravel uut (
        .vddio    (VDD3V3),
        .vssio    (VSS),
        .vdda     (VDD3V3),
        .vssa     (VSS),
        .vccd     (VDD1V8),
        .vssd     (VSS),
        .vdda1    (USER_VDD3V3),
        .vdda2    (USER_VDD3V3),
        .vssa1    (VSS),
        .vssa2    (VSS),
        .vccd1    (USER_VDD1V8),
        .vccd2    (USER_VDD1V8),
        .vssd1    (VSS),
        .vssd2    (VSS),
        .clock    (clk),
        .gpio     (gpio),
        .mprj_io  (mprj_io),
        .flash_csb(flash_csb),
        .flash_clk(flash_clk),
        .flash_io0(flash_io0),
        .flash_io1(flash_io1),
        .resetb   (RSTB)
    );

    spiflash #(
        // change the hex file to match your project
        .FILENAME("scan_controller.hex")
    ) spiflash (
        .csb(flash_csb),
        .clk(flash_clk),
        .io0(flash_io0),
        .io1(flash_io1),
        .io2(),         // not used
        .io3()          // not used
    );

endmodule
module scan_controller_tb;
    initial begin
        // change to suit your project
        $dumpfile ("scan_controller_tb.vcd");
        $dumpvars (0, scan_controller_tb);
        #1;
    end

    reg clk;
    reg RSTB;
    reg power1, power2;
    reg power3, power4;

    wire gpio;
    wire [37:0] mprj_io;

    ///// convenience signals that match what the cocotb test modules are looking for
    // change to suit your project. Here's how we can make some nicer named signals for inputs & outputs
    wire fw_ready = mprj_io[12];
    wire fw_done = mprj_io[13];
    wire data_rx = mprj_io[14];
    wire tb_clk = mprj_io[15];

    wire [1:0] driver_sel;
    assign mprj_io[9:8] = driver_sel;
    /////
    

    wire flash_csb;
    wire flash_clk;
    wire flash_io0;
    wire flash_io1;

    wire VDD3V3 = power1;
    wire VDD1V8 = power2;
    wire USER_VDD3V3 = power3;
    wire USER_VDD1V8 = power4;
    wire VSS = 1'b0;

    caravel uut (
        .vddio    (VDD3V3),
        .vssio    (VSS),
        .vdda     (VDD3V3),
        .vssa     (VSS),
        .vccd     (VDD1V8),
        .vssd     (VSS),
        .vdda1    (USER_VDD3V3),
        .vdda2    (USER_VDD3V3),
        .vssa1    (VSS),
        .vssa2    (VSS),
        .vccd1    (USER_VDD1V8),
        .vccd2    (USER_VDD1V8),
        .vssd1    (VSS),
        .vssd2    (VSS),
        .clock    (clk),
        .gpio     (gpio),
        .mprj_io  (mprj_io),
        .flash_csb(flash_csb),
        .flash_clk(flash_clk),
        .flash_io0(flash_io0),
        .flash_io1(flash_io1),
        .resetb   (RSTB)
    );

    spiflash #(
        // change the hex file to match your project
        .FILENAME("scan_controller.hex")
    ) spiflash (
        .csb(flash_csb),
        .clk(flash_clk),
        .io0(flash_io0),
        .io1(flash_io1),
        .io2(),         // not used
        .io3()          // not used
    );

endmodule
module scan_controller_tb;
    initial begin
        // change to suit your project
        $dumpfile ("scan_controller_tb.vcd");
        $dumpvars (0, scan_controller_tb);
        #1;
    end

    reg clk;
    reg RSTB;
    reg power1, power2;
    reg power3, power4;

    wire gpio;
    wire [37:0] mprj_io;

    ///// convenience signals that match what the cocotb test modules are looking for
    // change to suit your project. Here's how we can make some nicer named signals for inputs & outputs
    wire fw_ready = mprj_io[12];
    wire ext_clk_out = mprj_io[29];
    wire ext_data_out = mprj_io[30];

    wire [1:0] driver_sel;
    wire ext_clk, ext_latch, ext_scan, ext_data_in;
    assign mprj_io[21] = ext_clk;
    assign mprj_io[22] = ext_data_in;
    assign mprj_io[23] = ext_scan;
    assign mprj_io[24] = ext_latch;
    assign mprj_io[9:8] = driver_sel;
    /////
    

    wire flash_csb;
    wire flash_clk;
    wire flash_io0;
    wire flash_io1;

    wire VDD3V3 = power1;
    wire VDD1V8 = power2;
    wire USER_VDD3V3 = power3;
    wire USER_VDD1V8 = power4;
    wire VSS = 1'b0;

    caravel uut (
        .vddio    (VDD3V3),
        .vssio    (VSS),
        .vdda     (VDD3V3),
        .vssa     (VSS),
        .vccd     (VDD1V8),
        .vssd     (VSS),
        .vdda1    (USER_VDD3V3),
        .vdda2    (USER_VDD3V3),
        .vssa1    (VSS),
        .vssa2    (VSS),
        .vccd1    (USER_VDD1V8),
        .vccd2    (USER_VDD1V8),
        .vssd1    (VSS),
        .vssd2    (VSS),
        .clock    (clk),
        .gpio     (gpio),
        .mprj_io  (mprj_io),
        .flash_csb(flash_csb),
        .flash_clk(flash_clk),
        .flash_io0(flash_io0),
        .flash_io1(flash_io1),
        .resetb   (RSTB)
    );

    spiflash #(
        // change the hex file to match your project
        .FILENAME("scan_controller.hex")
    ) spiflash (
        .csb(flash_csb),
        .clk(flash_clk),
        .io0(flash_io0),
        .io1(flash_io1),
        .io2(),         // not used
        .io3()          // not used
    );

endmodule
module test_scan_controller_tb(
    input wire clk,
    input wire reset,

    input wire [1:0] driver_sel,
    input wire [8:0] active_select,
    input wire [7:0] inputs,
    input wire set_clk_div,
    output wire [7:0] outputs,
    output wire ready,
    output wire slow_clk
);

    // signals for user_project_wrapper
    wire [`MPRJ_IO_PADS-1:0] io_in;
    wire [`MPRJ_IO_PADS-1:0] io_out;
    wire [`MPRJ_IO_PADS-1:0] io_oeb;

    // map inputs to user_project_wrapper signals
    assign io_in[20:12] = active_select;
    assign io_in[28:21] = inputs;
    assign io_in[11]    = set_clk_div;
    assign io_in[9:8]  = driver_sel;
    assign outputs = io_out[36:29];
    assign ready = io_out[37];
    assign slow_clk = io_out[10];

    // 7 seg signals
    wire [6:0] seven_seg = outputs[6:0];

    `ifdef COCOTB
    initial begin
        $dumpfile ("test_scan_controller.vcd");
        $dumpvars (0, test_scan_controller_tb);
        #1;
    end
    `endif

    user_project_wrapper user_project_wrapper(
    `ifdef GL_TEST
        .vccd1( 1'b1),
        .vssd1( 1'b0),
    `endif
        .wb_clk_i   (clk),
        .wb_rst_i   (reset),
        .io_in      (io_in),
        .io_out     (io_out),
        .io_oeb     (io_oeb));

endmodule
module clk_divider #(
    parameter integer DIV_WIDTH = 8
)(
    input  wire clk,
    input  wire ce,
    input  wire reset,
    input  wire set,
    input  wire [DIV_WIDTH-1:0] divider,
    output wire active,
    output reg  slow_clk
);

    reg [DIV_WIDTH-1:0] counter;
    reg [DIV_WIDTH-1:0] compare;
    wire                match;

    reg [2:0] set_sync;
    reg       set_now;

    // Detect rising edge (with synchronizer)
    always @(posedge clk)
    begin
        set_sync <= { set_sync[1:0], set };
        set_now  <= ~set_sync[2] & set_sync[1];
    end

    assign active = set_sync[2];

    // Latch divider
    always @(posedge clk)
        if (set_now)
            compare <= divider;

    // Compare
    assign match = (counter == compare);

    // Counter
    always @(posedge clk or posedge reset)
        if (reset)
            counter <= 0;
        else if (ce)
            counter <= match ? 0 : (counter + 1);

    // Clock gen
    always @(posedge clk or posedge reset)
        if (reset)
            slow_clk <= 1'b0;
        else if (ce)
            slow_clk <= slow_clk ^ match;

endmodule // clk_divider
module ptp_tag_insert #
(
    parameter DATA_WIDTH = 64,
    parameter KEEP_WIDTH = DATA_WIDTH/8,
    parameter TAG_WIDTH = 16,
    parameter TAG_OFFSET = 1,
    parameter USER_WIDTH = TAG_WIDTH+TAG_OFFSET
)
(
    input  wire                   clk,
    input  wire                   rst,

    /*
     * AXI input
     */
    input  wire [DATA_WIDTH-1:0]  s_axis_tdata,
    input  wire [KEEP_WIDTH-1:0]  s_axis_tkeep,
    input  wire                   s_axis_tvalid,
    output wire                   s_axis_tready,
    input  wire                   s_axis_tlast,
    input  wire [USER_WIDTH-1:0]  s_axis_tuser,

    /*
     * AXI output
     */
    output wire [DATA_WIDTH-1:0]  m_axis_tdata,
    output wire [KEEP_WIDTH-1:0]  m_axis_tkeep,
    output wire                   m_axis_tvalid,
    input  wire                   m_axis_tready,
    output wire                   m_axis_tlast,
    output wire [USER_WIDTH-1:0]  m_axis_tuser,

    /*
     * Tag input
     */
    input  wire [TAG_WIDTH-1:0]   s_axis_tag,
    input  wire                   s_axis_tag_valid,
    output wire                   s_axis_tag_ready
);

reg [TAG_WIDTH-1:0] tag_reg = {TAG_WIDTH{1'b0}};
reg tag_valid_reg = 1'b0;

reg [USER_WIDTH-1:0] user;

assign s_axis_tready = m_axis_tready && tag_valid_reg;

assign m_axis_tdata  = s_axis_tdata;
assign m_axis_tkeep  = s_axis_tkeep;
assign m_axis_tvalid = s_axis_tvalid && tag_valid_reg;
assign m_axis_tlast  = s_axis_tlast;
assign m_axis_tuser  = user;

assign s_axis_tag_ready = !tag_valid_reg;

always @* begin
    user = s_axis_tuser;
    user[TAG_OFFSET +: TAG_WIDTH] = tag_reg;
end

always @(posedge clk) begin
    if (tag_valid_reg) begin
        if (s_axis_tvalid && s_axis_tready && s_axis_tlast) begin
            tag_valid_reg <= 1'b0;
        end
    end else begin
        tag_reg <= s_axis_tag;
        tag_valid_reg <= s_axis_tag_valid;
    end

    if (rst) begin
        tag_valid_reg <= 1'b0;
    end
end

endmodule
module ssio_sdr_out #
(
    // target ("SIM", "GENERIC", "XILINX", "ALTERA")
    parameter TARGET = "GENERIC",
    // IODDR style ("IODDR", "IODDR2")
    // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale
    // Use IODDR2 for Spartan-6
    parameter IODDR_STYLE = "IODDR2",
    // Width of register in bits
    parameter WIDTH = 1
)
(
    input  wire             clk,

    input  wire [WIDTH-1:0] input_d,

    output wire             output_clk,
    output wire [WIDTH-1:0] output_q
);

oddr #(
    .TARGET(TARGET),
    .IODDR_STYLE(IODDR_STYLE),
    .WIDTH(1)
)
clk_oddr_inst (
    .clk(clk),
    .d1(1'b0),
    .d2(1'b1),
    .q(output_clk)
);

(* IOB = "TRUE" *)
reg [WIDTH-1:0] output_q_reg = {WIDTH{1'b0}};

assign output_q = output_q_reg;

always @(posedge clk) begin
    output_q_reg <= input_d;
end

endmodule
module axis_eth_fcs #
(
    // Width of AXI stream interfaces in bits
    parameter DATA_WIDTH = 8,
    // Propagate tkeep signal
    // If disabled, tkeep assumed to be 1'b1
    parameter KEEP_ENABLE = (DATA_WIDTH>8),
    // tkeep signal width (words per cycle)
    parameter KEEP_WIDTH = (DATA_WIDTH/8)
)
(
    input  wire                   clk,
    input  wire                   rst,
    
    /*
     * AXI input
     */
    input  wire [DATA_WIDTH-1:0]  s_axis_tdata,
    input  wire [KEEP_WIDTH-1:0]  s_axis_tkeep,
    input  wire                   s_axis_tvalid,
    output wire                   s_axis_tready,
    input  wire                   s_axis_tlast,
    input  wire                   s_axis_tuser,
    
    /*
     * FCS output
     */
    output wire [31:0]            output_fcs,
    output wire                   output_fcs_valid
);

// bus width assertions
initial begin
    if (KEEP_WIDTH * 8 != DATA_WIDTH) begin
        $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)");
        $finish;
    end
end

reg [31:0] crc_state = 32'hFFFFFFFF;
reg [31:0] fcs_reg = 32'h00000000;
reg fcs_valid_reg = 1'b0;

wire [31:0] crc_next[KEEP_WIDTH-1:0];

assign s_axis_tready = 1;
assign output_fcs = fcs_reg;
assign output_fcs_valid = fcs_valid_reg;

generate

    genvar n;

    for (n = 0; n < KEEP_WIDTH; n = n + 1) begin : crc

        lfsr #(
            .LFSR_WIDTH(32),
            .LFSR_POLY(32'h4c11db7),
            .LFSR_CONFIG("GALOIS"),
            .LFSR_FEED_FORWARD(0),
            .REVERSE(1),
            .DATA_WIDTH(DATA_WIDTH/KEEP_WIDTH*(n+1)),
            .STYLE("AUTO")
        )
        eth_crc_inst (
            .data_in(s_axis_tdata[DATA_WIDTH/KEEP_WIDTH*(n+1)-1:0]),
            .state_in(crc_state),
            .data_out(),
            .state_out(crc_next[n])
        );

    end

endgenerate

integer i;

always @(posedge clk) begin
    fcs_valid_reg <= 1'b0;

    if (s_axis_tvalid) begin
        crc_state <= crc_next[KEEP_WIDTH-1];

        if (s_axis_tlast) begin
            crc_state <= 32'hFFFFFFFF;
            if (KEEP_ENABLE) begin
                fcs_reg <= ~crc_next[0];
                for (i = 0; i < KEEP_WIDTH; i = i + 1) begin
                    if (s_axis_tkeep[i]) begin
                        fcs_reg <= ~crc_next[i];
                    end
                end
            end else begin
                fcs_reg <= ~crc_next[KEEP_WIDTH-1];
            end
            fcs_valid_reg <= 1'b1;
        end
    end

    if (rst) begin
        crc_state <= 32'hFFFFFFFF;
        fcs_valid_reg <= 1'b0;
    end
end

endmodule
module ssio_sdr_out_diff #
(
    // target ("SIM", "GENERIC", "XILINX", "ALTERA")
    parameter TARGET = "GENERIC",
    // IODDR style ("IODDR", "IODDR2")
    // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale
    // Use IODDR2 for Spartan-6
    parameter IODDR_STYLE = "IODDR2",
    // Width of register in bits
    parameter WIDTH = 1
)
(
    input  wire             clk,

    input  wire [WIDTH-1:0] input_d,

    output wire             output_clk_p,
    output wire             output_clk_n,
    output wire [WIDTH-1:0] output_q_p,
    output wire [WIDTH-1:0] output_q_n
);

wire output_clk;
wire [WIDTH-1:0] output_q;

ssio_sdr_out #(
    .TARGET(TARGET),
    .IODDR_STYLE(IODDR_STYLE),
    .WIDTH(WIDTH)
)
ssio_ddr_out_inst(
    .clk(clk),
    .input_d(input_d),
    .output_clk(output_clk),
    .output_q(output_q)
);

genvar n;

generate

if (TARGET == "XILINX") begin
    OBUFDS
    clk_obufds_inst (
        .I(output_clk),
        .O(output_clk_p),
        .OB(output_clk_n)
    );
    for (n = 0; n < WIDTH; n = n + 1) begin
        OBUFDS
        data_obufds_inst (
            .I(output_q[n]),
            .O(output_q_p[n]),
            .OB(output_q_n[n])
        );
    end
end else if (TARGET == "ALTERA") begin
    ALT_OUTBUF_DIFF
    clk_outbuf_diff_inst (
        .i(output_clk),
        .o(output_clk_p),
        .obar(output_clk_n)
    );
    for (n = 0; n < WIDTH; n = n + 1) begin
        ALT_OUTBUF_DIFF
        data_outbuf_diff_inst (
            .i(output_q[n]),
            .o(output_q_p[n]),
            .obar(output_q_n[n])
        );
    end
end else begin
    assign output_clk_p = output_clk;
    assign output_clk_n = ~output_clk;
    assign output_q_p = output_q;
    assign output_q_n = ~output_q;
end

endgenerate

endmodule
module iddr #
(
    // target ("SIM", "GENERIC", "XILINX", "ALTERA")
    parameter TARGET = "GENERIC",
    // IODDR style ("IODDR", "IODDR2")
    // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale
    // Use IODDR2 for Spartan-6
    parameter IODDR_STYLE = "IODDR2",
    // Width of register in bits
    parameter WIDTH = 1
)
(
    input  wire             clk,

    input  wire [WIDTH-1:0] d,

    output wire [WIDTH-1:0] q1,
    output wire [WIDTH-1:0] q2
);

/*

Provides a consistent input DDR flip flop across multiple FPGA families
              _____       _____       _____       _____       ____
    clk  ____/     \_____/     \_____/     \_____/     \_____/
         _ _____ _____ _____ _____ _____ _____ _____ _____ _____ _
    d    _X_D0__X_D1__X_D2__X_D3__X_D4__X_D5__X_D6__X_D7__X_D8__X_
         _______ ___________ ___________ ___________ ___________ _
    q1   _______X___________X____D0_____X____D2_____X____D4_____X_
         _______ ___________ ___________ ___________ ___________ _
    q2   _______X___________X____D1_____X____D3_____X____D5_____X_

*/

genvar n;

generate

if (TARGET == "XILINX") begin
    for (n = 0; n < WIDTH; n = n + 1) begin : iddr
        if (IODDR_STYLE == "IODDR") begin
            IDDR #(
                .DDR_CLK_EDGE("SAME_EDGE_PIPELINED"),
                .SRTYPE("ASYNC")
            )
            iddr_inst (
                .Q1(q1[n]),
                .Q2(q2[n]),
                .C(clk),
                .CE(1'b1),
                .D(d[n]),
                .R(1'b0),
                .S(1'b0)
            );
        end else if (IODDR_STYLE == "IODDR2") begin
            wire q1_int;
            reg q1_delay;

            IDDR2 #(
                .DDR_ALIGNMENT("C0")
            )
            iddr_inst (
                .Q0(q1_int),
                .Q1(q2[n]),
                .C0(clk),
                .C1(~clk),
                .CE(1'b1),
                .D(d[n]),
                .R(1'b0),
                .S(1'b0)
            );

            always @(posedge clk) begin
                q1_delay <= q1_int;
            end

            assign q1[n] = q1_delay;
        end
    end
end else if (TARGET == "ALTERA") begin
    wire [WIDTH-1:0] q1_int;
    reg [WIDTH-1:0] q1_delay;

    altddio_in #(
        .WIDTH(WIDTH),
        .POWER_UP_HIGH("OFF")
    )
    altddio_in_inst (
        .aset(1'b0),
        .datain(d),
        .inclocken(1'b1),
        .inclock(clk),
        .aclr(1'b0),
        .dataout_h(q1_int),
        .dataout_l(q2)
    );

    always @(posedge clk) begin
        q1_delay <= q1_int;
    end

    assign q1 = q1_delay;
end else begin
    reg [WIDTH-1:0] d_reg_1 = {WIDTH{1'b0}};
    reg [WIDTH-1:0] d_reg_2 = {WIDTH{1'b0}};

    reg [WIDTH-1:0] q_reg_1 = {WIDTH{1'b0}};
    reg [WIDTH-1:0] q_reg_2 = {WIDTH{1'b0}};

    always @(posedge clk) begin
        d_reg_1 <= d;
    end

    always @(negedge clk) begin
        d_reg_2 <= d;
    end

    always @(posedge clk) begin
        q_reg_1 <= d_reg_1;
        q_reg_2 <= d_reg_2;
    end

    assign q1 = q_reg_1;
    assign q2 = q_reg_2;
end

endgenerate

endmodule
module xgmii_deinterleave
(
    input  wire [72:0] input_xgmii_dc,

    output wire [63:0] output_xgmii_d,
    output wire [7:0]  output_xgmii_c
);

assign output_xgmii_d[7:0] = input_xgmii_dc[7:0];
assign output_xgmii_c[0] = input_xgmii_dc[8];
assign output_xgmii_d[15:8] = input_xgmii_dc[16:9];
assign output_xgmii_c[1] = input_xgmii_dc[17];
assign output_xgmii_d[23:16] = input_xgmii_dc[25:18];
assign output_xgmii_c[2] = input_xgmii_dc[26];
assign output_xgmii_d[31:24] = input_xgmii_dc[34:27];
assign output_xgmii_c[3] = input_xgmii_dc[35];
assign output_xgmii_d[39:32] = input_xgmii_dc[43:36];
assign output_xgmii_c[4] = input_xgmii_dc[44];
assign output_xgmii_d[47:40] = input_xgmii_dc[52:45];
assign output_xgmii_c[5] = input_xgmii_dc[53];
assign output_xgmii_d[55:48] = input_xgmii_dc[61:54];
assign output_xgmii_c[6] = input_xgmii_dc[62];
assign output_xgmii_d[63:56] = input_xgmii_dc[70:63];
assign output_xgmii_c[7] = input_xgmii_dc[71];

endmodule
module ssio_sdr_in #
(
    // target ("SIM", "GENERIC", "XILINX", "ALTERA")
    parameter TARGET = "GENERIC",
    // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2")
    // Use BUFR for Virtex-5, Virtex-6, 7-series
    // Use BUFG for Ultrascale
    // Use BUFIO2 for Spartan-6
    parameter CLOCK_INPUT_STYLE = "BUFIO2",
    // Width of register in bits
    parameter WIDTH = 1
)
(
    input  wire             input_clk,

    input  wire [WIDTH-1:0] input_d,

    output wire             output_clk,

    output wire [WIDTH-1:0] output_q
);

wire clk_int;
wire clk_io;

generate

if (TARGET == "XILINX") begin

    // use Xilinx clocking primitives

    if (CLOCK_INPUT_STYLE == "BUFG") begin

        // buffer RX clock
        BUFG
        clk_bufg (
            .I(input_clk),
            .O(clk_int)
        );

        // pass through RX clock to logic and input buffers
        assign clk_io = clk_int;
        assign output_clk = clk_int;

    end else if (CLOCK_INPUT_STYLE == "BUFR") begin

        assign clk_int = input_clk;

        // pass through RX clock to input buffers
        BUFIO
        clk_bufio (
            .I(clk_int),
            .O(clk_io)
        );

        // pass through RX clock to logic
        BUFR #(
            .BUFR_DIVIDE("BYPASS")
        )
        clk_bufr (
            .I(clk_int),
            .O(output_clk),
            .CE(1'b1),
            .CLR(1'b0)
        );
        
    end else if (CLOCK_INPUT_STYLE == "BUFIO") begin

        assign clk_int = input_clk;

        // pass through RX clock to input buffers
        BUFIO
        clk_bufio (
            .I(clk_int),
            .O(clk_io)
        );

        // pass through RX clock to MAC
        BUFG
        clk_bufg (
            .I(clk_int),
            .O(output_clk)
        );

    end else if (CLOCK_INPUT_STYLE == "BUFIO2") begin

        // pass through RX clock to input buffers
        BUFIO2 #(
            .DIVIDE(1),
            .DIVIDE_BYPASS("TRUE"),
            .I_INVERT("FALSE"),
            .USE_DOUBLER("FALSE")
        )
        clk_bufio (
            .I(input_clk),
            .DIVCLK(clk_int),
            .IOCLK(clk_io),
            .SERDESSTROBE()
        );

        // pass through RX clock to MAC
        BUFG
        clk_bufg (
            .I(clk_int),
            .O(output_clk)
        );

    end

end else begin

    // pass through RX clock to input buffers
    assign clk_io = input_clk;

    // pass through RX clock to logic
    assign clk_int = input_clk;
    assign output_clk = clk_int;

end

endgenerate

(* IOB = "TRUE" *)
reg [WIDTH-1:0] output_q_reg = {WIDTH{1'b0}};

assign output_q = output_q_reg;

always @(posedge clk_io) begin
    output_q_reg <= input_d;
end

endmodule
module xgmii_interleave
(
    input  wire [63:0] input_xgmii_d,
    input  wire [7:0]  input_xgmii_c,

    output wire [72:0] output_xgmii_dc
);

assign output_xgmii_dc[7:0] = input_xgmii_d[7:0];
assign output_xgmii_dc[8] = input_xgmii_c[0];
assign output_xgmii_dc[16:9] = input_xgmii_d[15:8];
assign output_xgmii_dc[17] = input_xgmii_c[1];
assign output_xgmii_dc[25:18] = input_xgmii_d[23:16];
assign output_xgmii_dc[26] = input_xgmii_c[2];
assign output_xgmii_dc[34:27] = input_xgmii_d[31:24];
assign output_xgmii_dc[35] = input_xgmii_c[3];
assign output_xgmii_dc[43:36] = input_xgmii_d[39:32];
assign output_xgmii_dc[44] = input_xgmii_c[4];
assign output_xgmii_dc[52:45] = input_xgmii_d[47:40];
assign output_xgmii_dc[53] = input_xgmii_c[5];
assign output_xgmii_dc[61:54] = input_xgmii_d[55:48];
assign output_xgmii_dc[62] = input_xgmii_c[6];
assign output_xgmii_dc[70:63] = input_xgmii_d[63:56];
assign output_xgmii_dc[71] = input_xgmii_c[7];

endmodule
module ssio_sdr_in_diff #
(
    // target ("SIM", "GENERIC", "XILINX", "ALTERA")
    parameter TARGET = "GENERIC",
    // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2")
    // Use BUFR for Virtex-5, Virtex-6, 7-series
    // Use BUFG for Ultrascale
    // Use BUFIO2 for Spartan-6
    parameter CLOCK_INPUT_STYLE = "BUFIO2",
    // Width of register in bits
    parameter WIDTH = 1
)
(
    input  wire             input_clk_p,
    input  wire             input_clk_n,

    input  wire [WIDTH-1:0] input_d_p,
    input  wire [WIDTH-1:0] input_d_n,

    output wire             output_clk,

    output wire [WIDTH-1:0] output_q
);

wire input_clk;
wire [WIDTH-1:0] input_d;

genvar n;

generate

if (TARGET == "XILINX") begin
    IBUFDS
    clk_ibufds_inst (
        .I(input_clk_p),
        .IB(input_clk_n),
        .O(input_clk)
    );
    for (n = 0; n < WIDTH; n = n + 1) begin
        IBUFDS
        data_ibufds_inst (
            .I(input_d_p[n]),
            .IB(input_d_n[n]),
            .O(input_d[n])
        );
    end
end else if (TARGET == "ALTERA") begin
    ALT_INBUF_DIFF
    clk_inbuf_diff_inst (
        .i(input_clk_p),
        .ibar(input_clk_n),
        .o(input_clk)
    );
    for (n = 0; n < WIDTH; n = n + 1) begin
        ALT_INBUF_DIFF
        data_inbuf_diff_inst (
            .i(input_d_p[n]),
            .ibar(input_d_n[n]),
            .o(input_d[n])
        );
    end
end else begin
    assign input_clk = input_clk_p;
    assign input_d = input_d_p;
end

endgenerate

ssio_sdr_in #(
    .TARGET(TARGET),
    .IODDR_STYLE(IODDR_STYLE),
    .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE),
    .WIDTH(WIDTH)
)
ssio_ddr_in_inst(
    .input_clk(input_clk),
    .input_d(input_d),
    .output_clk(output_clk),
    .output_q(output_q)
);

endmodule
module mii_phy_if #
(
    // target ("SIM", "GENERIC", "XILINX", "ALTERA")
    parameter TARGET = "GENERIC",
    // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2")
    // Use BUFR for Virtex-5, Virtex-6, 7-series
    // Use BUFG for Ultrascale
    // Use BUFIO2 for Spartan-6
    parameter CLOCK_INPUT_STYLE = "BUFIO2"
)
(
    input  wire        rst,

    /*
     * MII interface to MAC
     */
    output wire        mac_mii_rx_clk,
    output wire        mac_mii_rx_rst,
    output wire [3:0]  mac_mii_rxd,
    output wire        mac_mii_rx_dv,
    output wire        mac_mii_rx_er,
    output wire        mac_mii_tx_clk,
    output wire        mac_mii_tx_rst,
    input  wire [3:0]  mac_mii_txd,
    input  wire        mac_mii_tx_en,
    input  wire        mac_mii_tx_er,

    /*
     * MII interface to PHY
     */
    input  wire        phy_mii_rx_clk,
    input  wire [3:0]  phy_mii_rxd,
    input  wire        phy_mii_rx_dv,
    input  wire        phy_mii_rx_er,
    input  wire        phy_mii_tx_clk,
    output wire [3:0]  phy_mii_txd,
    output wire        phy_mii_tx_en,
    output wire        phy_mii_tx_er
);

ssio_sdr_in #
(
    .TARGET(TARGET),
    .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE),
    .WIDTH(6)
)
rx_ssio_sdr_inst (
    .input_clk(phy_mii_rx_clk),
    .input_d({phy_mii_rxd, phy_mii_rx_dv, phy_mii_rx_er}),
    .output_clk(mac_mii_rx_clk),
    .output_q({mac_mii_rxd, mac_mii_rx_dv, mac_mii_rx_er})
);

(* IOB = "TRUE" *)
reg [3:0] phy_mii_txd_reg = 4'd0;
(* IOB = "TRUE" *)
reg phy_mii_tx_en_reg = 1'b0, phy_mii_tx_er_reg = 1'b0;

assign phy_mii_txd = phy_mii_txd_reg;
assign phy_mii_tx_en = phy_mii_tx_en_reg;
assign phy_mii_tx_er = phy_mii_tx_er_reg;

always @(posedge mac_mii_tx_clk) begin
    phy_mii_txd_reg <= mac_mii_txd;
    phy_mii_tx_en_reg <= mac_mii_tx_en;
    phy_mii_tx_er_reg <= mac_mii_tx_er;
end

generate

if (TARGET == "XILINX") begin
    BUFG
    mii_bufg_inst (
        .I(phy_mii_tx_clk),
        .O(mac_mii_tx_clk)
    );
end else begin
    assign mac_mii_tx_clk = phy_mii_tx_clk;
end

endgenerate

// reset sync
reg [3:0] tx_rst_reg = 4'hf;
assign mac_mii_tx_rst = tx_rst_reg[0];

always @(posedge mac_mii_tx_clk or posedge rst) begin
    if (rst) begin
        tx_rst_reg <= 4'hf;
    end else begin
        tx_rst_reg <= {1'b0, tx_rst_reg[3:1]};
    end
end

reg [3:0] rx_rst_reg = 4'hf;
assign mac_mii_rx_rst = rx_rst_reg[0];

always @(posedge mac_mii_rx_clk or posedge rst) begin
    if (rst) begin
        rx_rst_reg <= 4'hf;
    end else begin
        rx_rst_reg <= {1'b0, rx_rst_reg[3:1]};
    end
end

endmodule
module eth_phy_10g_rx #
(
    parameter DATA_WIDTH = 64,
    parameter CTRL_WIDTH = (DATA_WIDTH/8),
    parameter HDR_WIDTH = 2,
    parameter BIT_REVERSE = 0,
    parameter SCRAMBLER_DISABLE = 0,
    parameter PRBS31_ENABLE = 0,
    parameter SERDES_PIPELINE = 0,
    parameter BITSLIP_HIGH_CYCLES = 1,
    parameter BITSLIP_LOW_CYCLES = 8,
    parameter COUNT_125US = 125000/6.4
)
(
    input  wire                  clk,
    input  wire                  rst,

    /*
     * XGMII interface
     */
    output wire [DATA_WIDTH-1:0] xgmii_rxd,
    output wire [CTRL_WIDTH-1:0] xgmii_rxc,

    /*
     * SERDES interface
     */
    input  wire [DATA_WIDTH-1:0] serdes_rx_data,
    input  wire [HDR_WIDTH-1:0]  serdes_rx_hdr,
    output wire                  serdes_rx_bitslip,
    output wire                  serdes_rx_reset_req,

    /*
     * Status
     */
    output wire [6:0]            rx_error_count,
    output wire                  rx_bad_block,
    output wire                  rx_sequence_error,
    output wire                  rx_block_lock,
    output wire                  rx_high_ber,
    output wire                  rx_status,

    /*
     * Configuration
     */
    input  wire                  cfg_rx_prbs31_enable
);

// bus width assertions
initial begin
    if (DATA_WIDTH != 64) begin
        $error("Error: Interface width must be 64");
        $finish;
    end

    if (CTRL_WIDTH * 8 != DATA_WIDTH) begin
        $error("Error: Interface requires byte (8-bit) granularity");
        $finish;
    end

    if (HDR_WIDTH != 2) begin
        $error("Error: HDR_WIDTH must be 2");
        $finish;
    end
end

wire [DATA_WIDTH-1:0] encoded_rx_data;
wire [HDR_WIDTH-1:0]  encoded_rx_hdr;

eth_phy_10g_rx_if #(
    .DATA_WIDTH(DATA_WIDTH),
    .HDR_WIDTH(HDR_WIDTH),
    .BIT_REVERSE(BIT_REVERSE),
    .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE),
    .PRBS31_ENABLE(PRBS31_ENABLE),
    .SERDES_PIPELINE(SERDES_PIPELINE),
    .BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
    .BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
    .COUNT_125US(COUNT_125US)
)
eth_phy_10g_rx_if_inst (
    .clk(clk),
    .rst(rst),
    .encoded_rx_data(encoded_rx_data),
    .encoded_rx_hdr(encoded_rx_hdr),
    .serdes_rx_data(serdes_rx_data),
    .serdes_rx_hdr(serdes_rx_hdr),
    .serdes_rx_bitslip(serdes_rx_bitslip),
    .serdes_rx_reset_req(serdes_rx_reset_req),
    .rx_bad_block(rx_bad_block),
    .rx_sequence_error(rx_sequence_error),
    .rx_error_count(rx_error_count),
    .rx_block_lock(rx_block_lock),
    .rx_high_ber(rx_high_ber),
    .rx_status(rx_status),
    .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable)
);

xgmii_baser_dec_64 #(
    .DATA_WIDTH(DATA_WIDTH),
    .CTRL_WIDTH(CTRL_WIDTH),
    .HDR_WIDTH(HDR_WIDTH)
)
xgmii_baser_dec_inst (
    .clk(clk),
    .rst(rst),
    .encoded_rx_data(encoded_rx_data),
    .encoded_rx_hdr(encoded_rx_hdr),
    .xgmii_rxd(xgmii_rxd),
    .xgmii_rxc(xgmii_rxc),
    .rx_bad_block(rx_bad_block),
    .rx_sequence_error(rx_sequence_error)
);

endmodule
module eth_phy_10g #
(
    parameter DATA_WIDTH = 64,
    parameter CTRL_WIDTH = (DATA_WIDTH/8),
    parameter HDR_WIDTH = 2,
    parameter BIT_REVERSE = 0,
    parameter SCRAMBLER_DISABLE = 0,
    parameter PRBS31_ENABLE = 0,
    parameter TX_SERDES_PIPELINE = 0,
    parameter RX_SERDES_PIPELINE = 0,
    parameter BITSLIP_HIGH_CYCLES = 1,
    parameter BITSLIP_LOW_CYCLES = 8,
    parameter COUNT_125US = 125000/6.4
)
(
    input  wire                  rx_clk,
    input  wire                  rx_rst,
    input  wire                  tx_clk,
    input  wire                  tx_rst,

    /*
     * XGMII interface
     */
    input  wire [DATA_WIDTH-1:0] xgmii_txd,
    input  wire [CTRL_WIDTH-1:0] xgmii_txc,
    output wire [DATA_WIDTH-1:0] xgmii_rxd,
    output wire [CTRL_WIDTH-1:0] xgmii_rxc,

    /*
     * SERDES interface
     */
    output wire [DATA_WIDTH-1:0] serdes_tx_data,
    output wire [HDR_WIDTH-1:0]  serdes_tx_hdr,
    input  wire [DATA_WIDTH-1:0] serdes_rx_data,
    input  wire [HDR_WIDTH-1:0]  serdes_rx_hdr,
    output wire                  serdes_rx_bitslip,
    output wire                  serdes_rx_reset_req,

    /*
     * Status
     */
    output wire                  tx_bad_block,
    output wire [6:0]            rx_error_count,
    output wire                  rx_bad_block,
    output wire                  rx_sequence_error,
    output wire                  rx_block_lock,
    output wire                  rx_high_ber,
    output wire                  rx_status,

    /*
     * Configuration
     */
    input  wire                  cfg_tx_prbs31_enable,
    input  wire                  cfg_rx_prbs31_enable
);

eth_phy_10g_rx #(
    .DATA_WIDTH(DATA_WIDTH),
    .CTRL_WIDTH(CTRL_WIDTH),
    .HDR_WIDTH(HDR_WIDTH),
    .BIT_REVERSE(BIT_REVERSE),
    .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE),
    .PRBS31_ENABLE(PRBS31_ENABLE),
    .SERDES_PIPELINE(RX_SERDES_PIPELINE),
    .BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
    .BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
    .COUNT_125US(COUNT_125US)
)
eth_phy_10g_rx_inst (
    .clk(rx_clk),
    .rst(rx_rst),
    .xgmii_rxd(xgmii_rxd),
    .xgmii_rxc(xgmii_rxc),
    .serdes_rx_data(serdes_rx_data),
    .serdes_rx_hdr(serdes_rx_hdr),
    .serdes_rx_bitslip(serdes_rx_bitslip),
    .serdes_rx_reset_req(serdes_rx_reset_req),
    .rx_error_count(rx_error_count),
    .rx_bad_block(rx_bad_block),
    .rx_sequence_error(rx_sequence_error),
    .rx_block_lock(rx_block_lock),
    .rx_high_ber(rx_high_ber),
    .rx_status(rx_status),
    .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable)
);

eth_phy_10g_tx #(
    .DATA_WIDTH(DATA_WIDTH),
    .CTRL_WIDTH(CTRL_WIDTH),
    .HDR_WIDTH(HDR_WIDTH),
    .BIT_REVERSE(BIT_REVERSE),
    .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE),
    .PRBS31_ENABLE(PRBS31_ENABLE),
    .SERDES_PIPELINE(TX_SERDES_PIPELINE)
)
eth_phy_10g_tx_inst (
    .clk(tx_clk),
    .rst(tx_rst),
    .xgmii_txd(xgmii_txd),
    .xgmii_txc(xgmii_txc),
    .serdes_tx_data(serdes_tx_data),
    .serdes_tx_hdr(serdes_tx_hdr),
    .tx_bad_block(tx_bad_block),
    .cfg_tx_prbs31_enable(cfg_tx_prbs31_enable)
);

endmodule
module ptp_ts_extract #
(
    parameter TS_WIDTH = 96,
    parameter TS_OFFSET = 1,
    parameter USER_WIDTH = TS_WIDTH+TS_OFFSET
)
(
    input  wire                   clk,
    input  wire                   rst,

    /*
     * AXI stream input
     */
    input  wire                   s_axis_tvalid,
    input  wire                   s_axis_tlast,
    input  wire [USER_WIDTH-1:0]  s_axis_tuser,

    /*
     * Timestamp output
     */
    output wire [TS_WIDTH-1:0]    m_axis_ts,
    output wire                   m_axis_ts_valid
);

reg frame_reg = 1'b0;

assign m_axis_ts = s_axis_tuser >> TS_OFFSET;
assign m_axis_ts_valid = s_axis_tvalid && !frame_reg;

always @(posedge clk) begin
    if (s_axis_tvalid) begin
        frame_reg <= !s_axis_tlast;
    end

    if (rst) begin
        frame_reg <= 1'b0;
    end
end

endmodule
module gmii_phy_if #
(
    // target ("SIM", "GENERIC", "XILINX", "ALTERA")
    parameter TARGET = "GENERIC",
    // IODDR style ("IODDR", "IODDR2")
    // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale
    // Use IODDR2 for Spartan-6
    parameter IODDR_STYLE = "IODDR2",
    // Clock input style ("BUFG", "BUFR", "BUFIO", "BUFIO2")
    // Use BUFR for Virtex-5, Virtex-6, 7-series
    // Use BUFG for Ultrascale
    // Use BUFIO2 for Spartan-6
    parameter CLOCK_INPUT_STYLE = "BUFIO2"
)
(
    input  wire        clk,
    input  wire        rst,

    /*
     * GMII interface to MAC
     */
    output wire        mac_gmii_rx_clk,
    output wire        mac_gmii_rx_rst,
    output wire [7:0]  mac_gmii_rxd,
    output wire        mac_gmii_rx_dv,
    output wire        mac_gmii_rx_er,
    output wire        mac_gmii_tx_clk,
    output wire        mac_gmii_tx_rst,
    input  wire [7:0]  mac_gmii_txd,
    input  wire        mac_gmii_tx_en,
    input  wire        mac_gmii_tx_er,

    /*
     * GMII interface to PHY
     */
    input  wire        phy_gmii_rx_clk,
    input  wire [7:0]  phy_gmii_rxd,
    input  wire        phy_gmii_rx_dv,
    input  wire        phy_gmii_rx_er,
    input  wire        phy_mii_tx_clk,
    output wire        phy_gmii_tx_clk,
    output wire [7:0]  phy_gmii_txd,
    output wire        phy_gmii_tx_en,
    output wire        phy_gmii_tx_er,

    /*
     * Control
     */
    input  wire        mii_select
);

ssio_sdr_in #
(
    .TARGET(TARGET),
    .CLOCK_INPUT_STYLE(CLOCK_INPUT_STYLE),
    .WIDTH(10)
)
rx_ssio_sdr_inst (
    .input_clk(phy_gmii_rx_clk),
    .input_d({phy_gmii_rxd, phy_gmii_rx_dv, phy_gmii_rx_er}),
    .output_clk(mac_gmii_rx_clk),
    .output_q({mac_gmii_rxd, mac_gmii_rx_dv, mac_gmii_rx_er})
);

ssio_sdr_out #
(
    .TARGET(TARGET),
    .IODDR_STYLE(IODDR_STYLE),
    .WIDTH(10)
)
tx_ssio_sdr_inst (
    .clk(mac_gmii_tx_clk),
    .input_d({mac_gmii_txd, mac_gmii_tx_en, mac_gmii_tx_er}),
    .output_clk(phy_gmii_tx_clk),
    .output_q({phy_gmii_txd, phy_gmii_tx_en, phy_gmii_tx_er})
);

generate

if (TARGET == "XILINX") begin
    BUFGMUX
    gmii_bufgmux_inst (
        .I0(clk),
        .I1(phy_mii_tx_clk),
        .S(mii_select),
        .O(mac_gmii_tx_clk)
    );
end else begin
    assign mac_gmii_tx_clk = mii_select ? phy_mii_tx_clk : clk;
end

endgenerate

// reset sync
reg [3:0] tx_rst_reg = 4'hf;
assign mac_gmii_tx_rst = tx_rst_reg[0];

always @(posedge mac_gmii_tx_clk or posedge rst) begin
    if (rst) begin
        tx_rst_reg <= 4'hf;
    end else begin
        tx_rst_reg <= {1'b0, tx_rst_reg[3:1]};
    end
end

reg [3:0] rx_rst_reg = 4'hf;
assign mac_gmii_rx_rst = rx_rst_reg[0];

always @(posedge mac_gmii_rx_clk or posedge rst) begin
    if (rst) begin
        rx_rst_reg <= 4'hf;
    end else begin
        rx_rst_reg <= {1'b0, rx_rst_reg[3:1]};
    end
end

endmodule
module eth_phy_10g_rx_ber_mon #
(
    parameter HDR_WIDTH = 2,
    parameter COUNT_125US = 125000/6.4
)
(
    input  wire                  clk,
    input  wire                  rst,

    /*
     * SERDES interface
     */
    input  wire [HDR_WIDTH-1:0]  serdes_rx_hdr,

    /*
     * Status
     */
    output wire                  rx_high_ber
);

// bus width assertions
initial begin
    if (HDR_WIDTH != 2) begin
        $error("Error: HDR_WIDTH must be 2");
        $finish;
    end
end

parameter COUNT_WIDTH = $clog2($rtoi(COUNT_125US));

localparam [1:0]
    SYNC_DATA = 2'b10,
    SYNC_CTRL = 2'b01;

reg [COUNT_WIDTH-1:0] time_count_reg = COUNT_125US, time_count_next;
reg [3:0] ber_count_reg = 4'd0, ber_count_next;

reg rx_high_ber_reg = 1'b0, rx_high_ber_next;

assign rx_high_ber = rx_high_ber_reg;

always @* begin
    if (time_count_reg > 0) begin
        time_count_next = time_count_reg-1;
    end else begin
        time_count_next = time_count_reg;
    end
    ber_count_next = ber_count_reg;

    rx_high_ber_next = rx_high_ber_reg;

    if (serdes_rx_hdr == SYNC_CTRL || serdes_rx_hdr == SYNC_DATA) begin
        // valid header
        if (ber_count_reg != 4'd15) begin
            if (time_count_reg == 0) begin
                rx_high_ber_next = 1'b0;
            end
        end
    end else begin
        // invalid header
        if (ber_count_reg == 4'd15) begin
            rx_high_ber_next = 1'b1;
        end else begin
            ber_count_next = ber_count_reg + 1;
            if (time_count_reg == 0) begin
                rx_high_ber_next = 1'b0;
            end
        end
    end
    if (time_count_reg == 0) begin
        // 125 us timer expired
        ber_count_next = 4'd0;
        time_count_next = COUNT_125US;
    end
end

always @(posedge clk) begin
    time_count_reg <= time_count_next;
    ber_count_reg <= ber_count_next;
    rx_high_ber_reg <= rx_high_ber_next;

    if (rst) begin
        time_count_reg <= COUNT_125US;
        ber_count_reg <= 4'd0;
        rx_high_ber_reg <= 1'b0;
    end
end

endmodule
module oddr #
(
    // target ("SIM", "GENERIC", "XILINX", "ALTERA")
    parameter TARGET = "GENERIC",
    // IODDR style ("IODDR", "IODDR2")
    // Use IODDR for Virtex-4, Virtex-5, Virtex-6, 7 Series, Ultrascale
    // Use IODDR2 for Spartan-6
    parameter IODDR_STYLE = "IODDR2",
    // Width of register in bits
    parameter WIDTH = 1
)
(
    input  wire             clk,

    input  wire [WIDTH-1:0] d1,
    input  wire [WIDTH-1:0] d2,

    output wire [WIDTH-1:0] q
);

/*

Provides a consistent output DDR flip flop across multiple FPGA families
              _____       _____       _____       _____
    clk  ____/     \_____/     \_____/     \_____/     \_____
         _ ___________ ___________ ___________ ___________ __
    d1   _X____D0_____X____D2_____X____D4_____X____D6_____X__
         _ ___________ ___________ ___________ ___________ __
    d2   _X____D1_____X____D3_____X____D5_____X____D7_____X__
         _____ _____ _____ _____ _____ _____ _____ _____ ____
    d    _____X_D0__X_D1__X_D2__X_D3__X_D4__X_D5__X_D6__X_D7_

*/

genvar n;

generate

if (TARGET == "XILINX") begin
    for (n = 0; n < WIDTH; n = n + 1) begin : oddr
        if (IODDR_STYLE == "IODDR") begin
            ODDR #(
                .DDR_CLK_EDGE("SAME_EDGE"),
                .SRTYPE("ASYNC")
            )
            oddr_inst (
                .Q(q[n]),
                .C(clk),
                .CE(1'b1),
                .D1(d1[n]),
                .D2(d2[n]),
                .R(1'b0),
                .S(1'b0)
            );
        end else if (IODDR_STYLE == "IODDR2") begin
            ODDR2 #(
                .DDR_ALIGNMENT("C0"),
                .SRTYPE("ASYNC")
            )
            oddr_inst (
                .Q(q[n]),
                .C0(clk),
                .C1(~clk),
                .CE(1'b1),
                .D0(d1[n]),
                .D1(d2[n]),
                .R(1'b0),
                .S(1'b0)
            );
        end
    end
end else if (TARGET == "ALTERA") begin
    altddio_out #(
        .WIDTH(WIDTH),
        .POWER_UP_HIGH("OFF"),
        .OE_REG("UNUSED")
    )
    altddio_out_inst (
        .aset(1'b0),
        .datain_h(d1),
        .datain_l(d2),
        .outclocken(1'b1),
        .outclock(clk),
        .aclr(1'b0),
        .dataout(q)
    );
end else begin
    reg [WIDTH-1:0] d_reg_1 = {WIDTH{1'b0}};
    reg [WIDTH-1:0] d_reg_2 = {WIDTH{1'b0}};

    reg [WIDTH-1:0] q_reg = {WIDTH{1'b0}};

    always @(posedge clk) begin
        d_reg_1 <= d1;
        d_reg_2 <= d2;
    end

    always @(posedge clk) begin
        q_reg <= d1;
    end

    always @(negedge clk) begin
        q_reg <= d_reg_2;
    end

    assign q = q_reg;
end

endgenerate

endmodule
module eth_phy_10g_tx #
(
    parameter DATA_WIDTH = 64,
    parameter CTRL_WIDTH = (DATA_WIDTH/8),
    parameter HDR_WIDTH = 2,
    parameter BIT_REVERSE = 0,
    parameter SCRAMBLER_DISABLE = 0,
    parameter PRBS31_ENABLE = 0,
    parameter SERDES_PIPELINE = 0
)
(
    input  wire                  clk,
    input  wire                  rst,

    /*
     * XGMII interface
     */
    input  wire [DATA_WIDTH-1:0] xgmii_txd,
    input  wire [CTRL_WIDTH-1:0] xgmii_txc,

    /*
     * SERDES interface
     */
    output wire [DATA_WIDTH-1:0] serdes_tx_data,
    output wire [HDR_WIDTH-1:0]  serdes_tx_hdr,

    /*
     * Status
     */
    output wire                  tx_bad_block,

    /*
     * Configuration
     */
    input  wire                  cfg_tx_prbs31_enable
);

// bus width assertions
initial begin
    if (DATA_WIDTH != 64) begin
        $error("Error: Interface width must be 64");
        $finish;
    end

    if (CTRL_WIDTH * 8 != DATA_WIDTH) begin
        $error("Error: Interface requires byte (8-bit) granularity");
        $finish;
    end

    if (HDR_WIDTH != 2) begin
        $error("Error: HDR_WIDTH must be 2");
        $finish;
    end
end

wire [DATA_WIDTH-1:0] encoded_tx_data;
wire [HDR_WIDTH-1:0]  encoded_tx_hdr;

xgmii_baser_enc_64 #(
    .DATA_WIDTH(DATA_WIDTH),
    .CTRL_WIDTH(CTRL_WIDTH),
    .HDR_WIDTH(HDR_WIDTH)
)
xgmii_baser_enc_inst (
    .clk(clk),
    .rst(rst),
    .xgmii_txd(xgmii_txd),
    .xgmii_txc(xgmii_txc),
    .encoded_tx_data(encoded_tx_data),
    .encoded_tx_hdr(encoded_tx_hdr),
    .tx_bad_block(tx_bad_block)
);

eth_phy_10g_tx_if #(
    .DATA_WIDTH(DATA_WIDTH),
    .HDR_WIDTH(HDR_WIDTH),
    .BIT_REVERSE(BIT_REVERSE),
    .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE),
    .PRBS31_ENABLE(PRBS31_ENABLE),
    .SERDES_PIPELINE(SERDES_PIPELINE)
)
eth_phy_10g_tx_if_inst (
    .clk(clk),
    .rst(rst),
    .encoded_tx_data(encoded_tx_data),
    .encoded_tx_hdr(encoded_tx_hdr),
    .serdes_tx_data(serdes_tx_data),
    .serdes_tx_hdr(serdes_tx_hdr),
    .cfg_tx_prbs31_enable(cfg_tx_prbs31_enable)
);

endmodule
module test_axis_xgmii_rx_32;

// Parameters
parameter DATA_WIDTH = 32;
parameter KEEP_WIDTH = (DATA_WIDTH/8);
parameter CTRL_WIDTH = (DATA_WIDTH/8);
parameter PTP_TS_ENABLE = 0;
parameter PTP_TS_WIDTH = 96;
parameter USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1;

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] xgmii_rxd = 32'h07070707;
reg [CTRL_WIDTH-1:0] xgmii_rxc = 4'hf;
reg [PTP_TS_WIDTH-1:0] ptp_ts = 0;

// Outputs
wire [DATA_WIDTH-1:0] m_axis_tdata;
wire [KEEP_WIDTH-1:0] m_axis_tkeep;
wire m_axis_tvalid;
wire m_axis_tlast;
wire [USER_WIDTH-1:0] m_axis_tuser;
wire start_packet;
wire error_bad_frame;
wire error_bad_fcs;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        xgmii_rxd,
        xgmii_rxc,
        ptp_ts
    );
    $to_myhdl(
        m_axis_tdata,
        m_axis_tkeep,
        m_axis_tvalid,
        m_axis_tlast,
        m_axis_tuser,
        start_packet,
        error_bad_frame,
        error_bad_fcs
    );

    // dump file
    $dumpfile("test_axis_xgmii_rx_32.lxt");
    $dumpvars(0, test_axis_xgmii_rx_32);
end

axis_xgmii_rx_32 #(
    .DATA_WIDTH(DATA_WIDTH),
    .KEEP_WIDTH(KEEP_WIDTH),
    .CTRL_WIDTH(CTRL_WIDTH),
    .PTP_TS_ENABLE(PTP_TS_ENABLE),
    .PTP_TS_WIDTH(PTP_TS_WIDTH),
    .USER_WIDTH(USER_WIDTH)
)
UUT (
    .clk(clk),
    .rst(rst),
    .xgmii_rxd(xgmii_rxd),
    .xgmii_rxc(xgmii_rxc),
    .m_axis_tdata(m_axis_tdata),
    .m_axis_tkeep(m_axis_tkeep),
    .m_axis_tvalid(m_axis_tvalid),
    .m_axis_tlast(m_axis_tlast),
    .m_axis_tuser(m_axis_tuser),
    .ptp_ts(ptp_ts),
    .start_packet(start_packet),
    .error_bad_frame(error_bad_frame),
    .error_bad_fcs(error_bad_fcs)
);

endmodule