data/full_repos/permissive/136510272/projects/05_nes/cpu.v
1: b'%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:87: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS\'s CONST \'3\'h0\' generates 3 bits.\n                                                                             : ... In instance cpu\nreg  [7:0]  TR     = 3\'h0;       \n                     ^~~~\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:108: Operator ADD expects 8 bits on the RHS, but RHS\'s VARREF \'Cout\' generates 1 bits.\n                                                                              : ... In instance cpu\nwire [7:0]  HIDin   = DIN + Cout;         \n                          ^\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:122: Operator EQ expects 5 bits on the RHS, but RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\nwire debug_clk = CLK && MS == 1\'b0;\n                           ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:209: Operator ASSIGNDLY expects 16 bits on the Assign RHS, but Assign RHS\'s SEL generates 8 bits.\n                                                                              : ... In instance cpu\n        4\'h1: begin MS <= MSINC; EA <= XDin[7:0];  AM <= 1\'b1; end\n                                    ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:210: Operator ASSIGNDLY expects 16 bits on the Assign RHS, but Assign RHS\'s SEL generates 8 bits.\n                                                                              : ... In instance cpu\n        4\'h2: begin MS <= MSINC; EA <= EAINC[7:0]; TR <= DIN;  end\n                                    ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:215: Operator ASSIGNDLY expects 16 bits on the Assign RHS, but Assign RHS\'s VARREF \'DIN\' generates 8 bits.\n                                                                              : ... In instance cpu\n        4\'h4: begin MS <= MSINC; EA <= DIN;        AM <= 1\'b1; end\n                                    ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:216: Operator ASSIGNDLY expects 16 bits on the Assign RHS, but Assign RHS\'s SEL generates 8 bits.\n                                                                              : ... In instance cpu\n        4\'h5: begin MS <= MSINC; EA <= EAINC[7:0]; TR <= YDin[7:0]; Cout <= YDin[8]; end\n                                    ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:221: Operator ASSIGNDLY expects 16 bits on the Assign RHS, but Assign RHS\'s VARREF \'DIN\' generates 8 bits.\n                                                                              : ... In instance cpu\n        4\'h7: begin MS <= 5\'h11; EA <= DIN;       {AM, RD} <= {1\'b1, ENARD}; end\n                                    ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:225: Operator ASSIGNDLY expects 16 bits on the Assign RHS, but Assign RHS\'s SEL generates 8 bits.\n                                                                              : ... In instance cpu\n        4\'h8: begin MS <= 5\'h10; EA <= XDin[7:0]; {AM, RD} <= {1\'b1, ENARD}; end\n                                    ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:229: Operator ASSIGNDLY expects 16 bits on the Assign RHS, but Assign RHS\'s SEL generates 8 bits.\n                                                                              : ... In instance cpu\n        4\'h9: begin MS <= 5\'h10; EA <= YDin[7:0]; {AM, RD} <= {1\'b1, ENARD}; end\n                                    ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:238: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n                 begin MS <= 1\'b0;  PC <= EADIN; end\n                          ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:315: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n              8\'b011_011_00: begin MS <= 1\'b0;  PC <= EADIN; AM <= 1\'b0; end   \n                                      ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:316: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n              8\'b0x0_010_00: begin MS <= 1\'b0;  {AM, AS, WREQ} <= 3\'b000; end  \n                                      ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:324: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n              8\'b001_000_00: begin MS <= 1\'b0;  PC <= EA; {AS, WREQ, AM} <= 3\'b000; end\n                                      ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:327: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n                            default: begin MS <= 1\'b0; end\n                                              ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:348: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n        5\'h16: begin MS <= 1\'b0; AM <= 1\'b0; PC <= EADIN;  end\n                        ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:356: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n            else    begin PC <= PCINC; MS <= 1\'b0; end\n                                          ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:361: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n        5\'h19: begin MS <= 1\'b0; end   \n                        ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:366: Operator ASSIGNDLY expects 5 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'h0\' generates 1 bits.\n                                                                              : ... In instance cpu\n        5\'h1F: begin PC <= EADIN; MS <= 1\'b0; end\n                                     ^~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h0\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h1\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h2\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h3\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h4\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h5\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h6\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h7\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h8\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'h9\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'ha\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'hb\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'hc\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'hd\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'he\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:138: Operator CASE expects 5 bits on the Case Item, but Case Item\'s CONST \'4\'hf\' generates 4 bits.\n                                                                              : ... In instance cpu\n    else if (CE) case (MS)\n                 ^~~~\n%Warning-WIDTH: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:438: Operator ASSIGN expects 7 bits on the Assign RHS, but Assign RHS\'s CONST \'8\'h2b\' generates 8 bits.\n                                                                              : ... In instance cpu\n        8\'b100_110_10: {alu, RB, SW}              = 8\'b0101_01_1;          \n                                                  ^\n%Error: data/full_repos/permissive/136510272/projects/05_nes/cpu.v:575: Cannot find file containing module: \'alu\'\nalu ALU(\n^~~\n        ... Looked in:\n             data/full_repos/permissive/136510272/projects/05_nes,data/full_repos/permissive/136510272/alu\n             data/full_repos/permissive/136510272/projects/05_nes,data/full_repos/permissive/136510272/alu.v\n             data/full_repos/permissive/136510272/projects/05_nes,data/full_repos/permissive/136510272/alu.sv\n             alu\n             alu.v\n             alu.sv\n             obj_dir/alu\n             obj_dir/alu.v\n             obj_dir/alu.sv\n%Error: Exiting due to 1 error(s), 36 warning(s)\n'
module cpu(

    input  wire        RESET,
    input  wire        CLK,
    input  wire        CE,
    output wire [15:0] ADDR,
    input  wire [7:0]  DIN,
    output reg  [7:0]  DOUT,
    output wire [15:0] EAWR,
    output reg         WREQ,
    output reg         RD,
    input  wire        NMI,
    output wire [7:0]  DEBUG,
    input  wire [1:0]  DKEY

);

