module ILL_UNDEF (OPREG, ANZ_VAL, USER, CFG, ILL, UNDEF );

	input	[23:0]	OPREG;
	input	 [2:0]	ANZ_VAL;
	input	 [3:1]	CFG;		// 3=CUSTOM,2=MMU,1=FPU
	input			USER;
	
	output	reg		ILL;
	output			UNDEF;

	reg				undef_opc;
	reg				undef_am;
	reg				undef_im;
	
	wire	 [2:0]	valid;
	wire			gen12,gen22,gen13,gen23;
	wire			igen12,igen22,igen13,igen23;
	wire			lsbes;
	
	parameter udef_amode = 5'b10011;	// Undefined Addressing Mode
	parameter imode		 = 5'b10100;	// Immediate Addressing Mode 
	
	// [2]= minimum 3, [1]= minimum 2, [0]=minimum 1
	assign valid = {(ANZ_VAL[2] | (ANZ_VAL[1:0] == 2'b11)),(ANZ_VAL[2:1] != 2'b00),(ANZ_VAL != 3'b000)};
	assign lsbes = (OPREG[1:0] == 2'b10);	// Tag of all 3 Byte opcodes
	
	// +++++++++++++++++++++++++  Detect illegale opcodes  +++++++++++++++++++
	
	always @(OPREG or lsbes or valid or USER)
		casex ({valid[2:1],OPREG[13:2],lsbes})
		  15'bx1_xx_x000_1x10_11_0 : ILL = USER;	// SPRi/LPRi DCR
		  15'bx1_xx_x001_xx10_11_0 : ILL = USER;	// SPRi/LPRi BPC/DSR
		  15'bx1_xx_xx10_xx10_11_0 : ILL = USER;	// SPRi/LPRi CAR/CFG/PSR
		  15'bx1_xx_x101_1x10_11_0 : ILL = USER;	// SPRi/LPRi USP
		  15'bx1_xx_x111_0x10_11_0 : ILL = USER;	// SPRi/LPRi INTBASE
		  15'bx1_xx_x0x1_0111_11_x : ILL = USER & OPREG[0];	// BICPSRW,BISPSRW
		  15'bx1_00_10xx_0000_11_1 : ILL = USER;	// SETCFG - Achtung : is coded as 2 Byte Opcode 
		  15'b1x_00_xxxx_0001_11_1 : ILL = USER;	// LMR/SMR/RDVAL/WRVAL
		  15'b1x_10_01xx_0001_11_1 : ILL = USER;	// CINV
		  default				   : ILL = 1'b0;
		endcase

	// ++++++++++++++++++++++++ Detect Undefined opcodes  +++++++++++++++
	
	always @(OPREG or lsbes or valid or CFG)
		casex ({valid,OPREG[13:2],lsbes})
		  16'bx1x_xx_xxxx_1111_110 : undef_opc = 1'b1;		// Format 3 : xxx1
		  16'bx1x_xx_x100_0111_110 : undef_opc = 1'b1;		// Format 3 : 1000
		  16'b1xx_1x_xxxx_0000_111 : undef_opc = 1'b1;		// Format 5 : 1xxx
		  16'b1xx_01_xxxx_0000_111 : undef_opc = 1'b1;		// Format 5 : 01xx
		  16'b1xx_01_00xx_0100_111 : undef_opc = 1'b1;		// Format 6 : 0100
		  16'b1xx_10_10xx_x100_111 : undef_opc = 1'b1;		// Format 6/7 : 1010
		  16'b1xx_xx_xxxx_x011_111 : undef_opc = ~CFG[1];	// Format 9/11 : FPU Befehle wie MOVif etc. und ADDf etc.
		  16'b1xx_xx_xxxx_1111_111 : undef_opc = ~CFG[1];	// Format 12 : FPU Befehle wie POLYf etc.
		  16'b1xx_x1_xxxx_0001_111 : undef_opc = 1'b1;		// Format 14 : x1xx 
		  16'b1xx_10_00xx_0001_111 : undef_opc = 1'b1;		// Format 14 : 1000
		  16'b1xx_10_1xxx_0001_111 : undef_opc = 1'b1;		// Format 14 : 101x
		  16'b1xx_00_1xxx_0001_111 : undef_opc = ~CFG[2] | ~OPREG[18];	// Format 14 : LMR/SMR
		  16'b1xx_xx_xxxx_x011_011 : undef_opc = ~CFG[3];	// Format 15.1/15.5 : CUSTOM CCV0, CCAL0 etc.
		  16'b1xx_xx_xxxx_0001_011 : undef_opc = 1'b1;		// Format 15.0 - not yet in, requires HW change
		  16'b1xx_xx_xxxx_x1x1_011 : undef_opc = 1'b1;		// Format 15 : rest
		  16'b1xx_xx_xxxx_1001_011 : undef_opc = 1'b1;		// Format 15.4
		// completely undefined :
		  16'bxx1_xx_xxxx_0111_111 : undef_opc = 1'b1;		// Format 10
		  16'bxx1_xx_xxxx_100x_111 : undef_opc = 1'b1;		// Format 13/18
		  16'bxx1_xx_xxxx_x101_111 : undef_opc = 1'b1;		// Format 16/17
		  16'bxx1_xx_xxxx_xxx0_011 : undef_opc = 1'b1;		// Format 19
		  default				   : undef_opc = 1'b0;
		endcase

	// 2. Undefined Addressing mode 5'b10011
	
	assign gen12 = (OPREG[15:11] == udef_amode);
	assign gen22 = (OPREG[10:6]  == udef_amode);
	assign gen13 = (OPREG[23:19] == udef_amode);
	assign gen23 = (OPREG[18:14] == udef_amode);
	
	always @(OPREG or valid or gen12 or gen22 or gen13 or gen23)
		if (valid[2] && (OPREG[7:5] != 3'b000) && (OPREG[3:0] == 4'b1110)) undef_am = gen13 | gen23;	// nearly all 3 Byte opcodes
		  else
		    undef_am = valid[1] & gen12 & (OPREG[1:0] != 2'b10) & ((OPREG[3:2] != 2'b11) & gen22);	// all 2 Byte opcodes
		
	// 3. When is Immediate not allowed ?
	
	assign igen12 = (OPREG[15:11] == imode);
	assign igen22 = (OPREG[10:6]  == imode);
	assign igen13 = (OPREG[23:19] == imode);
	assign igen23 = (OPREG[18:14] == imode);
	
	always @(*)
		casex ({valid[2:1],OPREG[13:2],lsbes})
		  15'bx1_xxxxxx_x0xx11_0 : undef_im =  igen12 & (OPREG[5:4] != 2'b01);	// Format 2 : ADDQD,SPR,Scond
		  15'bx1_xxxxxx_x10111_0 : undef_im =  igen12;		// Format 2 : ACB,MOVQ
		  15'bx1_xxxxx0_011111_0 : undef_im =  igen12;		// Format 3 : CXPD,JUMP,JSR
		  15'bx1_xxxxxx_xxxxx0_0 : undef_im =  igen22;		// Format 4
		  15'bx1_xxxxxx_xxxx01_0 : undef_im = (igen12 & (OPREG[5:4] == 2'b10))	// Format 4 : SRC1 - not ADDR
											 |(igen22 & (OPREG[5:4] != 2'b00)); // Format 4 : SRC2 - CMP
		  15'b1x_xxxxxx_x10011_1 : undef_im =  igen23;		// Format 6+7
		  15'b1x_xxx0xx_0x1011_1 : undef_im =  igen13 | igen23;	// Format 8 EXT,CVTP
		  15'b1x_xxx0xx_101011_1 : undef_im =  igen23;		// Format 8 : INS
		  15'b1x_xxx0xx_111011_1 : undef_im =  igen13;		// Format 8 : CHECK
		  15'b1x_xxx1xx_101011_1 : undef_im =  igen13 | igen23;	// Format 8 MOVUS,MOVSU
		  15'b1x_xxx1xx_011011_1 : undef_im =  igen23;		// Format 8 : FFS
		  15'b1x_xxxxxx_001111_1 : undef_im =  igen23;		// Format 9
		  15'b1x_xxxxxx_101111_1 : undef_im =  igen23 & (OPREG[13:10] != 4'h2);	// Format 10 without CMPf
		  15'b1x_010xxx_111111_1 : undef_im =  igen23;		// Format 12 SCALB+LOGB
		  15'b1x_000xxx_000111_1 : undef_im =  igen13;		// Format 14 RDVAL+WRVAL
		  15'b1x_0011xx_000111_1 : undef_im =  igen13;		// Format 14 SMR
		  default				 : undef_im = 1'b0;
		endcase
		
	// Final Message :
	
	assign UNDEF = undef_opc | undef_am | undef_im;
	
endmodule