mirror of
https://github.com/marqs85/ossc.git
synced 2024-11-15 09:05:19 +00:00
315 lines
12 KiB
Verilog
315 lines
12 KiB
Verilog
/*
|
|
Legal Notice: (C)2006 Altera Corporation. All rights reserved. Your
|
|
use of Altera Corporation's design tools, logic functions and other
|
|
software and tools, and its AMPP partner logic functions, and any
|
|
output files any of the foregoing (including device programming or
|
|
simulation files), and any associated documentation or information are
|
|
expressly subject to the terms and conditions of the Altera Program
|
|
License Subscription Agreement or other applicable license agreement,
|
|
including, without limitation, that your use is for the sole purpose
|
|
of programming logic devices manufactured by Altera and sold by Altera
|
|
or its authorized distributors. Please refer to the applicable
|
|
agreement for further details.
|
|
*/
|
|
|
|
/*
|
|
This component supports 8, 16, 24, and 32 bit little endian data
|
|
and any CRC standard between 1 to 128 bits. Through parameterization
|
|
you can change the CRC standard which will take effect after you
|
|
regenerate your system in SOPC Builder.
|
|
|
|
Register Map:
|
|
000 -> reset the CRC peripheral to the inital value (data and byte enables ignored)
|
|
001 -> data write between 1-32 bits
|
|
010 -> reserved
|
|
011 -> reserved
|
|
100 -> read bits 1-32 of the crc result
|
|
101 -> read bits 33-64 of the crc result (where applicable)
|
|
110 -> read bits 65-96 of the crc result (where applicable)
|
|
111 -> read bits 97-128 of the crc result (where applicable)
|
|
|
|
Write latency = 0
|
|
Read latency = 1
|
|
|
|
Note: This component uses four blocks of eight bits of data in cascade.
|
|
To improve the timing of logic you can create seperate cascades
|
|
for 8, 16, 24, and 32 bit data which will allow for smaller area
|
|
and a shorter combinational depth. Since CRC logic consumes power
|
|
even when not in use you can also add a logic disable feature using
|
|
the chipselect signal. Even though the registered CRC value is
|
|
held constant when the circuit is not in use the input data will
|
|
change during this time and cause the CRC cascade logic to react.
|
|
*/
|
|
|
|
|
|
module CRC_Component (clk,
|
|
reset,
|
|
address,
|
|
writedata,
|
|
byteenable,
|
|
write,
|
|
read,
|
|
chipselect,
|
|
readdata);
|
|
|
|
/*
|
|
Using these parameters you can create any CRC ranging from one bit (parity checker)
|
|
up to 128 bits. The following list describes the function of each parameter:
|
|
|
|
crc_width:
|
|
The width of the registered CRC result, this value is typically apart of
|
|
the name of the standard (CRC32 is 32 bits wide). Adjusting this value
|
|
will impact the logic resource usage.
|
|
|
|
polynomial_initial:
|
|
The initial value set for the CRC result register. By writing any data to address 0
|
|
this value will be stored in the result register thereby clearing any previously existing
|
|
value. This value must be the same width as 'crc_width'
|
|
|
|
polynomial:
|
|
This is the divisor value used on the input data. Typically shown in polynomial format
|
|
the value symbolizes the placement of xor operation on the input data. In synthesis, the
|
|
polynomial bits that are '1' will create a not gate, whereas the bits that are '0' will
|
|
simply create a wire. Even with 32 stages of these operations cascaded, the simple logic
|
|
will not become a significant factor on logic utilization or fmax. This value must be the
|
|
same width as 'crc_width'
|
|
|
|
reflected_input:
|
|
Some CRC standards require that all the input bits be reflected around the center point.
|
|
This option is enabled with '1' and disabled with '0'. Typically this option is enabled
|
|
or disabled with 'reflected_output'.
|
|
|
|
reflected_output:
|
|
Some CRC standards require that all the output bits be reflected around the center point.
|
|
This operation occurs before the final optional xor output step. This option is enabled
|
|
with '1' and disabled with '0'. Typically this option is enabled or disabled with
|
|
'reflected_input' (to undo the input reversal typically).
|
|
|
|
xor_output:
|
|
This is the value used to bitwise xor the CRC result. Most standards use either all zeros
|
|
or all ones for this value. When zeros are used the CRC result is passed directly and when
|
|
ones are used the CRC result is inverted. Since it's no mandatory that this value be all
|
|
ones or zeros, this operation occurs before the output reflection when applicable.
|
|
*/
|
|
|
|
parameter crc_width = 32;
|
|
parameter polynomial_inital = 32'hFFFFFFFF;
|
|
parameter polynomial = 32'h04C11DB7;
|
|
parameter reflected_input = 1;
|
|
parameter reflected_output = 1;
|
|
parameter xor_output = 32'hFFFFFFFF;
|
|
|
|
|
|
input clk;
|
|
input reset;
|
|
input [2:0] address;
|
|
input [31:0] writedata;
|
|
input [3:0] byteenable;
|
|
input write;
|
|
input read;
|
|
input chipselect;
|
|
output [31:0] readdata;
|
|
|
|
reg [crc_width-1:0] crc_value;
|
|
wire [crc_width-1:0] poly = polynomial;
|
|
wire [crc_width-1:0] cascade [3:0];
|
|
wire [7:0] block0_data, block1_data, block2_data, block3_data;
|
|
wire [crc_width-1:0] result, result_xored;
|
|
wire [31:0] mux_result;
|
|
reg [31:0] readdata;
|
|
|
|
|
|
/*
|
|
Some standards like CRC16 and CRC32 require this bitreversal for serial
|
|
devices like ethernet, uarts, usb, etc...
|
|
*/
|
|
genvar index;
|
|
generate if (reflected_input == 1)
|
|
begin
|
|
for(index = 0; index < 8; index = index + 1)
|
|
begin: input_reflection
|
|
assign block0_data[index] = writedata[7-index];
|
|
assign block1_data[index] = writedata[15-index];
|
|
assign block2_data[index] = writedata[23-index];
|
|
assign block3_data[index] = writedata[31-index];
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
assign block0_data = writedata[7:0];
|
|
assign block1_data = writedata[15:8];
|
|
assign block2_data = writedata[23:16];
|
|
assign block3_data = writedata[31:24];
|
|
end
|
|
endgenerate
|
|
|
|
|
|
/*
|
|
Control for the registered events. It assumes that either 8, 16, 24, or 32
|
|
bit data is being written using byte enables. It is important that the data
|
|
be in little endian format and no gaps of byte enables be present (like
|
|
1011 or 1101 for example)
|
|
*/
|
|
always @ (posedge clk or posedge reset)
|
|
begin
|
|
if(reset == 1)
|
|
begin
|
|
crc_value <= 0;
|
|
end
|
|
else
|
|
begin
|
|
if(write && chipselect && (address == 3'b000))
|
|
begin
|
|
crc_value <= polynomial_inital; // reset the crc to the initial value
|
|
end
|
|
else if(write && chipselect && (address == 3'b001))
|
|
begin
|
|
if(byteenable == 4'b0001) // 8 bit data input
|
|
begin
|
|
crc_value <= cascade[0];
|
|
end
|
|
else if(byteenable == 4'b0011) // 16 bit data input
|
|
begin
|
|
crc_value <= cascade[1];
|
|
end
|
|
else if(byteenable == 4'b0111) // 24 bit data input
|
|
begin
|
|
crc_value <= cascade[2];
|
|
end
|
|
else if(byteenable == 4'b1111) // 32 bit data input
|
|
begin
|
|
crc_value <= cascade[3];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
/* four stages of cascade blocks (each block is crc_width x 8 bits) */
|
|
XOR_Shift_Block cascade_block0(.block_input(crc_value), .poly(poly), .data_input(block0_data), .block_output(cascade[0]));
|
|
defparam cascade_block0.crc_width = crc_width;
|
|
XOR_Shift_Block cascade_block1(.block_input(cascade[0]), .poly(poly), .data_input(block1_data), .block_output(cascade[1]));
|
|
defparam cascade_block1.crc_width = crc_width;
|
|
XOR_Shift_Block cascade_block2(.block_input(cascade[1]), .poly(poly), .data_input(block2_data), .block_output(cascade[2]));
|
|
defparam cascade_block2.crc_width = crc_width;
|
|
XOR_Shift_Block cascade_block3(.block_input(cascade[2]), .poly(poly), .data_input(block3_data), .block_output(cascade[3]));
|
|
defparam cascade_block3.crc_width = crc_width;
|
|
|
|
|
|
|
|
/*
|
|
Some standards like CRC16 and CRC32 require this bitreversal.
|
|
This is to better support serial devices like uarts, ethernet, usb, etc...)
|
|
*/
|
|
generate if (reflected_output == 1)
|
|
begin
|
|
for(index = 0; index < crc_width; index = index + 1)
|
|
begin: output_reflection32
|
|
assign result[index] = crc_value[(crc_width-1)-index];
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
assign result = crc_value;
|
|
end
|
|
endgenerate
|
|
|
|
|
|
/* This final xor operation occurs after the bit swap */
|
|
assign result_xored = result ^ xor_output;
|
|
|
|
|
|
/* Generates the appropriate MUX logic depending on the CRC width */
|
|
generate if((crc_width > 32) && (crc_width < 65))
|
|
begin
|
|
assign mux_result = (address == 3'b100)? result_xored[31:0] : result_xored[crc_width-1:32];
|
|
end
|
|
else if((crc_width > 64) && (crc_width < 97))
|
|
begin
|
|
assign mux_result = (address == 3'b100)? result_xored[31:0] :
|
|
((address == 3'b101)? result_xored[63:32] : result_xored[crc_width-1:64]);
|
|
end
|
|
else if((crc_width > 96) && (crc_width < 129))
|
|
begin
|
|
assign mux_result = (address == 3'b100)? result_xored[31:0] :
|
|
((address == 3'b101)? result_xored[63:32] :
|
|
((address == 3'b110)? result_xored[95:64] : result_xored[crc_width-1:96]));
|
|
end
|
|
else
|
|
begin
|
|
assign mux_result = result_xored;
|
|
end
|
|
endgenerate
|
|
|
|
|
|
/* Registering the return path of the CRC data (32 bits of it) */
|
|
always @ (posedge clk or posedge reset)
|
|
begin
|
|
if(reset == 1)
|
|
begin
|
|
readdata <= 0;
|
|
end
|
|
else if((read == 1) && (chipselect == 1))
|
|
begin
|
|
readdata <= mux_result;
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
/* a single cascade block of width: crc_width and a length of eight input bits */
|
|
module XOR_Shift_Block(block_input,
|
|
poly,
|
|
data_input,
|
|
block_output);
|
|
parameter crc_width = 32;
|
|
|
|
input [(crc_width-1):0] block_input;
|
|
input [(crc_width-1):0] poly;
|
|
input [7:0] data_input;
|
|
output [(crc_width-1):0] block_output;
|
|
|
|
wire [(crc_width-1):0] cascade [7:0];
|
|
|
|
XOR_Shift bit_0(.stage_input(block_input), .poly(poly), .new_bit(data_input[7]), .stage_output(cascade[0]));
|
|
defparam bit_0.crc_width = crc_width;
|
|
XOR_Shift bit_1(.stage_input(cascade[0]), .poly(poly), .new_bit(data_input[6]), .stage_output(cascade[1]));
|
|
defparam bit_1.crc_width = crc_width;
|
|
XOR_Shift bit_2(.stage_input(cascade[1]), .poly(poly), .new_bit(data_input[5]), .stage_output(cascade[2]));
|
|
defparam bit_2.crc_width = crc_width;
|
|
XOR_Shift bit_3(.stage_input(cascade[2]), .poly(poly), .new_bit(data_input[4]), .stage_output(cascade[3]));
|
|
defparam bit_3.crc_width = crc_width;
|
|
XOR_Shift bit_4(.stage_input(cascade[3]), .poly(poly), .new_bit(data_input[3]), .stage_output(cascade[4]));
|
|
defparam bit_4.crc_width = crc_width;
|
|
XOR_Shift bit_5(.stage_input(cascade[4]), .poly(poly), .new_bit(data_input[2]), .stage_output(cascade[5]));
|
|
defparam bit_5.crc_width = crc_width;
|
|
XOR_Shift bit_6(.stage_input(cascade[5]), .poly(poly), .new_bit(data_input[1]), .stage_output(cascade[6]));
|
|
defparam bit_6.crc_width = crc_width;
|
|
XOR_Shift bit_7(.stage_input(cascade[6]), .poly(poly), .new_bit(data_input[0]), .stage_output(cascade[7]));
|
|
defparam bit_7.crc_width = crc_width;
|
|
|
|
assign block_output = cascade[7];
|
|
|
|
endmodule
|
|
|
|
|
|
/* performs the 'new_bit' stuffing, shifting, and XOR operations for a single input bit */
|
|
module XOR_Shift (stage_input,
|
|
poly,
|
|
new_bit,
|
|
stage_output);
|
|
|
|
parameter crc_width = 32;
|
|
|
|
input [crc_width-1:0] stage_input;
|
|
input [crc_width-1:0] poly;
|
|
input new_bit;
|
|
output [crc_width-1:0] stage_output;
|
|
|
|
assign stage_output[0] = new_bit ^ stage_input[crc_width-1];
|
|
assign stage_output[crc_width-1:1] = stage_input[crc_width-2:0] ^ ({crc_width-1{stage_output[0]}} & poly[crc_width-1:1]);
|
|
|
|
endmodule
|