commit a170300310aed900b9b6874c3a467d01042b28c3
parent ed30ef3614097f55ff3018f7d1a480c02c625528
Author: Brian Swetland <swetland@frotz.net>
Date: Mon, 17 Dec 2018 16:17:23 -0800
eth_crc32_*: 32bit crc for ethernet fcs
In 2bit and 8bit per clock flavors. Including testbench.
Diffstat:
5 files changed, 334 insertions(+), 0 deletions(-)
diff --git a/hdl/eth_crc32_2.sv b/hdl/eth_crc32_2.sv
@@ -0,0 +1,66 @@
+// autogenerated by crctool -poly=4c11db7 -crcsz=32 -dinsz=2 -reverse
+
+module eth_crc32_2(
+ input clk,
+ input rst,
+ input en,
+ input [1:0]din,
+ output [31:0]crc
+ );
+
+reg [31:0]c;
+reg [31:0]n;
+
+wire [1:0]d = {din[0],din[1]};
+
+assign crc = {
+ c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7]
+ ,c[8],c[9],c[10],c[11],c[12],c[13],c[14],c[15]
+ ,c[16],c[17],c[18],c[19],c[20],c[21],c[22],c[23]
+ ,c[24],c[25],c[26],c[27],c[28],c[29],c[30],c[31]
+ };
+
+always_comb begin
+ n[0] = c[30]^d[0];
+ n[1] = c[30]^c[31]^d[0]^d[1];
+ n[2] = c[0]^c[30]^c[31]^d[0]^d[1];
+ n[3] = c[1]^c[31]^d[1];
+ n[4] = c[2]^c[30]^d[0];
+ n[5] = c[3]^c[30]^c[31]^d[0]^d[1];
+ n[6] = c[4]^c[31]^d[1];
+ n[7] = c[5]^c[30]^d[0];
+ n[8] = c[6]^c[30]^c[31]^d[0]^d[1];
+ n[9] = c[7]^c[31]^d[1];
+ n[10] = c[8]^c[30]^d[0];
+ n[11] = c[9]^c[30]^c[31]^d[0]^d[1];
+ n[12] = c[10]^c[30]^c[31]^d[0]^d[1];
+ n[13] = c[11]^c[31]^d[1];
+ n[14] = c[12];
+ n[15] = c[13];
+ n[16] = c[14]^c[30]^d[0];
+ n[17] = c[15]^c[31]^d[1];
+ n[18] = c[16];
+ n[19] = c[17];
+ n[20] = c[18];
+ n[21] = c[19];
+ n[22] = c[20]^c[30]^d[0];
+ n[23] = c[21]^c[30]^c[31]^d[0]^d[1];
+ n[24] = c[22]^c[31]^d[1];
+ n[25] = c[23];
+ n[26] = c[24]^c[30]^d[0];
+ n[27] = c[25]^c[31]^d[1];
+ n[28] = c[26];
+ n[29] = c[27];
+ n[30] = c[28];
+ n[31] = c[29];
+end
+
+always_ff @(posedge clk) begin
+ if (rst) begin
+ c <= 32'hFFFFFFFF;
+ end else if (en) begin
+ c <= n;
+ end
+end
+
+endmodule
diff --git a/hdl/eth_crc32_8.sv b/hdl/eth_crc32_8.sv
@@ -0,0 +1,66 @@
+// autogenerated by crctool -poly=4c11db7 -crcsz=32 -dinsz=8 -reverse
+
+module eth_crc32_8(
+ input clk,
+ input rst,
+ input en,
+ input [7:0]din,
+ output [31:0]crc
+ );
+
+reg [31:0]c;
+reg [31:0]n;
+
+wire [7:0]d = {din[0],din[1],din[2],din[3],din[4],din[5],din[6],din[7]};
+
+assign crc = {
+ c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7]
+ ,c[8],c[9],c[10],c[11],c[12],c[13],c[14],c[15]
+ ,c[16],c[17],c[18],c[19],c[20],c[21],c[22],c[23]
+ ,c[24],c[25],c[26],c[27],c[28],c[29],c[30],c[31]
+ };
+
+always_comb begin
+ n[0] = c[24]^c[30]^d[0]^d[6];
+ n[1] = c[24]^c[25]^c[30]^c[31]^d[0]^d[1]^d[6]^d[7];
+ n[2] = c[24]^c[25]^c[26]^c[30]^c[31]^d[0]^d[1]^d[2]^d[6]^d[7];
+ n[3] = c[25]^c[26]^c[27]^c[31]^d[1]^d[2]^d[3]^d[7];
+ n[4] = c[24]^c[26]^c[27]^c[28]^c[30]^d[0]^d[2]^d[3]^d[4]^d[6];
+ n[5] = c[24]^c[25]^c[27]^c[28]^c[29]^c[30]^c[31]^d[0]^d[1]^d[3]^d[4]^d[5]^d[6]^d[7];
+ n[6] = c[25]^c[26]^c[28]^c[29]^c[30]^c[31]^d[1]^d[2]^d[4]^d[5]^d[6]^d[7];
+ n[7] = c[24]^c[26]^c[27]^c[29]^c[31]^d[0]^d[2]^d[3]^d[5]^d[7];
+ n[8] = c[0]^c[24]^c[25]^c[27]^c[28]^d[0]^d[1]^d[3]^d[4];
+ n[9] = c[1]^c[25]^c[26]^c[28]^c[29]^d[1]^d[2]^d[4]^d[5];
+ n[10] = c[2]^c[24]^c[26]^c[27]^c[29]^d[0]^d[2]^d[3]^d[5];
+ n[11] = c[3]^c[24]^c[25]^c[27]^c[28]^d[0]^d[1]^d[3]^d[4];
+ n[12] = c[4]^c[24]^c[25]^c[26]^c[28]^c[29]^c[30]^d[0]^d[1]^d[2]^d[4]^d[5]^d[6];
+ n[13] = c[5]^c[25]^c[26]^c[27]^c[29]^c[30]^c[31]^d[1]^d[2]^d[3]^d[5]^d[6]^d[7];
+ n[14] = c[6]^c[26]^c[27]^c[28]^c[30]^c[31]^d[2]^d[3]^d[4]^d[6]^d[7];
+ n[15] = c[7]^c[27]^c[28]^c[29]^c[31]^d[3]^d[4]^d[5]^d[7];
+ n[16] = c[8]^c[24]^c[28]^c[29]^d[0]^d[4]^d[5];
+ n[17] = c[9]^c[25]^c[29]^c[30]^d[1]^d[5]^d[6];
+ n[18] = c[10]^c[26]^c[30]^c[31]^d[2]^d[6]^d[7];
+ n[19] = c[11]^c[27]^c[31]^d[3]^d[7];
+ n[20] = c[12]^c[28]^d[4];
+ n[21] = c[13]^c[29]^d[5];
+ n[22] = c[14]^c[24]^d[0];
+ n[23] = c[15]^c[24]^c[25]^c[30]^d[0]^d[1]^d[6];
+ n[24] = c[16]^c[25]^c[26]^c[31]^d[1]^d[2]^d[7];
+ n[25] = c[17]^c[26]^c[27]^d[2]^d[3];
+ n[26] = c[18]^c[24]^c[27]^c[28]^c[30]^d[0]^d[3]^d[4]^d[6];
+ n[27] = c[19]^c[25]^c[28]^c[29]^c[31]^d[1]^d[4]^d[5]^d[7];
+ n[28] = c[20]^c[26]^c[29]^c[30]^d[2]^d[5]^d[6];
+ n[29] = c[21]^c[27]^c[30]^c[31]^d[3]^d[6]^d[7];
+ n[30] = c[22]^c[28]^c[31]^d[4]^d[7];
+ n[31] = c[23]^c[29]^d[5];
+end
+
+always_ff @(posedge clk) begin
+ if (rst) begin
+ c <= 32'hFFFFFFFF;
+ end else if (en) begin
+ c <= n;
+ end
+end
+
+endmodule
diff --git a/hdl/eth_crc32_test.sv b/hdl/eth_crc32_test.sv
@@ -0,0 +1,94 @@
+// Copyright 2018, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+`default_nettype none
+
+module testbench(
+ input clk
+);
+
+reg [8:0]packet[0:103];
+
+initial $readmemh("hdl/eth_crc32_testpacket.hex", packet);
+
+reg [6:0]pktcount = 7'd0;
+reg rst = 1'b1;
+reg wr = 1'b0;
+reg [7:0]pktdata = 8'd0;
+reg pktdone = 1'b0;
+wire [31:0]crc0;
+wire [31:0]crc1;
+
+`ifdef BYTEWISE
+eth_crc32_8(
+ .clk(clk),
+ .en(wr & ~pktdone),
+ .rst(rst),
+ .din(pktdata),
+ .crc(crc0)
+);
+
+always_ff @(posedge clk) begin
+ rst <= 1'b0;
+ wr <= 1'b1;
+ if (~pktdone)
+ { pktdone, pktdata } <= packet[pktcount];
+ pktcount <= pktcount + 7'd1;
+ $display("WR=", wr, " DONE=", pktdone, " IDX=", pktcount, " DATA=", pktdata, " CRC=", crc0);
+ if (pktdone) begin
+ if(crc0 == 32'hdebb20e3) begin
+ $display("SUCCESS");
+ end else begin
+ $display("FAILURE");
+ end
+ $finish();
+ end
+ if (pktcount == 105) $finish();
+end
+`else
+reg [3:0]tick = 4'b0001;
+
+eth_crc32_2 ethcrc0(
+ .clk(clk),
+ .en(wr & ~pktdone),
+ .rst(rst),
+ .din(pktdata[1:0]),
+ .crc(crc0)
+);
+
+eth_crc32_8 ethcrc1(
+ .clk(clk),
+ .en(tick[3] & ~pktdone),
+ .rst(rst),
+ .din(pktdata),
+ .crc(crc1)
+);
+
+always_ff @(posedge clk) begin
+ rst <= 1'b0;
+ wr <= 1'b1;
+ if (~pktdone) begin
+ if (tick[0]) begin
+ { pktdone, pktdata } <= packet[pktcount];
+ pktcount <= pktcount + 7'd1;
+ end else begin
+ { pktdone, pktdata } <= { pktdone, 2'b0, pktdata[7:2] };
+ end
+ tick <= { tick[0], tick[3:1] };
+ end
+ $display("WR=", wr, " DONE=", pktdone, " IDX=", pktcount, " DATA=", pktdata, " CRCx2=", crc0, " CRCx8=", crc1);
+ if (pktdone) begin
+ if (crc0 != 32'hdebb20e3) begin
+ $display("CRC32x2 FAILED");
+ end else if (crc1 != 32'hdebb20e3) begin
+ $display("CRC32x8 FAILED");
+ end else begin
+ $display("SUCCESS");
+ end
+ $finish();
+ end
+ if (pktcount == 105) $finish();
+end
+`endif
+
+endmodule
diff --git a/hdl/eth_crc32_testpacket.hex b/hdl/eth_crc32_testpacket.hex
@@ -0,0 +1,103 @@
+FF
+FF
+FF
+FF
+FF
+FF
+E0
+D5
+5E
+E5
+70
+67
+08
+00
+45
+00
+00
+54
+00
+00
+40
+00
+40
+01
+30
+80
+0a
+00
+00
+2A
+FF
+FF
+FF
+FF
+08
+00
+C2
+0F
+4E
+0F
+37
+67
+90
+E5
+16
+5C
+00
+00
+00
+00
+42
+65
+08
+00
+00
+00
+00
+00
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+1A
+1B
+1C
+1D
+1E
+1F
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+2A
+2B
+2C
+2D
+2E
+2F
+30
+31
+32
+33
+34
+35
+36
+37
+FF
+37
+69
+D2
+100
diff --git a/project/eth-crc32-test.def b/project/eth-crc32-test.def
@@ -0,0 +1,5 @@
+
+PROJECT_TYPE := verilator-sim
+
+PROJECT_SRCS := hdl/eth_crc32_test.sv hdl/eth_crc32_2.sv hdl/eth_crc32_8.sv
+