diff --git a/fpga/mqnic/fb2CG/fpga_100g/fpga.xdc b/fpga/mqnic/fb2CG/fpga_100g/fpga.xdc index 7f445af6e..244f700e6 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/fpga.xdc +++ b/fpga/mqnic/fb2CG/fpga_100g/fpga.xdc @@ -42,9 +42,9 @@ set_property -dict {LOC D3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports { set_property -dict {LOC D4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {led_exp[1]}] # GPIO -#set_property -dict {LOC B4 IOSTANDARD LVCMOS33} [get_ports pps_in] ;# from SMA J6 via Q1 (inverted) -#set_property -dict {LOC A4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 4} [get_ports pps_out] ;# to SMA J6 via U4 and U5, and u.FL J7 (PPS OUT) via U3 -#set_property -dict {LOC A3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports pps_out_en] ; # to U5 IN (connects pps_out to SMA J6 when high) +set_property -dict {LOC B4 IOSTANDARD LVCMOS33} [get_ports pps_in] ;# from SMA J6 via Q1 (inverted) +set_property -dict {LOC A4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 4} [get_ports pps_out] ;# to SMA J6 via U4 and U5, and u.FL J7 (PPS OUT) via U3 +set_property -dict {LOC A3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports pps_out_en] ; # to U5 IN (connects pps_out to SMA J6 when high) #set_property -dict {LOC H2 IOSTANDARD LVCMOS33} [get_ports misc_ucoax] ; from u.FL J5 (PPS IN) # BMC interface diff --git a/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga.v b/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga.v index 7ca7cbdfb..eca7bcb5d 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga.v @@ -53,6 +53,10 @@ module fpga ( output wire [1:0] led_bmc, output wire [1:0] led_exp, + input wire pps_in, + output wire pps_out, + output wire pps_out_en, + /* * Board status */ @@ -1409,6 +1413,10 @@ core_inst ( .led_bmc(led_bmc), .led_exp(led_exp), + .pps_in(pps_in), + .pps_out(pps_out), + .pps_out_en(pps_out_en), + /* * PCIe */ diff --git a/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga_core.v index eb384008e..c082a5ca1 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga_core.v @@ -68,6 +68,10 @@ module fpga_core # output wire [1:0] led_bmc, output wire [1:0] led_exp, + input wire pps_in, + output wire pps_out, + output wire pps_out_en, + /* * PCIe */ @@ -416,6 +420,11 @@ wire [95:0] ptp_ts_96; wire ptp_ts_step; wire ptp_pps; +reg ptp_perout_enable_reg = 1'b0; +wire ptp_perout_locked; +wire ptp_perout_error; +wire ptp_perout_pulse; + // control registers reg axil_csr_awready_reg = 1'b0; reg axil_csr_wready_reg = 1'b0; @@ -455,6 +464,13 @@ reg [15:0] set_ptp_offset_count_reg = 0; reg set_ptp_offset_valid_reg = 0; wire set_ptp_offset_active; +reg [95:0] set_ptp_perout_start_ts_96_reg = 0; +reg set_ptp_perout_start_ts_96_valid_reg = 0; +reg [95:0] set_ptp_perout_period_ts_96_reg = 0; +reg set_ptp_perout_period_ts_96_valid_reg = 0; +reg [95:0] set_ptp_perout_width_ts_96_reg = 0; +reg set_ptp_perout_width_ts_96_valid_reg = 0; + assign axil_csr_awready = axil_csr_awready_reg; assign axil_csr_wready = axil_csr_wready_reg; assign axil_csr_bresp = 2'b00; @@ -500,6 +516,10 @@ always @(posedge clk_250mhz) begin set_ptp_period_valid_reg <= 1'b0; set_ptp_offset_valid_reg <= 1'b0; + set_ptp_perout_start_ts_96_valid_reg <= 1'b0; + set_ptp_perout_period_ts_96_valid_reg <= 1'b0; + set_ptp_perout_width_ts_96_valid_reg <= 1'b0; + if (axil_csr_awvalid && axil_csr_wvalid && !axil_csr_bvalid) begin // write operation axil_csr_awready_reg <= 1'b1; @@ -577,6 +597,34 @@ always @(posedge clk_250mhz) begin set_ptp_offset_count_reg <= axil_csr_wdata; set_ptp_offset_valid_reg <= 1'b1; end + 16'h0260: begin + // PTP perout control + ptp_perout_enable_reg <= axil_csr_wdata[0]; + end + 16'h0270: set_ptp_perout_start_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout start fns + 16'h0274: set_ptp_perout_start_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout start ns + 16'h0278: set_ptp_perout_start_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout start sec l + 16'h027C: begin + // PTP perout start sec h + set_ptp_perout_start_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_start_ts_96_valid_reg <= 1'b1; + end + 16'h0280: set_ptp_perout_period_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout period fns + 16'h0284: set_ptp_perout_period_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout period ns + 16'h0288: set_ptp_perout_period_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout period sec l + 16'h028C: begin + // PTP perout period sec h + set_ptp_perout_period_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_period_ts_96_valid_reg <= 1'b1; + end + 16'h0290: set_ptp_perout_width_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout width fns + 16'h0294: set_ptp_perout_width_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout width ns + 16'h0298: set_ptp_perout_width_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout width sec l + 16'h029C: begin + // PTP perout width sec h + set_ptp_perout_width_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_width_ts_96_valid_reg <= 1'b1; + end endcase end @@ -634,7 +682,7 @@ always @(posedge clk_250mhz) begin axil_csr_rdata_reg[17] <= qspi_cs; end // PHC - 16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features + 16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd1}; // PHC features 16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns 16'h0214: axil_csr_rdata_reg <= ptp_ts_96[45:16]; // PTP cur ns 16'h0218: axil_csr_rdata_reg <= ptp_ts_96[79:48]; // PTP cur sec l @@ -659,6 +707,27 @@ always @(posedge clk_250mhz) begin 16'h0254: axil_csr_rdata_reg <= set_ptp_offset_ns_reg; // PTP offset ns 16'h0258: axil_csr_rdata_reg <= set_ptp_offset_count_reg; // PTP offset count 16'h025C: axil_csr_rdata_reg <= set_ptp_offset_active; // PTP offset status + 16'h0260: begin + // PTP perout control + axil_csr_rdata_reg[0] <= ptp_perout_enable_reg; + end + 16'h0264: begin + // PTP perout status + axil_csr_rdata_reg[0] <= ptp_perout_locked; + axil_csr_rdata_reg[1] <= ptp_perout_error; + end + 16'h0270: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[15:0]; // PTP perout start fns + 16'h0274: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[45:16]; // PTP perout start ns + 16'h0278: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[79:48]; // PTP perout start sec l + 16'h027C: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[95:80]; // PTP perout start sec h + 16'h0280: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[15:0]; // PTP perout period fns + 16'h0284: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[45:16]; // PTP perout period ns + 16'h0288: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[79:48]; // PTP perout period sec l + 16'h028C: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[95:80]; // PTP perout period sec h + 16'h0290: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[15:0]; // PTP perout width fns + 16'h0294: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[45:16]; // PTP perout width ns + 16'h0298: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[79:48]; // PTP perout width sec l + 16'h029C: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[95:80]; // PTP perout width sec h endcase end @@ -687,6 +756,8 @@ always @(posedge clk_250mhz) begin qspi_dq_oe_reg <= 4'd0; pcie_dma_enable_reg <= 1'b0; + + ptp_perout_enable_reg <= 1'b0; end end @@ -1897,6 +1968,38 @@ ptp_clock_inst ( .output_pps(ptp_pps) ); +assign pps_out = ptp_perout_pulse; +assign pps_out_en = 1'b1; + +ptp_perout #( + .FNS_ENABLE(0), + .OUT_START_S(0), + .OUT_START_NS(0), + .OUT_START_FNS(0), + .OUT_PERIOD_S(1), + .OUT_PERIOD_NS(0), + .OUT_PERIOD_FNS(0), + .OUT_WIDTH_S(0), + .OUT_WIDTH_NS(500000000), + .OUT_WIDTH_FNS(0) +) +ptp_perout_inst ( + .clk(clk_250mhz), + .rst(rst_250mhz), + .input_ts_96(ptp_ts_96), + .input_ts_step(ptp_ts_step), + .enable(ptp_perout_enable_reg), + .input_start(set_ptp_perout_start_ts_96_reg), + .input_start_valid(set_ptp_perout_start_ts_96_valid_reg), + .input_period(set_ptp_perout_period_ts_96_reg), + .input_period_valid(set_ptp_perout_period_ts_96_valid_reg), + .input_width(set_ptp_perout_width_ts_96_reg), + .input_width_valid(set_ptp_perout_width_ts_96_valid_reg), + .locked(ptp_perout_locked), + .error(ptp_perout_error), + .output_pulse(ptp_perout_pulse) +); + reg [26:0] pps_led_counter_reg = 0; reg pps_led_reg = 0; diff --git a/fpga/mqnic/fb2CG/fpga_100g/tb/test_fpga_core.py b/fpga/mqnic/fb2CG/fpga_100g/tb/test_fpga_core.py index a79bb3e0d..af4db79fd 100755 --- a/fpga/mqnic/fb2CG/fpga_100g/tb/test_fpga_core.py +++ b/fpga/mqnic/fb2CG/fpga_100g/tb/test_fpga_core.py @@ -137,6 +137,7 @@ def bench(): clk_250mhz = Signal(bool(0)) rst_250mhz = Signal(bool(0)) + pps_in = Signal(bool(0)) m_axis_rq_tready = Signal(bool(0)) s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]) s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]) @@ -206,6 +207,8 @@ def bench(): led_green = Signal(intbv(0)[7:]) led_bmc = Signal(intbv(0)[2:]) led_exp = Signal(intbv(0)[2:]) + pps_out = Signal(bool(0)) + pps_out_en = Signal(bool(0)) m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]) m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]) m_axis_rq_tlast = Signal(bool(0)) @@ -556,6 +559,9 @@ def bench(): led_green=led_green, led_bmc=led_bmc, led_exp=led_exp, + pps_in=pps_in, + pps_out=pps_out, + pps_out_en=pps_out_en, m_axis_rq_tdata=m_axis_rq_tdata, m_axis_rq_tkeep=m_axis_rq_tkeep, m_axis_rq_tlast=m_axis_rq_tlast, diff --git a/fpga/mqnic/fb2CG/fpga_100g/tb/test_fpga_core.v b/fpga/mqnic/fb2CG/fpga_100g/tb/test_fpga_core.v index 7637858c9..5c970e104 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/tb/test_fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_100g/tb/test_fpga_core.v @@ -59,6 +59,7 @@ reg [7:0] current_test = 0; reg clk_250mhz = 0; reg rst_250mhz = 0; +reg pps_in = 0; reg m_axis_rq_tready = 0; reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0; reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0; @@ -128,6 +129,8 @@ wire [7:0] led_red; wire [7:0] led_green; wire [1:0] led_bmc; wire [1:0] led_exp; +wire pps_out; +wire pps_out_en; wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata; wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep; wire m_axis_rq_tlast; @@ -193,6 +196,7 @@ initial begin clk_250mhz, rst_250mhz, current_test, + pps_in, m_axis_rq_tready, s_axis_rc_tdata, s_axis_rc_tkeep, @@ -262,6 +266,8 @@ initial begin led_green, led_bmc, led_exp, + pps_out, + pps_out_en, m_axis_rq_tdata, m_axis_rq_tkeep, m_axis_rq_tlast, @@ -346,6 +352,9 @@ UUT ( .led_green(led_green), .led_bmc(led_bmc), .led_exp(led_exp), + .pps_in(pps_in), + .pps_out(pps_out), + .pps_out_en(pps_out_en), .m_axis_rq_tdata(m_axis_rq_tdata), .m_axis_rq_tkeep(m_axis_rq_tkeep), .m_axis_rq_tlast(m_axis_rq_tlast), diff --git a/fpga/mqnic/fb2CG/fpga_10g/fpga.xdc b/fpga/mqnic/fb2CG/fpga_10g/fpga.xdc index bc31c8e94..51d55b089 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/fpga.xdc +++ b/fpga/mqnic/fb2CG/fpga_10g/fpga.xdc @@ -42,9 +42,9 @@ set_property -dict {LOC D3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports { set_property -dict {LOC D4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {led_exp[1]}] # GPIO -#set_property -dict {LOC B4 IOSTANDARD LVCMOS33} [get_ports pps_in] ;# from SMA J6 via Q1 (inverted) -#set_property -dict {LOC A4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 4} [get_ports pps_out] ;# to SMA J6 via U4 and U5, and u.FL J7 (PPS OUT) via U3 -#set_property -dict {LOC A3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports pps_out_en] ; # to U5 IN (connects pps_out to SMA J6 when high) +set_property -dict {LOC B4 IOSTANDARD LVCMOS33} [get_ports pps_in] ;# from SMA J6 via Q1 (inverted) +set_property -dict {LOC A4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 4} [get_ports pps_out] ;# to SMA J6 via U4 and U5, and u.FL J7 (PPS OUT) via U3 +set_property -dict {LOC A3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports pps_out_en] ; # to U5 IN (connects pps_out to SMA J6 when high) #set_property -dict {LOC H2 IOSTANDARD LVCMOS33} [get_ports misc_ucoax] ; from u.FL J5 (PPS IN) # BMC interface diff --git a/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga.v b/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga.v index a52e1f859..6b245c1a1 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga.v @@ -53,6 +53,10 @@ module fpga ( output wire [1:0] led_bmc, output wire [1:0] led_exp, + input wire pps_in, + output wire pps_out, + output wire pps_out_en, + /* * Board status */ @@ -1406,6 +1410,10 @@ core_inst ( .led_bmc(led_bmc), .led_exp(led_exp), + .pps_in(pps_in), + .pps_out(pps_out), + .pps_out_en(pps_out_en), + /* * PCIe */ diff --git a/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga_core.v index aa367dbd6..c6b8dce30 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga_core.v @@ -66,6 +66,10 @@ module fpga_core # output wire [1:0] led_bmc, output wire [1:0] led_exp, + input wire pps_in, + output wire pps_out, + output wire pps_out_en, + /* * PCIe */ @@ -489,6 +493,11 @@ wire [95:0] ptp_ts_96; wire ptp_ts_step; wire ptp_pps; +reg ptp_perout_enable_reg = 1'b0; +wire ptp_perout_locked; +wire ptp_perout_error; +wire ptp_perout_pulse; + // control registers reg axil_csr_awready_reg = 1'b0; reg axil_csr_wready_reg = 1'b0; @@ -528,6 +537,13 @@ reg [15:0] set_ptp_offset_count_reg = 0; reg set_ptp_offset_valid_reg = 0; wire set_ptp_offset_active; +reg [95:0] set_ptp_perout_start_ts_96_reg = 0; +reg set_ptp_perout_start_ts_96_valid_reg = 0; +reg [95:0] set_ptp_perout_period_ts_96_reg = 0; +reg set_ptp_perout_period_ts_96_valid_reg = 0; +reg [95:0] set_ptp_perout_width_ts_96_reg = 0; +reg set_ptp_perout_width_ts_96_valid_reg = 0; + assign axil_csr_awready = axil_csr_awready_reg; assign axil_csr_wready = axil_csr_wready_reg; assign axil_csr_bresp = 2'b00; @@ -573,6 +589,10 @@ always @(posedge clk_250mhz) begin set_ptp_period_valid_reg <= 1'b0; set_ptp_offset_valid_reg <= 1'b0; + set_ptp_perout_start_ts_96_valid_reg <= 1'b0; + set_ptp_perout_period_ts_96_valid_reg <= 1'b0; + set_ptp_perout_width_ts_96_valid_reg <= 1'b0; + if (axil_csr_awvalid && axil_csr_wvalid && !axil_csr_bvalid) begin // write operation axil_csr_awready_reg <= 1'b1; @@ -650,6 +670,34 @@ always @(posedge clk_250mhz) begin set_ptp_offset_count_reg <= axil_csr_wdata; set_ptp_offset_valid_reg <= 1'b1; end + 16'h0260: begin + // PTP perout control + ptp_perout_enable_reg <= axil_csr_wdata[0]; + end + 16'h0270: set_ptp_perout_start_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout start fns + 16'h0274: set_ptp_perout_start_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout start ns + 16'h0278: set_ptp_perout_start_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout start sec l + 16'h027C: begin + // PTP perout start sec h + set_ptp_perout_start_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_start_ts_96_valid_reg <= 1'b1; + end + 16'h0280: set_ptp_perout_period_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout period fns + 16'h0284: set_ptp_perout_period_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout period ns + 16'h0288: set_ptp_perout_period_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout period sec l + 16'h028C: begin + // PTP perout period sec h + set_ptp_perout_period_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_period_ts_96_valid_reg <= 1'b1; + end + 16'h0290: set_ptp_perout_width_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout width fns + 16'h0294: set_ptp_perout_width_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout width ns + 16'h0298: set_ptp_perout_width_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout width sec l + 16'h029C: begin + // PTP perout width sec h + set_ptp_perout_width_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_width_ts_96_valid_reg <= 1'b1; + end endcase end @@ -707,7 +755,7 @@ always @(posedge clk_250mhz) begin axil_csr_rdata_reg[17] <= qspi_cs; end // PHC - 16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features + 16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd1}; // PHC features 16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns 16'h0214: axil_csr_rdata_reg <= ptp_ts_96[45:16]; // PTP cur ns 16'h0218: axil_csr_rdata_reg <= ptp_ts_96[79:48]; // PTP cur sec l @@ -732,6 +780,27 @@ always @(posedge clk_250mhz) begin 16'h0254: axil_csr_rdata_reg <= set_ptp_offset_ns_reg; // PTP offset ns 16'h0258: axil_csr_rdata_reg <= set_ptp_offset_count_reg; // PTP offset count 16'h025C: axil_csr_rdata_reg <= set_ptp_offset_active; // PTP offset status + 16'h0260: begin + // PTP perout control + axil_csr_rdata_reg[0] <= ptp_perout_enable_reg; + end + 16'h0264: begin + // PTP perout status + axil_csr_rdata_reg[0] <= ptp_perout_locked; + axil_csr_rdata_reg[1] <= ptp_perout_error; + end + 16'h0270: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[15:0]; // PTP perout start fns + 16'h0274: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[45:16]; // PTP perout start ns + 16'h0278: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[79:48]; // PTP perout start sec l + 16'h027C: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[95:80]; // PTP perout start sec h + 16'h0280: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[15:0]; // PTP perout period fns + 16'h0284: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[45:16]; // PTP perout period ns + 16'h0288: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[79:48]; // PTP perout period sec l + 16'h028C: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[95:80]; // PTP perout period sec h + 16'h0290: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[15:0]; // PTP perout width fns + 16'h0294: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[45:16]; // PTP perout width ns + 16'h0298: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[79:48]; // PTP perout width sec l + 16'h029C: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[95:80]; // PTP perout width sec h endcase end @@ -760,6 +829,8 @@ always @(posedge clk_250mhz) begin qspi_dq_oe_reg <= 4'd0; pcie_dma_enable_reg <= 1'b0; + + ptp_perout_enable_reg <= 1'b0; end end @@ -1970,6 +2041,38 @@ ptp_clock_inst ( .output_pps(ptp_pps) ); +assign pps_out = ptp_perout_pulse; +assign pps_out_en = 1'b1; + +ptp_perout #( + .FNS_ENABLE(0), + .OUT_START_S(0), + .OUT_START_NS(0), + .OUT_START_FNS(0), + .OUT_PERIOD_S(1), + .OUT_PERIOD_NS(0), + .OUT_PERIOD_FNS(0), + .OUT_WIDTH_S(0), + .OUT_WIDTH_NS(500000000), + .OUT_WIDTH_FNS(0) +) +ptp_perout_inst ( + .clk(clk_250mhz), + .rst(rst_250mhz), + .input_ts_96(ptp_ts_96), + .input_ts_step(ptp_ts_step), + .enable(ptp_perout_enable_reg), + .input_start(set_ptp_perout_start_ts_96_reg), + .input_start_valid(set_ptp_perout_start_ts_96_valid_reg), + .input_period(set_ptp_perout_period_ts_96_reg), + .input_period_valid(set_ptp_perout_period_ts_96_valid_reg), + .input_width(set_ptp_perout_width_ts_96_reg), + .input_width_valid(set_ptp_perout_width_ts_96_valid_reg), + .locked(ptp_perout_locked), + .error(ptp_perout_error), + .output_pulse(ptp_perout_pulse) +); + reg [26:0] pps_led_counter_reg = 0; reg pps_led_reg = 0; diff --git a/fpga/mqnic/fb2CG/fpga_10g/tb/test_fpga_core.py b/fpga/mqnic/fb2CG/fpga_10g/tb/test_fpga_core.py index 72b4a122a..fc9c72b31 100755 --- a/fpga/mqnic/fb2CG/fpga_10g/tb/test_fpga_core.py +++ b/fpga/mqnic/fb2CG/fpga_10g/tb/test_fpga_core.py @@ -145,6 +145,7 @@ def bench(): clk_250mhz = Signal(bool(0)) rst_250mhz = Signal(bool(0)) + pps_in = Signal(bool(0)) m_axis_rq_tready = Signal(bool(0)) s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]) s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]) @@ -242,6 +243,8 @@ def bench(): led_green = Signal(intbv(0)[7:]) led_bmc = Signal(intbv(0)[2:]) led_exp = Signal(intbv(0)[2:]) + pps_out = Signal(bool(0)) + pps_out_en = Signal(bool(0)) m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]) m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]) m_axis_rq_tlast = Signal(bool(0)) @@ -584,6 +587,9 @@ def bench(): led_green=led_green, led_bmc=led_bmc, led_exp=led_exp, + pps_in=pps_in, + pps_out=pps_out, + pps_out_en=pps_out_en, m_axis_rq_tdata=m_axis_rq_tdata, m_axis_rq_tkeep=m_axis_rq_tkeep, m_axis_rq_tlast=m_axis_rq_tlast, diff --git a/fpga/mqnic/fb2CG/fpga_10g/tb/test_fpga_core.v b/fpga/mqnic/fb2CG/fpga_10g/tb/test_fpga_core.v index 4bbf2c53c..5a93aa2e5 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/tb/test_fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_10g/tb/test_fpga_core.v @@ -57,6 +57,7 @@ reg [7:0] current_test = 0; reg clk_250mhz = 0; reg rst_250mhz = 0; +reg pps_in = 0; reg m_axis_rq_tready = 0; reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0; reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0; @@ -154,6 +155,8 @@ wire [7:0] led_red; wire [7:0] led_green; wire [1:0] led_bmc; wire [1:0] led_exp; +wire pps_out; +wire pps_out_en; wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata; wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep; wire m_axis_rq_tlast; @@ -225,6 +228,7 @@ initial begin clk_250mhz, rst_250mhz, current_test, + pps_in, m_axis_rq_tready, s_axis_rc_tdata, s_axis_rc_tkeep, @@ -322,6 +326,8 @@ initial begin led_green, led_bmc, led_exp, + pps_out, + pps_out_en, m_axis_rq_tdata, m_axis_rq_tkeep, m_axis_rq_tlast, @@ -410,6 +416,9 @@ UUT ( .led_green(led_green), .led_bmc(led_bmc), .led_exp(led_exp), + .pps_in(pps_in), + .pps_out(pps_out), + .pps_out_en(pps_out_en), .m_axis_rq_tdata(m_axis_rq_tdata), .m_axis_rq_tkeep(m_axis_rq_tkeep), .m_axis_rq_tlast(m_axis_rq_tlast), diff --git a/fpga/mqnic/fb2CG/fpga_25g/fpga.xdc b/fpga/mqnic/fb2CG/fpga_25g/fpga.xdc index bc31c8e94..51d55b089 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/fpga.xdc +++ b/fpga/mqnic/fb2CG/fpga_25g/fpga.xdc @@ -42,9 +42,9 @@ set_property -dict {LOC D3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports { set_property -dict {LOC D4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {led_exp[1]}] # GPIO -#set_property -dict {LOC B4 IOSTANDARD LVCMOS33} [get_ports pps_in] ;# from SMA J6 via Q1 (inverted) -#set_property -dict {LOC A4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 4} [get_ports pps_out] ;# to SMA J6 via U4 and U5, and u.FL J7 (PPS OUT) via U3 -#set_property -dict {LOC A3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports pps_out_en] ; # to U5 IN (connects pps_out to SMA J6 when high) +set_property -dict {LOC B4 IOSTANDARD LVCMOS33} [get_ports pps_in] ;# from SMA J6 via Q1 (inverted) +set_property -dict {LOC A4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 4} [get_ports pps_out] ;# to SMA J6 via U4 and U5, and u.FL J7 (PPS OUT) via U3 +set_property -dict {LOC A3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports pps_out_en] ; # to U5 IN (connects pps_out to SMA J6 when high) #set_property -dict {LOC H2 IOSTANDARD LVCMOS33} [get_ports misc_ucoax] ; from u.FL J5 (PPS IN) # BMC interface diff --git a/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga.v b/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga.v index 374085ebe..d273de175 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga.v +++ b/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga.v @@ -53,6 +53,10 @@ module fpga ( output wire [1:0] led_bmc, output wire [1:0] led_exp, + input wire pps_in, + output wire pps_out, + output wire pps_out_en, + /* * Board status */ @@ -1422,6 +1426,10 @@ core_inst ( .led_bmc(led_bmc), .led_exp(led_exp), + .pps_in(pps_in), + .pps_out(pps_out), + .pps_out_en(pps_out_en), + /* * PCIe */ diff --git a/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga_core.v b/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga_core.v index f1393a61b..98dd97bf0 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga_core.v @@ -66,6 +66,10 @@ module fpga_core # output wire [1:0] led_bmc, output wire [1:0] led_exp, + input wire pps_in, + output wire pps_out, + output wire pps_out_en, + /* * PCIe */ @@ -489,6 +493,11 @@ wire [95:0] ptp_ts_96; wire ptp_ts_step; wire ptp_pps; +reg ptp_perout_enable_reg = 1'b0; +wire ptp_perout_locked; +wire ptp_perout_error; +wire ptp_perout_pulse; + // control registers reg axil_csr_awready_reg = 1'b0; reg axil_csr_wready_reg = 1'b0; @@ -528,6 +537,13 @@ reg [15:0] set_ptp_offset_count_reg = 0; reg set_ptp_offset_valid_reg = 0; wire set_ptp_offset_active; +reg [95:0] set_ptp_perout_start_ts_96_reg = 0; +reg set_ptp_perout_start_ts_96_valid_reg = 0; +reg [95:0] set_ptp_perout_period_ts_96_reg = 0; +reg set_ptp_perout_period_ts_96_valid_reg = 0; +reg [95:0] set_ptp_perout_width_ts_96_reg = 0; +reg set_ptp_perout_width_ts_96_valid_reg = 0; + assign axil_csr_awready = axil_csr_awready_reg; assign axil_csr_wready = axil_csr_wready_reg; assign axil_csr_bresp = 2'b00; @@ -573,6 +589,10 @@ always @(posedge clk_250mhz) begin set_ptp_period_valid_reg <= 1'b0; set_ptp_offset_valid_reg <= 1'b0; + set_ptp_perout_start_ts_96_valid_reg <= 1'b0; + set_ptp_perout_period_ts_96_valid_reg <= 1'b0; + set_ptp_perout_width_ts_96_valid_reg <= 1'b0; + if (axil_csr_awvalid && axil_csr_wvalid && !axil_csr_bvalid) begin // write operation axil_csr_awready_reg <= 1'b1; @@ -650,6 +670,34 @@ always @(posedge clk_250mhz) begin set_ptp_offset_count_reg <= axil_csr_wdata; set_ptp_offset_valid_reg <= 1'b1; end + 16'h0260: begin + // PTP perout control + ptp_perout_enable_reg <= axil_csr_wdata[0]; + end + 16'h0270: set_ptp_perout_start_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout start fns + 16'h0274: set_ptp_perout_start_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout start ns + 16'h0278: set_ptp_perout_start_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout start sec l + 16'h027C: begin + // PTP perout start sec h + set_ptp_perout_start_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_start_ts_96_valid_reg <= 1'b1; + end + 16'h0280: set_ptp_perout_period_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout period fns + 16'h0284: set_ptp_perout_period_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout period ns + 16'h0288: set_ptp_perout_period_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout period sec l + 16'h028C: begin + // PTP perout period sec h + set_ptp_perout_period_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_period_ts_96_valid_reg <= 1'b1; + end + 16'h0290: set_ptp_perout_width_ts_96_reg[15:0] <= axil_csr_wdata; // PTP perout width fns + 16'h0294: set_ptp_perout_width_ts_96_reg[45:16] <= axil_csr_wdata; // PTP perout width ns + 16'h0298: set_ptp_perout_width_ts_96_reg[79:48] <= axil_csr_wdata; // PTP perout width sec l + 16'h029C: begin + // PTP perout width sec h + set_ptp_perout_width_ts_96_reg[95:80] <= axil_csr_wdata; + set_ptp_perout_width_ts_96_valid_reg <= 1'b1; + end endcase end @@ -707,7 +755,7 @@ always @(posedge clk_250mhz) begin axil_csr_rdata_reg[17] <= qspi_cs; end // PHC - 16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features + 16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd1}; // PHC features 16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns 16'h0214: axil_csr_rdata_reg <= ptp_ts_96[45:16]; // PTP cur ns 16'h0218: axil_csr_rdata_reg <= ptp_ts_96[79:48]; // PTP cur sec l @@ -732,6 +780,27 @@ always @(posedge clk_250mhz) begin 16'h0254: axil_csr_rdata_reg <= set_ptp_offset_ns_reg; // PTP offset ns 16'h0258: axil_csr_rdata_reg <= set_ptp_offset_count_reg; // PTP offset count 16'h025C: axil_csr_rdata_reg <= set_ptp_offset_active; // PTP offset status + 16'h0260: begin + // PTP perout control + axil_csr_rdata_reg[0] <= ptp_perout_enable_reg; + end + 16'h0264: begin + // PTP perout status + axil_csr_rdata_reg[0] <= ptp_perout_locked; + axil_csr_rdata_reg[1] <= ptp_perout_error; + end + 16'h0270: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[15:0]; // PTP perout start fns + 16'h0274: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[45:16]; // PTP perout start ns + 16'h0278: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[79:48]; // PTP perout start sec l + 16'h027C: axil_csr_rdata_reg <= set_ptp_perout_start_ts_96_reg[95:80]; // PTP perout start sec h + 16'h0280: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[15:0]; // PTP perout period fns + 16'h0284: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[45:16]; // PTP perout period ns + 16'h0288: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[79:48]; // PTP perout period sec l + 16'h028C: axil_csr_rdata_reg <= set_ptp_perout_period_ts_96_reg[95:80]; // PTP perout period sec h + 16'h0290: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[15:0]; // PTP perout width fns + 16'h0294: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[45:16]; // PTP perout width ns + 16'h0298: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[79:48]; // PTP perout width sec l + 16'h029C: axil_csr_rdata_reg <= set_ptp_perout_width_ts_96_reg[95:80]; // PTP perout width sec h endcase end @@ -760,6 +829,8 @@ always @(posedge clk_250mhz) begin qspi_dq_oe_reg <= 4'd0; pcie_dma_enable_reg <= 1'b0; + + ptp_perout_enable_reg <= 1'b0; end end @@ -1970,6 +2041,38 @@ ptp_clock_inst ( .output_pps(ptp_pps) ); +assign pps_out = ptp_perout_pulse; +assign pps_out_en = 1'b1; + +ptp_perout #( + .FNS_ENABLE(0), + .OUT_START_S(0), + .OUT_START_NS(0), + .OUT_START_FNS(0), + .OUT_PERIOD_S(1), + .OUT_PERIOD_NS(0), + .OUT_PERIOD_FNS(0), + .OUT_WIDTH_S(0), + .OUT_WIDTH_NS(500000000), + .OUT_WIDTH_FNS(0) +) +ptp_perout_inst ( + .clk(clk_250mhz), + .rst(rst_250mhz), + .input_ts_96(ptp_ts_96), + .input_ts_step(ptp_ts_step), + .enable(ptp_perout_enable_reg), + .input_start(set_ptp_perout_start_ts_96_reg), + .input_start_valid(set_ptp_perout_start_ts_96_valid_reg), + .input_period(set_ptp_perout_period_ts_96_reg), + .input_period_valid(set_ptp_perout_period_ts_96_valid_reg), + .input_width(set_ptp_perout_width_ts_96_reg), + .input_width_valid(set_ptp_perout_width_ts_96_valid_reg), + .locked(ptp_perout_locked), + .error(ptp_perout_error), + .output_pulse(ptp_perout_pulse) +); + reg [26:0] pps_led_counter_reg = 0; reg pps_led_reg = 0; diff --git a/fpga/mqnic/fb2CG/fpga_25g/tb/test_fpga_core.py b/fpga/mqnic/fb2CG/fpga_25g/tb/test_fpga_core.py index d0b8c9f59..1cefcdd48 100755 --- a/fpga/mqnic/fb2CG/fpga_25g/tb/test_fpga_core.py +++ b/fpga/mqnic/fb2CG/fpga_25g/tb/test_fpga_core.py @@ -145,6 +145,7 @@ def bench(): clk_250mhz = Signal(bool(0)) rst_250mhz = Signal(bool(0)) + pps_in = Signal(bool(0)) m_axis_rq_tready = Signal(bool(0)) s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]) s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]) @@ -242,6 +243,8 @@ def bench(): led_green = Signal(intbv(0)[7:]) led_bmc = Signal(intbv(0)[2:]) led_exp = Signal(intbv(0)[2:]) + pps_out = Signal(bool(0)) + pps_out_en = Signal(bool(0)) m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]) m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]) m_axis_rq_tlast = Signal(bool(0)) @@ -584,6 +587,9 @@ def bench(): led_green=led_green, led_bmc=led_bmc, led_exp=led_exp, + pps_in=pps_in, + pps_out=pps_out, + pps_out_en=pps_out_en, m_axis_rq_tdata=m_axis_rq_tdata, m_axis_rq_tkeep=m_axis_rq_tkeep, m_axis_rq_tlast=m_axis_rq_tlast, diff --git a/fpga/mqnic/fb2CG/fpga_25g/tb/test_fpga_core.v b/fpga/mqnic/fb2CG/fpga_25g/tb/test_fpga_core.v index 4bbf2c53c..5a93aa2e5 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/tb/test_fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_25g/tb/test_fpga_core.v @@ -57,6 +57,7 @@ reg [7:0] current_test = 0; reg clk_250mhz = 0; reg rst_250mhz = 0; +reg pps_in = 0; reg m_axis_rq_tready = 0; reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0; reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0; @@ -154,6 +155,8 @@ wire [7:0] led_red; wire [7:0] led_green; wire [1:0] led_bmc; wire [1:0] led_exp; +wire pps_out; +wire pps_out_en; wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata; wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep; wire m_axis_rq_tlast; @@ -225,6 +228,7 @@ initial begin clk_250mhz, rst_250mhz, current_test, + pps_in, m_axis_rq_tready, s_axis_rc_tdata, s_axis_rc_tkeep, @@ -322,6 +326,8 @@ initial begin led_green, led_bmc, led_exp, + pps_out, + pps_out_en, m_axis_rq_tdata, m_axis_rq_tkeep, m_axis_rq_tlast, @@ -410,6 +416,9 @@ UUT ( .led_green(led_green), .led_bmc(led_bmc), .led_exp(led_exp), + .pps_in(pps_in), + .pps_out(pps_out), + .pps_out_en(pps_out_en), .m_axis_rq_tdata(m_axis_rq_tdata), .m_axis_rq_tkeep(m_axis_rq_tkeep), .m_axis_rq_tlast(m_axis_rq_tlast),