`include	"defines.v"
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* ----------------------------------------------------------------------------------------
// complementary implementation module for IOT processor instructions
// ----------------------------------------------------------------------------------------
   these are special instructions implemented with opcode 6, i.e., "like" IOT instructions
   for periherals, but rather "anomalous" - here are implemented in a mixed way, mostly with
   IOPs and partly with micro-instructions (GTF, CAF and RTF)

      6000 SKON   Skip if Interrupt System On. The state of the interrupt enable flip-flop is tested. If this flip-flop is set,
                  indicating that the interrupt system is enabled, the PC is incremented to skip the next sequential instruction
                  and the interrupt system is turned off in the same manner as by an IOF instruction.
      6001 ION    Interrupt Turn On.
      6002 IOF    Interrupt Turn Off.
      6003 SRQ    Skip on Interrupt Request. If the interrupt request is asserted, indicating that one or more devices are
                  requesting a program interrupt, the PC is incremented to skip the next sequential instruction.
      6004 GTF    Get Flags.
      6005 RTF    Restore Flags.
      6006 SGT    Skip if Greater Than. If the Greater Than Flag is set, the PC is incremented to skip the next sequential instruction.
						The GT flag is used only by the AEmodule, so this instruction is NOP
      6007 CAF    Clear All Flags. AC and Link are cleared. Clears all I/O device flags and motion control flip-flops, and sets the
                  interrupt enable flip-flop in each peripheral device. */
module IOT_proc (clk, reset, iop_in, rtf_apply, cpu_global_int_enable, ION_req, ION_go, async_IOF, IR_in, sys_clear, sys_IRQ, IOSKP_out);

   // "bus" signals
	input clk;
	input reset;
	input [11:0] IR_in;		   // current IR
	input [2:0] iop_in;
	input rtf_apply;
	output IOSKP_out;			   // request the processor to skip next instruction			(in IOP1)
   //	output ORAC_out;			// request the processor to OR db_out to the accumulator (in IOP2)
   //	output ACCLR_out;			// request the processor to clear the accumulator			(in IOP4)

   // interrupt signals
	output   cpu_global_int_enable;   // global interrupt enable line
	input    sys_IRQ;          // an interrup request is pending?
	output   ION_req;          // ION instruction does not immediately set cpu_global_int_enable
	input    ION_go;           // the ION_req has been confirmed? If so, proceed to set cpu_global_int_enable
	input    async_IOF;        // interrupts can be directly disabled by using this "async IOF"
                              // used in the beginning of an interrupt service routine

   // other interface signals
	output   sys_clear;        // global line to issue clear all flags

	// decode the three IOP cycles
	wire IOP_1;					   // IOSKP  cycle
	wire IOP_2;					   // ACCLRC cycle
	wire IOP_4;					   // ORAC 	 cycle

	assign IOP_1 = iop_in[0];  // IOSKP cycle
	assign IOP_2 = iop_in[1];  // ACCLRC cycle
	assign IOP_4 = iop_in[2];  // ORAC cycle

	// IOT processor instructions
	wire do_SKON;	// 6000
	wire do_SKON2;	// 6000
	wire do_ION;	// 6001
	wire do_IOF;	// 6002
	wire do_SRQ;	// 6003
	wire do_GTF;	// 6004
	wire do_RTF;	// 6005
	wire do_SGT;	// 6006
	wire do_CAF;	// 6007

	// decode the required instruction

	assign do_SKON = (IR_in[8:3] == 6'd0) & (IR_in[2:0] == 3'b000) & IOP_1;		// SKON performed in two times
	assign do_SKON2= (IR_in[8:3] == 6'd0) & (IR_in[2:0] == 3'b000) & IOP_2;		// see below
	assign do_ION =  (IR_in[8:3] == 6'd0) & (IR_in[2:0] == 3'b001) & IOP_1 & ~cpu_global_int_enable; //*** 22.04.2013 *** only if int disabled
	assign do_IOF =  (IR_in[8:3] == 6'd0) & (IR_in[2:0] == 3'b010) & IOP_2;
	assign do_SRQ =  (IR_in[8:3] == 6'd0) & (IR_in[2:0] == 3'b011) & IOP_1;
	assign do_GTF =  (IR_in[8:3] == 6'd0) & (IR_in[2:0] == 3'b100);				// GTF fully implemented in uCode - no action required
	assign do_RTF = rtf_apply;		// RTF is handled by dedicated microcode, not by IOP pulses
	assign do_SGT =  (IR_in[8:3] == 6'd0) & (IR_in[2:0] == 3'b110);            // not implemented (part of EAE)
	assign do_CAF =  (IR_in[8:3] == 6'd0) & (IR_in[2:0] == 3'b111) & IOP_1;

	// general flags clear
	assign sys_clear = do_CAF;

	// note for SKON: at IOP_1 we ask for the skip if cpu_global_int_enable, then we clear cpu_global_int_enable
	// we cannot clear cpu_global_int_enable at IOP_1 or we don't skip - for this reason SKON
	// is splitted: first ask for skip, and later clear cpu_global_int_enable
	assign IOSKP_out = (do_SRQ & sys_IRQ) | (do_SKON & cpu_global_int_enable);

	// for the request to enable interrupt FF
	wire set_enareq;
	wire clr_enareq;

	// for the enable interrupt FF
	wire set_inten;
	wire clr_inten;

	assign set_enareq = do_ION;
	assign set_inten  = ION_go | do_RTF;

	assign clr_enareq = ION_req & ION_go;
	assign clr_inten = do_IOF | async_IOF | do_SKON2 | do_CAF;	// do_CAF aggiunto per prova

   // the effective interrupt enable is performed when an interrupt enable request is pending and we
	// reach a FETCH3 uCode step

   // this FF is set by a ION instruction, but interrupts are not yet enabled here
	// the ION_req output is set to signal that an interrupt enable request is pending
	ff_SR ION_req_ff1 (.clk(clk), .set(set_enareq), .res1(reset), .res2(clr_enareq), .Q(ION_req), .Q_n());

	// this FF is set when an interrupt enable request was pending and FETCH3 uCode step
	// note that the above FF is reset when ION_go is received
	// this FF is reset by a IOF instruction or by an async_IOF input from outside (memory extender?)
	ff_SR INTEN_ff    (.clk(clk), .set(set_inten),.res1(reset), .res2(clr_inten), .Q(cpu_global_int_enable),   .Q_n());
	/*
	always @(posedge clk) begin
		if (IOP_2) begin
			$display("--------IOP_1 posedge------------ set_inten=%d", set_inten);
		end
	end
	always @(negedge clk) begin
		if (IOP_2) begin
			$display("--------IOP_1 negedge------------ set_inten=%d", set_inten);
		end
	end*/

	/*always @(posedge clk) begin
		$display("cpu_global_int_enable=%d | async_IOF=%d", cpu_global_int_enable, async_IOF);
		if (do_ION)
			$display("--------do_ION-------------IR=%0o iop_in=%o", IR_in, iop_in);
		if (do_IOF)
			$display("--------do_IOF-------------IR=%0o iop_in=%o", IR_in, iop_in);
		if (do_SRQ) begin
			$display("--------do_SRQ-------------IR=%0o iop_in=%o sys_IRQ=%d IOSK_out=%d", IR_in, iop_in, sys_IRQ, IOSKP_out);
			//$display("set_ena=%d clr_ena=%d set_inten=%d clr_inten=%d | ION_req=%d cpu_global_int_enable=%d | async_IOF=%d", set_enareq, clr_enareq,
		   //      set_inten, clr_inten, ION_req, cpu_global_int_enable, async_IOF);
		end
		if (do_SKON) begin
			$display("--------do_SKON------------IR=%0o iop_in=%o sys_IRQ=%d", IR_in, iop_in, sys_IRQ);
			$display("set_ena=%d clr_ena=%d set_inten=%d clr_inten=%d | ION_req=%d cpu_global_int_enable=%d | async_IOF=%d", set_enareq, clr_enareq,
		         set_inten, clr_inten, ION_req, cpu_global_int_enable, async_IOF);
		end
		if (do_RTF) begin
			$display("---------do_RTF------------IR=%0o iop_in=%o, FLAG_rrstore=%d", IR_in, iop_in, FLAG_restore);
						$display("set_ena=%d clr_ena=%d set_inten=%d clr_inten=%d | ION_req=%d cpu_global_int_enable=%d | async_IOF=%d", set_enareq, clr_enareq,
		         set_inten, clr_inten, ION_req, cpu_global_int_enable, async_IOF);
		end
	end*/
endmodule



// ----------------------------------------------------------------------------------------
// modulo Memory Extender
// ----------------------------------------------------------------------------------------
module Mext_op (
    clk, reset,
    IR_in,
    iop_in,
    rtf_apply,
    db_out,
    DFBUS, IFBUS,
    load_IF,
    ORAC_out,
    load_SF,
    clr_IDF,
    cpu_int_inhibit,
    rtf_int_defer,
    SF_register,
    to_FLAGS
);

    input clk;
    input reset;

    input [11:0] IR_in;        // current IR
    input [2:0]  iop_in;
    input        rtf_apply;

    output [2:0]  DFBUS;
    output [2:0]  IFBUS;
    output [11:0] db_out;
    reg    [11:0] db_out;

    input load_IF;             // load IF, asserted externally at first JMP/JMS
    input load_SF;             // load Save Field Register, asserted externally at INT
    input clr_IDF;             // clear IF and DF, asserted externally at INT

    output ORAC_out;
    output cpu_int_inhibit;
    output rtf_int_defer;

    output [5:0] SF_register;  // Save Field Register exported for GTF/RIB
    input  [11:0] to_FLAGS;    // flags copied from AC by RTF

    wire [2:0] rd_IF;
    wire [2:0] rd_DF;

    assign SF_register = { rd_IF, rd_DF };

    wire [2:0] IB2IF;

    wire do_CDF;               // 62N1
    wire do_CIF;               // 62N2
    wire do_RDF;               // 6214
    wire do_RIF;               // 6224
    wire do_RIB;               // 6234
    wire do_RMF;               // 6244
    wire do_RTF;               // 6005

    // Decode the three IOP cycles
    wire IOP_1;                // IOSKP cycle
    wire IOP_2;                // ACCLRC cycle
    wire IOP_4;                // ORAC cycle
    wire is_MEMX_dev;

    assign IOP_1 = iop_in[0];
    assign IOP_2 = iop_in[1];
    assign IOP_4 = iop_in[2];

    assign is_MEMX_dev = (IR_in[8:6] == 3'o2);

    assign do_CDF = is_MEMX_dev & IR_in[0] & IOP_1;  // 62N1
    assign do_CIF = is_MEMX_dev & IR_in[1] & IOP_2;  // 62N2

    assign do_RDF = (IR_in[8:0] == 9'o214) & IOP_4;  // 6214
    assign do_RIF = (IR_in[8:0] == 9'o224) & IOP_4;  // 6224
    assign do_RIB = (IR_in[8:0] == 9'o234) & IOP_4;  // 6234
    assign do_RMF = (IR_in[8:0] == 9'o244) & IOP_4;  // 6244

    // RTF is instruction 6005.
    // It restores selected flags from AC.
    // In this module it restores AC6-11 into the Save Field Register
    // and sets the CPU interrupt inhibit flip-flop.
    //assign do_RTF = (IR_in[8:0] == 9'o005) & IOP_1;  // 6005
	 assign do_RTF = rtf_apply;

    // Main memory extension registers.
    //
    // DF is loaded directly by CDF, from the Save Field Register by RMF,
    // or from AC[9:11] by RTF.
    //
    // IB is loaded by CIF, from the Save Field Register by RMF,
    // or from AC[6:8] by RTF.  IF is not loaded directly by RTF;
    // it is loaded from IB only when load_IF is asserted at the following
    // JMP/JMS, exactly like CIF.  rtf_int_defer blocks program interrupt
    // acceptance until that transfer has occurred.

    R3 DF (
        .in(do_RTF ? to_FLAGS[2:0] :
            do_RMF ? rd_DF        :
                     IR_in[5:3]),
        .out(DFBUS),
        .clk(clk),
        .reset(reset | clr_IDF),
        .load_n(~(do_CDF | do_RMF | do_RTF))
    );

    R3 IB (
        .in(do_RTF ? to_FLAGS[5:3] :
            do_RMF ? rd_IF        :
                     IR_in[5:3]),
        .out(IB2IF),
        .clk(clk),
        .reset(reset | clr_IDF),
        .load_n(~(do_CIF | do_RMF | do_RTF))
    );

    R3 IF (
        .in(IB2IF),
        .out(IFBUS),
        .clk(clk),
        .reset(reset | clr_IDF),
        .load_n(~load_IF)
    );


    // Assert ORAC_out when the memory extension instruction must OR
    // db_out into AC.

    assign ORAC_out = (do_RDF | do_RIF | do_RIB) ? 1'b1 : 1'b0;


    // Save Field Register.
    //
    // During interrupt entry:
    //   load_SF = 1
    //   SFIF <= current IF
    //   SFDF <= current DF
    //
    // During RTF:
    //   SFIF <= to_FLAGS[5:3]   // AC6-8, saved IF
    //   SFDF <= to_FLAGS[2:0]   // AC9-11, saved DF

    R3 SFIF (
        .in(do_RTF ? to_FLAGS[5:3] : IFBUS),
        .out(rd_IF),
        .clk(clk),
        .reset(reset),
        .load_n(~(load_SF | do_RTF))
    );

    R3 SFDF (
        .in(do_RTF ? to_FLAGS[2:0] : DFBUS),
        .out(rd_DF),
        .clk(clk),
        .reset(reset),
        .load_n(~(load_SF | do_RTF))
    );


    // CPU interrupt inhibit flip-flop.
    //
    // Set by CIF and by RTF.
    // Cleared when the pending instruction field transfer becomes effective,
    // normally at the following JMP/JMS, which asserts load_IF.

 /*   ff_SR indir_addr (
        .clk(clk),
        .set(do_CIF | do_RTF),
        .res1(reset),
        .res2(load_IF),
        .Q(cpu_int_inhibit)
    );*/

	wire set_cpu_int_inhibit;
	wire clr_cpu_int_inhibit;

	assign set_cpu_int_inhibit = do_CIF | (do_RTF &  to_FLAGS[8]);
	assign clr_cpu_int_inhibit = load_IF | (do_RTF & ~to_FLAGS[8]);

	ff_SR indir_addr (
		.clk(clk),
		.set(set_cpu_int_inhibit),
		.res1(reset),
		.res2(clr_cpu_int_inhibit),
		.Q(cpu_int_inhibit)
	);

	// RTF restores the visible interrupt enable state immediately, so GTF
	// must see it, but a program interrupt must not be accepted until
	// the next JMP/JMS completes the field transfer.  This separate
	// inhibit is therefore used only in the interrupt-accept condition,
	// not in the GTF FLAGS bits.
	ff_SR rtf_defer_ff (
		.clk(clk),
		.set(do_RTF),
		.res1(reset),
		.res2(load_IF | load_SF),
		.Q(rtf_int_defer)
	);

	// per evitare tri-state
	always @ (*)
	if (do_RDF)
		db_out = {6'b000000, DFBUS, 3'b000};
	else if (do_RIF)
		db_out = {6'b000000, IFBUS, 3'b000};
	else if (do_RIB)
		db_out = {6'b000000, rd_IF, rd_DF };
	else
		db_out = 12'd0; // default to 0 because the value is ored with other boards

	`ifdef trace_mext

	// --------------------------------------------------------------------
	// Memory extension debug trace
	// --------------------------------------------------------------------
	// Notes:
	// - field_sel_dbg is the N field used by CDF/CIF, taken from IR[5:3].
	// - $strobe prints at the end of the current simulation time slot,
	//   so register outputs are normally shown after the clocked update.
	// --------------------------------------------------------------------

	wire [2:0] field_sel_dbg;
	wire [11:0] rdf_or_value_dbg;
	wire [11:0] rif_or_value_dbg;
	wire [11:0] rib_value_dbg;

	assign rdf_or_value_dbg = {6'b000000, DFBUS, 3'b000};
	assign rif_or_value_dbg = {6'b000000, IFBUS, 3'b000};
	assign rib_value_dbg    = {6'b000000, SF_register};

	assign field_sel_dbg = IR_in[5:3];

	always @(posedge clk) begin

		if (do_CDF) begin
			$strobe(
				"t=%0t  MEXT CDF   IR=%04o  field=%0o  DF<=%0o  DF=%0o IB=%0o IF=%0o  cpu_int_inhibit=%b",
				$time,
				IR_in,
				field_sel_dbg,
				field_sel_dbg,
				DFBUS,
				IB2IF,
				IFBUS,
				cpu_int_inhibit
			);
		end

		if (do_CIF) begin
			$strobe(
				"t=%0t  MEXT CIF   IR=%04o  field=%0o  IB<=%0o  DF=%0o IB=%0o IF=%0o  cpu_int_inhibit=%b",
				$time,
				IR_in,
				field_sel_dbg,
				field_sel_dbg,
				DFBUS,
				IB2IF,
				IFBUS,
				cpu_int_inhibit
			);
		end

		if (load_IF) begin
			$strobe(
				"t=%0t  MEXT LIF   IR=%04o  IF<=IB=%0o  DF=%0o IB=%0o IF=%0o  cpu_int_inhibit=%b",
				$time,
				IR_in,
				IB2IF,
				DFBUS,
				IB2IF,
				IFBUS,
				cpu_int_inhibit
			);
		end

		if (do_RDF) begin
			$strobe(
				"t=%0t  MEXT RDF   IR=%04o  DF=%0o  OR value=%04o  db_out=%04o  AC bits <= DF",
				$time,
				IR_in,
				DFBUS,
				rdf_or_value_dbg,
				db_out
			);
		end

		if (do_RIF) begin
			$strobe(
				"t=%0t  MEXT RIF   IR=%04o  IF=%0o  OR value=%04o  db_out=%04o  AC bits <= IF",
				$time,
				IR_in,
				IFBUS,
				rif_or_value_dbg,
				db_out
			);
		end

		if (do_RIB) begin
			$strobe(
				"t=%0t  MEXT RIB   IR=%04o  SF=%06o  db_out=%04o  rib_value=%04o  rd_IF=%0o rd_DF=%0o",
				$time,
				IR_in,
				SF_register,
				db_out,
				rib_value_dbg,
				rd_IF,
				rd_DF
			);
		end

		if (do_RMF) begin
			$strobe(
				"t=%0t  MEXT RMF   IR=%04o  restore DF<=%0o IB<=%0o  DF=%0o IB=%0o IF=%0o  cpu_int_inhibit=%b",
				$time,
				IR_in,
				rd_DF,
				rd_IF,
				DFBUS,
				IB2IF,
				IFBUS,
				cpu_int_inhibit
			);
		end

		if (clr_IDF) begin
			$strobe(
				"t=%0t  MEXT CLR   IR=%04o  clr_IDF=1  DF=%0o IB=%0o IF=%0o  cpu_int_inhibit=%b",
				$time,
				IR_in,
				DFBUS,
				IB2IF,
				IFBUS,
				cpu_int_inhibit
			);
		end

		if (load_SF) begin
			$strobe(
				"t=%0t  MEXT LSF   IR=%04o  save fields  SF=%06o  IF=%0o DF=%0o  cpu_int_inhibit=%b",
				$time,
				IR_in,
				SF_register,
				IFBUS,
				DFBUS,
				cpu_int_inhibit
			);
		end

	end
`endif
endmodule

// ========================================================================================
// ========================================================================================
// MODULO DI CONTROLLO - con il DATAPATH è il più importante di tutto
// ========================================================================================
// ========================================================================================
module control_unit (
	clk, 	// horizontal signals
	clk_n,
	reset,
	Txd, 	// RS-232
	Rxd,
	btn, 	// extras
	swx,
	Led,
	panel_led,
	pc_display,
	ac_display,
	switch_register,
	break_addr,
	addrld_button_level,
	brkset_button_level,
	exam_button_level,
	deposit_button_level,
	extaddr_button_level,
	panel_addr_display,
	panel_md_display);

   // * * Module parameters * *

	input  clk;                // clock
	input  clk_n;              // negated clock
	input  reset;              // reset
	output Txd;                // serial Txd
	input  Rxd;                // serial Rxd
	input  [3:0]  btn;         // front panels buttons
	input  [7:0]  swx;         // front panel switches
	output [7:0]  Led;         // front panel LEDS
	output [11:0] panel_led;   // front panel seven-segment display
	output [11:0] pc_display;  // direct PC export for external display
	output [11:0] ac_display;  // direct AC export for external display
	input  [11:0] switch_register;      // physical front-panel switch register
	input  [11:0] break_addr;           // front-panel hardware-breakpoint address
	input         addrld_button_level;   // debounced ADDRLD level from the physical panel
	input         brkset_button_level;   // debounced BRKSET level from the physical panel
	input         exam_button_level;     // debounced EXAM level from the physical panel
	input         deposit_button_level;  // debounced DEPOSIT level from the physical panel
	input         extaddr_button_level;  // debounced EXTADDR; used as MA- / ADDR-
	output [11:0] panel_addr_display;    // PANEL_ADDR exported to the Colorlight display
	output [11:0] panel_md_display;      // PANEL_MD exported to the Colorlight display

	wire int_req;					// interrupt request pending
	reg [50:0]ma[127:0];			// microprogram ROM 50-bit wide
	reg [7:0] jptable [20:0];	// used for the uprogram address of each macro-instruction

	wire [11:0] PC;            // program counter
	wire [11:0] IR;            // instruction register
	wire [11:0] AC;            // accumulator
	wire LINK;                 // link
	wire [7:0]  uPCBUS;		   // microprogram PC
	wire [50:0] uIRBUS;	      // microprogram
	wire uQual;					   // qualificator testable by ucode instructions
	wire jumpreq;
	wire jumpqual;
	wire overflow;



/*
	OTTO is the name of Quacktech Digital Equipment PDP-8 simulator

	OTTO uses a 50-bit microinstructions composed as follows:
		ma[20]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oZERO,  `dAC, `qCLA,  7'd0, `lkNOP};   // CLA

	uIRBUS is the 50-bit wide output of the ucode ROM
	- [50:50] ( 1 bit) forgotten! 	- never used nor discussed
	- [49:45] ( 5 bit) uOP_FILLER 	- a 5 zeroes string reserved for future use
	- [44:41] ( 4 bit) uOP_id 			- microcycle type, normally uOP_NOID
	- [40:37] ( 4 bit) IOP_req[3:0] 	- used only for IOP
	- [36:33] ( 4 bit) uOpcode			- microinstruction opcode
	- [32:29] ( 4 bit) muxsel			- source register for the DATAPATH mux
	- [28:24] ( 5 bit) ALU_OPC			- opcode for the ALU requested operation
	- [23:23] ( 1 bit) CYF 				- CARRY FLAG (included in the 6-bit codes for ALU_OPC)
	- [22:15] ( 8 bit) REGLOAD			- ALUBUS destination (REGLOAD values)
	- [14:10] ( 5 bit) cond 			- selector of the micronstruction qualifier
	- [09:03] ( 9 bit) uJPaddress 	- address for the next microinstruction (note 1)
	- [02:00] ( 3 bit) link_sel		- link selector

	Note 1: 	uJPAddress is normally taken from uIRBUS[9:3] with an added leading 0.
				if the uOpcode is uJPI (indirect jump), bits [11:9] of the current macroinstruction (IR) are used as an address to jptable[]
				which contains the address of the corresponding microcode sequence.

	Note 2: 	clock usage - in intention, a microinstruction is executed one clock cycle. In general:
				- on the rising edge the combinatorial networks are set and half clock period allows it to stabilize
				- on the falling edge the sequential logic (flip-flops, registers...) are triggered
				So uPC is incremented on the rising edge, the microinstructions lines become stable and
				on the falling edge the instruction is completed by latching/storing
