data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v
1: b'%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:45: Cannot find include file: openMSP430_defines.v\n`include "openMSP430_defines.v" \n         ^~~~~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/152581089/Verilog/MSP430,data/full_repos/permissive/152581089/openMSP430_defines.v\n             data/full_repos/permissive/152581089/Verilog/MSP430,data/full_repos/permissive/152581089/openMSP430_defines.v.v\n             data/full_repos/permissive/152581089/Verilog/MSP430,data/full_repos/permissive/152581089/openMSP430_defines.v.sv\n             openMSP430_defines.v\n             openMSP430_defines.v.v\n             openMSP430_defines.v.sv\n             obj_dir/openMSP430_defines.v\n             obj_dir/openMSP430_defines.v.v\n             obj_dir/openMSP430_defines.v.sv\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:987: Cannot find include file: openMSP430_undefines.v\n`include "openMSP430_undefines.v" \n         ^~~~~~~~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:117: Define or directive not defined: \'`IRQ_NR\'\noutput [`IRQ_NR-3:0] irq_acc;        \n        ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:134: Define or directive not defined: \'`IRQ_NR\'\ninput  [`IRQ_NR-3:0] irq;            \n        ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:199: Define or directive not defined: \'`I_IRQ_FETCH\'\nparameter I_IRQ_FETCH = `I_IRQ_FETCH;\n                        ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:199: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter I_IRQ_FETCH = `I_IRQ_FETCH;\n                                    ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:200: Define or directive not defined: \'`I_IRQ_DONE\'\nparameter I_IRQ_DONE  = `I_IRQ_DONE;\n                        ^~~~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:200: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter I_IRQ_DONE  = `I_IRQ_DONE;\n                                   ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:201: Define or directive not defined: \'`I_DEC\'\nparameter I_DEC       = `I_DEC;         \n                        ^~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:201: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter I_DEC       = `I_DEC;         \n                              ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:202: Define or directive not defined: \'`I_EXT1\'\nparameter I_EXT1      = `I_EXT1;        \n                        ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:202: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter I_EXT1      = `I_EXT1;        \n                               ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:203: Define or directive not defined: \'`I_EXT2\'\nparameter I_EXT2      = `I_EXT2;        \n                        ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:203: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter I_EXT2      = `I_EXT2;        \n                               ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:204: Define or directive not defined: \'`I_IDLE\'\nparameter I_IDLE      = `I_IDLE;        \n                        ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:204: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter I_IDLE      = `I_IDLE;        \n                               ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:210: Define or directive not defined: \'`E_IRQ_0\'\nparameter E_IRQ_0     = `E_IRQ_0;\n                        ^~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:210: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_IRQ_0     = `E_IRQ_0;\n                                ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:211: Define or directive not defined: \'`E_IRQ_1\'\nparameter E_IRQ_1     = `E_IRQ_1;\n                        ^~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:211: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_IRQ_1     = `E_IRQ_1;\n                                ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:212: Define or directive not defined: \'`E_IRQ_2\'\nparameter E_IRQ_2     = `E_IRQ_2;\n                        ^~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:212: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_IRQ_2     = `E_IRQ_2;\n                                ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:213: Define or directive not defined: \'`E_IRQ_3\'\nparameter E_IRQ_3     = `E_IRQ_3;\n                        ^~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:213: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_IRQ_3     = `E_IRQ_3;\n                                ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:214: Define or directive not defined: \'`E_IRQ_4\'\nparameter E_IRQ_4     = `E_IRQ_4;\n                        ^~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:214: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_IRQ_4     = `E_IRQ_4;\n                                ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:215: Define or directive not defined: \'`E_SRC_AD\'\nparameter E_SRC_AD    = `E_SRC_AD;\n                        ^~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:215: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_SRC_AD    = `E_SRC_AD;\n                                 ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:216: Define or directive not defined: \'`E_SRC_RD\'\nparameter E_SRC_RD    = `E_SRC_RD;\n                        ^~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:216: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_SRC_RD    = `E_SRC_RD;\n                                 ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:217: Define or directive not defined: \'`E_SRC_WR\'\nparameter E_SRC_WR    = `E_SRC_WR;\n                        ^~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:217: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_SRC_WR    = `E_SRC_WR;\n                                 ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:218: Define or directive not defined: \'`E_DST_AD\'\nparameter E_DST_AD    = `E_DST_AD;\n                        ^~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:218: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_DST_AD    = `E_DST_AD;\n                                 ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:219: Define or directive not defined: \'`E_DST_RD\'\nparameter E_DST_RD    = `E_DST_RD;\n                        ^~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:219: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_DST_RD    = `E_DST_RD;\n                                 ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:220: Define or directive not defined: \'`E_DST_WR\'\nparameter E_DST_WR    = `E_DST_WR;\n                        ^~~~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:220: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_DST_WR    = `E_DST_WR;\n                                 ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:221: Define or directive not defined: \'`E_EXEC\'\nparameter E_EXEC      = `E_EXEC;\n                        ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:221: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_EXEC      = `E_EXEC;\n                               ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:222: Define or directive not defined: \'`E_JUMP\'\nparameter E_JUMP      = `E_JUMP;\n                        ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:222: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_JUMP      = `E_JUMP;\n                               ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:223: Define or directive not defined: \'`E_IDLE\'\nparameter E_IDLE      = `E_IDLE;\n                        ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:223: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\nparameter E_IDLE      = `E_IDLE;\n                               ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:321: syntax error, unexpected \'{\'\n                          {1\'b0,    3\'h0, wdt_irq, {58{1\'b0}}};\n                          ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:339: Define or directive not defined: \'`IRQ_NR\'\nwire [`IRQ_NR-3:0] irq_acc     = irq_acc_all[61:64-`IRQ_NR];\n      ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:339: Define or directive not defined: \'`IRQ_NR\'\nwire [`IRQ_NR-3:0] irq_acc     = irq_acc_all[61:64-`IRQ_NR];\n                                                   ^~~~~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:339: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nwire [`IRQ_NR-3:0] irq_acc     = irq_acc_all[61:64-`IRQ_NR];\n                                                          ^\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:423: Define or directive not defined: \'`IDX\'\nwire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);\n                        ^~~~\n%Error: data/full_repos/permissive/152581089/Verilog/MSP430/omsp_frontend.v:423: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nwire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);\n                            ^\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module  omsp_frontend (


    dbg_halt_st,
    decode_noirq,
    e_state,
    exec_done,
    inst_ad,
    inst_as,
    inst_alu,
    inst_bw,
    inst_dest,
    inst_dext,
    inst_irq_rst,
    inst_jmp,
    inst_mov,
    inst_sext,
    inst_so,
    inst_src,
    inst_type,
    irq_acc,
    mab,
    mb_en,
    mclk_enable,
    mclk_wkup,
    nmi_acc,
    pc,
    pc_nxt,


    cpu_en_s,
    cpuoff,
    dbg_halt_cmd,
    dbg_reg_sel,
    fe_pmem_wait,
    gie,
    irq,
    mclk,
    mdb_in,
    nmi_pnd,
    nmi_wkup,
    pc_sw,
    pc_sw_wr,
    puc_rst,
    scan_enable,
    wdt_irq,
    wdt_wkup,
    wkup
);



