OpenCores
URL https://opencores.org/ocsvn/pci_blue_interface/pci_blue_interface/trunk

Subversion Repositories pci_blue_interface

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 49 to Rev 50
    Reverse comparison

Rev 49 → Rev 50

/trunk/function_lib/crc32_lib.v
1,5 → 1,5
//===========================================================================
// $Id: crc32_lib.v,v 1.2 2001-08-19 13:49:08 bbeaver Exp $
// $Id: crc32_lib.v,v 1.3 2001-08-20 11:42:24 bbeaver Exp $
//
// Copyright 2001 Blue Beaver. All Rights Reserved.
//
7,16 → 7,13
// new data.
// CRC-32 needs to start out with a value of all F's.
// When CRC-32 is applied to a block which ends with the CRC-32 of the
// block, the resulting CRC-32 checksum is always ????
// block, the resulting CRC-32 checksum is always 32'hCBF43926.
//
// IMPLEMENTATION NOTE: This is combinational logic. The user needs to put
// flops after this. It is possible that the initial value might be
// implemented as a preset to the flops, or as a clear with the flops
// wrapped before and after with inverters.
// NOTE: The verilog these routines is started from scratch. A new user might
// want to look at a wonderful paper by Ross Williams, which seems to
// be at ftp.adelaide.edu.au:/pub/rocksoft/crc_v3.txt
// Also see http://www.easics.be/webtools/crctool
//
// NOTE: The verilog these routines is based on comes from the nice web page:
// http://www.easics.be/webtools/crctool
//
// This library is free software; you can distribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
63,16 → 60,72
// This code was developed using VeriLogger Pro, by Synapticad.
// Their support is greatly appreciated.
//
// NOTE: There are other sequences of numbers which share the property
// of Grey Code that only 1 bit transitions per value change. The
// sequence 0x00, 0x1, 0x3, 0x7, 0x6, 0x4, 0x0 is one such
// sequence. It should be possible to make a library which counts
// in sequences less than 2**n long, yet still has this property.
// NOTE: I am greatly confused about the order in which the CRC should be
// sent over the wire to a remote machine. Bit 0 first? Bit 31 first?
// True or compliment values? The user has got to figure this out in
// order to interoperate with existing machines.
//
// NOTE: Bit order matters in this code, of course. The existing code on
// the net assumes that when you present a multi-bit word to a parallel
// CRC generator, the MSB corresponds to teh earliest data to arrive
// across a serial interface. Fine. Go with it.
// NOTE: The code also assumes that the data shifts into bit 0 of the shift
// register, and shifts out of bit 31. Fine. Go with it.
//
// NOTE: The math for the CRC-32 is beyond me.
//
// NOTE: But they are pretty easy to use.
// You initialize a CRC to a special value to keep from missing
// initial 0 bytes. That is 32'hFFFFFFFF for CRC-32.
// You update a CRC as data comes in.
// You append the calculated CRC to the end of your message.
// You have to agree on logic sense and bit order with the
// receiver, or everything you send will seem wrong.
// The receiver calculates a CRC the same way, but receives a
// message longer than the one you sent, due to the added CRC.
// After the CRC is processed by the receiver, you either compare
// the calculated CRC with the sent one, or look for a magic
// final value which indicates that the message had no errors.
//
// NOTE: Looking on the web, one finds a nice tutorial by Cypress entitled
// "Parallel Cyclic Redundancy Check (CRC) for HOTLink(TM)".
// This reminds me of how I learned to do this from a wonderful
// CRC tutorial on the web, done by Ross N. WIlliams.
//
// NOTE: The CRC-32 polynomial is:
// X**0 + X**1 + X**2 + X**4 + X**5 + X**7 + X**8 + X**10
// + X**11 + X**12 + X**16 + X**22 + X**23 + X**26 + X**32
// You initialize it to the value 32'hFFFFFFFF
// You append it to the end of the message.
// The receiver sees the value 32'hCBF43926 when the message is
// received no errors.
//
// That means that each clock a new bit comes in, you have to shift
// all the 32 running state bits 1 bit higher and drop the MSB.
// PLUS you have to XOR in (new bit ^ bit 31) to locations
// 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, and 26.
//
// That is simple but slow. If you keep track of the bits, you can
// see that it might be possible to apply 1 bit, shift it, apply
// another bit, shift THAT, and end up with a new formula of how
// to update the shift register based on applyig 1 bits at once.
//
// That is the general plan. Figure out how to apply several bits
// at a time. Write out the big formula, then simplify it if possible.
// Apply the bits, shift several bit locations at once, run faster.
//
// But what are the formulas? Good question. Use a computer to figure
// this out for you. And WIlliams wrote a program!
//
// NOTE: The idea is simple, so I may include one here too.
//
//===========================================================================
 
`timescale 1ns/1ps
 
// The LSB corresponds to bit 0, the new input bit.
`define CRC_32 32'b0000_0100_1100_0001_0001_1101_1011_0111
 