*/
   // values loaded from ucode ROM
   wire [3:0] uOP_id;         // see above
	wire [3:0] IOP_req;        // see above
   wire [3:0] uOpcode;        // see above
	wire [3:0] muxsel;         // see above
	wire [4:0] ALU_OPC;        // see above
	wire       CYF; 		      // see above
	wire [7:0] REGLOADx;       // old REGLOAD in encoded form (see defines.v)
	wire [4:0] cond;	         // see above
	wire [7:0] uJPaddress;	   // see above
	wire [2:0] link_sel;       // see above

	wire we_n;					   // RAM write
	wire cond_nop;				   // se settato le istruzioni sono eseguite come NOP
	wire MB0;
	wire MB1X;					   // 10-17 oct address for implicit autoincrement
	wire do_skip;
	wire or_skip, and_skip;

	wire [2:0] IOP_pulse; 	   // bus di uscita comandi IOP
	wire IOP_qual;

	//wire [11:0] INBUS;
	wire FETCH3;				   // #3 uistr of fetch op; used by INT and switch register
	wire ION_req, 					// interrupt enable request is pending
	     ION_go;
	wire cpu_global_int_enable;						// interrupt enabled
	wire async_IOF;
	wire ena_swreg;
	wire [11:0] SWREG;

	//wire IOSKP_xinp, ACCLR_xinp, ORAC_xinp;

   // memory extension module
	wire use_df;
	wire [2:0]DFBUS;
	wire [2:0]IFBUS;
	wire load_IF;
	wire load_SF;
	wire clr_IDF;
	wire sys_clear;	// global system reset (flags clear)

	wire [5:0] SF_register_rd;

   // interrupt
	wire cpu_int_inhibit;
	wire rtf_int_defer;

	// flags for implementing the IOT processor instructions GTF e RTF (see below for details)
	wire [11:0] FLAGS;
	wire [11:0] to_FLAGS; 	// value returned from datapath to allow FLAGS setting, must be used by the RTF instruction
									// to properly set the various fields

	// -------------------------------------------------------------------------------------------
	// IOT boards interconnections
	// -------------------------------------------------------------------------------------------
	// We have room for 8 IOT boards.
	// IMPORTANT: every request-bus bit must be driven.  Unused/future slots
	// are deliberately tied to zero below, so the reduction ORs remain safe
	// while preserving the slot-based architecture.
	wire [7:0] ORAC_req;
	wire [7:0] ACCLR_req;
	wire [7:0] IOSKP_req;

	// The active slots are:
	//   `bdIOT   : IOT processor, drives IOSKP only
	//   `bdTTY   : Teletype, drives IOSKP, ACCLR, ORAC
	//   `bdMEMX  : memory extension, drives ORAC only
	// All other request lines are explicitly inactive.
	assign ORAC_req [`bdIOT]  = 1'b0;
	assign ACCLR_req[`bdIOT]  = 1'b0;

	assign ACCLR_req[`bdMEMX] = 1'b0;
	assign IOSKP_req[`bdMEMX] = 1'b0;

	assign ORAC_req [3] = 1'b0;
	assign ACCLR_req[3] = 1'b0;
	assign IOSKP_req[3] = 1'b0;

	assign ORAC_req [4] = 1'b0;
	assign ACCLR_req[4] = 1'b0;
	assign IOSKP_req[4] = 1'b0;

	assign ORAC_req [5] = 1'b0;
	assign ACCLR_req[5] = 1'b0;
	assign IOSKP_req[5] = 1'b0;

	assign ORAC_req [6] = 1'b0;
	assign ACCLR_req[6] = 1'b0;
	assign IOSKP_req[6] = 1'b0;

	assign ORAC_req [7] = 1'b0;
	assign ACCLR_req[7] = 1'b0;
	assign IOSKP_req[7] = 1'b0;

	// Now these reduction ORs are safe, because no request bit is floating.
	wire ORAC_xinp  = |ORAC_req;
	wire ACCLR_xinp = |ACCLR_req;
	wire IOSKP_xinp = |IOSKP_req;

	// slots for data bus coming from the boards as outputs
	// assign to zero unused slots
	wire [11:0] INBUSx;  			// this is what goes to datapath
	wire [11:0] INBUS_bd [0:7];	// these are the outputs of the boards

	// note that they cannot be left uninitialized
	assign INBUS_bd[`bdIOT] = 12'b000000000000;		// IOP (does not use INBUS)
	//assign INBUS_bd[`bdTTY] = 12'b000000000000;	// TTY
	//assign INBUS_bd[`bdMEMX] = 12'b000000000000;	// MEMX
	assign INBUS_bd[3] = 12'b000000000000;
	assign INBUS_bd[4] = 12'b000000000000;
	assign INBUS_bd[5] = 12'b000000000000;
	assign INBUS_bd[6] = 12'b000000000000;
	assign INBUS_bd[7] = 12'b000000000000;

	// note that all the boards must return 0 when not requiring to pass data
	// because we do a wired OR
	assign INBUSx = INBUS_bd[0] |
	             INBUS_bd[1] |
	          INBUS_bd[2] |
	       INBUS_bd[3] |
	    INBUS_bd[4] |
	 INBUS_bd[5] |
	 INBUS_bd[6] |
	 INBUS_bd[7];

	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	// % IOT processor instr. module.        %
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	assign ION_go = FETCH3 & ION_req;	// conditions met, go with interrupt enable

	// RTF (6005) is implemented by special microcode and does not generate normal IOP pulses.
	// At uPC=102, the datapath FLAGSBUS has safely captured AC at uPC=100,
	// and the link has already been restored at uPC=101.  The control/memory-extension
	// logic may now restore the external flags without racing FLAGSBUS.
	wire rtf_apply;
	assign rtf_apply = (uPCBUS == 8'd102) &
	                   (IR[11:9] == 3'o6) &
	                   (IR[8:3]  == 6'o00) &
	                   (IR[2:0]  == 3'o5);

	IOT_proc INT(.clk(clk), .reset(reset),
				.IR_in(IR),
				.iop_in(IOP_pulse[2:0]),
					.rtf_apply(rtf_apply),
				.IOSKP_out (IOSKP_req[`bdIOT]),
				.sys_clear (sys_clear),
				.cpu_global_int_enable (cpu_global_int_enable),
				.ION_req(ION_req), .ION_go(ION_go), .async_IOF(async_IOF),
				.sys_IRQ(int_req) // input
				);

	// Reader enable / reader run relay from the console input device.
	// Routed to Led[0] so the Colorlight top-level can export it.
	wire reader_enable_relay;

	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	// % Teleprinter board istance           %
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	teletype TTY(.clk(clk), .clk_n(clk_n), .reset(reset),
				.IR_in(IR),
				.db_in(AC),
				.iop_in(IOP_pulse[2:0]),
				.IOSKP_out(IOSKP_req[`bdTTY]),
				.ACCLR_out(ACCLR_req[`bdTTY]),
		      .ORAC_out(ORAC_req[`bdTTY]),
			   .sys_clear (sys_clear),
				.db_out(INBUS_bd[`bdTTY]),
				.TTY_irq(int_req), // output
				.Rxd(Rxd),
				.Txd(Txd),
				.RdrRun(reader_enable_relay)
			  );

	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	// % Memory module istance               %
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		Mext_op   MEMEXP (.clk(clk_n), .reset(reset), .IR_in(IR), .iop_in(IOP_pulse[2:0]), .rtf_apply(rtf_apply),
				 .db_out(INBUS_bd[`bdMEMX]),
				 .DFBUS(DFBUS),
				 .IFBUS(IFBUS),
				 .load_IF(load_IF),
				 .ORAC_out(ORAC_req[`bdMEMX]),
				 .load_SF(load_SF),		// carica il Save Field (all'interrupt)
				 .clr_IDF(clr_IDF),
				 .cpu_int_inhibit(cpu_int_inhibit),
				 .rtf_int_defer(rtf_int_defer),
				 .SF_register (SF_register_rd),
				 .to_FLAGS(to_FLAGS)
				 );

	// settato quando si sta per eseguire un indirizzamento indiretto
	wire indir_mext;
	assign indir_mext =
				    (uOP_id == `uOP_INDR) && (// (*** 22.04.2013 ***)
					 (IR [11:9] == 3'b000) || 	// AND
					 (IR [11:9] == 3'b001) || 	// TAD
					 (IR [11:9] == 3'b010) || 	// ISZ
					 (IR [11:9] == 3'b011)  	// DCA
					 );
	ff_SR indir_addr(.clk(clk), .set(indir_mext), .res1(reset), .res2(uOP_id == `uOP_DIR), .Q(use_df));

   // **************
	// * HW WARNING *
	// **************
	//assign panel_led=IR;
	// Led[0] is the paper-tape reader enable relay.
	// Led[1] is a latched hardware-breakpoint-hit indicator.
	// Led[7] is RUN/HALT and is assigned below.
	assign Led[0]   = reader_enable_relay;
	assign Led[1]   = breakpoint_latched;
	assign Led[6:2] = swx[6:2];

   // **************
	// * HW WARNING *
	// **************
     // switch register - it is used for two purposes during simulation
   // on the very beginning of the ucode cicle it is interpreted as 'initial_PC
   // imediately after it becomes 'swreg_settings

	// Physical console switch register.
	// PDP-8/DEC front-panel convention is already handled in PDP_colorlight_top.v:
	//   SW00 is the most significant bit,
	//   SW11 is the least significant bit,
	//   closed-to-GND means logical 0,
	//   open/pulled-up means logical 1.
	assign SWREG = switch_register;

	// ----------------------------------------------------------------------
	// Front-panel command synchronization and memory-control FSM
	// EXTADDR is used by the Colorlight front panel as MA- / ADDR-.
	// ----------------------------------------------------------------------
	// The physical controls are debounced in PDP_colorlight_top.v, but they
	// arrive here from the top-level clock domain.  Synchronize them again in
	// the historical CPU clock domain before generating edges and RAM controls.
	reg [2:0] addrld_cpu_sync   = 3'b000;
	reg [2:0] brkset_cpu_sync   = 3'b000;
	reg [2:0] exam_cpu_sync     = 3'b000;
	reg [2:0] deposit_cpu_sync  = 3'b000;
	reg [2:0] extaddr_cpu_sync  = 3'b000;

	always @(posedge clk) begin
		if (reset) begin
			addrld_cpu_sync  <= 3'b000;
			brkset_cpu_sync  <= 3'b000;
			exam_cpu_sync    <= 3'b000;
			deposit_cpu_sync <= 3'b000;
			extaddr_cpu_sync <= 3'b000;
		end else begin
			addrld_cpu_sync  <= {addrld_cpu_sync[1:0],   addrld_button_level};
			brkset_cpu_sync  <= {brkset_cpu_sync[1:0],   brkset_button_level};
			exam_cpu_sync    <= {exam_cpu_sync[1:0],     exam_button_level};
			deposit_cpu_sync <= {deposit_cpu_sync[1:0],  deposit_button_level};
			extaddr_cpu_sync <= {extaddr_cpu_sync[1:0],  extaddr_button_level};
		end
	end

	wire addrld_cpu_level  = addrld_cpu_sync[2];
	wire brkset_cpu_level  = brkset_cpu_sync[2];
	wire exam_cpu_level    = exam_cpu_sync[2];
	wire deposit_cpu_level = deposit_cpu_sync[2];
	wire extaddr_cpu_level = extaddr_cpu_sync[2];

	// Console ADDR LOAD path.  ADDRLD is level-sensitive and accepted only
	// while the CPU is halted.  It directly loads the PC in the datapath with
	// the current physical switch-register value.
	wire panel_pc_load;
	assign panel_pc_load = addrld_cpu_level && !run;

	// Panel RAM access signals toward the datapath.
	reg        panel_mem_enable_reg      = 1'b0;
	reg        panel_mem_write_reg       = 1'b0;
	reg [11:0] panel_mem_addr_reg        = 12'o0200;
	reg [11:0] panel_mem_write_data_reg  = 12'o0000;
	wire [11:0] panel_mem_data;

	wire        panel_mem_enable;
	wire        panel_mem_write;
	wire [11:0] panel_mem_addr;
	wire [11:0] panel_mem_write_data;

	assign panel_mem_enable     = panel_mem_enable_reg;
	assign panel_mem_write      = panel_mem_write_reg;
	assign panel_mem_addr       = panel_mem_addr_reg;
	assign panel_mem_write_data = panel_mem_write_data_reg;

	// Front-panel address/data display registers.
	reg [11:0] panel_addr_reg = 12'o0200;
	reg [11:0] panel_md_reg   = 12'o0000;

	assign panel_addr_display = panel_addr_reg;
	assign panel_md_display   = panel_md_reg;

	localparam [2:0] PANEL_IDLE          = 3'd0;
	localparam [2:0] PANEL_EXAM_WAIT     = 3'd1;
	localparam [2:0] PANEL_EXAM_CAPTURE  = 3'd2;
	localparam [2:0] PANEL_DEPOSIT_WAIT  = 3'd3;

	localparam [1:0] PANEL_CMD_NONE      = 2'd0;
	localparam [1:0] PANEL_CMD_EXAM      = 2'd1;
	localparam [1:0] PANEL_CMD_DEPOSIT   = 2'd2;
	localparam [1:0] PANEL_CMD_ADDRLD    = 2'd3;

	reg [2:0] panel_state    = PANEL_IDLE;
	reg [1:0] panel_last_cmd = PANEL_CMD_NONE;

	reg exam_cpu_level_d    = 1'b0;
	reg deposit_cpu_level_d = 1'b0;
	reg extaddr_cpu_level_d = 1'b0;

	wire exam_cpu_key    = exam_cpu_level    & ~exam_cpu_level_d;
	wire deposit_cpu_key = deposit_cpu_level & ~deposit_cpu_level_d;
	wire extaddr_cpu_key = extaddr_cpu_level & ~extaddr_cpu_level_d;

	wire [11:0] next_exam_addr =
		(panel_last_cmd == PANEL_CMD_EXAM) ? (panel_addr_reg + 12'o0001) : panel_addr_reg;

	wire [11:0] next_deposit_addr =
		(panel_last_cmd == PANEL_CMD_DEPOSIT) ? (panel_addr_reg + 12'o0001) : panel_addr_reg;

	always @(posedge clk) begin
		if (reset) begin
			panel_mem_enable_reg      <= 1'b0;
			panel_mem_write_reg       <= 1'b0;
			panel_mem_addr_reg        <= 12'o0200;
			panel_mem_write_data_reg  <= 12'o0000;
			panel_addr_reg            <= 12'o0200;
			panel_md_reg              <= 12'o0000;
			panel_state               <= PANEL_IDLE;
			panel_last_cmd            <= PANEL_CMD_NONE;
			exam_cpu_level_d          <= 1'b0;
			deposit_cpu_level_d       <= 1'b0;
			extaddr_cpu_level_d       <= 1'b0;
		end else begin
			exam_cpu_level_d    <= exam_cpu_level;
			deposit_cpu_level_d <= deposit_cpu_level;
			extaddr_cpu_level_d <= extaddr_cpu_level;

			// Default: no panel RAM cycle unless a state below requests one.
			panel_mem_enable_reg <= 1'b0;
			panel_mem_write_reg  <= 1'b0;

			// ADDRLD is level-sensitive while held and has priority.
			if (addrld_cpu_level && !run) begin
				panel_addr_reg <= SWREG;
				panel_md_reg   <= 12'o0000;
				panel_state    <= PANEL_IDLE;
				panel_last_cmd <= PANEL_CMD_ADDRLD;
			end else begin
				case (panel_state)
					PANEL_IDLE: begin
						if (extaddr_cpu_key && !run) begin
							// EXTADDR is used as MA- / ADDR-:
							// decrement PANEL_ADDR, immediately read the new
							// location, and show coherent MA+MD.
							//
							// We set panel_last_cmd to EXAM when the read
							// completes; therefore a following EXAM advances
							// forward again to the next address.
							panel_mem_addr_reg   <= panel_addr_reg - 12'o0001;
							panel_addr_reg       <= panel_addr_reg - 12'o0001;
							panel_mem_enable_reg <= 1'b1;
							panel_mem_write_reg  <= 1'b0;
							panel_state          <= PANEL_EXAM_WAIT;
						end else if (exam_cpu_key && !run) begin
							panel_mem_addr_reg   <= next_exam_addr;
							panel_addr_reg       <= next_exam_addr;
							panel_mem_enable_reg <= 1'b1;
							panel_mem_write_reg  <= 1'b0;
							panel_state          <= PANEL_EXAM_WAIT;
						end else if (deposit_cpu_key && !run) begin
							panel_mem_addr_reg        <= next_deposit_addr;
							panel_mem_write_data_reg  <= SWREG;
							panel_addr_reg            <= next_deposit_addr;
							panel_md_reg              <= SWREG;
							panel_mem_enable_reg      <= 1'b1;
							panel_mem_write_reg       <= 1'b1;
							panel_state               <= PANEL_DEPOSIT_WAIT;
						end
					end

					// Keep the address selected through one falling RAM-clock edge.
					PANEL_EXAM_WAIT: begin
						panel_mem_enable_reg <= 1'b1;
						panel_mem_write_reg  <= 1'b0;
						panel_state          <= PANEL_EXAM_CAPTURE;
					end

					// Capture the RAM output after the clk_n edge has updated it.
					PANEL_EXAM_CAPTURE: begin
						panel_md_reg   <= panel_mem_data;
						panel_last_cmd <= PANEL_CMD_EXAM;
						panel_state    <= PANEL_IDLE;
					end

					// Hold write address/data/enable through one falling RAM-clock edge.
					PANEL_DEPOSIT_WAIT: begin
						panel_mem_enable_reg <= 1'b1;
						panel_mem_write_reg  <= 1'b1;
						panel_last_cmd       <= PANEL_CMD_DEPOSIT;
						panel_state          <= PANEL_IDLE;
					end

					default: begin
						panel_state <= PANEL_IDLE;
					end
				endcase
			end
		end
	end

   // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	// % DATAPATH istance                    %
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	datapath DP (
		.clk(clk),
		.clk_n(clk_n),
		.reset(reset),
		.panel_pc_load(panel_pc_load),
		.panel_pc_data(SWREG),
		.panel_mem_enable(panel_mem_enable),
		.panel_mem_write(panel_mem_write),
		.panel_mem_addr(panel_mem_addr),
		.panel_mem_write_data(panel_mem_write_data),
		.panel_mem_data(panel_mem_data),
		.muxsel(muxsel),
		.PCBUS(PC),
		.IRBUS(IR),
		.ACBUS(AC),
      .INBUS(INBUSx),
		.SWREG(SWREG),
	   .link(LINK),
		.link_sel(link_sel),
		.overflow_out(overflow),
		.CYF(CYF),
		.REGLOADx(REGLOADx),
		.ALU_OPC(ALU_OPC),
		.we_n(we_n),
		.MB0(MB0),
		.MB1X(MB1X),
		.DFBUS(DFBUS),
		.IFBUS(IFBUS),
		.use_df(use_df),
		.FLAGS(FLAGS),
		.FLAGSBUS (to_FLAGS)		// value returned to set FLAGS (stored in DP in a register)
		);

   // Direct exports for the external 74HC595 display.
	// These are passive taps: they do not feed anything back into the CPU.
	assign pc_display = PC;
	assign ac_display = AC;

   // **************
	// * HW WARNING *
	// **************
   // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	// % display selector istance            %
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   // selects which register is shown on seven segment display
   // selection is performed by the first 3 switches (LSB)
   mux8in_12w the_mux (
		.select(swx[2:0]),
		.a(PC),
		.b(IR),
		.c(AC),
		.d(SWREG),

		.e({3'b000, DFBUS, IFBUS, 3'b000}),
		.f({11'd0, LINK}),
		.g(12'd0),
		.h(12'd0),
		.y(panel_led));

   // **************
	// * HW WARNING *
	// **************
	// --------------------------------------------------------------------------------------
	// RUN/HALT FLIP FLOP
	// --------------------------------------------------------------------------------------
	// Colorlight front-panel convention:
	//   - btn[2] is a debounced CONT LEVEL generated in PDP_colorlight_top.v.
	//   - HALT_sw is a maintained switch.
	//
	// The actual CONT one-shot is generated here, inside the CPU clock domain.
	// HALT_sw is not used as a brutal asynchronous stop anymore.  When the
	// processor is running, it requests a stop at the next PDP-8 instruction
	// boundary, i.e. when the microprogram would normally return to uPC=1.
	// If CONT is pressed while HALT_sw is already on, exactly one PDP-8
	// instruction is executed and the processor returns to WAIT.
	wire CONT_level = btn[2];
	reg  CONT_level_d;
	wire CONT_key = CONT_level & ~CONT_level_d;


	wire HALT_sw  = swx[7];
	reg  run;
	reg  instruction_started;
	reg  breakpoint_ignore_once;
	reg  breakpoint_latched;
	wire run_light_long;

	// These wires are defined later, after uOpcode/uJPaddress/jumpqual
	// are decoded from the current microinstruction.  Verilog continuous
	// assignments make their textual position irrelevant.
	wire stop_at_instruction_boundary;
	wire program_halt_request;
	wire breakpoint_hit;

	always @(posedge clk) begin
		if (reset) begin
			run <= 1'b0;
			breakpoint_ignore_once <= 1'b0;
			breakpoint_latched <= 1'b0;
			CONT_level_d <= 1'b0;
		end else begin
			CONT_level_d <= CONT_level;

			// BRKSET is loaded in PDP_colorlight_top.v, but the CPU must also
			// forget any previous breakpoint-stop state.  Otherwise the old
			// breakpoint_ignore_once latch could make the first run after a new
			// BRKSET misleading.
			//
			// ADDRLD has the same effect: after loading a new PC, breakpoint
			// state is cleared and the next CONT uses the current BREAK_EN and
			// break_addr normally.
			if ((brkset_cpu_level && !run) || panel_pc_load) begin
				breakpoint_ignore_once <= 1'b0;
				breakpoint_latched <= 1'b0;
			end

			if (CONT_key) begin
				run <= 1'b1;   // CONT starts execution, even if HALT_sw is on
				breakpoint_latched <= 1'b0;
			end else if (stop_at_instruction_boundary || program_halt_request || breakpoint_hit) begin
				run <= 1'b0;   // clean stop at instruction boundary, PDP-8 HLT, or hardware breakpoint
			end


			// After a breakpoint stop the following CONT must be allowed to
			// execute the instruction located at the breakpoint address.
			// The bypass is cleared at the next real instruction boundary.
			if (breakpoint_hit) begin
				breakpoint_ignore_once <= 1'b1;
				breakpoint_latched <= 1'b1;
			end else if (instruction_boundary) begin
				breakpoint_ignore_once <= 1'b0;
			end
		end
	end

	// opzionale: per ora semplice
	assign run_light_long = 1'b0;
	assign Led[7] = run;

	// --------------------------------------------------------------------------------------
	// LOGICA VARIA
	// --------------------------------------------------------------------------------------
	// condizioni di skip da valutare in OR
	assign or_skip = 	(IR[`SMA] & ~IR[`INV]) & AC[11] |
						   (IR[`SZA] & ~IR[`INV]) & ~|AC   |
						   (IR[`SNL] & ~IR[`INV]) & LINK; //OR

	// devono lavorare in AND, come dire che se una condizione non � richiamata deve risultare come 1
	// in questo modo si chiappa anche il caso SKP
	assign and_skip = 	IR[`INV] &
						(IR[`SMA] ? ~AC[11] : 1) &
						(IR[`SZA] ?  |AC    : 1) &
						(IR[`SNL] ? ~LINK   : 1);

	assign do_skip = or_skip | and_skip;

	// IOP pulses production
   // IOP_req[3:0] comes from uIntruction (IOP1o, IOP2o, IOP4o, IOP1i etc. IOPxi currently not used?)
   assign IOP_pulse[0] = IOP_req[3] & IOP_req[0];
   assign IOP_pulse[1] = IOP_req[3] & IOP_req[1];
   assign IOP_pulse[2] = IOP_req[3] & IOP_req[2];

//??????????????????????????????????????????????????????????????????????????????????????????????????????????????
// the old instructione decode logic  has been modified
// we need to understand if this created problems to memory extender
//??????????????????????????????????????????????????????????????????????????????????????????????????????????????

	// IOP_qual = qualifier used in uInstructions
   // it is true if
   //    - the instruction requires an answer (IR[0, 1 or 2]
   //    - the peripheral  answers  with the request of an operation (IOSKP, ACCLR or ORAC)
   // at pulse 0 can require a skip
   // at pulse 1 can require a AC clear
   // at pulse 2 can require a OR with the peripheral produced value
   assign IOP_qual = IOP_req[0] & IOSKP_xinp | 	// true if IOP pulse 0 has a SKIP  input from peripheral
					      IOP_req[1] & ACCLR_xinp |	// true if IOP pulse 1 has a ACCLR input from peripheral
					      IOP_req[2] & ORAC_xinp;		// true if IOP pulse 0 has a ORAC  input from peripheral

   // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	// % ucode condition selector istance    %
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	// IOT instruction decoding helpers
	// IR[11:9] = 6  -> IOT instruction
	// IR[8:3]  = device code
	// IR[2:0]  = IOP pulse selection / subfunction

	wire is_IOT;
	wire is_proc_IOT;
	wire is_mext_IOT;

	assign is_IOT      = (IR[11:9] == 3'o6);
	assign is_proc_IOT = is_IOT & (IR[8:3] == 6'o00);  // 600x processor IOTs
	assign is_mext_IOT = is_IOT & (IR[8:6] == 3'o2);   // 62xx memory extension

	mux32in_1w cond_sel( .select(cond),
								   .in({
									1'b0,							// 31
									1'b0,							// 30
									is_proc_IOT & (IR[2:0] == 3'o0),   // 29 SKON / processor group 6000
									is_proc_IOT & (IR[2:0] == 3'o7),   // 28 CAF
									is_proc_IOT & (IR[2:0] == 3'o5),   // 27 RTF
									is_proc_IOT & (IR[2:0] == 3'o4),   // 26 GTF
									IR[4]&IR[6],				// 25 SWP
									IR[8]&IR[0],				// 24 GR3
								   IR[1] & ~(IR[2]|IR[3]),				// 23 BSW
								   cpu_global_int_enable & int_req &(cpu_int_inhibit==0) &(rtf_int_defer==0),	// 22 interrupt request
								   MB1X,										// 21 autoincrement
								   MB0,					   // 20 MB=0
								   IR[1],					// 19 HLT
								   IR[2],					// 18 OSR
								   do_skip,					// 17 alcolato in combinatoria
								   1'b0,						// 16 free
								   run, 						// 15 siamo in run?
								   IOP_qual,				// 14 vede se risposta da ingressi IOP
								   IR[8],					// 13 Group 2 OP
								   overflow,				// 12 ALU overflow
                           IR[0],					// 11 IAC
                           IR[1],					// 10 TWICE
                           IR[2],					// 9 RAL
                           IR[3],					// 8 RAR
                           IR[4],					// 7 CML / MQL
								   IR[5],					// 6 CMA
								   IR[6],					// 5 CLL / MQA
                           IR[7],					// 4 CLA
								   IR[11]&IR[10]&IR[9], // 3 OP (NOMEM), Group 1 etc. instruction that don't refer memory
								   ~IR[8],				   // 2 direct (IR[8] = 1 means indirect)
								   1'b0,						// 1 sempre falsa
								   1'b1}),					// 0 sempre vera
                           .out(uQual));

   // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	// % ucode program counter istance       %
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	// The original OTTO microPC was always free-running: with run=0 the
	// microprogram bounced between uPC=1 and uPC=120.  For the Colorlight
	// hardware panel we park it explicitly in U_WAIT when the CPU is halted.
	//
	// The old uPC=0/19 boot trick has been removed from the panel start path.
	// PC is now initialized directly to 0200 by the datapath reset logic, and
	// CONT always starts execution from the common FETCH entry point.
	localparam [7:0] U_FETCH = 8'd1;
	localparam [7:0] U_WAIT  = 8'd120;

	// Hardware breakpoint.
	// BREAK_EN is driven by the physical BREAK ENABLE switch.
	// The breakpoint address is loaded by BRKSET in PDP_colorlight_top.v and
	// is provided here as break_addr.
	// The CPU stops just before executing the instruction at break_addr.
	wire BREAK_EN;
	assign BREAK_EN = swx[0];

	wire micro_jump;
	wire [7:0] next_uPC_normal;
	wire instruction_boundary;
	wire cont_start;
	wire force_wait;
	wire force_fetch;
	wire panel_uPC_load;
	wire [7:0] panel_uPC_data;

	// In single-instruction mode the CPU must not stop on a spurious
	// WAIT-to-FETCH transition.  A valid instruction boundary is accepted
	// only after the running microprogram has actually reached the common
	// FETCH entry point of a real PDP-8 instruction.
	always @(posedge clk) begin
		if (reset || !run) begin
			instruction_started <= 1'b0;
		end else if (uPCBUS == U_FETCH) begin
			instruction_started <= 1'b1;
		end
	end

	assign micro_jump = jumpreq & jumpqual;

	assign next_uPC_normal =
		micro_jump ? uJPaddress : (uPCBUS + 8'd1);

	// A PDP-8 instruction is complete when the microprogram is about to
	// return to its common fetch entry point.  The instruction_started latch
	// prevents a WAIT-to-FETCH transition from being misinterpreted as the end
	// of a real PDP-8 instruction.
	assign instruction_boundary =
			run
		&& instruction_started
		&& (uPCBUS != U_WAIT)
		&& (next_uPC_normal == U_FETCH);

	assign stop_at_instruction_boundary =
		instruction_boundary && HALT_sw;

	// Hardware breakpoint: stop at an instruction boundary when the PC already
	// contains the breakpoint address.  HALT/single-instruction mode has priority
	// conceptually, so the breakpoint is disabled while HALT_sw is asserted.
	// breakpoint_ignore_once lets CONT execute the instruction at break_addr once
	// after the breakpoint has stopped the CPU there.
	assign breakpoint_hit =
		BREAK_EN
		&& instruction_boundary
		&& !HALT_sw
		&& !breakpoint_ignore_once
		&& (PC == break_addr);

	assign program_halt_request =
		run && (uOpcode == `uSTOP);

	assign cont_start  = CONT_key && !run;
	assign force_wait  = !run && !cont_start;
	assign force_fetch = cont_start;

	assign panel_uPC_load =
		force_wait ||
		force_fetch ||
		stop_at_instruction_boundary ||
		program_halt_request ||
		breakpoint_hit ||
		micro_jump;

	assign panel_uPC_data =
		force_fetch                 ? U_FETCH    :
		force_wait                  ? U_WAIT     :
		stop_at_instruction_boundary ? U_WAIT    :
		program_halt_request        ? U_WAIT     :
		breakpoint_hit              ? U_WAIT     :
		                              uJPaddress;

	up_counter_loadTTL uPC (
		.out   (uPCBUS),
		.data  (panel_uPC_data),
		.load  (panel_uPC_load),
		.clk   (clk),
		.reset (reset)
	);


	// microcycle type decode
	assign uOP_id 			= uIRBUS [44:41];

	assign FETCH3			=  uOP_id == `uOP_FET3 ? 1'b1 : 1'b0;
	assign load_IF 		=  uOP_id == `uOP_LIF  ? 1'b1 : 1'b0;
	assign load_SF 		=  uOP_id == `uOP_LSF  ? 1'b1 : 1'b0;
	assign clr_IDF 		=  uOP_id == `uOP_CIDF ? 1'b1 : 1'b0;


	assign uIRBUS 			= ma[uPCBUS];
	assign IOP_req[3:0]	= uIRBUS [40:37];		// usaati solo per le IOP
	assign uOpcode 	  	= uIRBUS [36:33];		// codice operazione
	assign muxsel     	= uIRBUS [32:29]; 	// selettore del mux
	assign ALU_OPC    	= uIRBUS [28:24]; 	// operazione dell'ALU - MSB = mode
	assign CYF        	= uIRBUS [23];			// carry to ALU
	// here REGLOAD is loaded from the uInstruction uOpcode
	assign REGLOADx    	= (cond_nop) ? `dXX   : uIRBUS[22:15]; // destinatario dell'ALUBUS selezionato dalla uistr
	assign cond 	  		= uIRBUS [14:10];		// selezione qualificatore
	assign uJPaddress 	= (uOpcode == `uJPI) ? jptable[IR[11:9]] : {1'b0,uIRBUS[9:3]}; // rivedere indice assoluto!
	assign link_sel   	= (cond_nop) ? `lkNOP : uIRBUS[2:0];

	assign cond_nop   	= (uOpcode == `uCOND) & (uQual == 0);

	// this is the only place where REGLOAD is used inside this module
	wire mem_write_req;

	assign mem_write_req = (REGLOADx == `dMEM) || (REGLOADx == `dPCMEM);
	assign we_n = ~mem_write_req;

//	assign we_n       	= (REGLOADx == `dMEM) ? 1'b0 : 1'b1;
//	assign we_n       	= REGLOAD[7];
	assign async_IOF 		= load_SF; // IOF (interrupt OFF) per servizio interrupt

	assign jumpreq 	   = (uOpcode == `uJPT) | (uOpcode == `uJPF) | (uOpcode == `uJPI);
	assign jumpqual  		= uQual ^ (uOpcode == `uJPF);

	integer i;

	// --------------------------------------------------------------------------------------
	// FLAGS for GTF/RT instructions
	// --------------------------------------------------------------------------------------
	// FLAGS[11:0] is automatically maintained updated with the proper values
	// and can be used as source (sFLAGS) in ALU operations of the microinstructions
	// see Small Computer Handbook // Table 4-1 Interrupt IOT Instructions
	// NOTE: dFLAGS in microinstruction sets the to_FLAGS value according to AC

	assign FLAGS[11] = LINK;							// Link
	assign FLAGS[10] = 0;								// Greater than
	assign FLAGS [9] = int_req & (cpu_int_inhibit==0);	// Interrupt Request line
																// al momento l'ihn_INT si trova nel memory extender
																//	ma forse dovrebbe stare nel IOT_proc ????????????????????
	assign FLAGS [8] = cpu_int_inhibit;				// Interrupt Inhibit FF
	assign FLAGS [7] = cpu_global_int_enable;		// Interrupt Enable FF
	assign FLAGS [6] = 0;								// User Flag
	assign FLAGS [5:0] = SF_register_rd; 			// Save Field Register

	// --------------------------------------------------------------------------------------
	// MICROPROGRAM MEMORY INITIALIZATION - note "initial"
	// --------------------------------------------------------------------------------------
	// the whole OTTO is implemented here. Note that all the addresses and bit positions are
	// absolute - it is not fine but it is so
	initial
	begin

	// * * INSTRUCTION JUMP TABLE
	// you must initialize all the elements or none will be initialized (don't know why)
	for (i=0; i<21; i=i+1)
		jptable[i] = 0;

	// the FETCH microcode ends always to use this jump table to implement the effective
	// macro-instruction
	jptable[0] = 46; // AND
	jptable[1] = 64; // TAD
	jptable[2] = 52; // ISZ
	jptable[3] = 48; // DCA
	jptable[4] = 58; // JMS
	jptable[5] = 16; // JMP
	jptable[6] = 96; // IOP
	jptable[7] = 70; // OP

	// * * MICROCODE ROM
	// you must initialize all the elements or none will be initialized (don't know why)
	for (i=0; i<128; i=i+1)
		ma[i] = 51'd0;		// clear full 51-bit microinstruction word

	// this is trick to initially load PC with the content of the switch register
	ma[0] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sSR,`oTO,    `dPC, `qTRUE, 7'd19, `lkNOP};	 	 // LD PC<-SR

	// ---------------------------------------------------------------------------------------------------------------------------------------------------
	// * * INSTRUCTION FETCH * *
	// ---------------------------------------------------------------------------------------------------------------------------------------------------
	ma[1] = {`uOP_FILLER,`uOP_DIR, `IOPNOP, `uJPF, `sAC,`oTO,    `dXX, `qRUN,   7'd120,`lkNOP};	 // if qRUN=FALSE, uJPF jump direct (uOP_DIR) to 120
	ma[2] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sAC,`oTO,    `dXX, `qIRQ,   7'd61, `lkNOP};	 // interrupt pendente?
	ma[3] = {`uOP_FILLER,`uOP_FET3,`IOPNOP, `uJPT, `sPC,`oTO,  	 `dAB, `qFALSE, 7'd0,  `lkNOP};	 // uJPT qFALSE (never) sPC (source) oTO (->) dAB (dest)
	ma[4] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sPC,`oAPLUS1,`dPC, `qFALSE, 7'd0,  `lkNOP};	 // uJPT qFALSE (never) sPC (source) oAPLUS1 (->) dPC (dest) INC PC
	ma[5] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMO,`oTO,    `dIR, `qFALSE, 7'd0,  `lkNOP};	 // uJPT qFALSE (never) sMO (source) oTO (->) dIR (dest) LD IR<-(MA)
	ma[6] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sEA,`oTO,    `dMA, `qNOMEM, 7'd12, `lkNOP};	 // LD MA<-EA jump if NOMEM (Group 1 etc. instructions)
																																 // EA is the effective address of a memory location
																																 // i.e., in the same page as the instruction or page 0
																																 // according to bit 7 of the instruction (bit 4 in DEC
																																 // manuals which use reverse notation 11=LSB)
	// we arrive here in case of a non-NOMEM instruction
	// at this point MA contains the EA (effective address) defined by the instruction

	// indirizzamento diretto? salta con EA in MA - ha anche funzioni di wait *** 21.04.2013 ***
	ma[7] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMO,`oTO,    `dXX, `qDIRECT,7'd12, `lkNOP};	 // NOMEM or direct addressing instr. both jump to 012

	// we arrive here in case of indirect addressing, with EA in MA
	// move LD MB<-(EA) (content of the effective address)
	ma[8] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMO,`oTO,    `dMB, `qFALSE, 7'd1,  `lkNOP};	 // memory output to MB and no jump

	// check for autoincrement - i.e., for memory locations 0-17 oct
	// in this case LD MB<-MB+1
	ma[9] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMB,`oAPLUS1,`dMB, `qAUTOI, 7'd0,  `lkNOP};	 // uCOND is executed only if the qualifier is TRUE
	ma[10]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMB,`oTO,	 `dMEM,`qAUTOI, 7'd0,  `lkNOP};	 // and write MB to memory (uCOND as above)

	// we are still in the case of indirect addressing, thus LD MA<-MB
	ma[11]= {`uOP_FILLER,`uOP_INDR,`IOPNOP, `uJPT, `sMB,`oTO,    `dMA, `qFALSE, 7'd0,  `lkNOP};	 // LD MA<-MB   indirizzamento indiretto

	// we arrive here in all cases with MA properly set as required
	ma[12]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMO,`oTO,    `dXX, `qFALSE, 7'd0,  `lkNOP};	 // NOP as wait memory *** confermata 21.04.2013 ***
	ma[13]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMO,`oTO,    `dMB, `qFALSE, 7'd0,  `lkNOP};	 // LD MB<-memory output
	ma[14]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPI, `sMO,`oTO,    `dXX, `qTRUE,  7'd0,  `lkNOP};	 // jump table - follow for the required macroinstruction
	// ---------------------------------------------------------------------------------------------------------------------------------------------------
	// * * end of INSTRUCTION FETCH * *
	// ---------------------------------------------------------------------------------------------------------------------------------------------------

	// JMP INSTRUCTION
	ma[16]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dPC, `qFALSE,7'd0, `lkNOP}; 	 // JMP instruction - LD PC<-MA
	ma[17]= {`uOP_FILLER,`uOP_LIF, `IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};		 // for memory extension - LD IF<-IB + uJPT qTRUE to 001

	// test only to set PC
	ma[19] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sSR,`oTO,    `dPC,`qTRUE,7'd1,`lkNOP};
//	ma[19] = {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`o7777,  `dSR,`qTRUE, 7'd1,`lkNOP};

	// GR3 INSTRUCTION
	ma[20]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oZERO,  `dAC, `qCLA,  7'd0, `lkNOP};   // CLA
	ma[21]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMQ,`oAORB,	 `dXX, `qSWP,  7'd26,`lkNOP};   // MQA+MQL
	ma[22]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMQ,`oAORB,	 `dAC, `qMQA,  7'd0, `lkNOP};   // MQA
	ma[23]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oTO,    `dMQ, `qMQL,  7'd0, `lkNOP};   // MQL
	ma[24]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oZERO,  `dAC, `qMQL,  7'd0, `lkNOP};   // MQL
	ma[25]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sAC,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};

	ma[26]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sAC,`oTO,    `dMB, `qFALSE,7'd1, `lkNOP};		// SWP
	ma[27]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMQ,`oTO,    `dAC, `qFALSE,7'd1, `lkNOP};
	ma[28]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dMQ, `qTRUE, 7'd1, `lkNOP};

	// GR2 INSTRUCTION
	ma[36]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `s00,`oTO,    `dXX, `qGR3,  7'd20,`lkNOP};   // Gruppo 3?
	ma[37]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dXX, `qSKP,  7'd42,`lkNOP};   // any SKP
	ma[38]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oZERO,  `dAC, `qCLA,  7'd0, `lkNOP};   // CLA
	ma[39]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sSR,`oAORB,  `dAC, `qOSR,  7'd0, `lkNOP};   // Nessuno skip, vediamo OSR (OR Switch Register)
	ma[40]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sSR,`oAORB,  `dXX, `qHLT,  7'd44,`lkNOP};   // oppure un HLT
	ma[41]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};   // continua con altre istruzioni
	ma[42]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sPC,`oAPLUS1,`dPC, `qFALSE,7'd0, `lkNOP};   // qui si esegue lo skip effettivo (PC<-PC+1)
	ma[43]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qTRUE, 7'd38,`lkNOP};   // processa la parte che resta dell'istruzione
	ma[44]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uSTOP,`sMB,`oTO,    `dXX, `qTRUE, 7'd0, `lkNOP};   // esegui HALT
	ma[45]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};   // esegui HALT

	// AND INSTRUCTION
	ma[46]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oAANDB, `dAC, `qFALSE,7'd0, `lkNOP};    // AND - LD AC<-AC & MB
	ma[47]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};    // jump to 001

	// DCA  INSTRUCTION
	ma[48]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sAC,`oTO,    `dMB, `qFALSE,7'd0, `lkNOP};    // LD MB<-AC (DCA)
	ma[49]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sAC,`oZERO,  `dAC, `qFALSE,7'd0, `lkNOP};    // CLA
	ma[50]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dMEM,`qTRUE, 7'd1, `lkNOP};    // LD MEM<-MB and jump to 001

	// ISZ INSTRUCTION
	ma[52]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oAPLUS1,`dMB, `qFALSE,7'd0, `lkNOP}; 	//INC MB
	ma[53]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dMEM,`qFALSE,7'd0, `lkNOP}; 	//INC MB
	ma[54]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPF, `sMB,`oTO,    `dXX, `qMB0,  7'd1, `lkNOP};	   // con MB siamo a zero?
	ma[55]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sPC,`oAPLUS1,`dPC, `qFALSE,7'd0, `lkNOP};	   //INC PC
	ma[56]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};

	// JMS INSTRUCTION
	ma[58]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sPC,`oTO,    `dMB, `qFALSE,7'd0, `lkNOP}; 	//salva PC in testa al subprogr
	ma[59]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oAPLUS1,`dPCMEM, `qFALSE,7'd0, `lkNOP}; //MA+1 -> PC + WR per la RAM
	ma[60]= {`uOP_FILLER,`uOP_LIF, `IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};

	// IRQ PROCESSING																										// *** 23.04.2013 *** dIEF ricavato da LSF
	ma[61]= {`uOP_FILLER,`uOP_LSF, `IOPNOP, `uJPT, `sMB,`o7777,  `dXX, `qFALSE,7'd0, `lkNOP};	 	// interrupt off (IOF)+LOAD SAVE FIELD
