fpga: x400: Add support for X410 motherboard FPGA

Co-authored-by: Andrew Moch <Andrew.Moch@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Javier Valenzuela <javier.valenzuela@ni.com>
Co-authored-by: Joerg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Kumaran Subramoniam <kumaran.subramoniam@ni.com>
Co-authored-by: Max Köhler <max.koehler@ni.com>
Co-authored-by: Michael Auchter <michael.auchter@ni.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Co-authored-by: Hector Rubio <hrubio@ni.com>


Original-commit: 6d3765605262016a80f71e36357f749ea35cbe5a
This commit is contained in:
Wade Fife
2021-06-10 11:56:58 -05:00
committed by Aaron Rossetto
co-authored by Andrew Moch Daniel Jepson Javier Valenzuela Joerg Hofrichter Kumaran Subramoniam Max Köhler Michael Auchter Paul Butler Hector Rubio
parent bfef20ea45
commit 61782b02d7
205 changed files with 299634 additions and 0 deletions
@@ -0,0 +1,120 @@
//
// Copyright 2021 Ettus Research, A National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: eth_100g_axi2lbus
//
// Description:
// Translate from AXI4S (Xilinx segmented ifc) to lbus.
//
// Built using example provided from Xilinx
//
// Parameters:
// - FIFO_DEPTH - FIFO will be 2** deep
// - NUM_SEG - Number of lbus segments coming in
import PkgEth100gLbus::*;
module eth_100g_axi2lbus #(
parameter FIFO_DEPTH = 5,
parameter NUM_SEG = 4
)
(
// AXIS IF
AxiStreamIf.slave axis,
// Lbus Segments
input logic lbus_rdy,
output lbus_t lbus_out [NUM_SEG-1:0]
);
localparam SEG_DATA_WIDTH = DATA_WIDTH/NUM_SEG;
localparam SEG_BYTES = SEG_DATA_WIDTH/8;
localparam SEG_MTY_WIDTH = $clog2(SEG_BYTES);
// post rotation lbus signals
lbus_t lbus_d [NUM_SEG-1:0];
// Find last so we can find SOP
logic found_last;
// Propagate ready when asserting , propagate delayed ready while deasserting
logic axis_tready_i;
assign axis.tready = axis_tready_i | lbus_rdy;
always @(posedge axis.clk) begin
axis_tready_i <= lbus_rdy;
end
//declare a segment width axis bus so I can use it's methods
AxiStreamIf #(.DATA_WIDTH(SEG_DATA_WIDTH),.USER_WIDTH($clog2(SEG_BYTES)))
seg_axi (axis.clk, axis.rst);
assign seg_axi.tlast = 1'b1;
logic [NUM_SEG:0] valid;
assign valid[NUM_SEG] = 1'b0;
genvar b;
genvar s;
generate begin : lbus_gen
for (s=0; s < NUM_SEG; s=s+1) begin : segment_loop
// Reverse data byte ordering on each segment
for (b = 0; b < DATA_WIDTH/32; b=b+1) begin : byte_loop
assign lbus_d[s].data[b*8 +: 8] = axis.tdata[((s+1)*(DATA_WIDTH/NUM_SEG)-8-(b*8)) +: 8];
end : byte_loop
// valid if tkeep is set for any bytes in the segment
assign valid[s] = (| axis.tkeep[s*SEG_BYTES +: SEG_BYTES]) & axis.tvalid;
// enable when valid and transfering
assign lbus_d[s].ena = valid[s] & axis.tready;
// eop on last valid byte if last is set
// we init an extra valid bit to 0 so if all valid bits for all segments are set we trigger an eop on the final segment
assign lbus_d[s].eop = (valid[s] ^ valid[s+1]) & axis.tlast;
// set error on all segmetns if tuser is set
assign lbus_d[s].err = valid[s] & axis.tuser;
// translate keep to trailing bytes and invert sign
always_comb begin
if (lbus_d[s].eop) begin
lbus_d[s].mty = SEG_BYTES - seg_axi.keep2trailing(axis.tkeep[s*SEG_BYTES+: SEG_BYTES]);
end else begin
lbus_d[s].mty = 'b0;
end
end
//SOP can only occur on segment 0, so init all the bits to zero, then assign segment 0
if (s==0) begin
assign lbus_d[s].sop = found_last & axis.tvalid & axis.tready;
end else begin
assign lbus_d[s].sop = 1'b0;
end
// assign the output DFF's
always_ff @(posedge axis.clk) begin
lbus_out[s].data <= lbus_d[s].data;
lbus_out[s].ena <= lbus_d[s].ena;
lbus_out[s].sop <= lbus_d[s].sop;
lbus_out[s].eop <= lbus_d[s].eop;
lbus_out[s].err <= lbus_d[s].err;
lbus_out[s].mty <= lbus_d[s].mty;
end
end : segment_loop
end : lbus_gen
endgenerate
// SOP Statemachine
always_ff @(posedge axis.clk) begin : sop_sm
if(axis.rst) begin
found_last <= 1'b1;
end else begin
if(axis.tvalid & axis.tlast & axis.tready) found_last <= 1'b1;
else if(axis.tvalid & axis.tready) found_last <= 1'b0;
end
end : sop_sm
endmodule