From 4d4c7df5b6b0e2f654932ece181d898ff4017f4d Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 5 May 2020 16:13:02 -0700 Subject: [PATCH] Parametrize eth_axis_fcs --- rtl/axis_eth_fcs.v | 114 ++++++++++++------- rtl/axis_eth_fcs_64.v | 227 ------------------------------------- tb/test_axis_eth_fcs.py | 9 +- tb/test_axis_eth_fcs.v | 14 ++- tb/test_axis_eth_fcs_64.py | 12 +- tb/test_axis_eth_fcs_64.v | 11 +- 6 files changed, 111 insertions(+), 276 deletions(-) delete mode 100644 rtl/axis_eth_fcs_64.v diff --git a/rtl/axis_eth_fcs.v b/rtl/axis_eth_fcs.v index 16e6a193..fbfebd17 100644 --- a/rtl/axis_eth_fcs.v +++ b/rtl/axis_eth_fcs.v @@ -29,69 +29,107 @@ THE SOFTWARE. /* * AXI4-Stream Ethernet FCS Generator */ -module axis_eth_fcs +module axis_eth_fcs # ( - input wire clk, - input wire rst, + // Width of AXI stream interfaces in bits + parameter DATA_WIDTH = 8, + // Propagate tkeep signal + // If disabled, tkeep assumed to be 1'b1 + parameter KEEP_ENABLE = (DATA_WIDTH>8), + // tkeep signal width (words per cycle) + parameter KEEP_WIDTH = (DATA_WIDTH/8) +) +( + input wire clk, + input wire rst, /* * AXI input */ - input wire [7:0] s_axis_tdata, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire s_axis_tuser, + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire [KEEP_WIDTH-1:0] s_axis_tkeep, + input wire s_axis_tvalid, + output wire s_axis_tready, + input wire s_axis_tlast, + input wire s_axis_tuser, /* * FCS output */ - output wire [31:0] output_fcs, - output wire output_fcs_valid + output wire [31:0] output_fcs, + output wire output_fcs_valid ); +// bus width assertions +initial begin + if (KEEP_WIDTH * 8 != DATA_WIDTH) begin + $error("Error: AXI stream interface requires byte (8-bit) granularity (instance %m)"); + $finish; + end +end + reg [31:0] crc_state = 32'hFFFFFFFF; reg [31:0] fcs_reg = 32'h00000000; reg fcs_valid_reg = 1'b0; -wire [31:0] crc_next; +wire [31:0] crc_next[KEEP_WIDTH-1:0]; assign s_axis_tready = 1; assign output_fcs = fcs_reg; assign output_fcs_valid = fcs_valid_reg; -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(8), - .STYLE("AUTO") -) -eth_crc_8 ( - .data_in(s_axis_tdata), - .state_in(crc_state), - .data_out(), - .state_out(crc_next) -); +generate + + genvar n; + + for (n = 0; n < KEEP_WIDTH; n = n + 1) begin : crc + + lfsr #( + .LFSR_WIDTH(32), + .LFSR_POLY(32'h4c11db7), + .LFSR_CONFIG("GALOIS"), + .LFSR_FEED_FORWARD(0), + .REVERSE(1), + .DATA_WIDTH(DATA_WIDTH/KEEP_WIDTH*(n+1)), + .STYLE("AUTO") + ) + eth_crc_inst ( + .data_in(s_axis_tdata[DATA_WIDTH/KEEP_WIDTH*(n+1)-1:0]), + .state_in(crc_state), + .data_out(), + .state_out(crc_next[n]) + ); + + end + +endgenerate + +integer i; always @(posedge clk) begin + fcs_valid_reg <= 1'b0; + + if (s_axis_tvalid) begin + crc_state <= crc_next[KEEP_WIDTH-1]; + + if (s_axis_tlast) begin + crc_state <= 32'hFFFFFFFF; + if (KEEP_ENABLE) begin + for (i = 0; i < KEEP_WIDTH; i = i + 1) begin + if (s_axis_tkeep[i]) begin + fcs_reg <= ~crc_next[i]; + end + end + end else begin + fcs_reg <= ~crc_next[KEEP_WIDTH-1]; + end + fcs_valid_reg <= 1'b1; + end + end + if (rst) begin crc_state <= 32'hFFFFFFFF; - fcs_reg <= 32'h00000000; fcs_valid_reg <= 1'b0; - end else begin - fcs_valid_reg <= 1'b0; - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - crc_state <= 32'hFFFFFFFF; - fcs_reg <= ~crc_next; - fcs_valid_reg <= 1'b1; - end else begin - crc_state <= crc_next; - end - end end end diff --git a/rtl/axis_eth_fcs_64.v b/rtl/axis_eth_fcs_64.v deleted file mode 100644 index e2fa4e37..00000000 --- a/rtl/axis_eth_fcs_64.v +++ /dev/null @@ -1,227 +0,0 @@ -/* - -Copyright (c) 2015-2018 Alex Forencich - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -// Language: Verilog 2001 - -`timescale 1ns / 1ps - -/* - * AXI4-Stream Ethernet FCS Generator (64 bit datapath) - */ -module axis_eth_fcs_64 -( - input wire clk, - input wire rst, - - /* - * AXI input - */ - input wire [63:0] s_axis_tdata, - input wire [7:0] s_axis_tkeep, - input wire s_axis_tvalid, - output wire s_axis_tready, - input wire s_axis_tlast, - input wire s_axis_tuser, - - /* - * FCS output - */ - output wire [31:0] output_fcs, - output wire output_fcs_valid -); - -reg [31:0] crc_state = 32'hFFFFFFFF; -reg [31:0] fcs_reg = 32'h00000000; -reg fcs_valid_reg = 1'b0; - -wire [31:0] crc_next0; -wire [31:0] crc_next1; -wire [31:0] crc_next2; -wire [31:0] crc_next3; -wire [31:0] crc_next4; -wire [31:0] crc_next5; -wire [31:0] crc_next6; -wire [31:0] crc_next7; - -assign s_axis_tready = 1'b1; -assign output_fcs = fcs_reg; -assign output_fcs_valid = fcs_valid_reg; - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(8), - .STYLE("AUTO") -) -eth_crc_8 ( - .data_in(s_axis_tdata[7:0]), - .state_in(crc_state), - .data_out(), - .state_out(crc_next0) -); - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(16), - .STYLE("AUTO") -) -eth_crc_16 ( - .data_in(s_axis_tdata[15:0]), - .state_in(crc_state), - .data_out(), - .state_out(crc_next1) -); - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(24), - .STYLE("AUTO") -) -eth_crc_24 ( - .data_in(s_axis_tdata[23:0]), - .state_in(crc_state), - .data_out(), - .state_out(crc_next2) -); - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(32), - .STYLE("AUTO") -) -eth_crc_32 ( - .data_in(s_axis_tdata[31:0]), - .state_in(crc_state), - .data_out(), - .state_out(crc_next3) -); - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(40), - .STYLE("AUTO") -) -eth_crc_40 ( - .data_in(s_axis_tdata[39:0]), - .state_in(crc_state), - .data_out(), - .state_out(crc_next4) -); - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(48), - .STYLE("AUTO") -) -eth_crc_48 ( - .data_in(s_axis_tdata[47:0]), - .state_in(crc_state), - .data_out(), - .state_out(crc_next5) -); - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(56), - .STYLE("AUTO") -) -eth_crc_56 ( - .data_in(s_axis_tdata[55:0]), - .state_in(crc_state), - .data_out(), - .state_out(crc_next6) -); - -lfsr #( - .LFSR_WIDTH(32), - .LFSR_POLY(32'h4c11db7), - .LFSR_CONFIG("GALOIS"), - .LFSR_FEED_FORWARD(0), - .REVERSE(1), - .DATA_WIDTH(64), - .STYLE("AUTO") -) -eth_crc_64 ( - .data_in(s_axis_tdata[63:0]), - .state_in(crc_state), - .data_out(), - .state_out(crc_next7) -); - -always @(posedge clk) begin - if (rst) begin - crc_state <= 32'hFFFFFFFF; - fcs_reg <= 1'b0; - fcs_valid_reg <= 1'b0; - end else begin - fcs_valid_reg <= 1'b0; - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - crc_state <= 32'hFFFFFFFF; - case (s_axis_tkeep) - 8'b00000001: fcs_reg <= ~crc_next0; - 8'b00000011: fcs_reg <= ~crc_next1; - 8'b00000111: fcs_reg <= ~crc_next2; - 8'b00001111: fcs_reg <= ~crc_next3; - 8'b00011111: fcs_reg <= ~crc_next4; - 8'b00111111: fcs_reg <= ~crc_next5; - 8'b01111111: fcs_reg <= ~crc_next6; - 8'b11111111: fcs_reg <= ~crc_next7; - endcase - fcs_valid_reg <= 1'b1; - end else begin - crc_state <= crc_next7; - end - end - end -end - -endmodule diff --git a/tb/test_axis_eth_fcs.py b/tb/test_axis_eth_fcs.py index 15fe19ba..10423462 100755 --- a/tb/test_axis_eth_fcs.py +++ b/tb/test_axis_eth_fcs.py @@ -45,14 +45,17 @@ build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) def bench(): # Parameters - + DATA_WIDTH = 8 + KEEP_ENABLE = (DATA_WIDTH>8) + KEEP_WIDTH = int(DATA_WIDTH/8) # Inputs clk = Signal(bool(0)) rst = Signal(bool(0)) current_test = Signal(intbv(0)[8:]) - s_axis_tdata = Signal(intbv(0)[8:]) + s_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) + s_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) s_axis_tvalid = Signal(bool(0)) s_axis_tlast = Signal(bool(0)) s_axis_tuser = Signal(bool(0)) @@ -71,6 +74,7 @@ def bench(): clk, rst, tdata=s_axis_tdata, + tkeep=s_axis_tkeep, tvalid=s_axis_tvalid, tready=s_axis_tready, tlast=s_axis_tlast, @@ -90,6 +94,7 @@ def bench(): current_test=current_test, s_axis_tdata=s_axis_tdata, + s_axis_tkeep=s_axis_tkeep, s_axis_tvalid=s_axis_tvalid, s_axis_tready=s_axis_tready, s_axis_tlast=s_axis_tlast, diff --git a/tb/test_axis_eth_fcs.v b/tb/test_axis_eth_fcs.v index 785ab4e3..7099ab23 100644 --- a/tb/test_axis_eth_fcs.v +++ b/tb/test_axis_eth_fcs.v @@ -32,13 +32,17 @@ THE SOFTWARE. module test_axis_eth_fcs; // Parameters +parameter DATA_WIDTH = 8; +parameter KEEP_ENABLE = (DATA_WIDTH>8); +parameter KEEP_WIDTH = (DATA_WIDTH/8); // Inputs reg clk = 0; reg rst = 0; reg [7:0] current_test = 0; -reg [7:0] s_axis_tdata = 0; +reg [DATA_WIDTH-1:0] s_axis_tdata = 0; +reg [KEEP_WIDTH-1:0] s_axis_tkeep = 0; reg s_axis_tvalid = 0; reg s_axis_tlast = 0; reg s_axis_tuser = 0; @@ -55,6 +59,7 @@ initial begin rst, current_test, s_axis_tdata, + s_axis_tkeep, s_axis_tvalid, s_axis_tlast, s_axis_tuser @@ -70,11 +75,16 @@ initial begin $dumpvars(0, test_axis_eth_fcs); end -axis_eth_fcs +axis_eth_fcs #( + .DATA_WIDTH(DATA_WIDTH), + .KEEP_ENABLE(KEEP_ENABLE), + .KEEP_WIDTH(KEEP_WIDTH) +) UUT ( .clk(clk), .rst(rst), .s_axis_tdata(s_axis_tdata), + .s_axis_tkeep(s_axis_tkeep), .s_axis_tvalid(s_axis_tvalid), .s_axis_tready(s_axis_tready), .s_axis_tlast(s_axis_tlast), diff --git a/tb/test_axis_eth_fcs_64.py b/tb/test_axis_eth_fcs_64.py index c592dab0..5eef3f12 100755 --- a/tb/test_axis_eth_fcs_64.py +++ b/tb/test_axis_eth_fcs_64.py @@ -29,8 +29,8 @@ import os import axis_ep import eth_ep -module = 'axis_eth_fcs_64' -testbench = 'test_%s' % module +module = 'axis_eth_fcs' +testbench = 'test_%s_64' % module srcs = [] @@ -45,15 +45,17 @@ build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) def bench(): # Parameters - + DATA_WIDTH = 64 + KEEP_ENABLE = (DATA_WIDTH>8) + KEEP_WIDTH = int(DATA_WIDTH/8) # Inputs clk = Signal(bool(0)) rst = Signal(bool(0)) current_test = Signal(intbv(0)[8:]) - s_axis_tdata = Signal(intbv(0)[64:]) - s_axis_tkeep = Signal(intbv(0)[8:]) + s_axis_tdata = Signal(intbv(0)[DATA_WIDTH:]) + s_axis_tkeep = Signal(intbv(1)[KEEP_WIDTH:]) s_axis_tvalid = Signal(bool(0)) s_axis_tlast = Signal(bool(0)) s_axis_tuser = Signal(bool(0)) diff --git a/tb/test_axis_eth_fcs_64.v b/tb/test_axis_eth_fcs_64.v index 1d137b1f..0faf33b8 100644 --- a/tb/test_axis_eth_fcs_64.v +++ b/tb/test_axis_eth_fcs_64.v @@ -27,11 +27,14 @@ THE SOFTWARE. `timescale 1ns / 1ps /* - * Testbench for axis_eth_fcs_64 + * Testbench for axis_eth_fcs */ module test_axis_eth_fcs_64; // Parameters +parameter DATA_WIDTH = 64; +parameter KEEP_ENABLE = (DATA_WIDTH>8); +parameter KEEP_WIDTH = (DATA_WIDTH/8); // Inputs reg clk = 0; @@ -72,7 +75,11 @@ initial begin $dumpvars(0, test_axis_eth_fcs_64); end -axis_eth_fcs_64 +axis_eth_fcs #( + .DATA_WIDTH(DATA_WIDTH), + .KEEP_ENABLE(KEEP_ENABLE), + .KEEP_WIDTH(KEEP_WIDTH) +) UUT ( .clk(clk), .rst(rst),