output               dbg_halt_st;
output               decode_noirq;
output         [3:0] e_state;
output               exec_done;
output         [7:0] inst_ad;
output         [7:0] inst_as;
output        [11:0] inst_alu;
output               inst_bw;
output        [15:0] inst_dest;
output        [15:0] inst_dext;
output               inst_irq_rst;
output         [7:0] inst_jmp;
output               inst_mov;
output        [15:0] inst_sext;
output         [7:0] inst_so;
output        [15:0] inst_src;
output         [2:0] inst_type;
output [`IRQ_NR-3:0] irq_acc;
output        [15:0] mab;
output               mb_en;
output               mclk_enable;
output               mclk_wkup;
output               nmi_acc;
output        [15:0] pc;
output        [15:0] pc_nxt;



input                cpu_en_s;
input                cpuoff;
input                dbg_halt_cmd;
input          [3:0] dbg_reg_sel;
input                fe_pmem_wait;
input                gie;
input  [`IRQ_NR-3:0] irq;
input                mclk;
input         [15:0] mdb_in;
input                nmi_pnd;
input                nmi_wkup;
input         [15:0] pc_sw;
input                pc_sw_wr;
input                puc_rst;
input                scan_enable;
input                wdt_irq;
input                wdt_wkup;
input                wkup;







function [63:0] one_hot64;
   input  [5:0] binary;
   begin
      one_hot64         = 64'h0000_0000_0000_0000;
      one_hot64[binary] =  1'b1;
   end
endfunction


function [15:0] one_hot16;
   input  [3:0] binary;
   begin
      one_hot16         = 16'h0000;
      one_hot16[binary] =  1'b1;
   end
endfunction


function [7:0] one_hot8;
   input  [2:0] binary;
   begin
      one_hot8         = 8'h00;
      one_hot8[binary] = 1'b1;
   end
endfunction


function  [5:0] get_irq_num;
   input [62:0] irq_all;
   integer      ii;
   begin
      get_irq_num = 6'h3f;
      for (ii = 62; ii >= 0; ii = ii - 1)
        if (&get_irq_num & irq_all[ii]) get_irq_num = ii[5:0];
   end
endfunction
   









parameter I_IRQ_FETCH = `I_IRQ_FETCH;
parameter I_IRQ_DONE  = `I_IRQ_DONE;
parameter I_DEC       = `I_DEC;
parameter I_EXT1      = `I_EXT1;
parameter I_EXT2      = `I_EXT2;
parameter I_IDLE      = `I_IDLE;





parameter E_IRQ_0     = `E_IRQ_0;
parameter E_IRQ_1     = `E_IRQ_1;
parameter E_IRQ_2     = `E_IRQ_2;
parameter E_IRQ_3     = `E_IRQ_3;
parameter E_IRQ_4     = `E_IRQ_4;
parameter E_SRC_AD    = `E_SRC_AD;
parameter E_SRC_RD    = `E_SRC_RD;
parameter E_SRC_WR    = `E_SRC_WR;
parameter E_DST_AD    = `E_DST_AD;
parameter E_DST_RD    = `E_DST_RD;
parameter E_DST_WR    = `E_DST_WR;
parameter E_EXEC      = `E_EXEC;
parameter E_JUMP      = `E_JUMP;
parameter E_IDLE      = `E_IDLE;







reg  [2:0] i_state;
reg  [2:0] i_state_nxt;

reg  [1:0] inst_sz;
wire [1:0] inst_sz_nxt;
wire       irq_detect;
wire [2:0] inst_type_nxt;
wire       is_const;
reg [15:0] sconst_nxt;
reg  [3:0] e_state_nxt;
           

wire   cpu_halt_cmd = dbg_halt_cmd | ~cpu_en_s;
   

always @(i_state    or inst_sz  or inst_sz_nxt  or pc_sw_wr or exec_done or
         irq_detect or cpuoff   or cpu_halt_cmd or e_state)
    case(i_state)
      I_IDLE     : i_state_nxt = (irq_detect & ~cpu_halt_cmd) ? I_IRQ_FETCH :
                                 (~cpuoff    & ~cpu_halt_cmd) ? I_DEC       : I_IDLE;
      I_IRQ_FETCH: i_state_nxt =  I_IRQ_DONE;
      I_IRQ_DONE : i_state_nxt =  I_DEC;
      I_DEC      : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
                          (cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE      :
                            cpu_halt_cmd & (e_state==E_IDLE)  ? I_IDLE      :
                                  pc_sw_wr                    ? I_DEC       :
                             ~exec_done & ~(e_state==E_IDLE)  ? I_DEC       :
                                  (inst_sz_nxt!=2'b00)        ? I_EXT1      : I_DEC;
      I_EXT1     : i_state_nxt =  pc_sw_wr                    ? I_DEC       : 
                                  (inst_sz!=2'b01)            ? I_EXT2      : I_DEC;
      I_EXT2     : i_state_nxt =  I_DEC;

      default    : i_state_nxt =  I_IRQ_FETCH;

    endcase


always @(posedge mclk or posedge puc_rst)
  if (puc_rst) i_state  <= I_IRQ_FETCH;
  else         i_state  <= i_state_nxt;


wire   decode_noirq =  ((i_state==I_DEC) &  (exec_done | (e_state==E_IDLE)));
wire   decode       =  decode_noirq | irq_detect;
wire   fetch        = ~((i_state==I_DEC) & ~(exec_done | (e_state==E_IDLE))) & ~(e_state_nxt==E_IDLE);


reg    dbg_halt_st;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)  dbg_halt_st <= 1'b0;
  else          dbg_halt_st <= cpu_halt_cmd & (i_state_nxt==I_IDLE);











reg         inst_irq_rst;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                  inst_irq_rst <= 1'b1;
  else if (exec_done)           inst_irq_rst <= 1'b0;


assign  irq_detect = (nmi_pnd | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE));

`ifdef CLOCK_GATING
wire       mclk_irq_num;
omsp_clock_gate clock_gate_irq_num (.gclk(mclk_irq_num),
                                    .clk (mclk), .enable(irq_detect), .scan_enable(scan_enable));
`else
wire       mclk_irq_num = mclk;
`endif


`ifdef  IRQ_16
wire [62:0] irq_all     = {nmi_pnd, irq, 48'h0000_0000_0000} |
`else
`ifdef  IRQ_32
wire [62:0] irq_all     = {nmi_pnd, irq, 32'h0000}           |
`else
`ifdef  IRQ_64
wire [62:0] irq_all     = {nmi_pnd, irq}                     |
`endif
`endif
`endif
                          {1'b0,    3'h0, wdt_irq, {58{1'b0}}};


reg  [5:0] irq_num;
always @(posedge mclk_irq_num or posedge puc_rst)
  if (puc_rst)         irq_num <= 6'h3f;
`ifdef CLOCK_GATING
  else
`else
  else if (irq_detect)
`endif
                       irq_num <= get_irq_num(irq_all);


wire [15:0] irq_addr    = {9'h1ff, irq_num, 1'b0};


wire        [63:0] irq_acc_all = one_hot64(irq_num) & {64{(i_state==I_IRQ_FETCH)}};
wire [`IRQ_NR-3:0] irq_acc     = irq_acc_all[61:64-`IRQ_NR];
wire               nmi_acc     = irq_acc_all[62];




`ifdef CPUOFF_EN



wire mclk_enable = inst_irq_rst ? cpu_en_s :


                  ~((cpuoff | ~cpu_en_s) &
                   (i_state==I_IDLE) &
                   (e_state==E_IDLE));

   

wire mirq_wkup;
omsp_and_gate and_mirq_wkup (.y(mirq_wkup), .a(wkup | wdt_wkup), .b(gie));


omsp_and_gate and_mclk_wkup (.y(mclk_wkup), .a(nmi_wkup | mirq_wkup), .b(cpu_en_s));

`else


assign  mclk_wkup   = 1'b1;
assign  mclk_enable = 1'b1;
`endif










reg  [15:0] pc;


wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
wire [15:0] pc_nxt  = pc_sw_wr               ? pc_sw    :
                      (i_state==I_IRQ_FETCH) ? irq_addr :
                      (i_state==I_IRQ_DONE)  ? mdb_in   :  pc_incr;

`ifdef CLOCK_GATING
wire       pc_en  = fetch                  |
                    pc_sw_wr               |
                    (i_state==I_IRQ_FETCH) |
                    (i_state==I_IRQ_DONE);
wire       mclk_pc;
omsp_clock_gate clock_gate_pc (.gclk(mclk_pc),
                               .clk (mclk), .enable(pc_en), .scan_enable(scan_enable));
`else
wire       mclk_pc = mclk;
`endif

always @(posedge mclk_pc or posedge puc_rst)
  if (puc_rst)  pc <= 16'h0000;
  else          pc <= pc_nxt;


reg pmem_busy;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)  pmem_busy <= 1'b0;
  else          pmem_busy <= fe_pmem_wait;
   

wire [15:0] mab      = pc_nxt;
wire        mb_en    = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~cpu_halt_cmd);







wire [15:0] ir  = mdb_in;


wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);



