data/full_repos/permissive/164102137/cpu.v
None: at end of input
1: b'%Error: data/full_repos/permissive/164102137/cpu.v:18: Cannot find include file: states.i\n`include "states.i" \n         ^~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/164102137,data/full_repos/permissive/164102137/states.i\n             data/full_repos/permissive/164102137,data/full_repos/permissive/164102137/states.i.v\n             data/full_repos/permissive/164102137,data/full_repos/permissive/164102137/states.i.sv\n             states.i\n             states.i.v\n             states.i.sv\n             obj_dir/states.i\n             obj_dir/states.i.v\n             obj_dir/states.i.sv\n%Error: Exiting due to 1 error(s)\n'
module cpu( clk, RST, AB, DB, WE, IRQ, NMI, RDY, Debug );

`include "states.i"

input clk;
input RST;
output [15:0] AB;
inout [7:0] DB;
output WE;
input IRQ;
input NMI;
input RDY;
input Debug;

reg N, V, D, B, I = 1, Z, C;

reg [7:0] S = 8'hff;
reg [7:0] X = 2;
reg [7:0] Y = 3;
reg [7:0] A = 8'h41;


reg m_ld;
reg m_sel_adj;
reg [7:0] M;


reg pc_ld;
reg [15:0] PC;


reg [7:0] ABH = 8'h04;
reg [7:0] ABL = 8'h00;

wire [15:0] AB = { ABH, ABL };
reg [7:0] ALU;


reg [3:0] ADJL;
reg [3:0] ADJH;
wire [7:0] ADJ = { ADJH, ADJL };



reg inc_ab;
wire [15:0] ABI = AB + inc_ab;



wire [2:0] sel_adh;
wire [2:0] sel_adl;


wire [7:0] PCH = PC[15:8];
wire [7:0] PCL = PC[7:0];
reg [7:0] ADH;
reg [7:0] ADL;

reg WE = 1;
reg [7:0] DO;
reg [7:0] AI;
reg CI;



wire take_irq = IRQ & ~I;
reg in_irq;
assign B = ~in_irq;

wire take_rst = RST;
reg in_rst;


reg ir_ld;
reg [7:0] IR;


wire [7:0] P = { N, V, 1'b1, B, D, I, Z, C };
reg cond_true;

wire NO;
wire ZO;
wire VO;
wire CO;
wire BCD_C = C | CO;

reg [1:0] p_sel;
reg z_ld;
reg i_ld;
reg d_ld;
reg n_ld;
reg c_ld;
reg v_ld;


reg [2:0] alu_ai;
reg [2:0] alu_bi;
reg [4:0] alu_op;
reg [2:0] alu_ld;
reg mem_bi;
reg inv_bi;

wire adj_lsd;
wire adj_msd;

alu alu(
    .AI(AI),
    .MI(M),
    .CI(CI),
    .OUT(ALU),
    .mem_bi(mem_bi),
    .inv_bi(inv_bi),
    .op(alu_op),
    .N(NO),
    .Z(ZO),
    .C(CO),
    .V(VO),
    .adj_lsd(adj_lsd),
    .adj_msd(adj_msd) );


assign DB = WE ? 8'hzz : DO;




reg ind;
wire brk = (IR == 8'h00);
wire jmp  = (IR == 8'h4c || IR == 8'h6c || IR == 8'h20 || IR == 8'h00);
reg rmw;
reg bcd;


reg [4:0] state = FETCH;




always @* begin
    sel_adl = ADL_ABI;
    case( state )
        DECODE:
            casez( IR )
                8'b0??0_?000:           sel_adl = ADL_ALU;
                8'b????_0001:           sel_adl = ADL_DB;
                8'b????_01??:           sel_adl = ADL_DB;
            endcase

        DATA:  if( !rmw )               sel_adl = ADL_PC;

        ABS0:                           sel_adl = ADL_ALU;

        ZP0:                            sel_adl = ADL_ALU;

        ZP1:                            sel_adl = ADL_ALU;

        STK0:  if( IR[3] )              sel_adl = ADL_PC;
               else                     sel_adl = ADL_ALU;

        STK1:
            casez( IR )
                8'b??0?_????:           sel_adl = ADL_ALU;
                8'b?01?_????:           sel_adl = ADL_PC;
                8'b?11?_????:           sel_adl = ADL_ALU;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           sel_adl = in_rst ? ADL_RST : ADL_BRK;
                8'b?1??_????:           sel_adl = ADL_ALU;
            endcase
        BRA0:                           sel_adl = ADL_ALU;
    endcase
end


always @* begin
    sel_adh = ADH_ABI;
    case( state )
        DECODE:
            casez( IR )
                8'b0??0_?000:           sel_adh = ADH_SP;
                8'b????_0001:           sel_adh = ADH_ZP;
                8'b????_01??:           sel_adh = ADH_ZP;
            endcase

        DATA:  if( !rmw )               sel_adh = ADH_PC;

        ABS0:                           sel_adh = ADH_DB;

        ABS1:                           sel_adh = ADH_ALU;

        ZP0:                            sel_adh = ADH_ZP;

        ZP1:                            sel_adh = ADH_ZP;

        STK0:  if( IR[3] )              sel_adh = ADH_PC;
               else                     sel_adh = ADH_SP;
        STK1:
            casez( IR )
                8'b??0?_????:           sel_adh = ADH_SP;
                8'b?01?_????:           sel_adh = ADH_PC;
                8'b?11?_????:           sel_adh = ADH_DB;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           sel_adh = ADH_FF;
                8'b?1??_????:           sel_adh = ADH_DB;
            endcase
        BRA0:                           sel_adh = ADH_PC;
        BRA1:                           sel_adh = ADH_ALU;
        BRA2:                           sel_adh = ADH_ALU;
    endcase
end


always @* begin
    inc_ab = 0;
    case( state )
        DECODE:
            casez( IR )
                8'b0??0_1000:           inc_ab = 0;
                default:                inc_ab = !take_irq;
            endcase
        BCD0:                           inc_ab = 1;
        RTS0:                           inc_ab = 1;
        IND0:                           inc_ab = 1;
        FETCH:                          inc_ab = !bcd & !take_irq;
        ABS0:                           inc_ab = 1;
    endcase
end



always @*
    case( sel_adh )
        ADH_ABI :                       ADH = ABI[15:8];
        ADH_ALU :                       ADH = ALU;
        ADH_DB  :                       ADH = DB;
        ADH_PC  :                       ADH = PCH;
        ADH_FF  :                       ADH = 8'hFF;
        ADH_SP  :                       ADH = 8'h01;
        ADH_ZP  :                       ADH = 8'h00;
        default:                        ADH = 8'h55;
    endcase

always @*
    case( sel_adl )
        ADL_ABI :						ADL = ABI[7:0];
        ADL_ALU :						ADL = ALU;
        ADL_DB  :						ADL = DB;
        ADL_PC  :						ADL = PCL;
        ADL_NMI :                       ADL = 8'hFA;
        ADL_RST :						ADL = 8'hFC;
        ADL_BRK :						ADL = 8'hFE;
    endcase


always @(posedge clk)
    ABH <= ADH;

always @(posedge clk)
    ABL <= ADL;



always @* begin
    pc_ld = 0;
    case( state )
        DECODE:                         pc_ld = 1;
        BCD0:                           pc_ld = 1;
        RTS0:                           pc_ld = 1;
        IND0:                           pc_ld = 1;
        FETCH:                          pc_ld = 1;
        ABS0:                           pc_ld = IR[3];
    endcase
end

always @(posedge clk)
    if( pc_ld )
        PC <= ABI;


always @(posedge clk)
    case( state )
        DECODE:
            casez( IR )
                8'b00?0_0000:           WE <= 0;
                8'b0?00_1000:           WE <= 0;
                8'b1000_01??:           WE <= 0;
                default:                WE <= 1;
            endcase

        STK0:
            casez( IR )
                8'b?0??_0???:           WE <= 0;
                default:                WE <= 1;
            endcase

        STK1:
            casez( IR )
                8'b?00?_????:           WE <= 0;
                default:                WE <= 1;
            endcase

        DATA:                           WE <= !rmw;

        ABS0:
            casez( IR )
                8'b100?_????:           WE <= CO;
                default:                WE <= 1;
            endcase

        ABS1:
            casez( IR )
                8'b100?_????:           WE <= 0;
                default:                WE <= 1;
            endcase

        ZP0:
            casez( IR )
                8'b1001_01??:           WE <= 0;
                default:                WE <= 1;
            endcase

        default:                        WE <= 1;
    endcase


always @* begin
    DO = 8'h55;
    case( state )
        STK0:
            casez( IR )
                8'b?00?_1???:           DO = P;
                8'b?10?_1???:           DO = ALU;
                8'b????_0???:           DO = PCH;
            endcase

        STK1:
            casez( IR )
                8'b????_0???:           DO = PCL;
            endcase

        STK2:                           DO = P;

        DATA:                           DO = ALU;
    endcase
end


always @*
    if( bcd & adj_lsd )                 ADJL = 6;
    else                                ADJL = 0;

always @*
    if( bcd & adj_msd )                 ADJH = 6;
    else                                ADJH = 0;


always @* begin
    m_ld = 0;
    case( state )
        ABS0:                           m_ld = 1;

        STK0:
            casez( IR )
                8'b??1?_1???:           m_ld = 1;
                8'b?1??_0???:           m_ld = 1;
            endcase

        ZP1, IND0, DECODE:              m_ld = 1;

        STK1, STK2:
            casez( IR )
                8'b?1??_????:           m_ld = 1;
            endcase

        DATA:                           m_ld = 1;

        FETCH:                          m_ld = 1;
    endcase
end


always @*
    case( state )
        FETCH:                          m_sel_adj = 1;
        default:                        m_sel_adj = 0;
    endcase

always @(posedge clk)
    if( m_ld )
        M <= m_sel_adj ? ADJ : DB;



always @* begin
    ir_ld = in_rst;
    case( state )
        FETCH:                          ir_ld = !bcd;

        BCD0:                           ir_ld = 1;

        DECODE:
            casez( IR )
                8'b???1_10?0:           ir_ld = 1;
                8'b1???_10?0:           ir_ld = 1;
                8'b????_1010:           ir_ld = 1;
            endcase
    endcase
end

always @(posedge clk)
    if( ir_ld & take_irq )              in_irq <= 1;
    else if( state == FETCH )           in_irq <= 0;

always @(posedge clk)
    if( ir_ld & take_rst )              in_rst <= 1;
    else if( state == FETCH )           in_rst <= 0;

always @(posedge clk)
    if( ir_ld )
        IR <= (take_irq|in_rst) ? 8'h00 : DB;



always @* begin
    alu_ai = AI_ZZZ;
    case( state )
        DECODE:
            casez( IR )
                8'b0??0_?000:           alu_ai = AI_S;
                8'b1011_1010:           alu_ai = AI_S;
                8'b100?_1010:           alu_ai = AI_X;
                8'b1001_1000:           alu_ai = AI_Y;
                8'b1010_10?0:           alu_ai = AI_A;
                8'b1?00_1000:           alu_ai = AI_Y;
                8'b1110_1000:           alu_ai = AI_X;
                8'b1100_1010:           alu_ai = AI_X;
                8'b0???_1010:           alu_ai = AI_A;
            endcase

        ABS0:
            casez( IR )
                8'b10?1_?110:           alu_ai = AI_Y;
                8'b???1_?001:           alu_ai = AI_Y;
                8'b???1_11??:           alu_ai = AI_X;
                8'b???0_????:           alu_ai = AI_M;
            endcase

        ZP0:
            casez( IR )
                8'b10?1_?110:           alu_ai = AI_Y;
                8'b????_01??:           alu_ai = AI_X;
                8'b???0_0001:           alu_ai = AI_X;
                8'b???1_0001:           alu_ai = AI_M;
            endcase

        ZP1:
            casez( IR )
                8'b???0_0001:           alu_ai = AI_X;
                8'b???1_0001:           alu_ai = AI_M;
            endcase

        STK0:
            casez( IR )
                8'b????_0???:           alu_ai = AI_S;
                8'b??0?_1???:           alu_ai = AI_A;
            endcase

        STK1:
            casez( IR )
                8'b?10?_????:           alu_ai = AI_S;
                8'b?0??_????:           alu_ai = AI_S;
                8'b?11?_????:           alu_ai = AI_M;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           alu_ai = AI_S;
                8'b?1??_????:           alu_ai = AI_M;
            endcase

        DATA:
            casez( IR )
                8'b0???_??10:           alu_ai = AI_M;
                8'b11??_?110:           alu_ai = AI_M;
                8'b100?_??00:           alu_ai = AI_Y;
                8'b100?_??01:           alu_ai = AI_A;
                8'b100?_??10:           alu_ai = AI_X;
            endcase

        FETCH:
            casez( IR )
                8'b101?_????:           alu_ai = AI_M;
                8'b0?10_1000:           alu_ai = AI_M;
                8'b0?00_1000:           alu_ai = AI_S;
                8'b001?_?100:           alu_ai = AI_A;
                8'b0???_??01:           alu_ai = AI_A;
                8'b11??_??01:           alu_ai = AI_A;
                8'b110?_??00:           alu_ai = AI_Y;
                8'b111?_??00:           alu_ai = AI_X;
            endcase

        ABS1:                           alu_ai = AI_M;
        BCD0:                           alu_ai = AI_A;
        BRA0:                           alu_ai = AI_PCL;
        BRA1:                           alu_ai = AI_PCH;
        BRA2:                           alu_ai = AI_PCH;
    endcase
end



always @* begin
    mem_bi = 0;
    case( state )

        ABS0:
            casez( IR )
                8'b1011_1110:           mem_bi = 1;
                8'b????_1001:           mem_bi = 1;
                8'b???1_11??:           mem_bi = 1;
                8'b???0_11??:           mem_bi = 0;
                8'b00?0_0000:           mem_bi = 0;
                8'b???0_0001:           mem_bi = 0;
                8'b???1_0001:           mem_bi = 1;
            endcase

        ZP0:
            casez( IR )
                8'b10?1_0110:           mem_bi = 1;
                8'b????_01??:           mem_bi = 1;
                8'b???0_0001:           mem_bi = 1;
                8'b???1_0001:           mem_bi = 0;
            endcase

        ZP1:
            casez( IR )
                8'b???0_0001:           mem_bi = 1;
                8'b???1_0001:           mem_bi = 0;
            endcase

        FETCH:
            casez( IR )
                8'b101?_????:           mem_bi = 0;
                8'b0??0_1000:           mem_bi = 0;
                8'b001?_??00:           mem_bi = 1;
                8'b0???_??01:           mem_bi = 1;
                8'b11??_??01:           mem_bi = 1;
                8'b11??_??00:           mem_bi = 1;
            endcase

        DECODE:                         mem_bi = 0;
        ABS1:                           mem_bi = 0;
        STK0:                           mem_bi = 0;
        STK1:                           mem_bi = 0;
        STK2:                           mem_bi = 0;
        BRA0:                           mem_bi = 1;
        BRA1:                           mem_bi = 0;
        BRA2:                           mem_bi = 0;
        DATA:                           mem_bi = 0;
        BCD0:                           mem_bi = 1;

    endcase
end


always @* begin
    inv_bi = 0;
    case( state )
        DECODE:
            casez( IR )
                8'b01?0_0000:           inv_bi = 0;
                8'b0?10_1000:           inv_bi = 0;
                8'b1000_1000:           inv_bi = 1;
                8'b11?0_1000:           inv_bi = 0;
                8'b1100_1010:           inv_bi = 1;
            endcase

        STK0:
            casez( IR )
                8'b?1??_0???:           inv_bi = 0;
                8'b?0??_0???:           inv_bi = 1;
                8'b??0?_1???:           inv_bi = 0;
            endcase

        STK1:
            casez( IR )
                8'b?10?_????:           inv_bi = 0;
                8'b?0??_????:           inv_bi = 1;
                8'b?11?_????:           inv_bi = 0;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           inv_bi = 1;
                8'b?1??_????:           inv_bi = 0;
            endcase

        DATA:
            casez( IR )
                8'b110?_?110:           inv_bi = 1;
                8'b111?_?110:           inv_bi = 0;
                8'b100?_???0:           inv_bi = 0;
                8'b100?_??01:           inv_bi = 0;
            endcase

        FETCH:
            casez( IR )
                8'b101?_????:           inv_bi = 0;
                8'b0?10_1000:           inv_bi = 0;
                8'b0?00_1000:           inv_bi = 1;
                8'b001?_??00:           inv_bi = 0;
                8'b0???_??01:           inv_bi = 0;
                8'b11??_??0?:           inv_bi = 1;
            endcase

        BCD0:
            casez( IR )
                8'b011?_??01:           inv_bi = 0;
                8'b111?_??01:           inv_bi = 1;
            endcase

        ABS0:                           inv_bi = 0;
        ABS1:                           inv_bi = 0;
        ZP0:                            inv_bi = 0;
        ZP1:                            inv_bi = 0;
        BRA0:                           inv_bi = 0;
        BRA1:                           inv_bi = 0;
        BRA2:                           inv_bi = 1;

    endcase
end



always @* begin
    alu_op = ALU_ADC;
    case( state )
        DECODE:
            casez( IR )
                8'b00?0_0000:           alu_op = ALU_AI;
                8'b01?0_0000:           alu_op = ALU_ADC;
                8'b0?00_1000:           alu_op = ALU_AI;
                8'b0?10_1000:           alu_op = ALU_ADC;
                8'b1000_1000:           alu_op = ALU_ADC;
                8'b1001_1000:           alu_op = ALU_AI;
                8'b1100_1000:           alu_op = ALU_ADC;
                8'b1110_1000:           alu_op = ALU_ADC;
                8'b00??_1010:           alu_op = ALU_ROL;
                8'b01??_1010:           alu_op = ALU_ROR;
                8'b100?_1010:           alu_op = ALU_AI;
                8'b1010_10?0:           alu_op = ALU_AI;
                8'b1011_1010:           alu_op = ALU_AI;
                8'b1100_1010:           alu_op = ALU_ADC;
            endcase

        DATA:
            casez( IR )
                8'b00??_??10:           alu_op = ALU_ROL;
                8'b01??_??10:           alu_op = ALU_ROR;
                8'b110?_?110:           alu_op = ALU_ADC;
                8'b111?_?110:           alu_op = ALU_ADC;
                8'b100?_??00:           alu_op = ALU_AI;
                8'b100?_??01:           alu_op = ALU_AI;
                8'b100?_??10:           alu_op = ALU_AI;
            endcase

        FETCH:
            casez( IR )
                8'b101?_????:           alu_op = ALU_AI;
                8'b0?10_1000:           alu_op = ALU_AI;
                8'b0?00_1000:           alu_op = ALU_ADC;
                8'b001?_??00:           alu_op = ALU_AND;
                8'b011?_??01:           alu_op = ALU_ADC;
                8'b000?_??01:           alu_op = ALU_ORA;
                8'b001?_??01:           alu_op = ALU_AND;
                8'b010?_??01:           alu_op = ALU_EOR;
                8'b11??_??01:           alu_op = ALU_ADC;
                8'b110?_??00:           alu_op = ALU_ADC;
                8'b111?_??00:           alu_op = ALU_ADC;
            endcase
    endcase
end



always @* begin
    alu_ld = 0;
    case( state )
        DECODE:
            casez( IR )
                8'b1000_1010:           alu_ld = LD_A;
                8'b0???_1010:           alu_ld = LD_A;
                8'b101?_1010:           alu_ld = LD_X;
                8'b110?_1010:           alu_ld = LD_X;
                8'b1001_1010:           alu_ld = LD_S;
                8'b1001_1000:           alu_ld = LD_A;
                8'b1110_1000:           alu_ld = LD_X;
                8'b1??0_1000:           alu_ld = LD_Y;
                8'b01?0_0000:           alu_ld = LD_S;
                8'b0?10_1000:           alu_ld = LD_S;
            endcase

        FETCH:
            casez( IR )
                8'b0???_??01:           alu_ld = LD_A;
                8'b101?_??01:           alu_ld = LD_A;
                8'b111?_??01:           alu_ld = LD_A;
                8'b?11?_10??:           alu_ld = LD_A;
                8'b101?_??10:           alu_ld = LD_X;
                8'b1010_??00:           alu_ld = LD_Y;
                8'b1011_?100:           alu_ld = LD_Y;
                8'b0?00_1000:           alu_ld = LD_S;
            endcase

        STK0:
            casez( IR )
                8'b?1??_0???:           alu_ld = LD_S;
                8'b?0??_0???:           alu_ld = LD_S;
            endcase

        STK1:
            casez( IR )
                8'b?10?_????:           alu_ld = LD_S;
                8'b?0??_????:           alu_ld = LD_S;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           alu_ld = LD_S;
            endcase

        BCD0:                           alu_ld = LD_A;
    endcase
end



always @* begin
    CI = 0;
    case( state )
        ZP1:
            casez( IR )
                8'b????_0001:           CI = 1;
            endcase

        DECODE:
            casez( IR )
                8'b0?10_1010:           CI = C;
                8'b01?0_0000:           CI = 1;
                8'b0?10_1000:           CI = 1;
                8'b11?0_1000:           CI = 1;
            endcase

        FETCH:
            casez( IR )
                8'b110?_??01:           CI = 1;
                8'b11??_??00:           CI = 1;
                8'b?11?_??01:           CI = C;
            endcase

        STK0:
            casez( IR )
                8'b?1??_0???:           CI = 1;
            endcase

        STK1:
            casez( IR )
                8'b?10?_????:           CI = 1;
            endcase

        ABS1:                           CI = 1;

        BRA1:                           CI = 1;

        DATA:
            casez( IR )
                8'b0?1?_?110:           CI = C;
                8'b111?_?110:           CI = 1;
            endcase

        BCD0:
            casez( IR )
                8'b011?_??01:           CI = 0;
                8'b111?_??01:           CI = 1;
            endcase
    endcase
end



always @*
    case( alu_ai )
        AI_PCL:                         AI = PCL;
        AI_PCH:                         AI = PCH;
        AI_A:                           AI = A;
        AI_X:                           AI = X;
        AI_Y:                           AI = Y;
        AI_M:                           AI = M;
        AI_S:                           AI = S;
        AI_ZZZ:                         AI = 8'h55;
    endcase



always @(posedge clk)
    case( alu_ld )
        LD_A:                           A <= ALU;
        LD_X:                           X <= ALU;
        LD_Y:                           Y <= ALU;
        LD_S:                           S <= ALU;
    endcase


always @* begin
    p_sel = 2'b00;
    case( state )
        STK0:
            casez( IR )
                8'b?01?_1???:           p_sel = 2'b01;
                8'b?10?_0???:           p_sel = 2'b01;
            endcase

        STK2:
            casez( IR )
                8'b0000_0000:           p_sel = 2'b00;
            endcase

        DATA:
            casez( IR )
                8'b0???_?110:           p_sel = 2'b00;
                8'b11??_?110:           p_sel = 2'b00;
                8'b0010_?100:           p_sel = 2'b01;
            endcase

        FETCH:
            casez( IR )
                8'b0110_1000:           p_sel = 2'b00;
                8'b011?_??01:           p_sel = 2'b00;
                8'b1010_????:           p_sel = 2'b00;
                8'b101?_?1??:           p_sel = 2'b00;
                8'b101?_??01:           p_sel = 2'b00;
                8'b11?0_??00:           p_sel = 2'b00;
                8'b11?0_??00:           p_sel = 2'b00;
                8'b11??_??01:           p_sel = 2'b00;
                8'b11??_??01:           p_sel = 2'b00;
            endcase

        DECODE:
            casez( IR )
                8'b00?1_1000:           p_sel = 2'b11;
                8'b11?1_1000:           p_sel = 2'bx0;
                8'b01?1_1000:           p_sel = 2'bx0;
                8'b1011_1000:           p_sel = 2'b1x;
                8'b0???_1010:           p_sel = 2'b00;
                8'b0???_1010:           p_sel = 2'b00;
                8'b100?_1000:           p_sel = 2'b00;
                8'b101?_1010:           p_sel = 2'b00;
                8'b10?0_10?0:           p_sel = 2'b00;
                8'b1?00_10?0:           p_sel = 2'b00;
                8'b1??0_1000:           p_sel = 2'b00;
            endcase

        BCD0:                           p_sel = 2'b10;
    endcase
end


always @* begin
    c_ld = 0;
    case( state )
        STK0:
            casez( IR )
                8'b?01?_1???:           c_ld = 1;
                8'b?10?_0???:           c_ld = 1;
            endcase

        DATA:
            casez( IR )
                8'b0???_?110:           c_ld = !WE;
            endcase

        FETCH:
            casez( IR )
                8'b011?_??01:           c_ld = 1;
                8'b11??_??01:           c_ld = 1;
                8'b11?0_??00:           c_ld = 1;
            endcase

        DECODE:
            casez( IR )
                8'b0???_1010:           c_ld = 1;
                8'b00?1_1000:           c_ld = 1;
            endcase

        BCD0:
            casez( IR )
                8'b011?_??01:           c_ld = 1;
            endcase

    endcase
end

always @* begin
    n_ld = 0;
    case( state )
        DATA:
            casez( IR )
                8'b0???_?110:           n_ld = !WE;
                8'b11??_?110:           n_ld = !WE;
                8'b0010_?100:           n_ld = 1;
            endcase

        DECODE:
            casez( IR )
                8'b1?00_10?0:           n_ld = 1;
                8'b10?0_10?0:           n_ld = 1;
                8'b100?_1000:           n_ld = 1;
                8'b101?_1010:           n_ld = 1;
                8'b1??0_1000:           n_ld = 1;
                8'b0???_1010:           n_ld = 1;
            endcase

        STK0:
            casez( IR )
                8'b?01?_1???:           n_ld = 1;
                8'b?10?_0???:           n_ld = 1;
            endcase

        FETCH:
            casez( IR )
                8'b0110_1000:           n_ld = 1;
                8'b0???_??01:           n_ld = 1;
                8'b1010_????:           n_ld = 1;
                8'b101?_?1??:           n_ld = 1;
                8'b11?0_??00:           n_ld = 1;
                8'b11??_??01:           n_ld = 1;
                8'b101?_??01:           n_ld = 1;
            endcase

        BCD0:                           n_ld = 1;
    endcase
end


always @* begin
    z_ld = 0;
    case( state )
        DATA:
            casez( IR )
                8'b0???_?110:           z_ld = !WE;
                8'b11??_?110:           z_ld = !WE;
            endcase

        DECODE:
            casez( IR )
                8'b1?00_10?0:           z_ld = 1;
                8'b10?0_10?0:           z_ld = 1;
                8'b100?_1000:           z_ld = 1;
                8'b101?_1010:           z_ld = 1;
                8'b1??0_1000:           z_ld = 1;
                8'b0???_1010:           z_ld = 1;
            endcase

        STK0:
            casez( IR )
                8'b?01?_1???:           z_ld = 1;
                8'b?10?_0???:           z_ld = 1;
            endcase

        FETCH:
            casez( IR )
                8'b0110_1000:           z_ld = 1;
                8'b0010_?100:           z_ld = 1;
                8'b0???_??01:           z_ld = 1;

                8'b1010_????:           z_ld = 1;
                8'b101?_?1??:           z_ld = 1;
                8'b11?0_??00:           z_ld = 1;
                8'b11??_??01:           z_ld = 1;
                8'b101?_??01:           z_ld = 1;
            endcase

        BCD0:                           z_ld = 1;
    endcase
end



always @* begin
    d_ld = 0;
    case( state )
        STK0:
            casez( IR )
                8'b?01?_1???:           d_ld = 1;
                8'b?10?_0???:           d_ld = 1;
            endcase

        DECODE:
            casez( IR )
                8'b11?1_1000:           d_ld = 1;
            endcase
    endcase
end




always @* begin
    i_ld = 0;
    case( state )
        STK0:
            casez( IR )
                8'b?01?_1???:           i_ld = 1;
                8'b?10?_0???:           i_ld = 1;
            endcase

        STK2:
            casez( IR )
                8'b0000_0000:           i_ld = 1;
            endcase

        DECODE:
            casez( IR )
                8'b01?1_1000:           i_ld = 1;
            endcase
    endcase
end



always @* begin
    v_ld = 0;
    case( state )
        DATA:
            casez( IR )
                8'b0010_?100:           v_ld = 1;
            endcase

        STK0:
            casez( IR )
                8'b?01?_1???:           v_ld = 1;
                8'b?10?_0???:           v_ld = 1;
            endcase

        FETCH:
            casez( IR )
                8'b?11?_??01:           v_ld = 1;
            endcase


        DECODE:
            casez( IR )
                8'b1011_1000:           v_ld = 1;
            endcase
    endcase
end


always @(posedge clk)
    if( c_ld )
        case( p_sel )
            2'b00:                      C <= CO;
            2'b01:                      C <= DB[0];
            2'b10:                      C <= BCD_C;
            2'b11:                      C <= IR[5];
        endcase

always @(posedge clk)
    if( v_ld )
        case( p_sel )
            2'b00:                      V <= VO;
            2'b01:                      V <= DB[6];
            2'b10:                      V <= 0;
            2'b11:                      V <= 0;
        endcase

always @(posedge clk)
    if( n_ld )
        case( p_sel[0] )
            1'b0:                       N <= NO;
            1'b1:                       N <= DB[7];
        endcase

always @(posedge clk)
    if( z_ld )
        case( p_sel[0] )
            1'b0:                       Z <= ZO;
            1'b1:                       Z <= DB[1];
        endcase

always @(posedge clk)
    if( d_ld )
        case( p_sel[0] )
            1'b0:                       D <= IR[5];
            1'b1:                       D <= DB[3];
        endcase

always @(posedge clk)
    if( i_ld )
        case( p_sel[0] )
            1'b0:                       I <= IR[5] | brk;
            1'b1:                       I <= DB[2];
        endcase



always @(posedge clk)
    if( RST )                           state <= DECODE;
    else case( state )
        DECODE:
            casez( IR )
                8'b1101_1011:           $finish;
                8'b???0_1001:           state <= FETCH;
                8'b???1_1001:           state <= ABS0;
                8'b1??0_00?0:           state <= FETCH;
                8'b???0_01??:           state <= DATA;
                8'b????_0001:           state <= ZP0;
                8'b???1_01??:           state <= ZP0;
                8'b????_11??:           state <= ABS0;
                8'b0??0_?000:           state <= STK0;
                8'b???1_0000:
                    if( cond_true )     state <= BRA0;
                    else                state <= FETCH;
            endcase

        DATA :  if( !rmw )              state <= FETCH;

        FETCH:  if( bcd )               state <= BCD0;
                else                    state <= DECODE;

        ABS0 :  if( CO )                state <= ABS1;
                else if( ind )          state <= IND0;
                else if( jmp )          state <= FETCH;
                else                    state <= DATA;

        ABS1 :                          state <= DATA;

        ZP0  :  if( ~IR[2] )            state <= ZP1;
                else                    state <= DATA;

        ZP1  :                          state <= ABS0;

        IND0 :                          state <= ABS0;

        STK0 :
            casez( IR )
                8'b????_1???:           state <= FETCH;
                8'b????_0???:           state <= STK1;
            endcase

        STK1 :
            casez( IR)
                8'b??0?_????:           state <= STK2;
                8'b?11?_????:           state <= RTS0;
                8'b?01?_????:           state <= ABS0;
            endcase

        STK2 :
            casez( IR)
                8'b?0??_????:           state <= IND0;
                8'b?1??_????:           state <= FETCH;
            endcase

        RTS0 :                          state <= FETCH;

        BRA0 : if( CO ^ M[7] )          state <= CO ? BRA1 : BRA2;
               else                     state <= FETCH;
        BRA1 :                          state <= FETCH;
        BRA2 :                          state <= FETCH;

        BCD0 :                          state <= DECODE;
    endcase





always @*
    casez( IR )
        8'b?11?_??01:                   bcd = D;
        default:                        bcd = 0;
    endcase



always @(posedge clk)
        if( state == DECODE )
            casez( IR )
                8'b0???_?110:           rmw <= 1;
                8'b11??_?110:           rmw <= 1;
                default:                rmw <= 0;
            endcase
        else if( state == DATA )        rmw <= 0;


always @(posedge clk)
    case( state )
        DECODE:                         ind <= ( IR == 8'h6c );
        default:                        ind <= 0;
    endcase

always @*
    casez( IR[7:4] )
        4'b000?:                        cond_true = ~N;
        4'b001?:                        cond_true = N;
        4'b010?:                        cond_true = ~V;
        4'b011?:                        cond_true = V;
        4'b1000:                        cond_true = 1;
        4'b1001:                        cond_true = ~C;
        4'b101?:                        cond_true = C;
        4'b110?:                        cond_true = ~Z;
        4'b111?:                        cond_true = Z;
    endcase

reg [8*6-1:0] statename;

always @*
    case( state )
            FETCH:  statename = "FETCH";
            DECODE: statename = "DECODE";
            DATA:   statename = "DATA";
            ABS0:   statename = "ABS0";
            ABS1:   statename = "ABS1";
            ZP0:    statename = "ZP0";
            ZP1:    statename = "ZP1";
            IND0:   statename = "IND0";
            STK0:   statename = "STK0";
            STK1:   statename = "STK1";
            STK2:   statename = "STK2";
            BRA0:   statename = "BRA0";
            BRA1:   statename = "BRA1";
            BRA2:   statename = "BRA2";
            RTS0:   statename = "RTS0";
            BCD0:   statename = "BCD0";
    endcase

wire [7:0] B_ = B ? "B" : "-";
wire [7:0] C_ = C ? "C" : "-";
wire [7:0] D_ = D ? "D" : "-";
wire [7:0] I_ = I ? "I" : "-";
wire [7:0] N_ = N ? "N" : "-";
wire [7:0] V_ = V ? "V" : "-";
wire [7:0] Z_ = Z ? "Z" : "-";

integer cycle;

always @( posedge clk )
    cycle <= cycle + 1;



always @( posedge clk )
      if( cycle[19:0] == 0 || IR == 8'hdb || !Debug )

      $display( "%d %8s AB:%h DB:%h DO:%h PC:%h IR:%h WE:%d M:%02x S:%02x A:%02x X:%02x Y:%02x AI:%h BI:%h CI:%d OP:%d ALU:%h CO:%h IRQ:%h%h RST:%h%h P:%s%s%s%s%s%s%s (%d)",
        cycle,
        statename, AB, DB, DO, PC, IR, WE, M, S, A, X, Y,
        AI, alu.BI, CI, alu_op, ALU, CO, IRQ, take_irq, RST, in_rst, N_, V_, B_, D_, I_, Z_, C_, cond_true  );

endmodule
module cpu( clk, RST, AB, DB, WE, IRQ, NMI, RDY, Debug );


`include "states.i"