assign ADDR  = AS ? {8'h01, S} : (AM ? EA : PC);
assign EAWR  = AS ? {8'h01, S} : EA;


assign  DEBUG = DKEY == 2'b11 ? A[7:0] :
                DKEY == 2'b10 ? X[7:0] :
                DKEY == 2'b01 ? Y[7:0] :
                                P[7:0];

`define DEBUGPC 0




`define NDX     5'h01
`define NDY     5'h04
`define ZP      5'h07
`define ZPX     5'h08
`define ZPY     5'h09
`define ABS     5'h0A
`define ABX     5'h0C
`define ABY     5'h0E


`define LAT1    5'h10
`define IMM     5'h11
`define IMP     5'h11
`define ACC     5'h11


`define EXEC    5'h11
`define EXEC2   5'h12
`define EXEC3   5'h13
`define EXEC4   5'h14
`define EXEC5   5'h15
`define EXEC6   5'h16


`define REL     5'h17
`define REL1    5'h18
`define REL2    5'h19
`define REL3    5'h1A




`define RST     5'h1D
`define RST2    5'h1E
`define RST3    5'h1F

initial begin EA = 16'h0000; WREQ = 1'b0; DOUT = 8'h00; RD = 1'b0; end


reg  [7:0]  A   = 8'h00;
reg  [7:0]  X   = 8'h00;
reg  [7:0]  Y   = 8'h00;
reg  [7:0]  S   = 8'h00;
reg  [7:0]  P   = 8'b00000000;
reg [15:0]  PC  = 16'hC000;


reg  [4:0]  MS     = `RST;
reg         AS     = 1'b0;
reg         AM     = 1'b0;
reg  [1:0]  IRQ    = 2'b11;
reg         ISBRK  = 1'b0;
reg         Cout   = 1'b0;
reg         HOP    = 1'b0;
reg  [7:0]  PCL    = 8'h00;
reg  [7:0]  TR     = 3'h0;
reg  [15:0] EA     = 16'h0000;
reg         NMI_trigger = 1'b0;


reg         WR     = 1'b0;
reg         FW     = 1'b0;
reg         SW     = 1'b0;
reg         ACC    = 1'b0;
reg         BR     = 1'b0;
reg         SEI    = 1'b0;
reg         ENARD  = 1'b0;
reg  [7:0]  opcode = 8'h0;


wire [15:0] PCINC   = PC + 1'b1;
wire [15:0] PCRel   = PCINC + {{8{DIN[7]}}, DIN[7:0]};
wire [4:0]  MSINC   = MS + 1'b1;
wire [15:0] EAINC   = EA + 1'b1;
wire [8:0]  XDin    = X + DIN;
wire [8:0]  YDin    = Y + DIN;
wire [7:0]  HIDin   = DIN + Cout;
wire [15:0] EADIN   = {DIN,   TR};
wire [15:0] EADIH   = {HIDin, TR};
wire        Latency = Cout | (opcode[7:5] == 3'b100) | INCDEC;
wire [4:0]  LATAD   = Latency ? `LAT1 : `EXEC;


wire        INCDEC  = ({opcode[7:6], opcode[2:0]} == 5'b11_1_10) ||
                      ({opcode[7],   opcode[2:0]} == 4'b0__1_10);


wire        NMI_status = NMI_trigger ^ NMI;


wire debug_clk = CLK && MS == 1'b0;
reg LN = 1'b1;


always @(posedge CLK) begin


    if (RESET || !DKEY[0]) begin

        MS   <= `RST;
        WREQ <= 1'b0;
        {AS, AM} <= 2'b00;       

    end


    else if (CE) case (MS)


        4'h0: begin


            if (DIN == 8'h02) begin

                AM <= 1'b0; 
                AS <= 1'b0;

            end else begin


                if (NMI_status) begin
                    NMI_trigger <= NMI_status ^ NMI_trigger;
                end


                if (NMI && NMI_status) begin

                    opcode <= 8'h00;
                    IRQ    <= 2'b01;
                    ISBRK  <= 1'b0; 
                    MS     <= `IMP;
                    HOP    <= 1'b0;
                    LN     <= 0;


                end else begin

                    opcode <= DIN;
                    IRQ    <= 2'b11;
                    PC     <= PCINC;
                    ISBRK  <= DIN == 8'h00;

                    casex (DIN)

                        8'bxxx_000_x1: begin MS <= `NDX; HOP <= 1'b1; end
                        8'bxxx_010_x1,
                        8'b1xx_000_x0: begin MS <= `IMM; HOP <= 1'b1; end
                        8'bxxx_100_x1: begin MS <= `NDY; HOP <= 1'b1; end
                        8'bxxx_110_x1: begin MS <= `ABY; HOP <= 1'b1; end
                        8'bxxx_001_xx: begin MS <= `ZP;  HOP <= 1'b1; end
                        8'bxxx_011_xx,
                        8'b001_000_00: begin MS <= `ABS; HOP <= 1'b1; end
                        8'b10x_101_1x: begin MS <= `ZPY; HOP <= 1'b1; end
                        8'bxxx_101_xx: begin MS <= `ZPX; HOP <= 1'b1; end
                        8'b10x_111_1x: begin MS <= `ABY; HOP <= 1'b1; end
                        8'bxxx_111_xx: begin MS <= `ABX; HOP <= 1'b1; end
                        8'bxxx_100_00: begin MS <= `REL; HOP <= 1'b1; end
                        8'b0xx_010_10: begin MS <= `ACC; HOP <= 1'b0; end
                        default:       begin MS <= `IMP; HOP <= 1'b0; end

                    endcase

                end


                AS      <= 1'b0;
                RD      <= 1'b0;
                WREQ    <= 1'b0;

            end

        end





        4'h1: begin MS <= MSINC; EA <= XDin[7:0];  AM <= 1'b1; end
        4'h2: begin MS <= MSINC; EA <= EAINC[7:0]; TR <= DIN;  end
        4'h3: begin MS <= `LAT1; EA <= EADIN;      RD <= ENARD; end



        4'h4: begin MS <= MSINC; EA <= DIN;        AM <= 1'b1; end
        4'h5: begin MS <= MSINC; EA <= EAINC[7:0]; TR <= YDin[7:0]; Cout <= YDin[8]; end
        4'h6: begin MS <= LATAD; EA <= EADIH;      RD <= ENARD; end



        4'h7: begin MS <= `EXEC; EA <= DIN;       {AM, RD} <= {1'b1, ENARD}; end



        4'h8: begin MS <= `LAT1; EA <= XDin[7:0]; {AM, RD} <= {1'b1, ENARD}; end



        4'h9: begin MS <= `LAT1; EA <= YDin[7:0]; {AM, RD} <= {1'b1, ENARD}; end



        4'hA: begin MS <= MSINC; TR <= DIN; PC <= PCINC;  end
        4'hB: begin


            if (opcode == 8'h4C)
                 begin MS <= 1'b0;  PC <= EADIN; end
            else begin MS <= `EXEC; EA <= EADIN; {AM, RD} <= {1'b1, ENARD}; end

        end



        4'hC: begin MS <= MSINC; TR <= XDin[7:0]; PC <= PCINC; Cout <= XDin[8]; end
        4'hD: begin MS <= LATAD; EA <= EADIH;     {AM, RD} <= {1'b1, ENARD}; end



        4'hE: begin MS <= MSINC; TR <= YDin[7:0]; PC <= PCINC; Cout <= YDin[8]; end
        4'hF: begin MS <= LATAD; EA <= EADIH;     {AM, RD} <= {1'b1, ENARD}; end


        `LAT1: MS <= `EXEC;





        `EXEC: begin

            RD  <= 1'b0;
            PCL <= PC[7:0];


            if (HOP | ISBRK) PC <= PCINC;

            casex (opcode)


                8'b100_xxx_01,
                8'b100_xx1_x0: {AM, MS, WREQ, DOUT} <= {1'b0, 5'h0,  1'b1, AR};


                8'b011_011_00: {MS, TR, EA} <= {MSINC, DIN, EA[15:8], EAINC[7:0]};


                8'b0xx_xx1_10,
                8'b11x_xx1_10: {AM, MS, WREQ, DOUT} <= {1'b0, MSINC, 1'b1, AR};


                8'b001_000_00: {AS, MS, WREQ, DOUT} <= {1'b1, MSINC, 1'b1, PC[15:8]};


                8'b000_000_00: {AS, MS, WREQ, DOUT} <= {1'b1, MSINC, 1'b1, ISBRK ? PCINC[15:8] : PC[15:8]};


                8'b01x_000_00: {AS, MS} <= {1'b1, MSINC};


                8'b000_010_00: {AS, MS, WREQ, DOUT} <= {1'b1, MSINC, 1'b1, P[7:6], 2'b11, P[3:0]};


                8'b010_010_00: {AS, MS, WREQ, DOUT} <= {1'b1, MSINC, 1'b1, A};


                8'b0x1_010_00: {AS, MS} <= {1'b1, MSINC};


                default: {AM, MS} <= 6'b0_00000;

            endcase

        end




        `EXEC2: casex (opcode)

8'b001_000_00: begin MS <= MSINC; DOUT <= PCL; end
8'b000_000_00: begin MS <= MSINC; DOUT <= PC[7:0]; end
8'b011_000_00: begin MS <= MSINC; PC[7:0] <= DIN; end
8'b010_000_00: begin MS <= MSINC; end
8'b011_011_00: begin MS <= 1'b0;  PC <= EADIN; AM <= 1'b0; end
8'b0x0_010_00: begin MS <= 1'b0;  {AM, AS, WREQ} <= 3'b000; end
                            default: begin MS <= MSINC; {AM, AS, WREQ} <= 3'b000; end

        endcase

        `EXEC3: casex (opcode)

