1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00
corundum/fpga/common/rtl/mqnic_port.v
Alex Forencich 6b256f82d3 Generate pause frames on TX
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-09-10 23:22:50 -07:00

842 lines
33 KiB
Verilog

// SPDX-License-Identifier: BSD-2-Clause-Views
/*
* Copyright (c) 2022-2023 The Regents of the University of California
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* NIC port
*/
module mqnic_port #
(
// PTP configuration
parameter PTP_TS_WIDTH = 96,
// Interface configuration
parameter PTP_TS_ENABLE = 1,
parameter TX_CPL_ENABLE = 1,
parameter TX_CPL_FIFO_DEPTH = 32,
parameter TX_TAG_WIDTH = 16,
parameter PFC_ENABLE = 1,
parameter LFC_ENABLE = PFC_ENABLE,
parameter MAC_CTRL_ENABLE = 0,
parameter TX_FIFO_DEPTH = 32768,
parameter RX_FIFO_DEPTH = 32768,
parameter TX_FIFO_DEPTH_WIDTH = $clog2(TX_FIFO_DEPTH)+1,
parameter RX_FIFO_DEPTH_WIDTH = $clog2(RX_FIFO_DEPTH)+1,
parameter MAX_TX_SIZE = 9214,
parameter MAX_RX_SIZE = 9214,
// Application block configuration
parameter APP_AXIS_DIRECT_ENABLE = 1,
parameter APP_AXIS_SYNC_ENABLE = 1,
// Register interface configuration
parameter REG_ADDR_WIDTH = 7,
parameter REG_DATA_WIDTH = 32,
parameter REG_STRB_WIDTH = (REG_DATA_WIDTH/8),
parameter RB_BASE_ADDR = 0,
parameter RB_NEXT_PTR = 0,
// Streaming interface configuration
parameter AXIS_DATA_WIDTH = 256,
parameter AXIS_KEEP_WIDTH = AXIS_DATA_WIDTH/8,
parameter AXIS_TX_USER_WIDTH = TX_TAG_WIDTH + 1,
parameter AXIS_RX_USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1,
parameter AXIS_RX_USE_READY = 0,
parameter AXIS_TX_PIPELINE = 0,
parameter AXIS_TX_FIFO_PIPELINE = 2,
parameter AXIS_TX_TS_PIPELINE = 0,
parameter AXIS_RX_PIPELINE = 0,
parameter AXIS_RX_FIFO_PIPELINE = 2,
parameter AXIS_SYNC_DATA_WIDTH = AXIS_DATA_WIDTH,
parameter AXIS_SYNC_KEEP_WIDTH = AXIS_SYNC_DATA_WIDTH/8,
parameter AXIS_SYNC_TX_USER_WIDTH = AXIS_TX_USER_WIDTH,
parameter AXIS_SYNC_RX_USER_WIDTH = AXIS_RX_USER_WIDTH
)
(
input wire clk,
input wire rst,
/*
* Control register interface
*/
input wire [REG_ADDR_WIDTH-1:0] ctrl_reg_wr_addr,
input wire [REG_DATA_WIDTH-1:0] ctrl_reg_wr_data,
input wire [REG_STRB_WIDTH-1:0] ctrl_reg_wr_strb,
input wire ctrl_reg_wr_en,
output wire ctrl_reg_wr_wait,
output wire ctrl_reg_wr_ack,
input wire [REG_ADDR_WIDTH-1:0] ctrl_reg_rd_addr,
input wire ctrl_reg_rd_en,
output wire [REG_DATA_WIDTH-1:0] ctrl_reg_rd_data,
output wire ctrl_reg_rd_wait,
output wire ctrl_reg_rd_ack,
/*
* Transmit data from interface FIFO
*/
input wire [AXIS_SYNC_DATA_WIDTH-1:0] s_axis_if_tx_tdata,
input wire [AXIS_SYNC_KEEP_WIDTH-1:0] s_axis_if_tx_tkeep,
input wire s_axis_if_tx_tvalid,
output wire s_axis_if_tx_tready,
input wire s_axis_if_tx_tlast,
input wire [AXIS_SYNC_TX_USER_WIDTH-1:0] s_axis_if_tx_tuser,
output wire [PTP_TS_WIDTH-1:0] m_axis_if_tx_cpl_ts,
output wire [TX_TAG_WIDTH-1:0] m_axis_if_tx_cpl_tag,
output wire m_axis_if_tx_cpl_valid,
input wire m_axis_if_tx_cpl_ready,
/*
* Receive data to interface FIFO
*/
output wire [AXIS_SYNC_DATA_WIDTH-1:0] m_axis_if_rx_tdata,
output wire [AXIS_SYNC_KEEP_WIDTH-1:0] m_axis_if_rx_tkeep,
output wire m_axis_if_rx_tvalid,
input wire m_axis_if_rx_tready,
output wire m_axis_if_rx_tlast,
output wire [AXIS_SYNC_RX_USER_WIDTH-1:0] m_axis_if_rx_tuser,
/*
* Application section datapath interface (synchronous MAC interface)
*/
output wire [AXIS_SYNC_DATA_WIDTH-1:0] m_axis_app_sync_tx_tdata,
output wire [AXIS_SYNC_KEEP_WIDTH-1:0] m_axis_app_sync_tx_tkeep,
output wire m_axis_app_sync_tx_tvalid,
input wire m_axis_app_sync_tx_tready,
output wire m_axis_app_sync_tx_tlast,
output wire [AXIS_SYNC_TX_USER_WIDTH-1:0] m_axis_app_sync_tx_tuser,
input wire [AXIS_SYNC_DATA_WIDTH-1:0] s_axis_app_sync_tx_tdata,
input wire [AXIS_SYNC_KEEP_WIDTH-1:0] s_axis_app_sync_tx_tkeep,
input wire s_axis_app_sync_tx_tvalid,
output wire s_axis_app_sync_tx_tready,
input wire s_axis_app_sync_tx_tlast,
input wire [AXIS_SYNC_TX_USER_WIDTH-1:0] s_axis_app_sync_tx_tuser,
output wire [PTP_TS_WIDTH-1:0] m_axis_app_sync_tx_cpl_ts,
output wire [TX_TAG_WIDTH-1:0] m_axis_app_sync_tx_cpl_tag,
output wire m_axis_app_sync_tx_cpl_valid,
input wire m_axis_app_sync_tx_cpl_ready,
input wire [PTP_TS_WIDTH-1:0] s_axis_app_sync_tx_cpl_ts,
input wire [TX_TAG_WIDTH-1:0] s_axis_app_sync_tx_cpl_tag,
input wire s_axis_app_sync_tx_cpl_valid,
output wire s_axis_app_sync_tx_cpl_ready,
output wire [AXIS_SYNC_DATA_WIDTH-1:0] m_axis_app_sync_rx_tdata,
output wire [AXIS_SYNC_KEEP_WIDTH-1:0] m_axis_app_sync_rx_tkeep,
output wire m_axis_app_sync_rx_tvalid,
input wire m_axis_app_sync_rx_tready,
output wire m_axis_app_sync_rx_tlast,
output wire [AXIS_SYNC_RX_USER_WIDTH-1:0] m_axis_app_sync_rx_tuser,
input wire [AXIS_SYNC_DATA_WIDTH-1:0] s_axis_app_sync_rx_tdata,
input wire [AXIS_SYNC_KEEP_WIDTH-1:0] s_axis_app_sync_rx_tkeep,
input wire s_axis_app_sync_rx_tvalid,
output wire s_axis_app_sync_rx_tready,
input wire s_axis_app_sync_rx_tlast,
input wire [AXIS_SYNC_RX_USER_WIDTH-1:0] s_axis_app_sync_rx_tuser,
/*
* Application section datapath interface (direct MAC interface)
*/
output wire [AXIS_DATA_WIDTH-1:0] m_axis_app_direct_tx_tdata,
output wire [AXIS_KEEP_WIDTH-1:0] m_axis_app_direct_tx_tkeep,
output wire m_axis_app_direct_tx_tvalid,
input wire m_axis_app_direct_tx_tready,
output wire m_axis_app_direct_tx_tlast,
output wire [AXIS_TX_USER_WIDTH-1:0] m_axis_app_direct_tx_tuser,
input wire [AXIS_DATA_WIDTH-1:0] s_axis_app_direct_tx_tdata,
input wire [AXIS_KEEP_WIDTH-1:0] s_axis_app_direct_tx_tkeep,
input wire s_axis_app_direct_tx_tvalid,
output wire s_axis_app_direct_tx_tready,
input wire s_axis_app_direct_tx_tlast,
input wire [AXIS_TX_USER_WIDTH-1:0] s_axis_app_direct_tx_tuser,
output wire [PTP_TS_WIDTH-1:0] m_axis_app_direct_tx_cpl_ts,
output wire [TX_TAG_WIDTH-1:0] m_axis_app_direct_tx_cpl_tag,
output wire m_axis_app_direct_tx_cpl_valid,
input wire m_axis_app_direct_tx_cpl_ready,
input wire [PTP_TS_WIDTH-1:0] s_axis_app_direct_tx_cpl_ts,
input wire [TX_TAG_WIDTH-1:0] s_axis_app_direct_tx_cpl_tag,
input wire s_axis_app_direct_tx_cpl_valid,
output wire s_axis_app_direct_tx_cpl_ready,
output wire [AXIS_DATA_WIDTH-1:0] m_axis_app_direct_rx_tdata,
output wire [AXIS_KEEP_WIDTH-1:0] m_axis_app_direct_rx_tkeep,
output wire m_axis_app_direct_rx_tvalid,
input wire m_axis_app_direct_rx_tready,
output wire m_axis_app_direct_rx_tlast,
output wire [AXIS_RX_USER_WIDTH-1:0] m_axis_app_direct_rx_tuser,
input wire [AXIS_DATA_WIDTH-1:0] s_axis_app_direct_rx_tdata,
input wire [AXIS_KEEP_WIDTH-1:0] s_axis_app_direct_rx_tkeep,
input wire s_axis_app_direct_rx_tvalid,
output wire s_axis_app_direct_rx_tready,
input wire s_axis_app_direct_rx_tlast,
input wire [AXIS_RX_USER_WIDTH-1:0] s_axis_app_direct_rx_tuser,
/*
* Transmit data output
*/
input wire tx_clk,
input wire tx_rst,
output wire [AXIS_DATA_WIDTH-1:0] m_axis_tx_tdata,
output wire [AXIS_KEEP_WIDTH-1:0] m_axis_tx_tkeep,
output wire m_axis_tx_tvalid,
input wire m_axis_tx_tready,
output wire m_axis_tx_tlast,
output wire [AXIS_TX_USER_WIDTH-1:0] m_axis_tx_tuser,
input wire [PTP_TS_WIDTH-1:0] s_axis_tx_cpl_ts,
input wire [TX_TAG_WIDTH-1:0] s_axis_tx_cpl_tag,
input wire s_axis_tx_cpl_valid,
output wire s_axis_tx_cpl_ready,
output wire tx_enable,
input wire tx_status,
output wire tx_lfc_en,
output wire tx_lfc_req,
output wire [7:0] tx_pfc_en,
output wire [7:0] tx_pfc_req,
input wire tx_fc_quanta_clk_en,
input wire [TX_FIFO_DEPTH_WIDTH-1:0] tx_fifo_status_depth,
/*
* Receive data input
*/
input wire rx_clk,
input wire rx_rst,
input wire [AXIS_DATA_WIDTH-1:0] s_axis_rx_tdata,
input wire [AXIS_KEEP_WIDTH-1:0] s_axis_rx_tkeep,
input wire s_axis_rx_tvalid,
output wire s_axis_rx_tready,
input wire s_axis_rx_tlast,
input wire [AXIS_RX_USER_WIDTH-1:0] s_axis_rx_tuser,
output wire rx_enable,
input wire rx_status,
output wire rx_lfc_en,
input wire rx_lfc_req,
output wire rx_lfc_ack,
output wire [7:0] rx_pfc_en,
input wire [7:0] rx_pfc_req,
output wire [7:0] rx_pfc_ack,
input wire rx_fc_quanta_clk_en,
input wire [RX_FIFO_DEPTH_WIDTH-1:0] rx_fifo_status_depth
);
localparam RBB = RB_BASE_ADDR & {REG_ADDR_WIDTH{1'b1}};
// check configuration
initial begin
if (REG_DATA_WIDTH != 32) begin
$error("Error: Register interface width must be 32 (instance %m)");
$finish;
end
if (REG_STRB_WIDTH * 8 != REG_DATA_WIDTH) begin
$error("Error: Register interface requires byte (8-bit) granularity (instance %m)");
$finish;
end
if (REG_ADDR_WIDTH < $clog2(64)) begin
$error("Error: Register address width too narrow (instance %m)");
$finish;
end
if (RB_NEXT_PTR >= RB_BASE_ADDR && RB_NEXT_PTR < RB_BASE_ADDR + 64) begin
$error("Error: RB_NEXT_PTR overlaps block (instance %m)");
$finish;
end
end
wire rx_lfc_req_int;
wire [7:0] rx_pfc_req_int;
// TX control
reg tx_enable_reg = 1'b0;
reg tx_pause_reg = 1'b0;
reg tx_lfc_en_reg = 1'b0;
reg tx_lfc_req_reg = 1'b0;
reg [7:0] tx_pfc_en_reg = 8'd0;
reg [7:0] tx_pfc_req_reg = 8'd0;
reg [9:0] tx_fc_quanta_step_reg = (AXIS_DATA_WIDTH*256)/512;
reg tx_enable_sync_1_reg = 1'b0;
reg tx_enable_sync_2_reg = 1'b0;
reg tx_lfc_en_sync_1_reg = 1'b0;
reg tx_lfc_en_sync_2_reg = 1'b0;
reg tx_lfc_req_sync_1_reg = 1'b0;
reg tx_lfc_req_sync_2_reg = 1'b0;
reg [7:0] tx_pfc_en_sync_1_reg = 8'd0;
reg [7:0] tx_pfc_en_sync_2_reg = 8'd0;
reg [7:0] tx_pfc_req_sync_1_reg = 8'd0;
reg [7:0] tx_pfc_req_sync_2_reg = 8'd0;
reg [9:0] tx_fc_quanta_step_sync_1_reg = 10'd0;
reg [9:0] tx_fc_quanta_step_sync_2_reg = 10'd0;
assign tx_enable = tx_enable_sync_2_reg;
assign tx_lfc_en = LFC_ENABLE ? tx_lfc_en_sync_2_reg : 1'b0;
assign tx_lfc_req = LFC_ENABLE ? tx_lfc_req_sync_2_reg : 1'b0;
assign tx_pfc_en = PFC_ENABLE ? tx_pfc_en_sync_2_reg : 8'd0;
assign tx_pfc_req = PFC_ENABLE ? tx_pfc_req_sync_2_reg : 8'd0;
always @(posedge tx_clk) begin
tx_enable_sync_1_reg <= tx_enable_reg;
tx_enable_sync_2_reg <= tx_enable_sync_1_reg;
tx_lfc_en_sync_1_reg <= tx_lfc_en_reg;
tx_lfc_en_sync_2_reg <= tx_lfc_en_sync_1_reg;
tx_lfc_req_sync_1_reg <= tx_lfc_req_reg;
tx_lfc_req_sync_2_reg <= tx_lfc_req_sync_1_reg;
tx_pfc_en_sync_1_reg <= tx_pfc_en_reg;
tx_pfc_en_sync_2_reg <= tx_pfc_en_sync_1_reg;
tx_pfc_req_sync_1_reg <= tx_pfc_req_reg;
tx_pfc_req_sync_2_reg <= tx_pfc_req_sync_1_reg;
tx_fc_quanta_step_sync_1_reg <= tx_fc_quanta_step_reg;
tx_fc_quanta_step_sync_2_reg <= tx_fc_quanta_step_sync_1_reg;
end
// TX status
reg tx_rst_sync_1_reg = 1'b0;
reg tx_rst_sync_2_reg = 1'b0;
reg tx_rst_sync_3_reg = 1'b0;
reg tx_status_sync_1_reg = 1'b0;
reg tx_status_sync_2_reg = 1'b0;
reg tx_status_sync_3_reg = 1'b0;
always @(posedge tx_clk or posedge tx_rst) begin
if (tx_rst) begin
tx_rst_sync_1_reg <= 1'b1;
tx_status_sync_1_reg <= 1'b0;
end else begin
tx_rst_sync_1_reg <= 1'b0;
tx_status_sync_1_reg <= tx_status;
end
end
always @(posedge clk) begin
tx_rst_sync_2_reg <= tx_rst_sync_1_reg;
tx_rst_sync_3_reg <= tx_rst_sync_2_reg;
tx_status_sync_2_reg <= tx_status_sync_1_reg;
tx_status_sync_3_reg <= tx_status_sync_2_reg;
end
// RX control
reg rx_enable_reg = 1'b0;
reg rx_pause_reg = 1'b0;
reg rx_lfc_en_reg = 1'b0;
reg rx_lfc_ack_reg = 1'b0;
reg [7:0] rx_pfc_en_reg = 8'd0;
reg [7:0] rx_pfc_ack_reg = 8'd0;
reg [9:0] rx_fc_quanta_step_reg = (AXIS_DATA_WIDTH*256)/512;
reg rx_enable_sync_1_reg = 1'b0;
reg rx_enable_sync_2_reg = 1'b0;
reg rx_lfc_en_sync_1_reg = 1'b0;
reg rx_lfc_en_sync_2_reg = 1'b0;
reg rx_lfc_ack_sync_1_reg = 1'b0;
reg rx_lfc_ack_sync_2_reg = 1'b0;
reg [7:0] rx_pfc_en_sync_1_reg = 8'd0;
reg [7:0] rx_pfc_en_sync_2_reg = 8'd0;
reg [7:0] rx_pfc_ack_sync_1_reg = 8'd0;
reg [7:0] rx_pfc_ack_sync_2_reg = 8'd0;
reg [9:0] rx_fc_quanta_step_sync_1_reg = 10'd0;
reg [9:0] rx_fc_quanta_step_sync_2_reg = 10'd0;
assign rx_enable = rx_enable_sync_2_reg;
assign rx_lfc_en = LFC_ENABLE ? rx_lfc_en_sync_2_reg : 1'b0;
assign rx_lfc_ack = LFC_ENABLE ? rx_lfc_ack_sync_2_reg : 1'b0;
assign rx_pfc_en = PFC_ENABLE ? rx_pfc_en_sync_2_reg : 8'd0;
assign rx_pfc_ack = PFC_ENABLE ? rx_pfc_ack_sync_2_reg : 8'd0;
always @(posedge rx_clk) begin
rx_enable_sync_1_reg <= rx_enable_reg;
rx_enable_sync_2_reg <= rx_enable_sync_1_reg;
rx_lfc_en_sync_1_reg <= rx_lfc_en_reg;
rx_lfc_en_sync_2_reg <= rx_lfc_en_sync_1_reg;
rx_lfc_ack_sync_1_reg <= rx_lfc_ack_reg;
rx_lfc_ack_sync_2_reg <= rx_lfc_ack_sync_1_reg;
rx_pfc_en_sync_1_reg <= rx_pfc_en_reg;
rx_pfc_en_sync_2_reg <= rx_pfc_en_sync_1_reg;
rx_pfc_ack_sync_1_reg <= rx_pfc_ack_reg;
rx_pfc_ack_sync_2_reg <= rx_pfc_ack_sync_1_reg;
rx_fc_quanta_step_sync_1_reg <= rx_fc_quanta_step_reg;
rx_fc_quanta_step_sync_2_reg <= rx_fc_quanta_step_sync_1_reg;
end
// RX status
reg rx_rst_sync_1_reg = 1'b0;
reg rx_rst_sync_2_reg = 1'b0;
reg rx_rst_sync_3_reg = 1'b0;
reg rx_status_sync_1_reg = 1'b0;
reg rx_status_sync_2_reg = 1'b0;
reg rx_status_sync_3_reg = 1'b0;
reg rx_lfc_req_sync_1_reg = 1'b0;
reg rx_lfc_req_sync_2_reg = 1'b0;
reg rx_lfc_req_sync_3_reg = 1'b0;
reg [7:0] rx_pfc_req_sync_1_reg = 8'd0;
reg [7:0] rx_pfc_req_sync_2_reg = 8'd0;
reg [7:0] rx_pfc_req_sync_3_reg = 8'd0;
always @(posedge rx_clk or posedge rx_rst) begin
if (rx_rst) begin
rx_rst_sync_1_reg <= 1'b1;
rx_status_sync_1_reg <= 1'b0;
rx_lfc_req_sync_1_reg <= 1'b0;
rx_pfc_req_sync_1_reg <= 8'd0;
end else begin
rx_rst_sync_1_reg <= 1'b0;
rx_status_sync_1_reg <= rx_status;
rx_lfc_req_sync_1_reg <= MAC_CTRL_ENABLE ? rx_lfc_req_int : rx_lfc_req;
rx_pfc_req_sync_1_reg <= MAC_CTRL_ENABLE ? rx_pfc_req_int : rx_pfc_req;
end
end
always @(posedge clk) begin
rx_rst_sync_2_reg <= rx_rst_sync_1_reg;
rx_rst_sync_3_reg <= rx_rst_sync_2_reg;
rx_status_sync_2_reg <= rx_status_sync_1_reg;
rx_status_sync_3_reg <= rx_status_sync_2_reg;
rx_lfc_req_sync_2_reg <= rx_lfc_req_sync_1_reg;
rx_lfc_req_sync_3_reg <= rx_lfc_req_sync_2_reg;
rx_pfc_req_sync_2_reg <= rx_pfc_req_sync_1_reg;
rx_pfc_req_sync_3_reg <= rx_pfc_req_sync_2_reg;
end
// control registers
reg ctrl_reg_wr_ack_reg = 1'b0;
reg [REG_DATA_WIDTH-1:0] ctrl_reg_rd_data_reg = {REG_DATA_WIDTH{1'b0}};
reg ctrl_reg_rd_ack_reg = 1'b0;
reg [RX_FIFO_DEPTH_WIDTH-1:0] rx_lfc_watermark_reg = RX_FIFO_DEPTH/2;
wire tx_fifo_pause_req = !tx_enable_reg || tx_pause_reg || (LFC_ENABLE && rx_lfc_en_reg && rx_lfc_req_sync_3_reg);
wire tx_fifo_pause_ack;
wire rx_fifo_pause_req = !rx_enable_reg || rx_pause_reg;
wire rx_fifo_pause_ack;
assign ctrl_reg_wr_wait = 1'b0;
assign ctrl_reg_wr_ack = ctrl_reg_wr_ack_reg;
assign ctrl_reg_rd_data = ctrl_reg_rd_data_reg;
assign ctrl_reg_rd_wait = 1'b0;
assign ctrl_reg_rd_ack = ctrl_reg_rd_ack_reg;
integer i;
always @(posedge clk) begin
ctrl_reg_wr_ack_reg <= 1'b0;
ctrl_reg_rd_data_reg <= {REG_DATA_WIDTH{1'b0}};
ctrl_reg_rd_ack_reg <= 1'b0;
if (tx_lfc_req_reg) begin
if (rx_fifo_status_depth == 0) begin
tx_lfc_req_reg <= 1'b0;
end
end else begin
if (rx_fifo_status_depth > rx_lfc_watermark_reg) begin
tx_lfc_req_reg <= 1'b1;
end
end
tx_pfc_req_reg <= 8'd0;
rx_lfc_ack_reg <= tx_fifo_pause_ack;
rx_pfc_ack_reg <= 8'd0;
if (ctrl_reg_wr_en && !ctrl_reg_wr_ack_reg) begin
// write operation
ctrl_reg_wr_ack_reg <= 1'b1;
case ({ctrl_reg_wr_addr >> 2, 2'b00})
// Port control
RBB+8'h20: begin
// Port ctrl: TX control/status
tx_enable_reg <= ctrl_reg_wr_data[0];
tx_pause_reg <= ctrl_reg_wr_data[8];
end
RBB+8'h24: begin
// Port ctrl: RX control/status
rx_enable_reg <= ctrl_reg_wr_data[0];
rx_pause_reg <= ctrl_reg_wr_data[8];
end
default: ctrl_reg_wr_ack_reg <= 1'b0;
endcase
if (MAC_CTRL_ENABLE) begin
if ({ctrl_reg_wr_addr >> 2, 2'b00} == RBB+8'h28) begin
// Port ctrl: FC control
tx_fc_quanta_step_reg <= ctrl_reg_wr_data[15:0];
rx_fc_quanta_step_reg <= ctrl_reg_wr_data[31:16];
ctrl_reg_wr_ack_reg <= 1'b1;
end
end
if (LFC_ENABLE) begin
if ({ctrl_reg_wr_addr >> 2, 2'b00} == RBB+8'h2C) begin
// Port ctrl: LFC control
rx_lfc_watermark_reg <= ctrl_reg_wr_data[23:0];
tx_lfc_en_reg <= ctrl_reg_wr_data[24];
rx_lfc_en_reg <= ctrl_reg_wr_data[25];
ctrl_reg_wr_ack_reg <= 1'b1;
end
end
if (PFC_ENABLE) begin
for (i = 0; i < 8; i = i + 1) begin
if ({ctrl_reg_wr_addr >> 2, 2'b00} == RBB+8'h30+i*4) begin
// Port ctrl: PFC control N
tx_pfc_en_reg[i] <= ctrl_reg_wr_data[24];
rx_pfc_en_reg[i] <= ctrl_reg_wr_data[25];
ctrl_reg_wr_ack_reg <= 1'b1;
end
end
end
end
if (ctrl_reg_rd_en && !ctrl_reg_rd_ack_reg) begin
// read operation
ctrl_reg_rd_ack_reg <= 1'b1;
case ({ctrl_reg_rd_addr >> 2, 2'b00})
// Port
RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C002; // Port: Type
RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000200; // Port: Version
RBB+8'h08: ctrl_reg_rd_data_reg <= RB_NEXT_PTR; // Port: Next header
RBB+8'h0C: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // Port: Offset
// Port control
RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C003; // Port ctrl: Type
RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000300; // Port ctrl: Version
RBB+8'h18: ctrl_reg_rd_data_reg <= 0; // Port ctrl: Next header
RBB+8'h1C: begin
// Port ctrl: features
ctrl_reg_rd_data_reg[0] <= LFC_ENABLE;
ctrl_reg_rd_data_reg[1] <= PFC_ENABLE;
ctrl_reg_rd_data_reg[2] <= MAC_CTRL_ENABLE;
end
RBB+8'h20: begin
// Port ctrl: TX control/status
ctrl_reg_rd_data_reg[0] <= tx_enable_reg;
ctrl_reg_rd_data_reg[8] <= tx_pause_reg;
ctrl_reg_rd_data_reg[16] <= tx_status_sync_3_reg;
ctrl_reg_rd_data_reg[17] <= tx_rst_sync_3_reg;
ctrl_reg_rd_data_reg[24] <= tx_fifo_pause_req;
ctrl_reg_rd_data_reg[25] <= tx_fifo_pause_ack;
end
RBB+8'h24: begin
// Port ctrl: RX control/status
ctrl_reg_rd_data_reg[0] <= rx_enable_reg;
ctrl_reg_rd_data_reg[8] <= rx_pause_reg;
ctrl_reg_rd_data_reg[16] <= rx_status_sync_3_reg;
ctrl_reg_rd_data_reg[17] <= rx_rst_sync_3_reg;
ctrl_reg_rd_data_reg[24] <= rx_fifo_pause_req;
ctrl_reg_rd_data_reg[25] <= rx_fifo_pause_ack;
end
default: ctrl_reg_rd_ack_reg <= 1'b0;
endcase
if (MAC_CTRL_ENABLE) begin
if ({ctrl_reg_rd_addr >> 2, 2'b00} == RBB+8'h28) begin
// Port ctrl: FC control
ctrl_reg_rd_data_reg[15:0] <= tx_fc_quanta_step_reg;
ctrl_reg_rd_data_reg[31:16] <= rx_fc_quanta_step_reg;
ctrl_reg_rd_ack_reg <= 1'b1;
end
end
if (LFC_ENABLE) begin
if ({ctrl_reg_rd_addr >> 2, 2'b00} == RBB+8'h2C) begin
// Port ctrl: LFC control
ctrl_reg_rd_data_reg[23:0] <= rx_lfc_watermark_reg;
ctrl_reg_rd_data_reg[24] <= tx_lfc_en_reg;
ctrl_reg_rd_data_reg[25] <= rx_lfc_en_reg;
ctrl_reg_rd_data_reg[28] <= tx_lfc_req_reg;
ctrl_reg_rd_data_reg[29] <= rx_lfc_req_sync_3_reg;
ctrl_reg_rd_ack_reg <= 1'b1;
end
end
if (PFC_ENABLE) begin
for (i = 0; i < 8; i = i + 1) begin
if ({ctrl_reg_rd_addr >> 2, 2'b00} == RBB+8'h30+i*4) begin
// Port ctrl: PFC control N
ctrl_reg_rd_data_reg[24] <= tx_pfc_en_reg[i];
ctrl_reg_rd_data_reg[25] <= rx_pfc_en_reg[i];
ctrl_reg_rd_data_reg[28] <= tx_pfc_req_reg[i];
ctrl_reg_rd_data_reg[29] <= rx_pfc_req_sync_3_reg[i];
ctrl_reg_rd_ack_reg <= 1'b1;
end
end
end
end
if (rst) begin
ctrl_reg_wr_ack_reg <= 1'b0;
ctrl_reg_rd_ack_reg <= 1'b0;
tx_enable_reg <= 1'b0;
tx_pause_reg <= 1'b0;
tx_lfc_en_reg <= 1'b0;
tx_lfc_req_reg <= 1'b0;
tx_pfc_en_reg <= 8'd0;
tx_pfc_req_reg <= 8'd0;
tx_fc_quanta_step_reg <= (AXIS_DATA_WIDTH*256)/512;
rx_enable_reg <= 1'b0;
rx_pause_reg <= 1'b0;
rx_lfc_en_reg <= 1'b0;
rx_lfc_ack_reg <= 1'b0;
rx_pfc_en_reg <= 8'd0;
rx_pfc_ack_reg <= 8'd0;
rx_fc_quanta_step_reg <= (AXIS_DATA_WIDTH*256)/512;
rx_lfc_watermark_reg <= RX_FIFO_DEPTH/2;
end
end
mqnic_port_tx #(
// PTP configuration
.PTP_TS_WIDTH(PTP_TS_WIDTH),
// Interface configuration
.PTP_TS_ENABLE(PTP_TS_ENABLE),
.TX_CPL_ENABLE(TX_CPL_ENABLE),
.TX_CPL_FIFO_DEPTH(TX_CPL_FIFO_DEPTH),
.TX_TAG_WIDTH(TX_TAG_WIDTH),
.PFC_ENABLE(PFC_ENABLE),
.LFC_ENABLE(LFC_ENABLE),
.MAC_CTRL_ENABLE(MAC_CTRL_ENABLE),
.MAX_TX_SIZE(MAX_TX_SIZE),
// Application block configuration
.APP_AXIS_DIRECT_ENABLE(APP_AXIS_DIRECT_ENABLE),
.APP_AXIS_SYNC_ENABLE(APP_AXIS_SYNC_ENABLE),
// Streaming interface configuration
.AXIS_DATA_WIDTH(AXIS_DATA_WIDTH),
.AXIS_KEEP_WIDTH(AXIS_KEEP_WIDTH),
.AXIS_TX_USER_WIDTH(AXIS_TX_USER_WIDTH),
.AXIS_TX_PIPELINE(AXIS_TX_PIPELINE),
.AXIS_TX_FIFO_PIPELINE(AXIS_TX_FIFO_PIPELINE),
.AXIS_TX_TS_PIPELINE(AXIS_TX_TS_PIPELINE),
.AXIS_SYNC_DATA_WIDTH(AXIS_SYNC_DATA_WIDTH),
.AXIS_SYNC_KEEP_WIDTH(AXIS_SYNC_KEEP_WIDTH),
.AXIS_SYNC_TX_USER_WIDTH(AXIS_SYNC_TX_USER_WIDTH)
)
port_tx_inst (
.clk(clk),
.rst(rst),
/*
* Transmit data from interface FIFO
*/
.s_axis_if_tx_tdata(s_axis_if_tx_tdata),
.s_axis_if_tx_tkeep(s_axis_if_tx_tkeep),
.s_axis_if_tx_tvalid(s_axis_if_tx_tvalid),
.s_axis_if_tx_tready(s_axis_if_tx_tready),
.s_axis_if_tx_tlast(s_axis_if_tx_tlast),
.s_axis_if_tx_tuser(s_axis_if_tx_tuser),
.m_axis_if_tx_cpl_ts(m_axis_if_tx_cpl_ts),
.m_axis_if_tx_cpl_tag(m_axis_if_tx_cpl_tag),
.m_axis_if_tx_cpl_valid(m_axis_if_tx_cpl_valid),
.m_axis_if_tx_cpl_ready(m_axis_if_tx_cpl_ready),
/*
* Application section datapath interface (synchronous MAC interface)
*/
.m_axis_app_sync_tx_tdata(m_axis_app_sync_tx_tdata),
.m_axis_app_sync_tx_tkeep(m_axis_app_sync_tx_tkeep),
.m_axis_app_sync_tx_tvalid(m_axis_app_sync_tx_tvalid),
.m_axis_app_sync_tx_tready(m_axis_app_sync_tx_tready),
.m_axis_app_sync_tx_tlast(m_axis_app_sync_tx_tlast),
.m_axis_app_sync_tx_tuser(m_axis_app_sync_tx_tuser),
.s_axis_app_sync_tx_tdata(s_axis_app_sync_tx_tdata),
.s_axis_app_sync_tx_tkeep(s_axis_app_sync_tx_tkeep),
.s_axis_app_sync_tx_tvalid(s_axis_app_sync_tx_tvalid),
.s_axis_app_sync_tx_tready(s_axis_app_sync_tx_tready),
.s_axis_app_sync_tx_tlast(s_axis_app_sync_tx_tlast),
.s_axis_app_sync_tx_tuser(s_axis_app_sync_tx_tuser),
.m_axis_app_sync_tx_cpl_ts(m_axis_app_sync_tx_cpl_ts),
.m_axis_app_sync_tx_cpl_tag(m_axis_app_sync_tx_cpl_tag),
.m_axis_app_sync_tx_cpl_valid(m_axis_app_sync_tx_cpl_valid),
.m_axis_app_sync_tx_cpl_ready(m_axis_app_sync_tx_cpl_ready),
.s_axis_app_sync_tx_cpl_ts(s_axis_app_sync_tx_cpl_ts),
.s_axis_app_sync_tx_cpl_tag(s_axis_app_sync_tx_cpl_tag),
.s_axis_app_sync_tx_cpl_valid(s_axis_app_sync_tx_cpl_valid),
.s_axis_app_sync_tx_cpl_ready(s_axis_app_sync_tx_cpl_ready),
/*
* Application section datapath interface (direct MAC interface)
*/
.m_axis_app_direct_tx_tdata(m_axis_app_direct_tx_tdata),
.m_axis_app_direct_tx_tkeep(m_axis_app_direct_tx_tkeep),
.m_axis_app_direct_tx_tvalid(m_axis_app_direct_tx_tvalid),
.m_axis_app_direct_tx_tready(m_axis_app_direct_tx_tready),
.m_axis_app_direct_tx_tlast(m_axis_app_direct_tx_tlast),
.m_axis_app_direct_tx_tuser(m_axis_app_direct_tx_tuser),
.s_axis_app_direct_tx_tdata(s_axis_app_direct_tx_tdata),
.s_axis_app_direct_tx_tkeep(s_axis_app_direct_tx_tkeep),
.s_axis_app_direct_tx_tvalid(s_axis_app_direct_tx_tvalid),
.s_axis_app_direct_tx_tready(s_axis_app_direct_tx_tready),
.s_axis_app_direct_tx_tlast(s_axis_app_direct_tx_tlast),
.s_axis_app_direct_tx_tuser(s_axis_app_direct_tx_tuser),
.m_axis_app_direct_tx_cpl_ts(m_axis_app_direct_tx_cpl_ts),
.m_axis_app_direct_tx_cpl_tag(m_axis_app_direct_tx_cpl_tag),
.m_axis_app_direct_tx_cpl_valid(m_axis_app_direct_tx_cpl_valid),
.m_axis_app_direct_tx_cpl_ready(m_axis_app_direct_tx_cpl_ready),
.s_axis_app_direct_tx_cpl_ts(s_axis_app_direct_tx_cpl_ts),
.s_axis_app_direct_tx_cpl_tag(s_axis_app_direct_tx_cpl_tag),
.s_axis_app_direct_tx_cpl_valid(s_axis_app_direct_tx_cpl_valid),
.s_axis_app_direct_tx_cpl_ready(s_axis_app_direct_tx_cpl_ready),
/*
* Transmit data output
*/
.tx_clk(tx_clk),
.tx_rst(tx_rst),
.m_axis_tx_tdata(m_axis_tx_tdata),
.m_axis_tx_tkeep(m_axis_tx_tkeep),
.m_axis_tx_tvalid(m_axis_tx_tvalid),
.m_axis_tx_tready(m_axis_tx_tready),
.m_axis_tx_tlast(m_axis_tx_tlast),
.m_axis_tx_tuser(m_axis_tx_tuser),
.s_axis_tx_cpl_ts(s_axis_tx_cpl_ts),
.s_axis_tx_cpl_tag(s_axis_tx_cpl_tag),
.s_axis_tx_cpl_valid(s_axis_tx_cpl_valid),
.s_axis_tx_cpl_ready(s_axis_tx_cpl_ready),
/*
* Flow control
*/
.tx_lfc_en(tx_lfc_en),
.tx_lfc_req(tx_lfc_req),
.tx_pfc_en(tx_pfc_en),
.tx_pfc_req(tx_pfc_req),
.tx_pause_req(1'b0),
.tx_pause_ack(),
.tx_fc_quanta_step(tx_fc_quanta_step_reg),
.tx_fc_quanta_clk_en(tx_fc_quanta_clk_en),
.fifo_pause_req(tx_fifo_pause_req),
.fifo_pause_ack(tx_fifo_pause_ack)
);
mqnic_port_rx #(
// PTP configuration
.PTP_TS_WIDTH(PTP_TS_WIDTH),
// Interface configuration
.PTP_TS_ENABLE(PTP_TS_ENABLE),
.PFC_ENABLE(PFC_ENABLE),
.LFC_ENABLE(LFC_ENABLE),
.MAC_CTRL_ENABLE(MAC_CTRL_ENABLE),
.MAX_RX_SIZE(MAX_RX_SIZE),
// Application block configuration
.APP_AXIS_DIRECT_ENABLE(APP_AXIS_DIRECT_ENABLE),
.APP_AXIS_SYNC_ENABLE(APP_AXIS_SYNC_ENABLE),
// Streaming interface configuration
.AXIS_DATA_WIDTH(AXIS_DATA_WIDTH),
.AXIS_KEEP_WIDTH(AXIS_KEEP_WIDTH),
.AXIS_RX_USER_WIDTH(AXIS_RX_USER_WIDTH),
.AXIS_RX_USE_READY(AXIS_RX_USE_READY),
.AXIS_RX_PIPELINE(AXIS_RX_PIPELINE),
.AXIS_RX_FIFO_PIPELINE(AXIS_RX_FIFO_PIPELINE),
.AXIS_SYNC_DATA_WIDTH(AXIS_SYNC_DATA_WIDTH),
.AXIS_SYNC_KEEP_WIDTH(AXIS_SYNC_KEEP_WIDTH),
.AXIS_SYNC_RX_USER_WIDTH(AXIS_SYNC_RX_USER_WIDTH)
)
port_rx_inst (
.clk(clk),
.rst(rst),
/*
* Receive data to interface FIFO
*/
.m_axis_if_rx_tdata(m_axis_if_rx_tdata),
.m_axis_if_rx_tkeep(m_axis_if_rx_tkeep),
.m_axis_if_rx_tvalid(m_axis_if_rx_tvalid),
.m_axis_if_rx_tready(m_axis_if_rx_tready),
.m_axis_if_rx_tlast(m_axis_if_rx_tlast),
.m_axis_if_rx_tuser(m_axis_if_rx_tuser),
/*
* Application section datapath interface (synchronous MAC interface)
*/
.m_axis_app_sync_rx_tdata(m_axis_app_sync_rx_tdata),
.m_axis_app_sync_rx_tkeep(m_axis_app_sync_rx_tkeep),
.m_axis_app_sync_rx_tvalid(m_axis_app_sync_rx_tvalid),
.m_axis_app_sync_rx_tready(m_axis_app_sync_rx_tready),
.m_axis_app_sync_rx_tlast(m_axis_app_sync_rx_tlast),
.m_axis_app_sync_rx_tuser(m_axis_app_sync_rx_tuser),
.s_axis_app_sync_rx_tdata(s_axis_app_sync_rx_tdata),
.s_axis_app_sync_rx_tkeep(s_axis_app_sync_rx_tkeep),
.s_axis_app_sync_rx_tvalid(s_axis_app_sync_rx_tvalid),
.s_axis_app_sync_rx_tready(s_axis_app_sync_rx_tready),
.s_axis_app_sync_rx_tlast(s_axis_app_sync_rx_tlast),
.s_axis_app_sync_rx_tuser(s_axis_app_sync_rx_tuser),
/*
* Application section datapath interface (direct MAC interface)
*/
.m_axis_app_direct_rx_tdata(m_axis_app_direct_rx_tdata),
.m_axis_app_direct_rx_tkeep(m_axis_app_direct_rx_tkeep),
.m_axis_app_direct_rx_tvalid(m_axis_app_direct_rx_tvalid),
.m_axis_app_direct_rx_tready(m_axis_app_direct_rx_tready),
.m_axis_app_direct_rx_tlast(m_axis_app_direct_rx_tlast),
.m_axis_app_direct_rx_tuser(m_axis_app_direct_rx_tuser),
.s_axis_app_direct_rx_tdata(s_axis_app_direct_rx_tdata),
.s_axis_app_direct_rx_tkeep(s_axis_app_direct_rx_tkeep),
.s_axis_app_direct_rx_tvalid(s_axis_app_direct_rx_tvalid),
.s_axis_app_direct_rx_tready(s_axis_app_direct_rx_tready),
.s_axis_app_direct_rx_tlast(s_axis_app_direct_rx_tlast),
.s_axis_app_direct_rx_tuser(s_axis_app_direct_rx_tuser),
/*
* Receive data input
*/
.rx_clk(rx_clk),
.rx_rst(rx_rst),
.s_axis_rx_tdata(s_axis_rx_tdata),
.s_axis_rx_tkeep(s_axis_rx_tkeep),
.s_axis_rx_tvalid(s_axis_rx_tvalid),
.s_axis_rx_tready(s_axis_rx_tready),
.s_axis_rx_tlast(s_axis_rx_tlast),
.s_axis_rx_tuser(s_axis_rx_tuser),
/*
* Flow control
*/
.rx_lfc_en(rx_lfc_en),
.rx_lfc_req(rx_lfc_req_int),
.rx_lfc_ack(rx_lfc_ack),
.rx_pfc_en(rx_pfc_en),
.rx_pfc_req(rx_pfc_req_int),
.rx_pfc_ack(rx_pfc_ack),
.rx_fc_quanta_step(rx_fc_quanta_step_reg),
.rx_fc_quanta_clk_en(rx_fc_quanta_clk_en),
.fifo_pause_req(rx_fifo_pause_req),
.fifo_pause_ack(rx_fifo_pause_ack)
);
endmodule
`resetall