input clk;
input RST;
output [15:0] AB;
inout [7:0] DB;
output WE;
input IRQ;
input NMI;
input RDY;
input Debug;

reg N, V, D, B, I = 1, Z, C;

reg [7:0] S = 8'hff;
reg [7:0] X = 2;
reg [7:0] Y = 3;
reg [7:0] A = 8'h41;


reg m_ld;
reg m_sel_adj;
reg [7:0] M;


reg pc_ld;
reg [15:0] PC;


reg [7:0] ABH = 8'h04;
reg [7:0] ABL = 8'h00;

wire [15:0] AB = { ABH, ABL };
reg [7:0] ALU;


reg [3:0] ADJL;
reg [3:0] ADJH;
wire [7:0] ADJ = { ADJH, ADJL };



reg inc_ab;
wire [15:0] ABI = AB + inc_ab;



wire [2:0] sel_adh;
wire [2:0] sel_adl;


wire [7:0] PCH = PC[15:8];
wire [7:0] PCL = PC[7:0];
reg [7:0] ADH;
reg [7:0] ADL;

reg WE = 1;
reg [7:0] DO;
reg [7:0] AI;
reg CI;



wire take_irq = IRQ & ~I;
reg in_irq;
assign B = ~in_irq;

wire take_rst = RST;
reg in_rst;