// Given a 32-bit CRC-32 running value, update it using 8 new bits of data.
// The way to make this fast is to find common sub-expressions.
//
79,14 → 132,284
// The user needs to supply external flops to make this work.
 
module crc32_8_comb (
present_crc32,
present_crc_32,
data_in_8,
next_crc32
next_crc_32
);
 
input [31:0] present_crc32;
input [31:0] present_crc_32;
input [7:0] data_in_8;
output [31:0] next_crc32;
output [31:0] next_crc_32;
 
endmodule
 
module crc32_16_comb (
present_crc_32,
data_in_8,
next_crc_32
);
 
input [31:0] present_crc_32;
input [15:0] data_in_8;
output [31:0] next_crc_32;
 
endmodule
 
module crc32_32_comb (
present_crc_32,
data_in_8,
next_crc_32
);
 
input [31:0] present_crc_32;
input [31:0] data_in_8;
output [31:0] next_crc_32;
 
endmodule
 
module crc32_64_comb (
present_crc_32,
data_in_8,
next_crc_32
);
 
input [31:0] present_crc_32;
input [63:0] data_in_8;
output [31:0] next_crc_32;
 
endmodule
 
 
// Try to make a program which will generate formulas for how to do CRC-32
// several bits at a time.
// The idea is to get a single-bit implementation which works. (!)
// Then apply an initial value for state and an input data stream.
// The initial value will have a single bit set, and the data stream
// will have a single 1-bit followed by 0 bits.
// Grind the state machine forward the desired number of bits N, and
// look at the stored state. Each place in the shift register where
// there is a 1'b1, that is a bit which is sensitive to the input
// or state bit in a parallel implementation N bits wide.
//
// remember CRC_32 = 32'b0000_0100_1100_0001_0001_1101_1011_0111
 
`define CALCULATE_FUNCTIONAL_DEPENDENCE_ON_INPUT_AND_STATE
`ifdef CALCULATE_FUNCTIONAL_DEPENDENCE_ON_INPUT_AND_STATE
module print_out_formulas ();
 
parameter NUM_BITS_TO_DO_IN_PARALLEL = 8'h10;
 
reg [31:0] running_state;
reg [31:0] input_vector;
reg xor_value;
integer i, j;
 
reg [1023:0] corner_turner; // use to read out formulas for each bit
 