8'b000_000_00: begin MS <= MSINC; DOUT <= {P[7:6], 2'b11, P[3:0]}; end
8'b001_000_00: begin MS <= 1'b0;  PC <= EA; {AS, WREQ, AM} <= 3'b000; end
8'b011_000_00: begin MS <= MSINC; PC[15:8] <= DIN; end
8'b010_000_00: begin MS <= MSINC; PC[7:0]  <= DIN;  end
                            default: begin MS <= 1'b0; end

        endcase

        `EXEC4: casex (opcode)

8'b000_000_00: begin MS <= MSINC; {AS, AM, WREQ} <= 3'b010; EA <= {12'hFFF, 1'b1, IRQ, 1'b0}; end
8'b011_000_00: begin MS <= `REL2;{AS, AM} <= 2'b00; PC <= PCINC; end
8'b010_000_00: begin MS <= MSINC; AS <= 1'b0; PC[15:8] <= DIN; end
8'b0x1_010_00: begin MS <= MSINC; AS <= 1'b0; end

        endcase

        `EXEC5: casex (opcode)

8'b000_000_00: begin MS <= MSINC; TR <= DIN; EA <= EAINC; end
8'b010_000_00: begin {MS, LN} <= {5'h0, 1'b1}; end

        endcase


        `EXEC6: begin MS <= 1'b0; AM <= 1'b0; PC <= EADIN;  end




        `REL: begin

            if (BR) begin PC <= PCRel; MS <= PCRel[15:8] == PC[15:8] ? `REL2 : `REL1; end
            else    begin PC <= PCINC; MS <= 1'b0; end

        end

        `REL1: begin MS <= MSINC; end
        `REL2: begin MS <= 1'b0; end


        `RST:  begin MS <= MSINC; PC <= 16'hFFFC;  end
        `RST2: begin MS <= MSINC; PC <= PCINC; TR <= DIN; end
        `RST3: begin PC <= EADIN; MS <= 1'b0; end

    endcase


    else begin
    
        WREQ <= 1'b0;
    
    end
