Files
iverilog/ivtest/contrib/gencrc.v
T
Stephen Williams cea237b407 Add ivtest to the iverilog source tree
By adding ivtest to the iverilog source tree, it is easier to keep
the regression test synchronized with the source that is being tested.
This should be especially helpful for PRs that add a new feature, and
have a matching ivtest PR with the regression test for that feature.
2022-01-15 10:18:50 -08:00

302 lines
9.9 KiB
Verilog

`begin_keywords "1364-2005"
//
// Copyright (c) 1999 Thomas Coonan ([email protected])
//
// This source code is free software; you can redistribute it
// and/or modify it in source code form under the terms of the GNU
// General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
//
//
// Behavioral Verilog for CRC16 and CRC32 for use in a testbench.
//
// The specific polynomials and conventions regarding bit-ordering etc.
// are specific to the Cable Modem DOCSIS protocol, but the general scheme
// should be reusable for other types of CRCs with some fiddling.
//
// This CRC code works for a specific type of network protocol, and it
// must do certain byte swappings, etc. You may need to play with it
// for your protocol. Also, make sure the polynomials are what you
// really want. This is obviously, not synthesizable - I just used this
// in a testbench at one point.
//
// These tasks are crude and rely on some global parameters. They should
// also read from a file, yada yada yada. It is probably better to do this
// with a PLI call, but here it is anyway..
//
// The test case includes a golden DOCSIS (Cable Modem) test message that
// was captured in a lab.
//
// tom coonan, 1999.
//
module test_gencrc;
// *** Buffer for the Golden Message ***
reg [7:0] test_packet[0:54];
// *** Global parameter block for the CRC32 calculator.
//
parameter CRC32_POLY = 32'h04C11DB7;
reg [ 7:0] crc32_packet[0:255];
integer crc32_length;
reg [31:0] crc32_result;
// *** Global parameter block for the CRC16 calculator.
//
parameter CRC16_POLY = 16'h1020;
reg [ 7:0] crc16_packet[0:255];
integer crc16_length;
reg [15:0] crc16_result;
`define TEST_GENCRC
`ifdef TEST_GENCRC
// Call the main test task and then quit.
//
initial begin
main_test;
$finish;
end
`endif
// ****************************************************************
// *
// * GOLDEN MESSAGE
// *
// * The golden message is a DOCSIS frame that was captured off
// * the Broadcom reference design. It is a MAP message. It
// * includes a HCS (crc 16) and a CRC32.
// *
// *
// ****************************************************************
//
task initialize_test_packet;
begin
test_packet[00] = 8'hC2; // FC. HCS coverage starts here.
test_packet[01] = 8'h00; // MACPARAM
test_packet[02] = 8'h00; // MAC LEN
test_packet[03] = 8'h30; // MAC LEN. HCS Coverage includes this byte and ends here.
test_packet[04] = 8'hF2; // CRC16 (also known as HCS)
test_packet[05] = 8'hCF; // CRC16 cont..
test_packet[06] = 8'h01; // Start of the IEEE payload. CRC32 covererage starts here. This is the DA field
test_packet[07] = 8'hE0; // DA field cont..
test_packet[08] = 8'h2F; // DA field cont..
test_packet[09] = 8'h00; // DA field cont..
test_packet[10] = 8'h00; // DA field cont..
test_packet[11] = 8'h01; // DA field cont..
test_packet[12] = 8'h00; // SA field
test_packet[13] = 8'h80; // SA field cont..
test_packet[14] = 8'h42; // SA field cont..
test_packet[15] = 8'h42; // SA field cont..
test_packet[16] = 8'h20; // SA field cont..
test_packet[17] = 8'h9E; // SA field cont..
test_packet[18] = 8'h00; // IEEE LEN field
test_packet[19] = 8'h1E; // IEEE LEN field cont.
test_packet[20] = 8'h00; // LLC field.
test_packet[21] = 8'h00; // LLC field cont...
test_packet[22] = 8'h03; // LLC field cont...
test_packet[23] = 8'h01; // LLC field cont...
test_packet[24] = 8'h03; // LLC field cont... This is also the TYPE, which indicates MAP.
test_packet[25] = 8'h00; // LLC field cont...
test_packet[26] = 8'h01; // Start of MAP message payload.
test_packet[27] = 8'h01; // MAP message payload..
test_packet[28] = 8'h02; // MAP message payload..
test_packet[29] = 8'h00; // MAP message payload..
test_packet[30] = 8'h00; // MAP message payload..
test_packet[31] = 8'h18; // MAP message payload..
test_packet[32] = 8'hAA; // MAP message payload..
test_packet[33] = 8'h58; // MAP message payload..
test_packet[34] = 8'h00; // MAP message payload..
test_packet[35] = 8'h18; // MAP message payload..
test_packet[36] = 8'hA8; // MAP message payload..
test_packet[37] = 8'hA0; // MAP message payload..
test_packet[38] = 8'h02; // MAP message payload..
test_packet[39] = 8'h03; // MAP message payload..
test_packet[40] = 8'h03; // MAP message payload..
test_packet[41] = 8'h08; // MAP message payload..
test_packet[42] = 8'hFF; // MAP message payload..
test_packet[43] = 8'hFC; // MAP message payload..
test_packet[44] = 8'h40; // MAP message payload..
test_packet[45] = 8'h00; // MAP message payload..
test_packet[46] = 8'h00; // MAP message payload..
test_packet[47] = 8'h01; // MAP message payload..
test_packet[48] = 8'hC0; // MAP message payload..
test_packet[49] = 8'h14; // Last byte of MAP payload, last byte covered by CRC32.
test_packet[50] = 8'hDD; // CRC32 Starts here
test_packet[51] = 8'hBF; // CRC32 cont..
test_packet[52] = 8'hC1; // CRC32 cont..
test_packet[53] = 8'h2E; // Last byte of CRC32, last byte of DOCSIS.
end
endtask
// *************************************************************************
// *
// * Main test task.
// *
// * Use our primary "golden packet". Copy into the generic global
// * variables that the low-level 'gencrc16' and 'gencrc32' tasks use.
// * Comare against the expected values and report SUCCESS or FAILURE.
// *
// *************************************************************************
//
task main_test;
integer i, j;
integer num_errors;
reg [15:0] crc16_expected;
reg [31:0] crc32_expected;
begin
num_errors = 0;
// Initialize the Golden Message!
//
initialize_test_packet;
// **** TEST CRC16
//
//
// Copy golden test_packet into the main crc16 buffer..
for (i=0; i<4; i=i+1) begin
crc16_packet[i] = test_packet[i];
end
crc16_expected = {test_packet[4], test_packet[5]};
crc16_length = 4; // Must tell test function the length
gencrc16; // Call main test function
if (crc16_result !== crc16_expected)
begin
num_errors = num_errors + 1;
$display ("FAILED - Actual crc16_result = %h, Expected = %h",
crc16_result, crc16_expected);
end
// **** TEST CRC16
//
j = 0;
for (i=6; i<50; i=i+1) begin
crc32_packet[j] = test_packet[i];
j = j + 1;
end
crc32_expected = {test_packet[50], test_packet[51], test_packet[52], test_packet[53]};
crc32_length = 44;
gencrc32;
if (crc32_result !== crc32_expected)
begin
$display ("FAILED - Actual crc32_result = %h, Expected = %h",
crc32_result, crc32_expected);
num_errors = num_errors + 1;
end
if(num_errors == 0)
$display("PASSED");
end
endtask
// ****************************************************************
// *
// * Main working CRC tasks are: gencrc16, gencrc32.
// *
// * These tasks rely on some globals (see front of program).
// *
// ****************************************************************
// Generate a (DOCSIS) CRC16.
//
// Uses the GLOBAL variables:
//
// Globals referenced:
// parameter CRC16_POLY = 16'h1020;
// reg [ 7:0] crc16_packet[0:255];
// integer crc16_length;
//
// Globals modified:
// reg [15:0] crc16_result;
//
task gencrc16;
integer byte, bit;
reg msb;
reg [7:0] current_byte;
reg [15:0] temp;
begin
crc16_result = 16'hffff;
for (byte = 0; byte < crc16_length; byte = byte + 1) begin
current_byte = crc16_packet[byte];
for (bit = 0; bit < 8; bit = bit + 1) begin
msb = crc16_result[15];
crc16_result = crc16_result << 1;
if (msb != current_byte[bit]) begin
crc16_result = crc16_result ^ CRC16_POLY;
crc16_result[0] = 1;
end
end
end
// Last step is to "mirror" every bit, swap the 2 bytes, and then complement each bit.
//
// Mirror:
for (bit = 0; bit < 16; bit = bit + 1)
temp[15-bit] = crc16_result[bit];
// Swap and Complement:
crc16_result = ~{temp[7:0], temp[15:8]};
end
endtask
// Generate a (DOCSIS) CRC32.
//
// Uses the GLOBAL variables:
//
// Globals referenced:
// parameter CRC32_POLY = 32'h04C11DB7;
// reg [ 7:0] crc32_packet[0:255];
// integer crc32_length;
//
// Globals modified:
// reg [31:0] crc32_result;
//
task gencrc32;
integer byte, bit;
reg msb;
reg [7:0] current_byte;
reg [31:0] temp;
begin
crc32_result = 32'hffffffff;
for (byte = 0; byte < crc32_length; byte = byte + 1) begin
current_byte = crc32_packet[byte];
for (bit = 0; bit < 8; bit = bit + 1) begin
msb = crc32_result[31];
crc32_result = crc32_result << 1;
if (msb != current_byte[bit]) begin
crc32_result = crc32_result ^ CRC32_POLY;
crc32_result[0] = 1;
end
end
end
// Last step is to "mirror" every bit, swap the 4 bytes, and then complement each bit.
//
// Mirror:
for (bit = 0; bit < 32; bit = bit + 1)
temp[31-bit] = crc32_result[bit];
// Swap and Complement:
crc32_result = ~{temp[7:0], temp[15:8], temp[23:16], temp[31:24]};
end
endtask
endmodule
`end_keywords