Files
Jungfraujoch/fpga/hdl/network_config.v
T
2025-09-08 20:28:59 +02:00

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