wire [15:0] ext_incr = ((i_state==I_EXT1)     &  inst_as[`SYMB]) |
                       ((i_state==I_EXT2)     &  inst_ad[`SYMB]) |
                       ((i_state==I_EXT1)     & ~inst_as[`SYMB] &
                       ~(i_state_nxt==I_EXT2) &  inst_ad[`SYMB])   ? 16'hfffe : 16'h0000;

wire [15:0] ext_nxt  = ir + ext_incr;


reg [15:0] inst_sext;

`ifdef CLOCK_GATING
wire       inst_sext_en  = (decode & is_const)                 |
                           (decode & inst_type_nxt[`INST_JMP]) |
                           ((i_state==I_EXT1) & is_sext);
wire       mclk_inst_sext;
omsp_clock_gate clock_gate_inst_sext (.gclk(mclk_inst_sext),
                                      .clk (mclk), .enable(inst_sext_en), .scan_enable(scan_enable));
`else
wire       mclk_inst_sext = mclk;
`endif

always @(posedge mclk_inst_sext or posedge puc_rst)
  if (puc_rst)                                 inst_sext <= 16'h0000;
  else if (decode & is_const)                  inst_sext <= sconst_nxt;
  else if (decode & inst_type_nxt[`INST_JMP])  inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
`ifdef CLOCK_GATING
  else                                         inst_sext <= ext_nxt;
`else
  else if ((i_state==I_EXT1) & is_sext)        inst_sext <= ext_nxt;
`endif


wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;



reg [15:0] inst_dext;

`ifdef CLOCK_GATING
wire       inst_dext_en  = ((i_state==I_EXT1) & ~is_sext) |
                            (i_state==I_EXT2);
wire       mclk_inst_dext;
omsp_clock_gate clock_gate_inst_dext (.gclk(mclk_inst_dext),
                                      .clk (mclk), .enable(inst_dext_en), .scan_enable(scan_enable));
`else
wire       mclk_inst_dext = mclk;
`endif

always @(posedge mclk_inst_dext or posedge puc_rst)
  if (puc_rst)                           inst_dext <= 16'h0000;
  else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
`ifdef CLOCK_GATING
  else                                   inst_dext <= ext_nxt;
`else
  else if  (i_state==I_EXT2)             inst_dext <= ext_nxt;
`endif


wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));






`ifdef CLOCK_GATING
wire       mclk_decode;
omsp_clock_gate clock_gate_decode (.gclk(mclk_decode),
                                   .clk (mclk), .enable(decode), .scan_enable(scan_enable));
`else
wire       mclk_decode = mclk;
`endif










reg  [2:0] inst_type;
assign     inst_type_nxt = {(ir[15:14]!=2'b00),
                            (ir[15:13]==3'b001),
                            (ir[15:13]==3'b000)} & {3{~irq_detect}};
   
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)      inst_type <= 3'b000;
`ifdef CLOCK_GATING
  else              inst_type <= inst_type_nxt;
`else
  else if (decode)  inst_type <= inst_type_nxt;
`endif















reg   [7:0] inst_so;
wire  [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});

always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_so <= 8'h00;
`ifdef CLOCK_GATING
  else             inst_so <= inst_so_nxt;
`else
  else if (decode) inst_so <= inst_so_nxt;
`endif















reg   [2:0] inst_jmp_bin;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_jmp_bin <= 3'h0;
`ifdef CLOCK_GATING
  else             inst_jmp_bin <= ir[12:10];
`else
  else if (decode) inst_jmp_bin <= ir[12:10];
`endif

wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}};




















wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
wire [11:0] inst_to_nxt  = inst_to_1hot[15:4];

reg         inst_mov;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_mov <= 1'b0;
`ifdef CLOCK_GATING
  else             inst_mov <= inst_to_nxt[`MOV];
`else
  else if (decode) inst_mov <= inst_to_nxt[`MOV];
`endif







reg [3:0] inst_dest_bin;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_dest_bin <= 4'h0;
`ifdef CLOCK_GATING
  else             inst_dest_bin <= ir[3:0];
`else
  else if (decode) inst_dest_bin <= ir[3:0];
`endif

wire  [15:0] inst_dest = dbg_halt_st          ? one_hot16(dbg_reg_sel) :
                         inst_type[`INST_JMP] ? 16'h0001               :
                         inst_so[`IRQ]  |
                         inst_so[`PUSH] |
                         inst_so[`CALL]       ? 16'h0002               :
                                                one_hot16(inst_dest_bin);



reg [3:0] inst_src_bin;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_src_bin <= 4'h0;
`ifdef CLOCK_GATING
  else             inst_src_bin <= ir[11:8];
`else
  else if (decode) inst_src_bin <= ir[11:8];
`endif

wire  [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin)  :
                        inst_so[`RETI]      ? 16'h0002                 :
                        inst_so[`IRQ]       ? 16'h0001                 :
                        inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000;





















reg [12:0] inst_as_nxt;

wire [3:0] src_reg = inst_type_nxt[`INST_SO] ? ir[3:0] : ir[11:8];