reg ir_ld;
reg [7:0] IR;


wire [7:0] P = { N, V, 1'b1, B, D, I, Z, C };
reg cond_true;

wire NO;
wire ZO;
wire VO;
wire CO;
wire BCD_C = C | CO;

reg [1:0] p_sel;
reg z_ld;
reg i_ld;
reg d_ld;
reg n_ld;
reg c_ld;
reg v_ld;


reg [2:0] alu_ai;
reg [2:0] alu_bi;
reg [4:0] alu_op;
reg [2:0] alu_ld;
reg mem_bi;
reg inv_bi;

wire adj_lsd;
wire adj_msd;

alu alu(
    .AI(AI),
    .MI(M),
    .CI(CI),
    .OUT(ALU),
    .mem_bi(mem_bi),
    .inv_bi(inv_bi),
    .op(alu_op),
    .N(NO),
    .Z(ZO),
    .C(CO),
    .V(VO),
    .adj_lsd(adj_lsd),
    .adj_msd(adj_msd) );


assign DB = WE ? 8'hzz : DO;




reg ind;
wire brk = (IR == 8'h00);
wire jmp  = (IR == 8'h4c || IR == 8'h6c || IR == 8'h20 || IR == 8'h00);
reg rmw;
reg bcd;


reg [4:0] state = FETCH;




always @* begin
    sel_adl = ADL_ABI;
    case( state )
        DECODE:
            casez( IR )
                8'b0??0_?000:           sel_adl = ADL_ALU;
                8'b????_0001:           sel_adl = ADL_DB;
                8'b????_01??:           sel_adl = ADL_DB;
            endcase

        DATA:  if( !rmw )               sel_adl = ADL_PC;

        ABS0:                           sel_adl = ADL_ALU;

        ZP0:                            sel_adl = ADL_ALU;

        ZP1:                            sel_adl = ADL_ALU;

        STK0:  if( IR[3] )              sel_adl = ADL_PC;
               else                     sel_adl = ADL_ALU;

        STK1:
            casez( IR )
                8'b??0?_????:           sel_adl = ADL_ALU;
                8'b?01?_????:           sel_adl = ADL_PC;
                8'b?11?_????:           sel_adl = ADL_ALU;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           sel_adl = in_rst ? ADL_RST : ADL_BRK;
                8'b?1??_????:           sel_adl = ADL_ALU;
            endcase
        BRA0:                           sel_adl = ADL_ALU;
    endcase
end


always @* begin
    sel_adh = ADH_ABI;
    case( state )
        DECODE:
            casez( IR )
                8'b0??0_?000:           sel_adh = ADH_SP;
                8'b????_0001:           sel_adh = ADH_ZP;
                8'b????_01??:           sel_adh = ADH_ZP;
            endcase

        DATA:  if( !rmw )               sel_adh = ADH_PC;

        ABS0:                           sel_adh = ADH_DB;

        ABS1:                           sel_adh = ADH_ALU;

        ZP0:                            sel_adh = ADH_ZP;

        ZP1:                            sel_adh = ADH_ZP;

        STK0:  if( IR[3] )              sel_adh = ADH_PC;
               else                     sel_adh = ADH_SP;
        STK1:
            casez( IR )
                8'b??0?_????:           sel_adh = ADH_SP;
                8'b?01?_????:           sel_adh = ADH_PC;
                8'b?11?_????:           sel_adh = ADH_DB;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           sel_adh = ADH_FF;
                8'b?1??_????:           sel_adh = ADH_DB;
            endcase
        BRA0:                           sel_adh = ADH_PC;
        BRA1:                           sel_adh = ADH_ALU;
        BRA2:                           sel_adh = ADH_ALU;
    endcase
end


always @* begin
    inc_ab = 0;
    case( state )
        DECODE:
            casez( IR )
                8'b0??0_1000:           inc_ab = 0;
                default:                inc_ab = !take_irq;
            endcase
        BCD0:                           inc_ab = 1;
        RTS0:                           inc_ab = 1;
        IND0:                           inc_ab = 1;
        FETCH:                          inc_ab = !bcd & !take_irq;
        ABS0:                           inc_ab = 1;
    endcase
end



always @*
    case( sel_adh )
        ADH_ABI :                       ADH = ABI[15:8];
        ADH_ALU :                       ADH = ALU;
        ADH_DB  :                       ADH = DB;
        ADH_PC  :                       ADH = PCH;
        ADH_FF  :                       ADH = 8'hFF;
        ADH_SP  :                       ADH = 8'h01;
        ADH_ZP  :                       ADH = 8'h00;
        default:                        ADH = 8'h55;
    endcase

always @*
    case( sel_adl )
        ADL_ABI :						ADL = ABI[7:0];
        ADL_ALU :						ADL = ALU;
        ADL_DB  :						ADL = DB;
        ADL_PC  :						ADL = PCL;
        ADL_NMI :                       ADL = 8'hFA;
        ADL_RST :						ADL = 8'hFC;
        ADL_BRK :						ADL = 8'hFE;
    endcase


always @(posedge clk)
    ABH <= ADH;

always @(posedge clk)
    ABL <= ADL;



always @* begin
    pc_ld = 0;
    case( state )
        DECODE:                         pc_ld = 1;
        BCD0:                           pc_ld = 1;
        RTS0:                           pc_ld = 1;
        IND0:                           pc_ld = 1;
        FETCH:                          pc_ld = 1;
        ABS0:                           pc_ld = IR[3];
    endcase
end

always @(posedge clk)
    if( pc_ld )
        PC <= ABI;


always @(posedge clk)
    case( state )
        DECODE:
            casez( IR )
                8'b00?0_0000:           WE <= 0;
                8'b0?00_1000:           WE <= 0;
                8'b1000_01??:           WE <= 0;
                default:                WE <= 1;
            endcase

        STK0:
            casez( IR )
                8'b?0??_0???:           WE <= 0;
                default:                WE <= 1;
            endcase

        STK1:
            casez( IR )
                8'b?00?_????:           WE <= 0;
                default:                WE <= 1;
            endcase

        DATA:                           WE <= !rmw;

        ABS0:
            casez( IR )
                8'b100?_????:           WE <= CO;
                default:                WE <= 1;
            endcase

        ABS1:
            casez( IR )
                8'b100?_????:           WE <= 0;
                default:                WE <= 1;
            endcase

        ZP0:
            casez( IR )
                8'b1001_01??:           WE <= 0;
                default:                WE <= 1;
            endcase

        default:                        WE <= 1;
    endcase


always @* begin
    DO = 8'h55;
    case( state )
        STK0:
            casez( IR )
                8'b?00?_1???:           DO = P;
                8'b?10?_1???:           DO = ALU;
                8'b????_0???:           DO = PCH;
            endcase

        STK1:
            casez( IR )
                8'b????_0???:           DO = PCL;
            endcase

        STK2:                           DO = P;

        DATA:                           DO = ALU;
    endcase
end


always @*
    if( bcd & adj_lsd )                 ADJL = 6;
    else                                ADJL = 0;

always @*
    if( bcd & adj_msd )                 ADJH = 6;
    else                                ADJH = 0;


always @* begin
    m_ld = 0;
    case( state )
        ABS0:                           m_ld = 1;

        STK0:
            casez( IR )
                8'b??1?_1???:           m_ld = 1;
                8'b?1??_0???:           m_ld = 1;
            endcase

        ZP1, IND0, DECODE:              m_ld = 1;

        STK1, STK2:
            casez( IR )
                8'b?1??_????:           m_ld = 1;
            endcase

        DATA:                           m_ld = 1;

        FETCH:                          m_ld = 1;
    endcase
end


always @*
    case( state )
        FETCH:                          m_sel_adj = 1;
        default:                        m_sel_adj = 0;
    endcase

always @(posedge clk)
    if( m_ld )
        M <= m_sel_adj ? ADJ : DB;



always @* begin
    ir_ld = in_rst;
    case( state )
        FETCH:                          ir_ld = !bcd;

        BCD0:                           ir_ld = 1;

        DECODE:
            casez( IR )
                8'b???1_10?0:           ir_ld = 1;
                8'b1???_10?0:           ir_ld = 1;
                8'b????_1010:           ir_ld = 1;
            endcase
    endcase
end

always @(posedge clk)
    if( ir_ld & take_irq )              in_irq <= 1;
    else if( state == FETCH )           in_irq <= 0;

always @(posedge clk)
    if( ir_ld & take_rst )              in_rst <= 1;
    else if( state == FETCH )           in_rst <= 0;

always @(posedge clk)
    if( ir_ld )
        IR <= (take_irq|in_rst) ? 8'h00 : DB;



always @* begin
    alu_ai = AI_ZZZ;
    case( state )
        DECODE:
            casez( IR )
                8'b0??0_?000:           alu_ai = AI_S;
                8'b1011_1010:           alu_ai = AI_S;
                8'b100?_1010:           alu_ai = AI_X;
                8'b1001_1000:           alu_ai = AI_Y;
                8'b1010_10?0:           alu_ai = AI_A;
                8'b1?00_1000:           alu_ai = AI_Y;
                8'b1110_1000:           alu_ai = AI_X;
                8'b1100_1010:           alu_ai = AI_X;
                8'b0???_1010:           alu_ai = AI_A;
            endcase

        ABS0:
            casez( IR )
                8'b10?1_?110:           alu_ai = AI_Y;
                8'b???1_?001:           alu_ai = AI_Y;
                8'b???1_11??:           alu_ai = AI_X;
                8'b???0_????:           alu_ai = AI_M;
            endcase

        ZP0:
            casez( IR )
                8'b10?1_?110:           alu_ai = AI_Y;
                8'b????_01??:           alu_ai = AI_X;
                8'b???0_0001:           alu_ai = AI_X;
                8'b???1_0001:           alu_ai = AI_M;
            endcase

        ZP1:
            casez( IR )
                8'b???0_0001:           alu_ai = AI_X;
                8'b???1_0001:           alu_ai = AI_M;
            endcase

        STK0:
            casez( IR )
                8'b????_0???:           alu_ai = AI_S;
                8'b??0?_1???:           alu_ai = AI_A;
            endcase

        STK1:
            casez( IR )
                8'b?10?_????:           alu_ai = AI_S;
                8'b?0??_????:           alu_ai = AI_S;
                8'b?11?_????:           alu_ai = AI_M;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           alu_ai = AI_S;
                8'b?1??_????:           alu_ai = AI_M;
            endcase

        DATA:
            casez( IR )
                8'b0???_??10:           alu_ai = AI_M;
                8'b11??_?110:           alu_ai = AI_M;
                8'b100?_??00:           alu_ai = AI_Y;
                8'b100?_??01:           alu_ai = AI_A;
                8'b100?_??10:           alu_ai = AI_X;
            endcase

        FETCH:
            casez( IR )
                8'b101?_????:           alu_ai = AI_M;
                8'b0?10_1000:           alu_ai = AI_M;
                8'b0?00_1000:           alu_ai = AI_S;
                8'b001?_?100:           alu_ai = AI_A;
                8'b0???_??01:           alu_ai = AI_A;
                8'b11??_??01:           alu_ai = AI_A;
                8'b110?_??00:           alu_ai = AI_Y;
                8'b111?_??00:           alu_ai = AI_X;
            endcase

        ABS1:                           alu_ai = AI_M;
        BCD0:                           alu_ai = AI_A;
        BRA0:                           alu_ai = AI_PCL;
        BRA1:                           alu_ai = AI_PCH;
        BRA2:                           alu_ai = AI_PCH;
    endcase
end



always @* begin
    mem_bi = 0;
    case( state )

        ABS0:
            casez( IR )
                8'b1011_1110:           mem_bi = 1;
                8'b????_1001:           mem_bi = 1;
                8'b???1_11??:           mem_bi = 1;
                8'b???0_11??:           mem_bi = 0;
                8'b00?0_0000:           mem_bi = 0;
                8'b???0_0001:           mem_bi = 0;
                8'b???1_0001:           mem_bi = 1;
            endcase

        ZP0:
            casez( IR )
                8'b10?1_0110:           mem_bi = 1;
                8'b????_01??:           mem_bi = 1;
                8'b???0_0001:           mem_bi = 1;
                8'b???1_0001:           mem_bi = 0;
            endcase

        ZP1:
            casez( IR )
                8'b???0_0001:           mem_bi = 1;
                8'b???1_0001:           mem_bi = 0;
            endcase

        FETCH:
            casez( IR )
                8'b101?_????:           mem_bi = 0;
                8'b0??0_1000:           mem_bi = 0;
                8'b001?_??00:           mem_bi = 1;
                8'b0???_??01:           mem_bi = 1;
                8'b11??_??01:           mem_bi = 1;
                8'b11??_??00:           mem_bi = 1;
            endcase

        DECODE:                         mem_bi = 0;
        ABS1:                           mem_bi = 0;
        STK0:                           mem_bi = 0;
        STK1:                           mem_bi = 0;
        STK2:                           mem_bi = 0;
        BRA0:                           mem_bi = 1;
        BRA1:                           mem_bi = 0;
        BRA2:                           mem_bi = 0;
        DATA:                           mem_bi = 0;
        BCD0:                           mem_bi = 1;

    endcase
end


always @* begin
    inv_bi = 0;
    case( state )
        DECODE:
            casez( IR )
                8'b01?0_0000:           inv_bi = 0;
                8'b0?10_1000:           inv_bi = 0;
                8'b1000_1000:           inv_bi = 1;
                8'b11?0_1000:           inv_bi = 0;
                8'b1100_1010:           inv_bi = 1;
            endcase

        STK0:
            casez( IR )
                8'b?1??_0???:           inv_bi = 0;
                8'b?0??_0???:           inv_bi = 1;
                8'b??0?_1???:           inv_bi = 0;
            endcase

        STK1:
            casez( IR )
                8'b?10?_????:           inv_bi = 0;
                8'b?0??_????:           inv_bi = 1;
                8'b?11?_????:           inv_bi = 0;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           inv_bi = 1;
                8'b?1??_????:           inv_bi = 0;
            endcase

        DATA:
            casez( IR )
                8'b110?_?110:           inv_bi = 1;
                8'b111?_?110:           inv_bi = 0;
                8'b100?_???0:           inv_bi = 0;
                8'b100?_??01:           inv_bi = 0;
            endcase

        FETCH:
            casez( IR )
                8'b101?_????:           inv_bi = 0;
                8'b0?10_1000:           inv_bi = 0;
                8'b0?00_1000:           inv_bi = 1;
                8'b001?_??00:           inv_bi = 0;
                8'b0???_??01:           inv_bi = 0;
                8'b11??_??0?:           inv_bi = 1;
            endcase

        BCD0:
            casez( IR )
                8'b011?_??01:           inv_bi = 0;
                8'b111?_??01:           inv_bi = 1;
            endcase

        ABS0:                           inv_bi = 0;
        ABS1:                           inv_bi = 0;
        ZP0:                            inv_bi = 0;
        ZP1:                            inv_bi = 0;
        BRA0:                           inv_bi = 0;
        BRA1:                           inv_bi = 0;
        BRA2:                           inv_bi = 1;

    endcase
end



always @* begin
    alu_op = ALU_ADC;
    case( state )
        DECODE:
            casez( IR )
                8'b00?0_0000:           alu_op = ALU_AI;
                8'b01?0_0000:           alu_op = ALU_ADC;
                8'b0?00_1000:           alu_op = ALU_AI;
                8'b0?10_1000:           alu_op = ALU_ADC;
                8'b1000_1000:           alu_op = ALU_ADC;
                8'b1001_1000:           alu_op = ALU_AI;
                8'b1100_1000:           alu_op = ALU_ADC;
                8'b1110_1000:           alu_op = ALU_ADC;
                8'b00??_1010:           alu_op = ALU_ROL;
                8'b01??_1010:           alu_op = ALU_ROR;
                8'b100?_1010:           alu_op = ALU_AI;
                8'b1010_10?0:           alu_op = ALU_AI;
                8'b1011_1010:           alu_op = ALU_AI;
                8'b1100_1010:           alu_op = ALU_ADC;
            endcase

        DATA:
            casez( IR )
                8'b00??_??10:           alu_op = ALU_ROL;
                8'b01??_??10:           alu_op = ALU_ROR;
                8'b110?_?110:           alu_op = ALU_ADC;
                8'b111?_?110:           alu_op = ALU_ADC;
                8'b100?_??00:           alu_op = ALU_AI;
                8'b100?_??01:           alu_op = ALU_AI;
                8'b100?_??10:           alu_op = ALU_AI;
            endcase

        FETCH:
            casez( IR )
                8'b101?_????:           alu_op = ALU_AI;
                8'b0?10_1000:           alu_op = ALU_AI;
                8'b0?00_1000:           alu_op = ALU_ADC;
                8'b001?_??00:           alu_op = ALU_AND;
                8'b011?_??01:           alu_op = ALU_ADC;
                8'b000?_??01:           alu_op = ALU_ORA;
                8'b001?_??01:           alu_op = ALU_AND;
                8'b010?_??01:           alu_op = ALU_EOR;
                8'b11??_??01:           alu_op = ALU_ADC;
                8'b110?_??00:           alu_op = ALU_ADC;
                8'b111?_??00:           alu_op = ALU_ADC;
            endcase
    endcase
end



always @* begin
    alu_ld = 0;
    case( state )
        DECODE:
            casez( IR )
                8'b1000_1010:           alu_ld = LD_A;
                8'b0???_1010:           alu_ld = LD_A;
                8'b101?_1010:           alu_ld = LD_X;
                8'b110?_1010:           alu_ld = LD_X;
                8'b1001_1010:           alu_ld = LD_S;
                8'b1001_1000:           alu_ld = LD_A;
                8'b1110_1000:           alu_ld = LD_X;
                8'b1??0_1000:           alu_ld = LD_Y;
                8'b01?0_0000:           alu_ld = LD_S;
                8'b0?10_1000:           alu_ld = LD_S;
            endcase

        FETCH:
            casez( IR )
                8'b0???_??01:           alu_ld = LD_A;
                8'b101?_??01:           alu_ld = LD_A;
                8'b111?_??01:           alu_ld = LD_A;
                8'b?11?_10??:           alu_ld = LD_A;
                8'b101?_??10:           alu_ld = LD_X;
                8'b1010_??00:           alu_ld = LD_Y;
                8'b1011_?100:           alu_ld = LD_Y;
                8'b0?00_1000:           alu_ld = LD_S;
            endcase

        STK0:
            casez( IR )
                8'b?1??_0???:           alu_ld = LD_S;
                8'b?0??_0???:           alu_ld = LD_S;
            endcase

        STK1:
            casez( IR )
                8'b?10?_????:           alu_ld = LD_S;
                8'b?0??_????:           alu_ld = LD_S;
            endcase

        STK2:
            casez( IR )
                8'b?0??_????:           alu_ld = LD_S;
            endcase

        BCD0:                           alu_ld = LD_A;
    endcase
end



always @* begin
    CI = 0;
    case( state )
        ZP1:
            casez( IR )
                8'b????_0001:           CI = 1;
            endcase

        DECODE:
            casez( IR )
                8'b0?10_1010:           CI = C;
                8'b01?0_0000:           CI = 1;
                8'b0?10_1000:           CI = 1;
                8'b11?0_1000:           CI = 1;
            endcase

        FETCH:
            casez( IR )
                8'b110?_??01:           CI = 1;
                8'b11??_??00:           CI = 1;
                8'b?11?_??01:           CI = C;
            endcase

        STK0:
            casez( IR )
                8'b?1??_0???:           CI = 1;
            endcase

        STK1:
            casez( IR )
                8'b?10?_????:           CI = 1;
            endcase

        ABS1:                           CI = 1;

        BRA1:                           CI = 1;

        DATA:
            casez( IR )
                8'b0?1?_?110:           CI = C;
                8'b111?_?110:           CI = 1;
            endcase

        BCD0:
            casez( IR )
                8'b011?_??01:           CI = 0;
                8'b111?_??01:           CI = 1;
            endcase
    endcase
end



always @*
    case( alu_ai )
        AI_PCL:                         AI = PCL;
        AI_PCH:                         AI = PCH;
        AI_A:                           AI = A;
        AI_X:                           AI = X;
        AI_Y:                           AI = Y;
        AI_M:                           AI = M;
        AI_S:                           AI = S;
        AI_ZZZ:                         AI = 8'h55;
    endcase



always @(posedge clk)
    case( alu_ld )
        LD_A:                           A <= ALU;
        LD_X:                           X <= ALU;
        LD_Y:                           Y <= ALU;
        LD_S:                           S <= ALU;
    endcase


always @* begin
    p_sel = 2'b00;
    case( state )
        STK0:
            casez( IR )
                8'b?01?_1???:           p_sel = 2'b01;
                8'b?10?_0???:           p_sel = 2'b01;
            endcase

        STK2:
            casez( IR )
                8'b0000_0000:           p_sel = 2'b00;
            endcase

        DATA:
            casez( IR )
                8'b0???_?110:           p_sel = 2'b00;
                8'b11??_?110:           p_sel = 2'b00;
                8'b0010_?100:           p_sel = 2'b01;
            endcase

        FETCH:
            casez( IR )
                8'b0110_1000:           p_sel = 2'b00;
                8'b011?_??01:           p_sel = 2'b00;
                8'b1010_????:           p_sel = 2'b00;
                8'b101?_?1??:           p_sel = 2'b00;
                8'b101?_??01:           p_sel = 2'b00;
                8'b11?0_??00:           p_sel = 2'b00;
                8'b11?0_??00:           p_sel = 2'b00;
                8'b11??_??01:           p_sel = 2'b00;
                8'b11??_??01:           p_sel = 2'b00;
            endcase

        DECODE:
            casez( IR )
                8'b00?1_1000:           p_sel = 2'b11;
                8'b11?1_1000:           p_sel = 2'bx0;
                8'b01?1_1000:           p_sel = 2'bx0;
                8'b1011_1000:           p_sel = 2'b1x;
                8'b0???_1010:           p_sel = 2'b00;
                8'b0???_1010:           p_sel = 2'b00;
                8'b100?_1000:           p_sel = 2'b00;
                8'b101?_1010:           p_sel = 2'b00;
                8'b10?0_10?0:           p_sel = 2'b00;
                8'b1?00_10?0:           p_sel = 2'b00;
                8'b1??0_1000:           p_sel = 2'b00;
            endcase

        BCD0:                           p_sel = 2'b10;
    endcase
end


always @* begin
    c_ld = 0;
    case( state )
        STK0:
            casez( IR )
                8'b?01?_1???:           c_ld = 1;
                8'b?10?_0???:           c_ld = 1;
            endcase

        DATA:
            casez( IR )
                8'b0???_?110:           c_ld = !WE;
            endcase

        FETCH:
            casez( IR )
                8'b011?_??01:           c_ld = 1;
                8'b11??_??01:           c_ld = 1;
                8'b11?0_??00:           c_ld = 1;
            endcase

        DECODE:
            casez( IR )
                8'b0???_1010:           c_ld = 1;
                8'b00?1_1000:           c_ld = 1;
            endcase

        BCD0:
            casez( IR )
                8'b011?_??01:           c_ld = 1;
            endcase

    endcase
end

always @* begin
    n_ld = 0;
    case( state )
        DATA:
            casez( IR )
                8'b0???_?110:           n_ld = !WE;
                8'b11??_?110:           n_ld = !WE;
                8'b0010_?100:           n_ld = 1;
            endcase

        DECODE:
            casez( IR )
                8'b1?00_10?0:           n_ld = 1;
                8'b10?0_10?0:           n_ld = 1;
                8'b100?_1000:           n_ld = 1;
                8'b101?_1010:           n_ld = 1;
                8'b1??0_1000:           n_ld = 1;
                8'b0???_1010:           n_ld = 1;
            endcase

        STK0:
            casez( IR )
                8'b?01?_1???:           n_ld = 1;
                8'b?10?_0???:           n_ld = 1;
            endcase

        FETCH:
            casez( IR )
                8'b0110_1000:           n_ld = 1;
                8'b0???_??01:           n_ld = 1;
                8'b1010_????:           n_ld = 1;
                8'b101?_?1??:           n_ld = 1;
                8'b11?0_??00:           n_ld = 1;
                8'b11??_??01:           n_ld = 1;
                8'b101?_??01:           n_ld = 1;
            endcase

        BCD0:                           n_ld = 1;
    endcase
end


always @* begin
    z_ld = 0;
    case( state )
        DATA:
            casez( IR )
                8'b0???_?110:           z_ld = !WE;
                8'b11??_?110:           z_ld = !WE;
            endcase

        DECODE:
            casez( IR )
                8'b1?00_10?0:           z_ld = 1;
                8'b10?0_10?0:           z_ld = 1;
                8'b100?_1000:           z_ld = 1;
                8'b101?_1010:           z_ld = 1;
                8'b1??0_1000:           z_ld = 1;
                8'b0???_1010:           z_ld = 1;
            endcase

        STK0:
            casez( IR )
                8'b?01?_1???:           z_ld = 1;
                8'b?10?_0???:           z_ld = 1;
            endcase

        FETCH:
            casez( IR )
                8'b0110_1000:           z_ld = 1;
                8'b0010_?100:           z_ld = 1;
                8'b0???_??01:           z_ld = 1;

                8'b1010_????:           z_ld = 1;
                8'b101?_?1??:           z_ld = 1;
                8'b11?0_??00:           z_ld = 1;
                8'b11??_??01:           z_ld = 1;
                8'b101?_??01:           z_ld = 1;
            endcase

        BCD0:                           z_ld = 1;
    endcase
end



always @* begin
    d_ld = 0;
    case( state )
        STK0:
            casez( IR )
                8'b?01?_1???:           d_ld = 1;
                8'b?10?_0???:           d_ld = 1;
            endcase

        DECODE:
            casez( IR )
                8'b11?1_1000:           d_ld = 1;
            endcase
    endcase
end




always @* begin
    i_ld = 0;
    case( state )
        STK0:
            casez( IR )
                8'b?01?_1???:           i_ld = 1;
                8'b?10?_0???:           i_ld = 1;
            endcase

        STK2:
            casez( IR )
                8'b0000_0000:           i_ld = 1;
            endcase

        DECODE:
            casez( IR )
                8'b01?1_1000:           i_ld = 1;
            endcase
    endcase
end



always @* begin
    v_ld = 0;
    case( state )
        DATA:
            casez( IR )
                8'b0010_?100:           v_ld = 1;
            endcase

        STK0:
            casez( IR )
                8'b?01?_1???:           v_ld = 1;
                8'b?10?_0???:           v_ld = 1;
            endcase

        FETCH:
            casez( IR )
                8'b?11?_??01:           v_ld = 1;
            endcase


        DECODE:
            casez( IR )
                8'b1011_1000:           v_ld = 1;
            endcase
    endcase
end


always @(posedge clk)
    if( c_ld )
        case( p_sel )
            2'b00:                      C <= CO;
            2'b01:                      C <= DB[0];
            2'b10:                      C <= BCD_C;
            2'b11:                      C <= IR[5];
        endcase

always @(posedge clk)
    if( v_ld )
        case( p_sel )
            2'b00:                      V <= VO;
            2'b01:                      V <= DB[6];
            2'b10:                      V <= 0;
            2'b11:                      V <= 0;
        endcase

always @(posedge clk)
    if( n_ld )
        case( p_sel[0] )
            1'b0:                       N <= NO;
            1'b1:                       N <= DB[7];
        endcase

always @(posedge clk)
    if( z_ld )
        case( p_sel[0] )
            1'b0:                       Z <= ZO;
            1'b1:                       Z <= DB[1];
        endcase

always @(posedge clk)
    if( d_ld )
        case( p_sel[0] )
            1'b0:                       D <= IR[5];
            1'b1:                       D <= DB[3];
        endcase

always @(posedge clk)
    if( i_ld )
        case( p_sel[0] )
            1'b0:                       I <= IR[5] | brk;
            1'b1:                       I <= DB[2];
        endcase



always @(posedge clk)
    if( RST )                           state <= DECODE;
    else case( state )
        DECODE:
            casez( IR )
                8'b1101_1011:           $finish;
                8'b???0_1001:           state <= FETCH;
                8'b???1_1001:           state <= ABS0;
                8'b1??0_00?0:           state <= FETCH;
                8'b???0_01??:           state <= DATA;
                8'b????_0001:           state <= ZP0;
                8'b???1_01??:           state <= ZP0;
                8'b????_11??:           state <= ABS0;
                8'b0??0_?000:           state <= STK0;
                8'b???1_0000:
                    if( cond_true )     state <= BRA0;
                    else                state <= FETCH;
            endcase

        DATA :  if( !rmw )              state <= FETCH;

        FETCH:  if( bcd )               state <= BCD0;
                else                    state <= DECODE;

        ABS0 :  if( CO )                state <= ABS1;
                else if( ind )          state <= IND0;
                else if( jmp )          state <= FETCH;
                else                    state <= DATA;

        ABS1 :                          state <= DATA;

        ZP0  :  if( ~IR[2] )            state <= ZP1;
                else                    state <= DATA;

        ZP1  :                          state <= ABS0;

        IND0 :                          state <= ABS0;

        STK0 :
            casez( IR )
                8'b????_1???:           state <= FETCH;
                8'b????_0???:           state <= STK1;
            endcase

        STK1 :
            casez( IR)
                8'b??0?_????:           state <= STK2;
                8'b?11?_????:           state <= RTS0;
                8'b?01?_????:           state <= ABS0;
            endcase

        STK2 :
            casez( IR)
                8'b?0??_????:           state <= IND0;
                8'b?1??_????:           state <= FETCH;
            endcase

        RTS0 :                          state <= FETCH;

        BRA0 : if( CO ^ M[7] )          state <= CO ? BRA1 : BRA2;
               else                     state <= FETCH;
        BRA1 :                          state <= FETCH;
        BRA2 :                          state <= FETCH;

        BCD0 :                          state <= DECODE;
    endcase





always @*
    casez( IR )
        8'b?11?_??01:                   bcd = D;
        default:                        bcd = 0;
    endcase



always @(posedge clk)
        if( state == DECODE )
            casez( IR )
                8'b0???_?110:           rmw <= 1;
                8'b11??_?110:           rmw <= 1;
                default:                rmw <= 0;
            endcase
        else if( state == DATA )        rmw <= 0;


always @(posedge clk)
    case( state )
        DECODE:                         ind <= ( IR == 8'h6c );
        default:                        ind <= 0;
    endcase

always @*
    casez( IR[7:4] )
        4'b000?:                        cond_true = ~N;
        4'b001?:                        cond_true = N;
        4'b010?:                        cond_true = ~V;
        4'b011?:                        cond_true = V;
        4'b1000:                        cond_true = 1;
        4'b1001:                        cond_true = ~C;
        4'b101?:                        cond_true = C;
        4'b110?:                        cond_true = ~Z;
        4'b111?:                        cond_true = Z;
    endcase

reg [8*6-1:0] statename;

always @*
    case( state )
            FETCH:  statename = "FETCH";
            DECODE: statename = "DECODE";
            DATA:   statename = "DATA";
            ABS0:   statename = "ABS0";
            ABS1:   statename = "ABS1";
            ZP0:    statename = "ZP0";
            ZP1:    statename = "ZP1";
            IND0:   statename = "IND0";
            STK0:   statename = "STK0";
            STK1:   statename = "STK1";
            STK2:   statename = "STK2";
            BRA0:   statename = "BRA0";
            BRA1:   statename = "BRA1";
            BRA2:   statename = "BRA2";
            RTS0:   statename = "RTS0";
            BCD0:   statename = "BCD0";
    endcase

wire [7:0] B_ = B ? "B" : "-";
wire [7:0] C_ = C ? "C" : "-";
wire [7:0] D_ = D ? "D" : "-";
wire [7:0] I_ = I ? "I" : "-";
wire [7:0] N_ = N ? "N" : "-";
wire [7:0] V_ = V ? "V" : "-";
wire [7:0] Z_ = Z ? "Z" : "-";

integer cycle;

always @( posedge clk )
    cycle <= cycle + 1;



always @( posedge clk )
      if( cycle[19:0] == 0 || IR == 8'hdb || !Debug )

      $display( "%d %8s AB:%h DB:%h DO:%h PC:%h IR:%h WE:%d M:%02x S:%02x A:%02x X:%02x Y:%02x AI:%h BI:%h CI:%d OP:%d ALU:%h CO:%h IRQ:%h%h RST:%h%h P:%s%s%s%s%s%s%s (%d)",
        cycle,
        statename, AB, DB, DO, PC, IR, WE, M, S, A, X, Y,
        AI, alu.BI, CI, alu_op, ALU, CO, IRQ, take_irq, RST, in_rst, N_, V_, B_, D_, I_, Z_, C_, cond_true  );

endmodule