300 lines
9.7 KiB
Verilog
300 lines
9.7 KiB
Verilog
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
|
|
|
`timescale 1ns/1ps
|
|
|
|
// parameters imported from source files
|
|
`define JFJOCH_NET_MAGIC 32'h52344158
|
|
|
|
`define ADDR_JFJOCH_NET_MAGIC 16'h0000
|
|
`define ADDR_JFJOCH_NET_MODE 16'h0004
|
|
`define ADDR_MAC_ADDR_LO 16'h0008
|
|
`define ADDR_MAC_ADDR_HI 16'h000C
|
|
`define ADDR_IPV4_ADDR 16'h0010
|
|
`define ADDR_ETH_STATUS 16'h0014
|
|
`define ADDR_PACKETS_ETH_LO 16'h0018
|
|
`define ADDR_PACKETS_ETH_HI 16'h001C
|
|
`define ADDR_PACKETS_ICMP_LO 16'h0020
|
|
`define ADDR_PACKETS_ICMP_HI 16'h0024
|
|
`define ADDR_PTP_TIMESTAMP_LO 16'h0028
|
|
`define ADDR_PTP_TIMESTAMP_HI 16'h002C
|
|
`define ADDR_PTP_TIMESTAMP_NS 16'h0030
|
|
`define ADDR_PTP_TIMESTAMP_ERR 16'h0034
|
|
|
|
module network_config
|
|
#(parameter C_S_AXI_ADDR_WIDTH = 16,
|
|
parameter C_S_AXI_DATA_WIDTH = 32,
|
|
parameter DIRECT = 0
|
|
)(
|
|
(* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 clk CLK" *)
|
|
(* X_INTERFACE_PARAMETER = "ASSOCIATED_BUSIF s_axi, ASSOCIATED_RESET resetn" *)
|
|
input clk ,
|
|
(* X_INTERFACE_INFO = "xilinx.com:signal:reset:1.0 resetn RST" *)
|
|
(* X_INTERFACE_PARAMETER = "POLARITY ACTIVE_LOW" *)
|
|
input resetn ,
|
|
|
|
input wire [C_S_AXI_ADDR_WIDTH-1:0] s_axi_AWADDR,
|
|
input wire s_axi_AWVALID,
|
|
output wire s_axi_AWREADY,
|
|
input wire [C_S_AXI_DATA_WIDTH-1:0] s_axi_WDATA,
|
|
input wire [C_S_AXI_DATA_WIDTH/8-1:0] s_axi_WSTRB,
|
|
input wire s_axi_WVALID,
|
|
output wire s_axi_WREADY,
|
|
output wire [1:0] s_axi_BRESP,
|
|
output wire s_axi_BVALID,
|
|
input wire s_axi_BREADY,
|
|
input wire [C_S_AXI_ADDR_WIDTH-1:0] s_axi_ARADDR,
|
|
input wire s_axi_ARVALID,
|
|
output wire s_axi_ARREADY,
|
|
output wire [C_S_AXI_DATA_WIDTH-1:0] s_axi_RDATA,
|
|
output wire [1:0] s_axi_RRESP,
|
|
output wire s_axi_RVALID,
|
|
input wire s_axi_RREADY,
|
|
|
|
output reg [47:0] fpga_mac_addr ,
|
|
output reg [31:0] fpga_ipv4_addr ,
|
|
|
|
input [79:0] ptp_timestamp ,
|
|
input [1:0] ptp_sync ,
|
|
input [31:0] ptp_error ,
|
|
input [63:0] packets_eth ,
|
|
input packets_eth_valid ,
|
|
input [63:0] packets_icmp ,
|
|
input packets_icmp_valid ,
|
|
output reg direct ,
|
|
output reg enable ,
|
|
output reg clear_counters ,
|
|
input eth_stat_rx_status
|
|
);
|
|
|
|
//------------------------Parameter----------------------
|
|
localparam
|
|
|
|
WRIDLE = 2'd0,
|
|
WRDATA = 2'd1,
|
|
WRRESP = 2'd2,
|
|
WRRESET = 2'd3,
|
|
RDIDLE = 2'd0,
|
|
RDDATA = 2'd1,
|
|
RDRESET = 2'd2,
|
|
ADDR_BITS = C_S_AXI_ADDR_WIDTH;
|
|
|
|
//------------------------Local signal-------------------
|
|
reg [1:0] wstate = WRRESET;
|
|
reg [1:0] wnext;
|
|
reg [ADDR_BITS-1:0] waddr;
|
|
wire [31:0] wmask;
|
|
wire aw_hs;
|
|
wire w_hs;
|
|
reg [1:0] rstate = RDRESET;
|
|
reg [1:0] rnext;
|
|
reg [31:0] rdata;
|
|
wire ar_hs;
|
|
wire [ADDR_BITS-1:0] raddr;
|
|
|
|
reg [63:0] reg_packets_eth;
|
|
reg [63:0] reg_packets_icmp;
|
|
reg [79:0] reg_ptp_timestamp;
|
|
reg [31:0] reg_ptp_error;
|
|
|
|
(* ASYNC_REG = "TRUE" *) reg reg_eth_stat_rx_status_1;
|
|
(* ASYNC_REG = "TRUE" *) reg reg_eth_stat_rx_status_2;
|
|
|
|
//------------------------Instantiation------------------
|
|
|
|
//------------------------AXI write fsm------------------
|
|
assign s_axi_AWREADY = (wstate == WRIDLE);
|
|
assign s_axi_WREADY = (wstate == WRDATA);
|
|
assign s_axi_BRESP = 2'b00; // OKAY
|
|
assign s_axi_BVALID = (wstate == WRRESP);
|
|
assign wmask = { {8{s_axi_WSTRB[3]}}, {8{s_axi_WSTRB[2]}}, {8{s_axi_WSTRB[1]}}, {8{s_axi_WSTRB[0]}} };
|
|
assign aw_hs = s_axi_AWVALID & s_axi_AWREADY;
|
|
assign w_hs = s_axi_WVALID & s_axi_WREADY;
|
|
|
|
// wstate
|
|
always @(posedge clk) begin
|
|
if (!resetn)
|
|
wstate <= WRRESET;
|
|
else
|
|
wstate <= wnext;
|
|
end
|
|
|
|
// wnext
|
|
always @(*) begin
|
|
case (wstate)
|
|
WRIDLE:
|
|
if (s_axi_AWVALID)
|
|
wnext = WRDATA;
|
|
else
|
|
wnext = WRIDLE;
|
|
WRDATA:
|
|
if (s_axi_WVALID)
|
|
wnext = WRRESP;
|
|
else
|
|
wnext = WRDATA;
|
|
WRRESP:
|
|
if (s_axi_BREADY)
|
|
wnext = WRIDLE;
|
|
else
|
|
wnext = WRRESP;
|
|
default:
|
|
wnext = WRIDLE;
|
|
endcase
|
|
end
|
|
|
|
// waddr
|
|
always @(posedge clk) begin
|
|
if (aw_hs)
|
|
waddr <= s_axi_AWADDR[ADDR_BITS-1:0];
|
|
end
|
|
|
|
//------------------------AXI read fsm-------------------
|
|
assign s_axi_ARREADY = (rstate == RDIDLE);
|
|
assign s_axi_RDATA = rdata;
|
|
assign s_axi_RRESP = 2'b00; // OKAY
|
|
assign s_axi_RVALID = (rstate == RDDATA);
|
|
assign ar_hs = s_axi_ARVALID & s_axi_ARREADY;
|
|
assign raddr = s_axi_ARADDR[ADDR_BITS-1:0];
|
|
|
|
// rstate
|
|
always @(posedge clk) begin
|
|
if (!resetn)
|
|
rstate <= RDRESET;
|
|
else
|
|
rstate <= rnext;
|
|
end
|
|
|
|
// rnext
|
|
always @(*) begin
|
|
case (rstate)
|
|
RDIDLE:
|
|
if (s_axi_ARVALID)
|
|
rnext = RDDATA;
|
|
else
|
|
rnext = RDIDLE;
|
|
RDDATA:
|
|
if (s_axi_RREADY & s_axi_RVALID)
|
|
rnext = RDIDLE;
|
|
else
|
|
rnext = RDDATA;
|
|
default:
|
|
rnext = RDIDLE;
|
|
endcase
|
|
end
|
|
|
|
// rdata
|
|
always @(posedge clk) begin
|
|
if (ar_hs) begin
|
|
case (raddr)
|
|
`ADDR_MAC_ADDR_HI: begin
|
|
rdata <= fpga_mac_addr[47:32];
|
|
end
|
|
`ADDR_MAC_ADDR_LO: begin
|
|
rdata <= fpga_mac_addr[31:0];
|
|
end
|
|
`ADDR_IPV4_ADDR: begin
|
|
rdata <= fpga_ipv4_addr;
|
|
end
|
|
`ADDR_JFJOCH_NET_MAGIC: begin
|
|
rdata <= `JFJOCH_NET_MAGIC;
|
|
end
|
|
`ADDR_JFJOCH_NET_MODE: begin
|
|
rdata[0] <= enable;
|
|
rdata[1] <= direct;
|
|
rdata[2] <= clear_counters;
|
|
rdata[31:3] <= 0;
|
|
end
|
|
`ADDR_PACKETS_ETH_HI: begin
|
|
rdata <= reg_packets_eth[63:32];
|
|
end
|
|
`ADDR_PACKETS_ETH_LO: begin
|
|
rdata <= reg_packets_eth[31:0];
|
|
end
|
|
`ADDR_PACKETS_ICMP_HI: begin
|
|
rdata <= reg_packets_icmp[63:32];
|
|
end
|
|
`ADDR_PACKETS_ICMP_LO: begin
|
|
rdata <= reg_packets_icmp[31:0];
|
|
end
|
|
`ADDR_ETH_STATUS: begin
|
|
rdata[0] <= reg_eth_stat_rx_status_2;
|
|
rdata[31:1] <= 0;
|
|
end
|
|
`ADDR_PTP_TIMESTAMP_HI:
|
|
rdata <= reg_ptp_timestamp[79:64];
|
|
`ADDR_PTP_TIMESTAMP_LO:
|
|
rdata <= reg_ptp_timestamp[63:32];
|
|
`ADDR_PTP_TIMESTAMP_NS:
|
|
rdata <= reg_ptp_timestamp[31:0];
|
|
`ADDR_PTP_TIMESTAMP_ERR:
|
|
rdata <= reg_ptp_error;
|
|
default:
|
|
rdata <= 32'hffffffff;
|
|
endcase
|
|
end
|
|
end
|
|
|
|
//------------------------Register logic-----------------
|
|
|
|
always @ (posedge clk) begin
|
|
reg_eth_stat_rx_status_1 <= eth_stat_rx_status;
|
|
reg_eth_stat_rx_status_2 <= reg_eth_stat_rx_status_1;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (!resetn)
|
|
fpga_mac_addr[47:32] <= 0;
|
|
else if (w_hs && waddr == `ADDR_MAC_ADDR_HI )
|
|
fpga_mac_addr[47:32] <= (s_axi_WDATA[31:0] & wmask) | (fpga_mac_addr[47:32] & !wmask);
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (!resetn)
|
|
fpga_mac_addr[31:0] <= 0;
|
|
else if (w_hs && waddr == `ADDR_MAC_ADDR_LO )
|
|
fpga_mac_addr[31:0] <= (s_axi_WDATA[31:0] & wmask) | (fpga_mac_addr[31:0] & !wmask);
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (!resetn)
|
|
fpga_ipv4_addr <= 0;
|
|
else if (w_hs && waddr == `ADDR_IPV4_ADDR )
|
|
fpga_ipv4_addr <= (s_axi_WDATA[31:0] & wmask) | (fpga_ipv4_addr & !wmask);
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (!resetn) begin
|
|
enable <= 1'b1;
|
|
direct <= DIRECT;
|
|
clear_counters <= 1'b0;
|
|
end else if (w_hs && waddr == `ADDR_JFJOCH_NET_MODE && s_axi_WSTRB[0]) begin
|
|
enable <= s_axi_WDATA[0];
|
|
direct <= s_axi_WDATA[1];
|
|
clear_counters <= s_axi_WDATA[2];
|
|
end
|
|
end
|
|
|
|
always @ (posedge clk) begin
|
|
if (!resetn)
|
|
begin
|
|
reg_packets_eth <= 0;
|
|
reg_packets_icmp <= 0;
|
|
reg_ptp_timestamp <= 0;
|
|
reg_ptp_error <= 32'hFFFFFFFF;
|
|
end
|
|
else
|
|
begin
|
|
if (packets_eth_valid)
|
|
reg_packets_eth <= packets_eth;
|
|
if (packets_icmp_valid)
|
|
reg_packets_icmp <= packets_icmp;
|
|
if (ptp_sync)
|
|
reg_ptp_timestamp <= ptp_timestamp;
|
|
else
|
|
reg_ptp_timestamp <= 80'h0;
|
|
reg_ptp_error <= ptp_error;
|
|
end
|
|
end
|
|
|
|
endmodule
|