always @(src_reg or ir or inst_type_nxt)
  begin
     if (inst_type_nxt[`INST_JMP])
       inst_as_nxt =  13'b0000000000001;
     else if (src_reg==4'h3)
       case (ir[5:4])
         2'b11  : inst_as_nxt =  13'b1000000000000;
         2'b10  : inst_as_nxt =  13'b0100000000000;
         2'b01  : inst_as_nxt =  13'b0010000000000;
         default: inst_as_nxt =  13'b0001000000000;
       endcase
     else if (src_reg==4'h2)
       case (ir[5:4])
         2'b11  : inst_as_nxt =  13'b0000100000000;
         2'b10  : inst_as_nxt =  13'b0000010000000;
         2'b01  : inst_as_nxt =  13'b0000001000000;
         default: inst_as_nxt =  13'b0000000000001;
       endcase
     else if (src_reg==4'h0)
       case (ir[5:4])
         2'b11  : inst_as_nxt =  13'b0000000100000;
         2'b10  : inst_as_nxt =  13'b0000000000100;
         2'b01  : inst_as_nxt =  13'b0000000010000;
         default: inst_as_nxt =  13'b0000000000001;
       endcase
     else
       case (ir[5:4])
         2'b11  : inst_as_nxt =  13'b0000000001000;
         2'b10  : inst_as_nxt =  13'b0000000000100;
         2'b01  : inst_as_nxt =  13'b0000000000010;
         default: inst_as_nxt =  13'b0000000000001;
       endcase
  end
assign    is_const = |inst_as_nxt[12:7];

reg [7:0] inst_as;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_as <= 8'h00;
`ifdef CLOCK_GATING
  else             inst_as <= {is_const, inst_as_nxt[6:0]};
`else
  else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
`endif








always @(inst_as_nxt)
  begin
     if (inst_as_nxt[7])        sconst_nxt = 16'h0004;
     else if (inst_as_nxt[8])   sconst_nxt = 16'h0008;
     else if (inst_as_nxt[9])   sconst_nxt = 16'h0000;
     else if (inst_as_nxt[10])  sconst_nxt = 16'h0001;
     else if (inst_as_nxt[11])  sconst_nxt = 16'h0002;
     else if (inst_as_nxt[12])  sconst_nxt = 16'hffff;
     else                       sconst_nxt = 16'h0000;
  end












reg  [7:0] inst_ad_nxt;

wire [3:0] dest_reg = ir[3:0];

always @(dest_reg or ir or inst_type_nxt)
  begin
     if (~inst_type_nxt[`INST_TO])
       inst_ad_nxt =  8'b00000000;
     else if (dest_reg==4'h2)
       case (ir[7])
         1'b1   : inst_ad_nxt =  8'b01000000;
         default: inst_ad_nxt =  8'b00000001;
       endcase
     else if (dest_reg==4'h0)
       case (ir[7])
         1'b1   : inst_ad_nxt =  8'b00010000;
         default: inst_ad_nxt =  8'b00000001;
       endcase
     else
       case (ir[7])
         1'b1   : inst_ad_nxt =  8'b00000010;
         default: inst_ad_nxt =  8'b00000001;
       endcase
  end

reg [7:0] inst_ad;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_ad <= 8'h00;
`ifdef CLOCK_GATING
  else             inst_ad <= inst_ad_nxt;
`else
  else if (decode) inst_ad <= inst_ad_nxt;
`endif







reg       inst_bw;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)     inst_bw     <= 1'b0;
  else if (decode) inst_bw     <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_cmd;


assign    inst_sz_nxt = {1'b0,  (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
                        {1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_sz     <= 2'b00;
`ifdef CLOCK_GATING
  else             inst_sz     <= inst_sz_nxt;
`else
  else if (decode) inst_sz     <= inst_sz_nxt;
`endif







reg  [3:0] e_state;





wire src_acalc_pre =  inst_as_nxt[`IDX]   | inst_as_nxt[`SYMB]    | inst_as_nxt[`ABS];
wire src_rd_pre    =  inst_as_nxt[`INDIR] | inst_as_nxt[`INDIR_I] | inst_as_nxt[`IMM]  | inst_so_nxt[`RETI];
wire dst_acalc_pre =  inst_ad_nxt[`IDX]   | inst_ad_nxt[`SYMB]    | inst_ad_nxt[`ABS];
wire dst_acalc     =  inst_ad[`IDX]       | inst_ad[`SYMB]        | inst_ad[`ABS];
wire dst_rd_pre    =  inst_ad_nxt[`IDX]   | inst_so_nxt[`PUSH]    | inst_so_nxt[`CALL] | inst_so_nxt[`RETI];
wire dst_rd        =  inst_ad[`IDX]       | inst_so[`PUSH]        | inst_so[`CALL]     | inst_so[`RETI];

wire inst_branch   =  (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI];

reg exec_jmp;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                   exec_jmp <= 1'b0;
  else if (inst_branch & decode) exec_jmp <= 1'b1;
  else if (e_state==E_JUMP)      exec_jmp <= 1'b0;

reg exec_dst_wr;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                exec_dst_wr <= 1'b0;
  else if (e_state==E_DST_RD) exec_dst_wr <= 1'b1;
  else if (e_state==E_DST_WR) exec_dst_wr <= 1'b0;

reg exec_src_wr;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                                         exec_src_wr <= 1'b0;
  else if (inst_type[`INST_SO] & (e_state==E_SRC_RD))  exec_src_wr <= 1'b1;
  else if ((e_state==E_SRC_WR) || (e_state==E_DST_WR)) exec_src_wr <= 1'b0;

reg exec_dext_rdy;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                exec_dext_rdy <= 1'b0;
  else if (e_state==E_DST_RD) exec_dext_rdy <= 1'b0;
  else if (inst_dext_rdy)     exec_dext_rdy <= 1'b1;


wire [3:0] e_first_state = ~dbg_halt_st  & inst_so_nxt[`IRQ] ? E_IRQ_0  :
                            cpu_halt_cmd | (i_state==I_IDLE) ? E_IDLE   :
                            cpuoff                           ? E_IDLE   :
                            src_acalc_pre                    ? E_SRC_AD :
                            src_rd_pre                       ? E_SRC_RD :
                            dst_acalc_pre                    ? E_DST_AD :
                            dst_rd_pre                       ? E_DST_RD : E_EXEC;






always @(e_state       or dst_acalc     or dst_rd   or inst_sext_rdy or
         inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr   or
         e_first_state or exec_src_wr)
    case(e_state)
      E_IDLE   : e_state_nxt =  e_first_state;
      E_IRQ_0  : e_state_nxt =  E_IRQ_1;
      E_IRQ_1  : e_state_nxt =  E_IRQ_2;
      E_IRQ_2  : e_state_nxt =  E_IRQ_3;
      E_IRQ_3  : e_state_nxt =  E_IRQ_4;
      E_IRQ_4  : e_state_nxt =  E_EXEC;

      E_SRC_AD : e_state_nxt =  inst_sext_rdy     ? E_SRC_RD : E_SRC_AD;

      E_SRC_RD : e_state_nxt =  dst_acalc         ? E_DST_AD : 
                                 dst_rd           ? E_DST_RD : E_EXEC;

      E_DST_AD : e_state_nxt =  (inst_dext_rdy |
                                 exec_dext_rdy)   ? E_DST_RD : E_DST_AD;

      E_DST_RD : e_state_nxt =  E_EXEC;

      E_EXEC   : e_state_nxt =  exec_dst_wr       ? E_DST_WR :
                                exec_jmp          ? E_JUMP   :
                                exec_src_wr       ? E_SRC_WR : e_first_state;

      E_JUMP   : e_state_nxt =  e_first_state;
      E_DST_WR : e_state_nxt =  exec_jmp          ? E_JUMP   : e_first_state;
      E_SRC_WR : e_state_nxt =  e_first_state;

      default  : e_state_nxt =  E_IRQ_0;

    endcase


always @(posedge mclk or posedge puc_rst)
  if (puc_rst) e_state  <= E_IRQ_1;
  else         e_state  <= e_state_nxt;





wire exec_done = exec_jmp        ? (e_state==E_JUMP)   :
                 exec_dst_wr     ? (e_state==E_DST_WR) :
                 exec_src_wr     ? (e_state==E_SRC_WR) : (e_state==E_EXEC);























reg  [11:0] inst_alu;

wire        alu_src_inv   = inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
                            inst_to_nxt[`CMP]  | inst_to_nxt[`BIC] ;

wire        alu_inc       = inst_to_nxt[`SUB]  | inst_to_nxt[`CMP];

wire        alu_inc_c     = inst_to_nxt[`ADDC] | inst_to_nxt[`DADD] |
                            inst_to_nxt[`SUBC];

wire        alu_add       = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC]       |
                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC]       |
                            inst_to_nxt[`CMP]  | inst_type_nxt[`INST_JMP] |
                            inst_so_nxt[`RETI];

 
wire        alu_and       = inst_to_nxt[`AND]  | inst_to_nxt[`BIC]  |
                            inst_to_nxt[`BIT];

wire        alu_or        = inst_to_nxt[`BIS];

wire        alu_xor       = inst_to_nxt[`XOR];

wire        alu_dadd      = inst_to_nxt[`DADD];

wire        alu_stat_7    = inst_to_nxt[`BIT]  | inst_to_nxt[`AND]  |
                            inst_so_nxt[`SXT];

wire        alu_stat_f    = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC] |
                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
                            inst_to_nxt[`CMP]  | inst_to_nxt[`DADD] |
                            inst_to_nxt[`BIT]  | inst_to_nxt[`XOR]  |
                            inst_to_nxt[`AND]  |
                            inst_so_nxt[`RRC]  | inst_so_nxt[`RRA]  |
                            inst_so_nxt[`SXT];

wire        alu_shift     = inst_so_nxt[`RRC]  | inst_so_nxt[`RRA];

wire        exec_no_wr    = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];

wire [11:0] inst_alu_nxt  = {exec_no_wr,
                             alu_shift,
                             alu_stat_f,
                             alu_stat_7,
                             alu_dadd,
                             alu_xor,
                             alu_or,
                             alu_and,
                             alu_add,
                             alu_inc_c,
                             alu_inc,
                             alu_src_inv};

always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_alu <= 12'h000;
`ifdef CLOCK_GATING
  else             inst_alu <= inst_alu_nxt;
`else
  else if (decode) inst_alu <= inst_alu_nxt;
`endif


endmodule
module  omsp_frontend (


    dbg_halt_st,
    decode_noirq,
    e_state,
    exec_done,
    inst_ad,
    inst_as,
    inst_alu,
    inst_bw,
    inst_dest,
    inst_dext,
    inst_irq_rst,
    inst_jmp,
    inst_mov,
    inst_sext,
    inst_so,
    inst_src,
    inst_type,
    irq_acc,
    mab,
    mb_en,
    mclk_enable,
    mclk_wkup,
    nmi_acc,
    pc,
    pc_nxt,


    cpu_en_s,
    cpuoff,
    dbg_halt_cmd,
    dbg_reg_sel,
    fe_pmem_wait,
    gie,
    irq,
    mclk,
    mdb_in,
    nmi_pnd,
    nmi_wkup,
    pc_sw,
    pc_sw_wr,
    puc_rst,
    scan_enable,
    wdt_irq,
    wdt_wkup,
    wkup
);




output               dbg_halt_st;
output               decode_noirq;
output         [3:0] e_state;
output               exec_done;
output         [7:0] inst_ad;
output         [7:0] inst_as;
output        [11:0] inst_alu;
output               inst_bw;
output        [15:0] inst_dest;
output        [15:0] inst_dext;
output               inst_irq_rst;
output         [7:0] inst_jmp;
output               inst_mov;
output        [15:0] inst_sext;
output         [7:0] inst_so;
output        [15:0] inst_src;
output         [2:0] inst_type;
output [`IRQ_NR-3:0] irq_acc;
output        [15:0] mab;
output               mb_en;
output               mclk_enable;
output               mclk_wkup;
output               nmi_acc;
output        [15:0] pc;
output        [15:0] pc_nxt;



input                cpu_en_s;
input                cpuoff;
input                dbg_halt_cmd;
input          [3:0] dbg_reg_sel;
input                fe_pmem_wait;
input                gie;
input  [`IRQ_NR-3:0] irq;
input                mclk;
input         [15:0] mdb_in;
input                nmi_pnd;
input                nmi_wkup;
input         [15:0] pc_sw;
input                pc_sw_wr;
input                puc_rst;
input                scan_enable;
input                wdt_irq;
input                wdt_wkup;
input                wkup;







function [63:0] one_hot64;
   input  [5:0] binary;
   begin
      one_hot64         = 64'h0000_0000_0000_0000;
      one_hot64[binary] =  1'b1;
   end
endfunction


function [15:0] one_hot16;
   input  [3:0] binary;
   begin
      one_hot16         = 16'h0000;
      one_hot16[binary] =  1'b1;
   end
endfunction


function [7:0] one_hot8;
   input  [2:0] binary;
   begin
      one_hot8         = 8'h00;
      one_hot8[binary] = 1'b1;
   end
endfunction


function  [5:0] get_irq_num;
   input [62:0] irq_all;
   integer      ii;
   begin
      get_irq_num = 6'h3f;
      for (ii = 62; ii >= 0; ii = ii - 1)
        if (&get_irq_num & irq_all[ii]) get_irq_num = ii[5:0];
   end
endfunction
   









parameter I_IRQ_FETCH = `I_IRQ_FETCH;
parameter I_IRQ_DONE  = `I_IRQ_DONE;
parameter I_DEC       = `I_DEC;
parameter I_EXT1      = `I_EXT1;
parameter I_EXT2      = `I_EXT2;
parameter I_IDLE      = `I_IDLE;





parameter E_IRQ_0     = `E_IRQ_0;
parameter E_IRQ_1     = `E_IRQ_1;
parameter E_IRQ_2     = `E_IRQ_2;
parameter E_IRQ_3     = `E_IRQ_3;
parameter E_IRQ_4     = `E_IRQ_4;
parameter E_SRC_AD    = `E_SRC_AD;
parameter E_SRC_RD    = `E_SRC_RD;
parameter E_SRC_WR    = `E_SRC_WR;
parameter E_DST_AD    = `E_DST_AD;
parameter E_DST_RD    = `E_DST_RD;
parameter E_DST_WR    = `E_DST_WR;
parameter E_EXEC      = `E_EXEC;
parameter E_JUMP      = `E_JUMP;
parameter E_IDLE      = `E_IDLE;







reg  [2:0] i_state;
reg  [2:0] i_state_nxt;

reg  [1:0] inst_sz;
wire [1:0] inst_sz_nxt;
wire       irq_detect;
wire [2:0] inst_type_nxt;
wire       is_const;
reg [15:0] sconst_nxt;
reg  [3:0] e_state_nxt;
           

wire   cpu_halt_cmd = dbg_halt_cmd | ~cpu_en_s;
   

always @(i_state    or inst_sz  or inst_sz_nxt  or pc_sw_wr or exec_done or
         irq_detect or cpuoff   or cpu_halt_cmd or e_state)
    case(i_state)
      I_IDLE     : i_state_nxt = (irq_detect & ~cpu_halt_cmd) ? I_IRQ_FETCH :
                                 (~cpuoff    & ~cpu_halt_cmd) ? I_DEC       : I_IDLE;
      I_IRQ_FETCH: i_state_nxt =  I_IRQ_DONE;
      I_IRQ_DONE : i_state_nxt =  I_DEC;
      I_DEC      : i_state_nxt =  irq_detect                  ? I_IRQ_FETCH :
                          (cpuoff | cpu_halt_cmd) & exec_done ? I_IDLE      :
                            cpu_halt_cmd & (e_state==E_IDLE)  ? I_IDLE      :
                                  pc_sw_wr                    ? I_DEC       :
                             ~exec_done & ~(e_state==E_IDLE)  ? I_DEC       :
                                  (inst_sz_nxt!=2'b00)        ? I_EXT1      : I_DEC;
      I_EXT1     : i_state_nxt =  pc_sw_wr                    ? I_DEC       : 
                                  (inst_sz!=2'b01)            ? I_EXT2      : I_DEC;
      I_EXT2     : i_state_nxt =  I_DEC;

      default    : i_state_nxt =  I_IRQ_FETCH;

    endcase


always @(posedge mclk or posedge puc_rst)
  if (puc_rst) i_state  <= I_IRQ_FETCH;
  else         i_state  <= i_state_nxt;


wire   decode_noirq =  ((i_state==I_DEC) &  (exec_done | (e_state==E_IDLE)));
wire   decode       =  decode_noirq | irq_detect;
wire   fetch        = ~((i_state==I_DEC) & ~(exec_done | (e_state==E_IDLE))) & ~(e_state_nxt==E_IDLE);


reg    dbg_halt_st;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)  dbg_halt_st <= 1'b0;
  else          dbg_halt_st <= cpu_halt_cmd & (i_state_nxt==I_IDLE);











reg         inst_irq_rst;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                  inst_irq_rst <= 1'b1;
  else if (exec_done)           inst_irq_rst <= 1'b0;


assign  irq_detect = (nmi_pnd | ((|irq | wdt_irq) & gie)) & ~cpu_halt_cmd & ~dbg_halt_st & (exec_done | (i_state==I_IDLE));

`ifdef CLOCK_GATING
wire       mclk_irq_num;
omsp_clock_gate clock_gate_irq_num (.gclk(mclk_irq_num),
                                    .clk (mclk), .enable(irq_detect), .scan_enable(scan_enable));
`else
wire       mclk_irq_num = mclk;
`endif


`ifdef  IRQ_16
wire [62:0] irq_all     = {nmi_pnd, irq, 48'h0000_0000_0000} |
`else
`ifdef  IRQ_32
wire [62:0] irq_all     = {nmi_pnd, irq, 32'h0000}           |
`else
`ifdef  IRQ_64
wire [62:0] irq_all     = {nmi_pnd, irq}                     |
`endif
`endif
`endif
                          {1'b0,    3'h0, wdt_irq, {58{1'b0}}};


reg  [5:0] irq_num;
always @(posedge mclk_irq_num or posedge puc_rst)
  if (puc_rst)         irq_num <= 6'h3f;
`ifdef CLOCK_GATING
  else
`else
  else if (irq_detect)
`endif
                       irq_num <= get_irq_num(irq_all);


wire [15:0] irq_addr    = {9'h1ff, irq_num, 1'b0};


wire        [63:0] irq_acc_all = one_hot64(irq_num) & {64{(i_state==I_IRQ_FETCH)}};
wire [`IRQ_NR-3:0] irq_acc     = irq_acc_all[61:64-`IRQ_NR];
wire               nmi_acc     = irq_acc_all[62];




`ifdef CPUOFF_EN



wire mclk_enable = inst_irq_rst ? cpu_en_s :


                  ~((cpuoff | ~cpu_en_s) &
                   (i_state==I_IDLE) &
                   (e_state==E_IDLE));

   

wire mirq_wkup;
omsp_and_gate and_mirq_wkup (.y(mirq_wkup), .a(wkup | wdt_wkup), .b(gie));


omsp_and_gate and_mclk_wkup (.y(mclk_wkup), .a(nmi_wkup | mirq_wkup), .b(cpu_en_s));

`else


assign  mclk_wkup   = 1'b1;
assign  mclk_enable = 1'b1;
`endif










reg  [15:0] pc;


wire [15:0] pc_incr = pc + {14'h0000, fetch, 1'b0};
wire [15:0] pc_nxt  = pc_sw_wr               ? pc_sw    :
                      (i_state==I_IRQ_FETCH) ? irq_addr :
                      (i_state==I_IRQ_DONE)  ? mdb_in   :  pc_incr;

`ifdef CLOCK_GATING
wire       pc_en  = fetch                  |
                    pc_sw_wr               |
                    (i_state==I_IRQ_FETCH) |
                    (i_state==I_IRQ_DONE);
wire       mclk_pc;
omsp_clock_gate clock_gate_pc (.gclk(mclk_pc),
                               .clk (mclk), .enable(pc_en), .scan_enable(scan_enable));
`else
wire       mclk_pc = mclk;
`endif

always @(posedge mclk_pc or posedge puc_rst)
  if (puc_rst)  pc <= 16'h0000;
  else          pc <= pc_nxt;


reg pmem_busy;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)  pmem_busy <= 1'b0;
  else          pmem_busy <= fe_pmem_wait;
   

wire [15:0] mab      = pc_nxt;
wire        mb_en    = fetch | pc_sw_wr | (i_state==I_IRQ_FETCH) | pmem_busy | (dbg_halt_st & ~cpu_halt_cmd);







wire [15:0] ir  = mdb_in;


wire is_sext = (inst_as[`IDX] | inst_as[`SYMB] | inst_as[`ABS] | inst_as[`IMM]);



wire [15:0] ext_incr = ((i_state==I_EXT1)     &  inst_as[`SYMB]) |
                       ((i_state==I_EXT2)     &  inst_ad[`SYMB]) |
                       ((i_state==I_EXT1)     & ~inst_as[`SYMB] &
                       ~(i_state_nxt==I_EXT2) &  inst_ad[`SYMB])   ? 16'hfffe : 16'h0000;

wire [15:0] ext_nxt  = ir + ext_incr;


reg [15:0] inst_sext;

`ifdef CLOCK_GATING
wire       inst_sext_en  = (decode & is_const)                 |
                           (decode & inst_type_nxt[`INST_JMP]) |
                           ((i_state==I_EXT1) & is_sext);
wire       mclk_inst_sext;
omsp_clock_gate clock_gate_inst_sext (.gclk(mclk_inst_sext),
                                      .clk (mclk), .enable(inst_sext_en), .scan_enable(scan_enable));
`else
wire       mclk_inst_sext = mclk;
`endif

always @(posedge mclk_inst_sext or posedge puc_rst)
  if (puc_rst)                                 inst_sext <= 16'h0000;
  else if (decode & is_const)                  inst_sext <= sconst_nxt;
  else if (decode & inst_type_nxt[`INST_JMP])  inst_sext <= {{5{ir[9]}},ir[9:0],1'b0};
`ifdef CLOCK_GATING
  else                                         inst_sext <= ext_nxt;
`else
  else if ((i_state==I_EXT1) & is_sext)        inst_sext <= ext_nxt;
`endif


wire inst_sext_rdy = (i_state==I_EXT1) & is_sext;



reg [15:0] inst_dext;

`ifdef CLOCK_GATING
wire       inst_dext_en  = ((i_state==I_EXT1) & ~is_sext) |
                            (i_state==I_EXT2);
wire       mclk_inst_dext;
omsp_clock_gate clock_gate_inst_dext (.gclk(mclk_inst_dext),
                                      .clk (mclk), .enable(inst_dext_en), .scan_enable(scan_enable));
`else
wire       mclk_inst_dext = mclk;
`endif

always @(posedge mclk_inst_dext or posedge puc_rst)
  if (puc_rst)                           inst_dext <= 16'h0000;
  else if ((i_state==I_EXT1) & ~is_sext) inst_dext <= ext_nxt;
`ifdef CLOCK_GATING
  else                                   inst_dext <= ext_nxt;
`else
  else if  (i_state==I_EXT2)             inst_dext <= ext_nxt;
`endif


wire inst_dext_rdy = (((i_state==I_EXT1) & ~is_sext) | (i_state==I_EXT2));






`ifdef CLOCK_GATING
wire       mclk_decode;
omsp_clock_gate clock_gate_decode (.gclk(mclk_decode),
                                   .clk (mclk), .enable(decode), .scan_enable(scan_enable));
`else
wire       mclk_decode = mclk;
`endif










reg  [2:0] inst_type;
assign     inst_type_nxt = {(ir[15:14]!=2'b00),
                            (ir[15:13]==3'b001),
                            (ir[15:13]==3'b000)} & {3{~irq_detect}};
   
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)      inst_type <= 3'b000;
`ifdef CLOCK_GATING
  else              inst_type <= inst_type_nxt;
`else
  else if (decode)  inst_type <= inst_type_nxt;
`endif















reg   [7:0] inst_so;
wire  [7:0] inst_so_nxt = irq_detect ? 8'h80 : (one_hot8(ir[9:7]) & {8{inst_type_nxt[`INST_SO]}});

always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_so <= 8'h00;
`ifdef CLOCK_GATING
  else             inst_so <= inst_so_nxt;
`else
  else if (decode) inst_so <= inst_so_nxt;
`endif















reg   [2:0] inst_jmp_bin;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_jmp_bin <= 3'h0;
`ifdef CLOCK_GATING
  else             inst_jmp_bin <= ir[12:10];
`else
  else if (decode) inst_jmp_bin <= ir[12:10];
`endif

wire [7:0] inst_jmp = one_hot8(inst_jmp_bin) & {8{inst_type[`INST_JMP]}};




















wire [15:0] inst_to_1hot = one_hot16(ir[15:12]) & {16{inst_type_nxt[`INST_TO]}};
wire [11:0] inst_to_nxt  = inst_to_1hot[15:4];

reg         inst_mov;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_mov <= 1'b0;
`ifdef CLOCK_GATING
  else             inst_mov <= inst_to_nxt[`MOV];
`else
  else if (decode) inst_mov <= inst_to_nxt[`MOV];
`endif







reg [3:0] inst_dest_bin;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_dest_bin <= 4'h0;
`ifdef CLOCK_GATING
  else             inst_dest_bin <= ir[3:0];
`else
  else if (decode) inst_dest_bin <= ir[3:0];
`endif

wire  [15:0] inst_dest = dbg_halt_st          ? one_hot16(dbg_reg_sel) :
                         inst_type[`INST_JMP] ? 16'h0001               :
                         inst_so[`IRQ]  |
                         inst_so[`PUSH] |
                         inst_so[`CALL]       ? 16'h0002               :
                                                one_hot16(inst_dest_bin);



reg [3:0] inst_src_bin;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_src_bin <= 4'h0;
`ifdef CLOCK_GATING
  else             inst_src_bin <= ir[11:8];
`else
  else if (decode) inst_src_bin <= ir[11:8];
`endif

wire  [15:0] inst_src = inst_type[`INST_TO] ? one_hot16(inst_src_bin)  :
                        inst_so[`RETI]      ? 16'h0002                 :
                        inst_so[`IRQ]       ? 16'h0001                 :
                        inst_type[`INST_SO] ? one_hot16(inst_dest_bin) : 16'h0000;





















reg [12:0] inst_as_nxt;

wire [3:0] src_reg = inst_type_nxt[`INST_SO] ? ir[3:0] : ir[11:8];

always @(src_reg or ir or inst_type_nxt)
  begin
     if (inst_type_nxt[`INST_JMP])
       inst_as_nxt =  13'b0000000000001;
     else if (src_reg==4'h3)
       case (ir[5:4])
         2'b11  : inst_as_nxt =  13'b1000000000000;
         2'b10  : inst_as_nxt =  13'b0100000000000;
         2'b01  : inst_as_nxt =  13'b0010000000000;
         default: inst_as_nxt =  13'b0001000000000;
       endcase
     else if (src_reg==4'h2)
       case (ir[5:4])
         2'b11  : inst_as_nxt =  13'b0000100000000;
         2'b10  : inst_as_nxt =  13'b0000010000000;
         2'b01  : inst_as_nxt =  13'b0000001000000;
         default: inst_as_nxt =  13'b0000000000001;
       endcase
     else if (src_reg==4'h0)
       case (ir[5:4])
         2'b11  : inst_as_nxt =  13'b0000000100000;
         2'b10  : inst_as_nxt =  13'b0000000000100;
         2'b01  : inst_as_nxt =  13'b0000000010000;
         default: inst_as_nxt =  13'b0000000000001;
       endcase
     else
       case (ir[5:4])
         2'b11  : inst_as_nxt =  13'b0000000001000;
         2'b10  : inst_as_nxt =  13'b0000000000100;
         2'b01  : inst_as_nxt =  13'b0000000000010;
         default: inst_as_nxt =  13'b0000000000001;
       endcase
  end
assign    is_const = |inst_as_nxt[12:7];

reg [7:0] inst_as;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_as <= 8'h00;
`ifdef CLOCK_GATING
  else             inst_as <= {is_const, inst_as_nxt[6:0]};
`else
  else if (decode) inst_as <= {is_const, inst_as_nxt[6:0]};
`endif








always @(inst_as_nxt)
  begin
     if (inst_as_nxt[7])        sconst_nxt = 16'h0004;
     else if (inst_as_nxt[8])   sconst_nxt = 16'h0008;
     else if (inst_as_nxt[9])   sconst_nxt = 16'h0000;
     else if (inst_as_nxt[10])  sconst_nxt = 16'h0001;
     else if (inst_as_nxt[11])  sconst_nxt = 16'h0002;
     else if (inst_as_nxt[12])  sconst_nxt = 16'hffff;
     else                       sconst_nxt = 16'h0000;
  end












reg  [7:0] inst_ad_nxt;

wire [3:0] dest_reg = ir[3:0];

always @(dest_reg or ir or inst_type_nxt)
  begin
     if (~inst_type_nxt[`INST_TO])
       inst_ad_nxt =  8'b00000000;
     else if (dest_reg==4'h2)
       case (ir[7])
         1'b1   : inst_ad_nxt =  8'b01000000;
         default: inst_ad_nxt =  8'b00000001;
       endcase
     else if (dest_reg==4'h0)
       case (ir[7])
         1'b1   : inst_ad_nxt =  8'b00010000;
         default: inst_ad_nxt =  8'b00000001;
       endcase
     else
       case (ir[7])
         1'b1   : inst_ad_nxt =  8'b00000010;
         default: inst_ad_nxt =  8'b00000001;
       endcase
  end

reg [7:0] inst_ad;
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_ad <= 8'h00;
`ifdef CLOCK_GATING
  else             inst_ad <= inst_ad_nxt;
`else
  else if (decode) inst_ad <= inst_ad_nxt;
`endif







reg       inst_bw;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)     inst_bw     <= 1'b0;
  else if (decode) inst_bw     <= ir[6] & ~inst_type_nxt[`INST_JMP] & ~irq_detect & ~cpu_halt_cmd;


assign    inst_sz_nxt = {1'b0,  (inst_as_nxt[`IDX] | inst_as_nxt[`SYMB] | inst_as_nxt[`ABS] | inst_as_nxt[`IMM])} +
                        {1'b0, ((inst_ad_nxt[`IDX] | inst_ad_nxt[`SYMB] | inst_ad_nxt[`ABS]) & ~inst_type_nxt[`INST_SO])};
always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_sz     <= 2'b00;
`ifdef CLOCK_GATING
  else             inst_sz     <= inst_sz_nxt;
`else
  else if (decode) inst_sz     <= inst_sz_nxt;
`endif







reg  [3:0] e_state;





wire src_acalc_pre =  inst_as_nxt[`IDX]   | inst_as_nxt[`SYMB]    | inst_as_nxt[`ABS];
wire src_rd_pre    =  inst_as_nxt[`INDIR] | inst_as_nxt[`INDIR_I] | inst_as_nxt[`IMM]  | inst_so_nxt[`RETI];
wire dst_acalc_pre =  inst_ad_nxt[`IDX]   | inst_ad_nxt[`SYMB]    | inst_ad_nxt[`ABS];
wire dst_acalc     =  inst_ad[`IDX]       | inst_ad[`SYMB]        | inst_ad[`ABS];
wire dst_rd_pre    =  inst_ad_nxt[`IDX]   | inst_so_nxt[`PUSH]    | inst_so_nxt[`CALL] | inst_so_nxt[`RETI];
wire dst_rd        =  inst_ad[`IDX]       | inst_so[`PUSH]        | inst_so[`CALL]     | inst_so[`RETI];

wire inst_branch   =  (inst_ad_nxt[`DIR] & (ir[3:0]==4'h0)) | inst_type_nxt[`INST_JMP] | inst_so_nxt[`RETI];

reg exec_jmp;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                   exec_jmp <= 1'b0;
  else if (inst_branch & decode) exec_jmp <= 1'b1;
  else if (e_state==E_JUMP)      exec_jmp <= 1'b0;

reg exec_dst_wr;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                exec_dst_wr <= 1'b0;
  else if (e_state==E_DST_RD) exec_dst_wr <= 1'b1;
  else if (e_state==E_DST_WR) exec_dst_wr <= 1'b0;

reg exec_src_wr;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                                         exec_src_wr <= 1'b0;
  else if (inst_type[`INST_SO] & (e_state==E_SRC_RD))  exec_src_wr <= 1'b1;
  else if ((e_state==E_SRC_WR) || (e_state==E_DST_WR)) exec_src_wr <= 1'b0;

reg exec_dext_rdy;
always @(posedge mclk or posedge puc_rst)
  if (puc_rst)                exec_dext_rdy <= 1'b0;
  else if (e_state==E_DST_RD) exec_dext_rdy <= 1'b0;
  else if (inst_dext_rdy)     exec_dext_rdy <= 1'b1;


wire [3:0] e_first_state = ~dbg_halt_st  & inst_so_nxt[`IRQ] ? E_IRQ_0  :
                            cpu_halt_cmd | (i_state==I_IDLE) ? E_IDLE   :
                            cpuoff                           ? E_IDLE   :
                            src_acalc_pre                    ? E_SRC_AD :
                            src_rd_pre                       ? E_SRC_RD :
                            dst_acalc_pre                    ? E_DST_AD :
                            dst_rd_pre                       ? E_DST_RD : E_EXEC;






always @(e_state       or dst_acalc     or dst_rd   or inst_sext_rdy or
         inst_dext_rdy or exec_dext_rdy or exec_jmp or exec_dst_wr   or
         e_first_state or exec_src_wr)
    case(e_state)
      E_IDLE   : e_state_nxt =  e_first_state;
      E_IRQ_0  : e_state_nxt =  E_IRQ_1;
      E_IRQ_1  : e_state_nxt =  E_IRQ_2;
      E_IRQ_2  : e_state_nxt =  E_IRQ_3;
      E_IRQ_3  : e_state_nxt =  E_IRQ_4;
      E_IRQ_4  : e_state_nxt =  E_EXEC;

      E_SRC_AD : e_state_nxt =  inst_sext_rdy     ? E_SRC_RD : E_SRC_AD;

      E_SRC_RD : e_state_nxt =  dst_acalc         ? E_DST_AD : 
                                 dst_rd           ? E_DST_RD : E_EXEC;

      E_DST_AD : e_state_nxt =  (inst_dext_rdy |
                                 exec_dext_rdy)   ? E_DST_RD : E_DST_AD;

      E_DST_RD : e_state_nxt =  E_EXEC;

      E_EXEC   : e_state_nxt =  exec_dst_wr       ? E_DST_WR :
                                exec_jmp          ? E_JUMP   :
                                exec_src_wr       ? E_SRC_WR : e_first_state;

      E_JUMP   : e_state_nxt =  e_first_state;
      E_DST_WR : e_state_nxt =  exec_jmp          ? E_JUMP   : e_first_state;
      E_SRC_WR : e_state_nxt =  e_first_state;

      default  : e_state_nxt =  E_IRQ_0;

    endcase


always @(posedge mclk or posedge puc_rst)
  if (puc_rst) e_state  <= E_IRQ_1;
  else         e_state  <= e_state_nxt;





wire exec_done = exec_jmp        ? (e_state==E_JUMP)   :
                 exec_dst_wr     ? (e_state==E_DST_WR) :
                 exec_src_wr     ? (e_state==E_SRC_WR) : (e_state==E_EXEC);























reg  [11:0] inst_alu;

wire        alu_src_inv   = inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
                            inst_to_nxt[`CMP]  | inst_to_nxt[`BIC] ;

wire        alu_inc       = inst_to_nxt[`SUB]  | inst_to_nxt[`CMP];

wire        alu_inc_c     = inst_to_nxt[`ADDC] | inst_to_nxt[`DADD] |
                            inst_to_nxt[`SUBC];

wire        alu_add       = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC]       |
                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC]       |
                            inst_to_nxt[`CMP]  | inst_type_nxt[`INST_JMP] |
                            inst_so_nxt[`RETI];

 
wire        alu_and       = inst_to_nxt[`AND]  | inst_to_nxt[`BIC]  |
                            inst_to_nxt[`BIT];

wire        alu_or        = inst_to_nxt[`BIS];

wire        alu_xor       = inst_to_nxt[`XOR];

wire        alu_dadd      = inst_to_nxt[`DADD];

wire        alu_stat_7    = inst_to_nxt[`BIT]  | inst_to_nxt[`AND]  |
                            inst_so_nxt[`SXT];

wire        alu_stat_f    = inst_to_nxt[`ADD]  | inst_to_nxt[`ADDC] |
                            inst_to_nxt[`SUB]  | inst_to_nxt[`SUBC] |
                            inst_to_nxt[`CMP]  | inst_to_nxt[`DADD] |
                            inst_to_nxt[`BIT]  | inst_to_nxt[`XOR]  |
                            inst_to_nxt[`AND]  |
                            inst_so_nxt[`RRC]  | inst_so_nxt[`RRA]  |
                            inst_so_nxt[`SXT];

wire        alu_shift     = inst_so_nxt[`RRC]  | inst_so_nxt[`RRA];

wire        exec_no_wr    = inst_to_nxt[`CMP] | inst_to_nxt[`BIT];

wire [11:0] inst_alu_nxt  = {exec_no_wr,
                             alu_shift,
                             alu_stat_f,
                             alu_stat_7,
                             alu_dadd,
                             alu_xor,
                             alu_or,
                             alu_and,
                             alu_add,
                             alu_inc_c,
                             alu_inc,
                             alu_src_inv};

always @(posedge mclk_decode or posedge puc_rst)
  if (puc_rst)     inst_alu <= 12'h000;
`ifdef CLOCK_GATING
  else             inst_alu <= inst_alu_nxt;
`else
  else if (decode) inst_alu <= inst_alu_nxt;
`endif


endmodule