end




always @* begin

    alu = {1'b0, opcode[7:5]};
    RA  = 2'b00;
    RB  = 2'b00;
    WR  = 1'b0;
    FW  = 1'b0;
    SW  = 1'b0;
    ACC = 1'b0;
    BR  = 1'b0;
    SEI = 1'b0;
    ENARD = 1'b1;


    casex (opcode)

        8'b100_xxx_01,
        8'b100_xx1_x0: ENARD = 1'b0;

    endcase

    case (opcode[7:6])

2'b00: BR = (P[7] == opcode[5]);
2'b01: BR = (P[6] == opcode[5]);
2'b10: BR = (P[0] == opcode[5]);
2'b11: BR = (P[1] == opcode[5]);

    endcase

    case (MS)
    `EXEC: casex (opcode)


        8'b100_xxx_01: RA <= {2'b00};


        8'b100_xx1_10: RA <= {2'b01};


        8'b100_xx1_00: RA <= {2'b10};


        8'b110_xxx_01: FW = opcode[6];


        8'bxxx_xxx_01: {WR, FW} = 2'b11;


        8'b100_010_00: {alu, RA, RB, WR, FW} = 10'b1110_10_10_11;
        8'b110_010_10: {alu, RA, RB, WR, FW} = 10'b1110_01_01_11;
        8'b110_010_00: {alu, RA, RB, WR, FW} = 10'b1111_10_10_11;
        8'b111_010_00: {alu, RA, RB, WR, FW} = 10'b1111_01_01_11;


        8'b101_010_10: {alu, RB, RA, FW, WR, ACC} = 11'b0101_00_01_1_1_1;
        8'b101_010_00: {alu, RB, RA, FW, WR, ACC} = 11'b0101_00_10_1_1_1;
        8'b100_110_10: {alu, RB, SW}              = 8'b0101_01_1;
        8'b100_110_00: {alu, RB, FW, WR}          = 8'b0101_10_1_1;
        8'b100_010_10: {alu, RB, FW, WR}          = 8'b0101_01_1_1;
        8'b101_110_10: {alu, RB, RA, FW, WR}      = 10'b0101_11_01_11;


        8'b0xx_010_10: {alu, ACC, RB, RA, FW, WR} = {2'b10, opcode[6:5], 1'b1, 6'b00_00_11};


        8'b0xx_xx1_10: {alu, FW} = {2'b10, opcode[6:5], 1'b1};


        8'b11x_xx1_10: {alu, FW} = {3'b111, opcode[5], 1'b1};


        8'b101_xx1_00,
        8'b101_000_00: {WR, RA, FW} = 4'b1_10_1;


        8'b101_xx1_10,
        8'b101_000_10: {WR, RA, FW} = 4'b1_01_1;


        8'b110_xx1_00,
        8'b110_000_00: {RA, FW} = 3'b10_1;


        8'b111_xx1_00,
        8'b111_000_00: {alu, RA, FW} = 7'b0110_01_1;


        8'bxxx_110_00: {alu, FW} = 5'b1100_1;


        8'b001_0x1_00: {alu, FW} = 5'b1101_1;


        8'b01x_000_00,
        8'b0x1_010_00: {alu, RB, SW} = 7'b1111_11_1;

    endcase


    `EXEC2: casex (opcode)

        8'b010_000_00: {alu, RB, SW, RA, WR} = 10'b1111_11_1_11_1;
        8'b011_000_00: {alu, RB, SW}         =  7'b1111_11_1;
        8'b001_000_00,
        8'b000_000_00,
        8'b0x0_010_00: {alu, RB, SW}     = 7'b1110_11_1;
        8'b001_010_00: {RA, WR}          = 3'b11_1;
        8'b011_010_00: {RA, WR, FW, alu} = 8'b00_11_0101;

    endcase

    `EXEC3: casex (opcode)

8'b000_000_00,
8'b001_000_00: {alu, RB, SW} = 7'b1110_11_1;
8'b010_000_00: {alu, RB, SW} = 7'b1111_11_1;

    endcase


    `EXEC4: casex (opcode)

8'b000_000_00: {alu, RB, SW, SEI} = 8'b1110_11_11;

    endcase

    endcase

end




always @(posedge CLK) begin

    if (RESET) begin
        
        A <= 8'h00;
        X <= 8'h00;
        Y <= 8'h00;
        S <= 8'h00;
        P <= 8'h00;
        
    end
    else begin


        if (WR) case (RA)
            2'b00: A <= AR;
            2'b01: X <= AR;
            2'b10: Y <= AR;
        endcase


        if (SEI)P <= {P[7:6], 2'b11, P[3], 1'b1, P[1:0]};
        else if (WR && RA == 2'b11) P <= DIN;
        else if (FW)P <= AF;


        if (SW) S <= AR;
    
    end

end




reg [3:0] alu = 4'h0;
reg [1:0] RA = 2'b00;
reg [1:0] RB = 2'b00;
reg [7:0] Ax; reg [7:0] Bx;
reg [7:0] AR; reg [7:0] AF;

always @* begin


    casex (RA)
        2'b00: Ax = A;
        2'b01: Ax = X;
        2'b1x: Ax = Y;
    endcase


    case (RB)
        2'b00: Bx = (ACC ? A : DIN);
        2'b01: Bx = X;
        2'b10: Bx = Y;
        2'b11: Bx = S;
    endcase

end

alu ALU(

Ax, Bx, alu, P, opcode[7:5],
AR, AF

);

endmodule
module cpu(

    input  wire        RESET,
    input  wire        CLK,
    input  wire        CE,
    output wire [15:0] ADDR,
    input  wire [7:0]  DIN,
    output reg  [7:0]  DOUT,
    output wire [15:0] EAWR,
    output reg         WREQ,
    output reg         RD,
    input  wire        NMI,
    output wire [7:0]  DEBUG,
    input  wire [1:0]  DKEY

);


assign ADDR  = AS ? {8'h01, S} : (AM ? EA : PC);
assign EAWR  = AS ? {8'h01, S} : EA;


assign  DEBUG = DKEY == 2'b11 ? A[7:0] :
                DKEY == 2'b10 ? X[7:0] :
                DKEY == 2'b01 ? Y[7:0] :
                                P[7:0];

`define DEBUGPC 0




`define NDX     5'h01
`define NDY     5'h04
`define ZP      5'h07
`define ZPX     5'h08
`define ZPY     5'h09
`define ABS     5'h0A
`define ABX     5'h0C
`define ABY     5'h0E


`define LAT1    5'h10
`define IMM     5'h11
`define IMP     5'h11
`define ACC     5'h11


`define EXEC    5'h11
`define EXEC2   5'h12
`define EXEC3   5'h13
`define EXEC4   5'h14
`define EXEC5   5'h15
`define EXEC6   5'h16


`define REL     5'h17
`define REL1    5'h18
`define REL2    5'h19
`define REL3    5'h1A




`define RST     5'h1D
`define RST2    5'h1E
`define RST3    5'h1F

initial begin EA = 16'h0000; WREQ = 1'b0; DOUT = 8'h00; RD = 1'b0; end


reg  [7:0]  A   = 8'h00;
reg  [7:0]  X   = 8'h00;
reg  [7:0]  Y   = 8'h00;
reg  [7:0]  S   = 8'h00;
reg  [7:0]  P   = 8'b00000000;
reg [15:0]  PC  = 16'hC000;


reg  [4:0]  MS     = `RST;
reg         AS     = 1'b0;
reg         AM     = 1'b0;
reg  [1:0]  IRQ    = 2'b11;
reg         ISBRK  = 1'b0;
reg         Cout   = 1'b0;
reg         HOP    = 1'b0;
reg  [7:0]  PCL    = 8'h00;
reg  [7:0]  TR     = 3'h0;
reg  [15:0] EA     = 16'h0000;
reg         NMI_trigger = 1'b0;


reg         WR     = 1'b0;
reg         FW     = 1'b0;
reg         SW     = 1'b0;
reg         ACC    = 1'b0;
reg         BR     = 1'b0;
reg         SEI    = 1'b0;
reg         ENARD  = 1'b0;
reg  [7:0]  opcode = 8'h0;


wire [15:0] PCINC   = PC + 1'b1;
wire [15:0] PCRel   = PCINC + {{8{DIN[7]}}, DIN[7:0]};
wire [4:0]  MSINC   = MS + 1'b1;
wire [15:0] EAINC   = EA + 1'b1;
wire [8:0]  XDin    = X + DIN;
wire [8:0]  YDin    = Y + DIN;
wire [7:0]  HIDin   = DIN + Cout;
wire [15:0] EADIN   = {DIN,   TR};
wire [15:0] EADIH   = {HIDin, TR};
wire        Latency = Cout | (opcode[7:5] == 3'b100) | INCDEC;
wire [4:0]  LATAD   = Latency ? `LAT1 : `EXEC;


wire        INCDEC  = ({opcode[7:6], opcode[2:0]} == 5'b11_1_10) ||
                      ({opcode[7],   opcode[2:0]} == 4'b0__1_10);


wire        NMI_status = NMI_trigger ^ NMI;


wire debug_clk = CLK && MS == 1'b0;
reg LN = 1'b1;


always @(posedge CLK) begin


    if (RESET || !DKEY[0]) begin

        MS   <= `RST;
        WREQ <= 1'b0;
        {AS, AM} <= 2'b00;       

    end


    else if (CE) case (MS)


        4'h0: begin


            if (DIN == 8'h02) begin

                AM <= 1'b0; 
                AS <= 1'b0;

            end else begin


                if (NMI_status) begin
                    NMI_trigger <= NMI_status ^ NMI_trigger;
                end


                if (NMI && NMI_status) begin

                    opcode <= 8'h00;
                    IRQ    <= 2'b01;
                    ISBRK  <= 1'b0; 
                    MS     <= `IMP;
                    HOP    <= 1'b0;
                    LN     <= 0;


                end else begin

                    opcode <= DIN;
                    IRQ    <= 2'b11;
                    PC     <= PCINC;
                    ISBRK  <= DIN == 8'h00;

                    casex (DIN)

                        8'bxxx_000_x1: begin MS <= `NDX; HOP <= 1'b1; end
                        8'bxxx_010_x1,
                        8'b1xx_000_x0: begin MS <= `IMM; HOP <= 1'b1; end
                        8'bxxx_100_x1: begin MS <= `NDY; HOP <= 1'b1; end
                        8'bxxx_110_x1: begin MS <= `ABY; HOP <= 1'b1; end
                        8'bxxx_001_xx: begin MS <= `ZP;  HOP <= 1'b1; end
                        8'bxxx_011_xx,
                        8'b001_000_00: begin MS <= `ABS; HOP <= 1'b1; end
                        8'b10x_101_1x: begin MS <= `ZPY; HOP <= 1'b1; end
                        8'bxxx_101_xx: begin MS <= `ZPX; HOP <= 1'b1; end
                        8'b10x_111_1x: begin MS <= `ABY; HOP <= 1'b1; end
                        8'bxxx_111_xx: begin MS <= `ABX; HOP <= 1'b1; end
                        8'bxxx_100_00: begin MS <= `REL; HOP <= 1'b1; end
                        8'b0xx_010_10: begin MS <= `ACC; HOP <= 1'b0; end
                        default:       begin MS <= `IMP; HOP <= 1'b0; end

                    endcase

                end


                AS      <= 1'b0;
                RD      <= 1'b0;
                WREQ    <= 1'b0;

            end

        end





        4'h1: begin MS <= MSINC; EA <= XDin[7:0];  AM <= 1'b1; end
        4'h2: begin MS <= MSINC; EA <= EAINC[7:0]; TR <= DIN;  end
        4'h3: begin MS <= `LAT1; EA <= EADIN;      RD <= ENARD; end



        4'h4: begin MS <= MSINC; EA <= DIN;        AM <= 1'b1; end
        4'h5: begin MS <= MSINC; EA <= EAINC[7:0]; TR <= YDin[7:0]; Cout <= YDin[8]; end
        4'h6: begin MS <= LATAD; EA <= EADIH;      RD <= ENARD; end



        4'h7: begin MS <= `EXEC; EA <= DIN;       {AM, RD} <= {1'b1, ENARD}; end



        4'h8: begin MS <= `LAT1; EA <= XDin[7:0]; {AM, RD} <= {1'b1, ENARD}; end



        4'h9: begin MS <= `LAT1; EA <= YDin[7:0]; {AM, RD} <= {1'b1, ENARD}; end



        4'hA: begin MS <= MSINC; TR <= DIN; PC <= PCINC;  end
        4'hB: begin


            if (opcode == 8'h4C)
                 begin MS <= 1'b0;  PC <= EADIN; end
            else begin MS <= `EXEC; EA <= EADIN; {AM, RD} <= {1'b1, ENARD}; end

        end



        4'hC: begin MS <= MSINC; TR <= XDin[7:0]; PC <= PCINC; Cout <= XDin[8]; end
        4'hD: begin MS <= LATAD; EA <= EADIH;     {AM, RD} <= {1'b1, ENARD}; end



        4'hE: begin MS <= MSINC; TR <= YDin[7:0]; PC <= PCINC; Cout <= YDin[8]; end
        4'hF: begin MS <= LATAD; EA <= EADIH;     {AM, RD} <= {1'b1, ENARD}; end


        `LAT1: MS <= `EXEC;





        `EXEC: begin

            RD  <= 1'b0;
            PCL <= PC[7:0];


            if (HOP | ISBRK) PC <= PCINC;

            casex (opcode)


                8'b100_xxx_01,
                8'b100_xx1_x0: {AM, MS, WREQ, DOUT} <= {1'b0, 5'h0,  1'b1, AR};


                8'b011_011_00: {MS, TR, EA} <= {MSINC, DIN, EA[15:8], EAINC[7:0]};


                8'b0xx_xx1_10,
                8'b11x_xx1_10: {AM, MS, WREQ, DOUT} <= {1'b0, MSINC, 1'b1, AR};


                8'b001_000_00: {AS, MS, WREQ, DOUT} <= {1'b1, MSINC, 1'b1, PC[15:8]};


                8'b000_000_00: {AS, MS, WREQ, DOUT} <= {1'b1, MSINC, 1'b1, ISBRK ? PCINC[15:8] : PC[15:8]};


                8'b01x_000_00: {AS, MS} <= {1'b1, MSINC};


                8'b000_010_00: {AS, MS, WREQ, DOUT} <= {1'b1, MSINC, 1'b1, P[7:6], 2'b11, P[3:0]};


                8'b010_010_00: {AS, MS, WREQ, DOUT} <= {1'b1, MSINC, 1'b1, A};


                8'b0x1_010_00: {AS, MS} <= {1'b1, MSINC};


                default: {AM, MS} <= 6'b0_00000;

            endcase

        end




        `EXEC2: casex (opcode)

8'b001_000_00: begin MS <= MSINC; DOUT <= PCL; end
8'b000_000_00: begin MS <= MSINC; DOUT <= PC[7:0]; end
8'b011_000_00: begin MS <= MSINC; PC[7:0] <= DIN; end
8'b010_000_00: begin MS <= MSINC; end
8'b011_011_00: begin MS <= 1'b0;  PC <= EADIN; AM <= 1'b0; end
8'b0x0_010_00: begin MS <= 1'b0;  {AM, AS, WREQ} <= 3'b000; end
                            default: begin MS <= MSINC; {AM, AS, WREQ} <= 3'b000; end

        endcase

        `EXEC3: casex (opcode)

