`timescale 1ns /10ps

module prbs_31_10bit (
    Reset_n           ,
    Clock             ,
    Enable            ,
    D_In              ,
    Lock              ,
    Err_Inj           ,
    D_Out             ,
    Error             ,
    ErrorCnt          ,
    ClearErrorCnt          
);


parameter BusWidth =10;    //-- enter "Bus Width" here
parameter OrderOfPolynomial =31; //-- enter "Order of Polynomial" here

parameter Width_i =(BusWidth > OrderOfPolynomial)?  BusWidth : OrderOfPolynomial;


input Reset_n;
input Clock;
input Enable;
input Lock;
input Err_Inj;
input ClearErrorCnt;

//DATA IN 
input [BusWidth-1:0]  D_In;

//DATA OUT 
output [BusWidth-1:0]  D_Out;



//Error 
output [7:0]  ErrorCnt;

//Error 
output  Error;


reg [BusWidth-1:0] Reg1; 
reg [Width_i-1:0] Reg2; 
reg [BusWidth-1:0] Reg3; 
wire [Width_i:1] X; 
reg [Width_i:1] Y; 
//wire [Width_i:1] Y ; 
reg [Width_i:1] Z; 
//wire [Width_i:1] Z ; 

reg [0:2] Err_Inj2;
reg Reg_Err;
reg Reg_Err2;

reg [7:0] RegErrorCnt; 


assign X=Reg2;


always @(X)
	begin
//	Y <=0;
   if(OrderOfPolynomial > BusWidth)
         Y[Width_i :(BusWidth + 1)] <= X[(Width_i - BusWidth) : 1];
//-------------------------------------- add code from "PRBS_Calculator.xls" here...

  Y[10] <= X[31] ^ X[28] ^ 1 ;
  Y[9] <= X[30] ^ X[27] ^ 1 ;
  Y[8] <= X[29] ^ X[26] ^ 1 ;
  Y[7] <= X[28] ^ X[25] ^ 1 ;
  Y[6] <= X[27] ^ X[24] ^ 1 ;
  Y[5] <= X[26] ^ X[23] ^ 1 ;
  Y[4] <= X[25] ^ X[22] ^ 1 ;
  Y[3] <= X[24] ^ X[21] ^ 1 ;
  Y[2] <= X[23] ^ X[20] ^ 1 ;
  Y[1] <= X[22] ^ X[19] ^ 1 ;




//-------------------------------------- end code from "PRBS_Calculator.xls"

	end	



		
always @ (Lock or Reg1 or Y or X)
	begin
//	Z <=0;
   if(OrderOfPolynomial > BusWidth)
         Z[Width_i :(BusWidth + 1)] <= X[(Width_i - BusWidth) : 1];
	if (Lock==1'b0)	
  		Z[BusWidth : 1] <= Reg1 ;
  	else 
  		Z[BusWidth : 1] <= Y[BusWidth : 1];
	end


//assign Z[BusWidth : 1] = (Lock==1'b0)?  Reg1 : Y[BusWidth : 1] ;



always @(posedge Clock or negedge Reset_n)
	if (~Reset_n)
		begin	
		Reg1 <=0;
		Reg2 <=0;
		Reg3 <=0;
		Err_Inj2 <=0;
		Reg_Err <=0;
		end
	else
		begin
		if (Enable==1'b1)
			begin
			Reg2 <= #1 Z;
			Reg1 <= #1 D_In;
			Reg3 <= #1 Y[BusWidth:1];
			Err_Inj2 <= # 1 {Err_Inj,Err_Inj2[0],Err_Inj2[0] & ~Err_Inj2[1]};
      			if (Reg2[(BusWidth - 1) : 0] == Reg3) 
        			Reg_Err <= #1  0;
        		else	
        			Reg_Err <= #1  1;
      			end	
			
		end
		
always @(posedge Clock or negedge Reset_n)
	if (~Reset_n)
		begin	
		Reg_Err2 <=0;
		RegErrorCnt <=0;
		end
	else
		begin	
		if (Enable==1'b1)
      			Reg_Err2 <= #1 Reg_Err;
      		else	
      			Reg_Err2 <= #1  0;
					
    		if (ClearErrorCnt ) 
      			RegErrorCnt <= #1 0;
      		else
      			if ( (Reg_Err2) && (RegErrorCnt < 8'hFF) ) 
      				RegErrorCnt <= #1 (RegErrorCnt + 1 );
		end


assign   D_Out = {Reg2[(BusWidth - 1) : 1] , (Reg2[0] ^ Err_Inj2[2])};
assign   Error = Reg_Err2;
assign   ErrorCnt = RegErrorCnt;


endmodule
