mirror of
				https://github.com/marqs85/ossc
				synced 2025-10-26 13:36:02 +03: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
 | 