initial
begin
$display ("Calculating functional dependence on input bits. Rightmost bit is State Bit 0.");
for (i = 0; i < NUM_BITS_TO_DO_IN_PARALLEL; i = i + 1)
begin
running_state = 32'h00000000;
input_vector = 32'h80000000; // MSB first for this program
for (j = 0; j < i + 1; j = j + 1)
begin
xor_value = input_vector[31] ^ running_state[31];
running_state[31:0] = xor_value
? {running_state[30:0], 1'b0} ^ `CRC_32
: {running_state[30:0], 1'b0};
input_vector[31:0] = {input_vector[30:0], 1'b0};
end
$display ("input bit number (bigger is earlier) %d, dependence %b",
i, running_state[31:0]);
// First entry, which gets shifted the most in corner_turner, is the last bit loaded
corner_turner[1023:0] = {corner_turner[1023 - 32 : 0], running_state[31:0]};
end
 
// try to read out formulas by sweeping a 1-bit through the corner_turner array.
for (i = 0; i < 32; i = i + 1) // each state bit depends on:
begin
$display ("State Variable %d depends on input bit number (bigger is earlier) :", i);
for (j = 0; j < NUM_BITS_TO_DO_IN_PARALLEL; j = j + 1)
begin
if (corner_turner[(NUM_BITS_TO_DO_IN_PARALLEL - j - 1) * 32 + i] != 1'b0)
$display ("%d", j);
end
end
$display ("State bits all just shift towards the MSB by the number of bits acted on each clock.");
end
endmodule
`endif // CALCULATE_FUNCTIONAL_DEPENDENCE_ON_INPUT_AND_STATE
 
// `define SERIAL_VERSION_FOR_DEBUG
`ifdef SERIAL_VERSION_FOR_DEBUG
// a slow one to make sure I did things right.
module crc_32_1_bit_at_a_time (
present_crc_32,
data_in,
next_crc_32
);
 
input [31:0] present_crc_32;
input data_in;
output [31:0] next_crc_32;
 
wire xor_value = data_in ^ present_crc_32[31];
 
assign next_crc_32[31:0] = xor_value
? {present_crc_32[30:0], 1'b0} ^ `CRC_32
: {present_crc_32[30:0], 1'b0};
endmodule
 
module test_crc_1 ();
 
integer i, j;
reg [31:0] present_crc_32;
wire [31:0] next_crc_32;
reg [7:0] data_in;
 
initial
begin
#10;
$display ("running serial version of code");
present_crc_32[31:0] = 32'hFFFFFFFF;
data_in = 1'b0;
for (i = 0; i < 43; i = i + 1)
begin
data_in[7:0] = 8'h00;
for (j = 0; j < 8; j = j + 1)
begin
#0 ;
present_crc_32[31:0] = next_crc_32[31:0];
data_in[7:0] = {data_in[6:0], 1'b0};
end
end
data_in[7:0] = 8'h28;
for (j = 0; j < 8; j = j + 1)
begin
#0 ;
present_crc_32[31:0] = next_crc_32[31:0];
data_in[7:0] = {data_in[6:0], 1'b0};
end
$display ("after 40 bytes of 1'b0, I want 32'h864D7F99, I get 32\`h%x", ~present_crc_32[31:0]);
 
present_crc_32[31:0] = 32'hFFFFFFFF;
data_in = 1'b0;
for (i = 0; i < 40; i = i + 1)
begin
data_in[7:0] = 8'hFF;
for (j = 0; j < 8; j = j + 1)
begin
#0 ;
present_crc_32[31:0] = next_crc_32[31:0];
data_in[7:0] = {data_in[6:0], 1'b0};
end
end
for (i = 0; i < 3; i = i + 1)
begin
data_in[7:0] = 8'h00;
for (j = 0; j < 8; j = j + 1)
begin
#0 ;
present_crc_32[31:0] = next_crc_32[31:0];
data_in[7:0] = {data_in[6:0], 1'b0};
end
end
data_in[7:0] = 8'h28;
for (j = 0; j < 8; j = j + 1)
begin
#0 ;
present_crc_32[31:0] = next_crc_32[31:0];
data_in[7:0] = {data_in[6:0], 1'b0};
end
$display ("after 40 bytes of 1'b1, I want 32'hC55E457A, I get 32\`h%x", ~present_crc_32[31:0]);
 
present_crc_32[31:0] = 32'hFFFFFFFF;
data_in = 1'b0;
for (i = 0; i < 40; i = i + 1)
begin
data_in[7:0] = i + 1;
for (j = 0; j < 8; j = j + 1)
begin
#0 ;
present_crc_32[31:0] = next_crc_32[31:0];
data_in[7:0] = {data_in[6:0], 1'b0};
end
end
for (i = 0; i < 3; i = i + 1)
begin
data_in[7:0] = 8'h00;
for (j = 0; j < 8; j = j + 1)
begin
#0 ;
present_crc_32[31:0] = next_crc_32[31:0];
data_in[7:0] = {data_in[6:0], 1'b0};
end
end
data_in[7:0] = 8'h28;
for (j = 0; j < 8; j = j + 1)
begin
#0 ;
present_crc_32[31:0] = next_crc_32[31:0];
data_in[7:0] = {data_in[6:0], 1'b0};
end
$display ("after 40 bytes of 1'b1, I want 32'hBF671ED0, I get 32\`h%x", ~present_crc_32[31:0]);
end
 
crc_32_1_bit_at_a_time test_1_bit (
.present_crc_32 (present_crc_32[31:0]),
.data_in (data_in[7]),
.next_crc_32 (next_crc_32[31:0])
);
 
// Angie Tso's CRC-32 Test Cases
// tsoa@ttc.com
// Angie Tso
// Telecommunications Techniques Corp. E-mail: tsoa@ttc.com
// 20400 Observation Drive, Voice : 301-353-1550 ext.4061
// Germantown, MD 20876-4023 Fax : 301-353-1536 Mail Stop O
//
// Angie posted the following on the cell-relay list Mon, 24 Oct 1994 18:33:11 GMT=20
// --------------------------------------------------------------------------------
//
// Here are the examples of valid AAL-5 CS-PDU in I.363:
// (There are three examples in I.363)
//
// 40 Octets filled with "0"
// CPCS-UU = 0, CPI = 0, Length = 40, CRC-32 = 864d7f99
// char pkt_data[48]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x00,0x00,0x00,0x28,0x86,0x4d,0x7f,0x99};
//
// 40 Octets filled with "1"
// CPCS-UU = 0, CPI = 0, Length = 40, CRC-32 = c55e457a
// char pkt_data[48]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
// 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
// 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
// 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
// 0x00,0x00,0x00,0x28,0xc5,0x5e,0x45,0x7a};
//
// 40 Octets counting: 1 to 40
// CPCS-UU = 0, CPI = 0, Length = 40, CRC-32 = bf671ed0
// char pkt_data[48]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,
// 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
// 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,
// 0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
// 0x00,0x00,0x00,0x28,0xbf,0x67,0x1e,0xd0};
//
// Here is one out of my calculation for your reference:
//
// 40 Octets counting: 1 to 40
// CPCS-UU = 11, CPI = 22, CRC-32 = acba602a
// char pkt_data[48]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,
// 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
// 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,
// 0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
// 0x11,0x22,0x00,0x28,0xac,0xba,0x60,0x2a};
 
endmodule
`endif // SERIAL_VERSION_FOR_DEBUG
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.