//	ma[61]= {`uOP_FILLER,`uOP_LSF, `IOPNOP, `uJPT, `sMB,`o7777,  `dIEF,`qFALSE,7'd0, `lkNOP};	 	// interrupt off (IOF)+LOAD SAVE FIELD
	ma[62]= {`uOP_FILLER,`uOP_CIDF,`IOPNOP, `uJPT, `sMA,`oZERO,  `dAB, `qTRUE,7'd58, `lkNOP};    // 0 -> MA e MB + CLEAR IF AND DF

	// TAD INSTRUCTION
	ma[64]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oAPLUSB,`dAC, `qFALSE,7'd0, `lkNOP}; 	//TAD
	ma[65]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPF, `sAC,`oTO,    `dXX, `qOFL,  7'd1, `lkNOP};    // no carry, salta
	ma[66]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qOFL,  7'd1, `lkCML}; 	// complement LINK e salta

	// GR1 INSTRUCTION
	ma[70]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `s00,`oTO,    `dXX, `qGR2,  7'd36,`lkNOP};   	// Gruppo 2?
	ma[71]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oZERO,  `dAC, `qCLA,  7'd0, `lkNOP};   // CLA
	ma[72]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMA,`oTO,    `dXX, `qCLL,  7'd0, `lkCLL};   // CLL
	ma[73]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oCPL,   `dAC, `qCMA,  7'd0, `lkNOP};   // CMA
	ma[74]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oTO,    `dXX, `qCML,  7'd0, `lkCML};   // CML
	ma[75]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPF, `sAC,`oTO,    `dXX, `qIAC,  7'd79,`lkNOP};   // IAC?
	ma[76]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sAC,`oAPLUS1,`dAC, `qIAC,  7'd0, `lkNOP};   // IAC!
	ma[77]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPF, `sAC,`oTO,    `dXX, `qOFL,  7'd79,`lkNOP};   // no carry, salta
	ma[78]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMB,`oTO,    `dXX, `qTRUE, 7'd1, `lkCML}; 	 // complement LINK e salta

	ma[79]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMA,`oTO,    `dSRA,`qRAR,  7'd0, `lkLSB};   // RAR
	ma[80]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMA,`oTO,    `dSLA,`qRAL,  7'd0, `lkMSB};   // RAL
	ma[81]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPF, `sMA,`oTO,    `dXX, `qTWI,  7'd84,`lkNOP};   // ROTATE TWICE
	ma[82]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMA,`oTO,    `dSRA,`qRAR,  7'd0, `lkLSB};   // RAR	eventuale seconda esecuzione
	ma[83]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uCOND,`sMA,`oTO,    `dSLA,`qRAL,  7'd0, `lkMSB};   // RAL	eventuale seconda esecuzione
	ma[84]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dXX, `qBSW,  7'd90,`lkNOP};   // BSW	(BYTE SWAP)
	ma[85]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMB,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};   // continua con altre istruzioni

	ma[90]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dSLA,`qFALSE,7'd0, `lkNOP};   // RAL
	ma[91]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dSLA,`qFALSE,7'd0, `lkNOP};   // RAL
	ma[92]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dSLA,`qFALSE,7'd0, `lkNOP};   // RAL
	ma[93]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dSLA,`qFALSE,7'd0, `lkNOP};   // RAL
	ma[94]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dSLA,`qFALSE,7'd0, `lkNOP};   // RAL
	ma[95]= {`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dSLA,`qTRUE, 7'd1, `lkNOP};   // RAL

// GTF - get flags into acc
	ma[96]= {`uOP_FILLER,`uOP_NOID,`IOPNOP,`uCOND, `sFLAGS,`oTO, `dAC, `qGTF,  7'd0, `lkNOP};    // sFLAGS qGTF
	ma[97]= {`uOP_FILLER,`uOP_NOID,`IOPNOP,`uJPT,  `sFLAGS,`oTO, `dXX, `qGTF,  7'd1, `lkNOP};    // finished? new fetch

//	CAF - clear AC and flags - not sure what they mean with "flags", for now just AC and link; will see instruction tests
   ma[98]= {`uOP_FILLER,`uOP_NOID,`IOPNOP,`uCOND, `sPC,`oZERO,  `dAC, `qCAF,  7'd0, `lkCLL};    // qCAF
	ma[99]= {`uOP_FILLER,`uOP_NOID,`IOPNOP,`uJPT,  `sFLAGS,`oTO, `dXX, `qCAF,  7'd101, `lkNOP};  // finished? new fetch

//	RTF - restore flags
   ma[100]= {`uOP_FILLER,`uOP_NOID,`IOPNOP,`uCOND, `sAC,`oTO, `dFLAGS, `qRTF,  7'd0, `lkNOP};   // dFLAGS qRTF
   ma[101]= {`uOP_FILLER,`uOP_NOID,`IOPNOP,`uCOND, `sAC,`oTO, `dXX,    `qRTF,  7'd0, `lkRTF};   // dFLAGS qRTF
// RTF is completed as a normal IOT, so no jump now to fetch a new instruction

// SGT - we don't have the EAE, so for us is always a NOP and neither check it

/* poco tempo fa avevo modificato questa parte che era composta da due uistruzioni per ogni IOP
   chiedendomi perché ne avessi messe due di cui la prima era di fatto un NOP e avevo quindi
   commentato la prima di ogni gruppo di due
   Bisogna sempre ricordare che sembra che si fa IOP1, IOP2 e IOP4 per ogni istruzione
   ma in realtà con i tre IOP noi offriamo alla periferica se vuole compiere un'azione
   - skip con IOP1
   - clear AC con IOP2
   - OR periferica to AC con IOP4
   e che una sola è svolta per ciascuna istruzione

   Qui però emerge la debolezza del mio progetto:
   - il vero PDP ammette un numero maggiore di operazioni (es. destinazione PC)
   - noi abbiamo una anomalia, perché ci permettiamo il lusso di passare sempre AC alla
     periferica che può usarlo quando vuole (e dovrebbe rendere le cose più facili)

   Il qualificatore qIOP è originato nella periferica e significa solo la risposta "Sì"
   ai tre quesiti di cui sopra (vuoi skip? vuoi CLA? vuoi darmi un dato per AC?) e viene
   ridotto a un solo filo dalla assign IOP_qual = ... che sta qui sopra (il condition flag è uno solo e
   il suo significato cambia in funzione dello IOP)

   Solo la tastiera però può richiedere l'OR con AC (assign IOP_qual = do_KRS;) quindi non
   sembra che nel nostro caso (TLS, 6046) esso possa scattare.

   Ma allora perché:
   - era stata necessaria la doppia bufferizzazione (R12 TXREG (.in(db_in), .o....)?
   - perché abbiamo avuto tanti problemi a prendere il valore da AC in IOP4, tanto che poi
   (forse sbagliando) l'abbiamo portato in IOP2?
   - perché avevo messo due microistruzioni per ogni IOP?
   Sarebbe interessante rimettere il TXREG e riattivare le doppie microistruzioni
   e vedere che succede.
*/

//	the first IOPxo seems to be not necessary
//	ma[102]= {`uOP_FILLER,`uOP_NOID,`IOP1o, `uJPT, `sMB,`oZERO,   `dXX, `qFALSE,7'd0, `lkNOP};	// forzata a NOP
	ma[102]= {`uOP_FILLER,`uOP_NOID,`IOP1o, `uCOND,`sPC,`oAPLUS1, `dPC, `qIOP,  7'd0, `lkNOP};   // skip

//	ma[104]= {`uOP_FILLER,`uOP_NOID,`IOP2o, `uJPT, `sMB,`oZERO,   `dXX, `qFALSE,7'd0, `lkNOP};
	ma[103]= {`uOP_FILLER,`uOP_NOID,`IOP2o, `uCOND,`sPC,`oZERO,   `dAC, `qIOP,  7'd0, `lkNOP};   // clear accumulator

//	ma[106]={`uOP_FILLER,`uOP_NOID,`IOP4o, `uJPT, `sMB,`oZERO,   `dXX, `qFALSE,7'd0, `lkNOP};
	ma[104]={`uOP_FILLER,`uOP_NOID,`IOP4o, `uCOND,`sIN,`oAORB,   `dAC, `qIOP,  7'd0, `lkNOP};    // OR accumulator from IN bus

	ma[105]={`uOP_FILLER,`uOP_NOID,`IOPNOP,`uJPT, `sMA,`oTO,     `dXX, `qTRUE, 7'd1, `lkNOP};

	// HALT STATE
	ma[120]={`uOP_FILLER,`uOP_NOID,`IOPNOP, `uJPT, `sMA,`oTO,    `dXX, `qTRUE, 7'd1, `lkNOP};
	end
endmodule

// queste sarebbero combinazioni di due istruzioni che io faccio in colpo solo, per� mi costringe ad avere un mux in pi�
//	ma[28]= {`uJPT,`sMA,`oTO,    `dXX, `mRD, `qFALSE,6'd0, `lkSTL}; 	 // STL (CLL+CML)
//	ma[29]= {`uJPT,`s00,`o7777,  `dAC, `mRD, `qFALSE,6'd0, `lkNOP};      // STA	(CLA+CMA)
//	ma[30]= {`uJPT,`s00,`o2CP,   `dAC, `mRD, `qFALSE,6'd0, `lkNOP};   	 // CIA	(CMA+IAC)
//	ma[31]= {`uJPT,`sMA,`oTO,    `dXX, `mRD, `qFALSE,6'd0, `lkNOP};      // NOP
//	ma[32]= {`uJPT,`sAC,`oZERO,  `dAC, `mRD, `qFALSE,6'd0, `lkNOP};      // CLA