8'b000_000_00: begin MS <= MSINC; DOUT <= {P[7:6], 2'b11, P[3:0]}; end
8'b001_000_00: begin MS <= 1'b0;  PC <= EA; {AS, WREQ, AM} <= 3'b000; end
8'b011_000_00: begin MS <= MSINC; PC[15:8] <= DIN; end
8'b010_000_00: begin MS <= MSINC; PC[7:0]  <= DIN;  end
                            default: begin MS <= 1'b0; end

        endcase

        `EXEC4: casex (opcode)

8'b000_000_00: begin MS <= MSINC; {AS, AM, WREQ} <= 3'b010; EA <= {12'hFFF, 1'b1, IRQ, 1'b0}; end
8'b011_000_00: begin MS <= `REL2;{AS, AM} <= 2'b00; PC <= PCINC; end
8'b010_000_00: begin MS <= MSINC; AS <= 1'b0; PC[15:8] <= DIN; end
8'b0x1_010_00: begin MS <= MSINC; AS <= 1'b0; end

        endcase

        `EXEC5: casex (opcode)

8'b000_000_00: begin MS <= MSINC; TR <= DIN; EA <= EAINC; end
8'b010_000_00: begin {MS, LN} <= {5'h0, 1'b1}; end

        endcase


        `EXEC6: begin MS <= 1'b0; AM <= 1'b0; PC <= EADIN;  end




        `REL: begin

            if (BR) begin PC <= PCRel; MS <= PCRel[15:8] == PC[15:8] ? `REL2 : `REL1; end
            else    begin PC <= PCINC; MS <= 1'b0; end

        end

        `REL1: begin MS <= MSINC; end
        `REL2: begin MS <= 1'b0; end


        `RST:  begin MS <= MSINC; PC <= 16'hFFFC;  end
        `RST2: begin MS <= MSINC; PC <= PCINC; TR <= DIN; end
        `RST3: begin PC <= EADIN; MS <= 1'b0; end

    endcase


    else begin
    
        WREQ <= 1'b0;
    
    end
