mirror of
				https://github.com/marqs85/ossc
				synced 2025-11-04 01:46: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
 |