end




always @* begin

    alu = {1'b0, opcode[7:5]};
    RA  = 2'b00;
    RB  = 2'b00;
    WR  = 1'b0;
    FW  = 1'b0;
    SW  = 1'b0;
    ACC = 1'b0;
    BR  = 1'b0;
    SEI = 1'b0;
    ENARD = 1'b1;


    casex (opcode)

        8'b100_xxx_01,
        8'b100_xx1_x0: ENARD = 1'b0;

    endcase

    case (opcode[7:6])

2'b00: BR = (P[7] == opcode[5]);
2'b01: BR = (P[6] == opcode[5]);
2'b10: BR = (P[0] == opcode[5]);
2'b11: BR = (P[1] == opcode[5]);

    endcase

    case (MS)
    `EXEC: casex (opcode)


        8'b100_xxx_01: RA <= {2'b00};


        8'b100_xx1_10: RA <= {2'b01};


        8'b100_xx1_00: RA <= {2'b10};


        8'b110_xxx_01: FW = opcode[6];


        8'bxxx_xxx_01: {WR, FW} = 2'b11;


        8'b100_010_00: {alu, RA, RB, WR, FW} = 10'b1110_10_10_11;
        8'b110_010_10: {alu, RA, RB, WR, FW} = 10'b1110_01_01_11;
        8'b110_010_00: {alu, RA, RB, WR, FW} = 10'b1111_10_10_11;
        8'b111_010_00: {alu, RA, RB, WR, FW} = 10'b1111_01_01_11;


        8'b101_010_10: {alu, RB, RA, FW, WR, ACC} = 11'b0101_00_01_1_1_1;
        8'b101_010_00: {alu, RB, RA, FW, WR, ACC} = 11'b0101_00_10_1_1_1;
        8'b100_110_10: {alu, RB, SW}              = 8'b0101_01_1;
        8'b100_110_00: {alu, RB, FW, WR}          = 8'b0101_10_1_1;
        8'b100_010_10: {alu, RB, FW, WR}          = 8'b0101_01_1_1;
        8'b101_110_10: {alu, RB, RA, FW, WR}      = 10'b0101_11_01_11;


        8'b0xx_010_10: {alu, ACC, RB, RA, FW, WR} = {2'b10, opcode[6:5], 1'b1, 6'b00_00_11};


        8'b0xx_xx1_10: {alu, FW} = {2'b10, opcode[6:5], 1'b1};


        8'b11x_xx1_10: {alu, FW} = {3'b111, opcode[5], 1'b1};


        8'b101_xx1_00,
        8'b101_000_00: {WR, RA, FW} = 4'b1_10_1;


        8'b101_xx1_10,
        8'b101_000_10: {WR, RA, FW} = 4'b1_01_1;


        8'b110_xx1_00,
        8'b110_000_00: {RA, FW} = 3'b10_1;


        8'b111_xx1_00,
        8'b111_000_00: {alu, RA, FW} = 7'b0110_01_1;


        8'bxxx_110_00: {alu, FW} = 5'b1100_1;


        8'b001_0x1_00: {alu, FW} = 5'b1101_1;


        8'b01x_000_00,
        8'b0x1_010_00: {alu, RB, SW} = 7'b1111_11_1;

    endcase


    `EXEC2: casex (opcode)

        8'b010_000_00: {alu, RB, SW, RA, WR} = 10'b1111_11_1_11_1;
        8'b011_000_00: {alu, RB, SW}         =  7'b1111_11_1;
        8'b001_000_00,
        8'b000_000_00,
        8'b0x0_010_00: {alu, RB, SW}     = 7'b1110_11_1;
        8'b001_010_00: {RA, WR}          = 3'b11_1;
        8'b011_010_00: {RA, WR, FW, alu} = 8'b00_11_0101;

    endcase

    `EXEC3: casex (opcode)

8'b000_000_00,
8'b001_000_00: {alu, RB, SW} = 7'b1110_11_1;
8'b010_000_00: {alu, RB, SW} = 7'b1111_11_1;

    endcase


    `EXEC4: casex (opcode)

8'b000_000_00: {alu, RB, SW, SEI} = 8'b1110_11_11;

    endcase

    endcase

end




always @(posedge CLK) begin

    if (RESET) begin
        
        A <= 8'h00;
        X <= 8'h00;
        Y <= 8'h00;
        S <= 8'h00;
        P <= 8'h00;
        
    end
    else begin


        if (WR) case (RA)
            2'b00: A <= AR;
            2'b01: X <= AR;
            2'b10: Y <= AR;
        endcase


        if (SEI)P <= {P[7:6], 2'b11, P[3], 1'b1, P[1:0]};
        else if (WR && RA == 2'b11) P <= DIN;
        else if (FW)P <= AF;


        if (SW) S <= AR;
    
    end

end




reg [3:0] alu = 4'h0;
reg [1:0] RA = 2'b00;
reg [1:0] RB = 2'b00;
reg [7:0] Ax; reg [7:0] Bx;
reg [7:0] AR; reg [7:0] AF;

always @* begin


    casex (RA)
        2'b00: Ax = A;
        2'b01: Ax = X;
        2'b1x: Ax = Y;
    endcase


    case (RB)
        2'b00: Bx = (ACC ? A : DIN);
        2'b01: Bx = X;
        2'b10: Bx = Y;
        2'b11: Bx = S;
    endcase

end

alu ALU(

Ax, Bx, alu, P, opcode[7:5],
AR, AF

);

endmodule