`default_nettype none module decoder (clk, rst, instr, address_code, decoded); `include "parameters.vh" input wire clk; input wire rst; input wire [7:0] instr; output logic [4:0] address_code; output logic [7:0] decoded; logic [2:0] row; logic [2:0] column; logic [1:0] sector; initial address_code = 0; always_comb begin row = instr[7:5]; column = instr[4:2]; sector = instr[1:0]; end wire sec_2_stp = (sector == 2) && ((column == 0 && row <= 3) || (column == 4)); wire sec_2_nop = (sector == 2) && ((column == 0 && (row == 4 || row == 6 || row == 7)) || (column == 6 && (row != 4 && row != 5))); always_comb begin address_code = 5'h1f; decoded = 8'hff; if (!rst) begin if (sector == 1) begin case (row) 0: decoded = I_ORA; 1: decoded = I_AND; 2: decoded = I_EOR; 3: decoded = I_ADC; 4: decoded = (column == 2 ? I_NOP : I_STA); 5: decoded = I_LDA; 6: decoded = I_CMP; 7: decoded = I_SBC; endcase address_code = column; end else if (sector == 2) begin case (row) 0: decoded = (sec_2_stp ? I_STP : (sec_2_nop ? I_NOP : I_ASL)); 1: decoded = (sec_2_stp ? I_STP : (sec_2_nop ? I_NOP : I_ROL)); 2: decoded = (sec_2_stp ? I_STP : (sec_2_nop ? I_NOP : I_LSR)); 3: decoded = (sec_2_stp ? I_STP : (sec_2_nop ? I_NOP : I_ROR)); 4: decoded = (sec_2_stp ? I_STP : (sec_2_nop ? I_NOP : (column[0] ? I_STX : I_TXA))); 5: decoded = (sec_2_stp ? I_STP : (column == 2 ? I_TAX : (column == 6 ? I_TSX : I_LDX))); 6: decoded = (sec_2_stp ? I_STP : (sec_2_nop ? I_NOP : (column == 2 ? I_DEX : I_DEC))); 7: decoded = (sec_2_stp ? I_STP : ((sec_2_nop || column == 2) ? I_NOP : I_INC)); endcase end else if (sector == 0) begin if (column == 0) begin case (row) 0: decoded = I_BRK; 1: decoded = I_JSR; 2: decoded = I_RTI; 3: decoded = I_RTS; 4: decoded = I_NOP; 5: decoded = I_LDY; 6: decoded = I_CPY; 7: decoded = I_CPX; endcase end else if (column == 1) begin case (row) 0: decoded = I_NOP; 1: decoded = I_BIT; 2: decoded = I_NOP; 3: decoded = I_NOP; 4: decoded = I_STY; 5: decoded = I_LDY; 6: decoded = I_CPY; 7: decoded = I_CPX; endcase end else if (column == 2) begin case (row) 0: decoded = I_PHP; 1: decoded = I_PLP; 2: decoded = I_PHA; 3: decoded = I_PLA; 4: decoded = I_DEY; 5: decoded = I_TAY; 6: decoded = I_INY; 7: decoded = I_INX; endcase end else if (column == 3) begin case (row) 0: decoded = I_NOP; 1: decoded = I_BIT; 2: decoded = I_JMP; 3: decoded = I_JMP; 4: decoded = I_STY; 5: decoded = I_LDY; 6: decoded = I_CPY; 7: decoded = I_CPX; endcase end else if (column == 4) begin case (row) 0: decoded = I_BPL; 1: decoded = I_BMI; 2: decoded = I_BVC; 3: decoded = I_BVS; 4: decoded = I_BCC; 5: decoded = I_BCS; 6: decoded = I_BNE; 7: decoded = I_BEQ; endcase end else if (column == 5) begin case (row) 0: decoded = I_NOP; 1: decoded = I_NOP; 2: decoded = I_NOP; 3: decoded = I_NOP; 4: decoded = I_STY; 5: decoded = I_LDY; 6: decoded = I_NOP; 7: decoded = I_NOP; endcase end else if (column == 6) begin case (row) 0: decoded = I_CLC; 1: decoded = I_SEC; 2: decoded = I_CLI; 3: decoded = I_SEI; 4: decoded = I_TYA; 5: decoded = I_CLV; 6: decoded = I_CLD; 7: decoded = I_SED; endcase end else if (column == 7) begin case (row) 0: decoded = I_NOP; 1: decoded = I_NOP; 2: decoded = I_NOP; 3: decoded = I_NOP; 4: decoded = I_SHY; 5: decoded = I_LDY; 6: decoded = I_NOP; 7: decoded = I_NOP; endcase end end if (sector == 0) begin if (column == 0) begin if (row == 0 || (row >= 2 && row <= 4)) begin address_code = ADDR_MODE_IMPLIED; end else if (row == 1) begin address_code = ADDR_MODE_ABSOLUTE; end else begin address_code = ADDR_MODE_IMMEDIATE; end end else if(column == 1) begin address_code = ADDR_MODE_ZP; end else if (column == 2) begin address_code = ADDR_MODE_IMPLIED; end else if (column == 3) begin if (row == 3) begin address_code = ADDR_MODE_INDIRECT; end else begin address_code = ADDR_MODE_ABSOLUTE; end end else if (column == 4) begin address_code = ADDR_MODE_RELATIVE; end else if (column == 5) begin address_code = ADDR_MODE_INDEXED_ZP; end else if (column == 6) begin address_code = ADDR_MODE_IMPLIED; end else if (column == 7) begin address_code = ADDR_MODE_INDEXED_ABSOLUTE_X; end end else if(sector == 1) begin if (column == 0) begin address_code = ADDR_MODE_PREINDEXED_INDIRECT; end else if (column == 1) begin address_code = ADDR_MODE_ZP; end else if (column == 2) begin address_code = ADDR_MODE_IMMEDIATE; end else if (column == 3) begin address_code = ADDR_MODE_ABSOLUTE; end else if (column == 4) begin address_code = ADDR_MODE_POSTINDEXED_INDIRECT; end else if (column == 5) begin address_code = ADDR_MODE_INDEXED_ZP; end else if (column == 6) begin address_code = ADDR_MODE_INDEXED_ABSOLUTE_Y; end else if (column == 7) begin address_code = ADDR_MODE_INDEXED_ABSOLUTE_X; end end else if(sector == 2) begin if (column == 0) begin address_code = ADDR_MODE_IMMEDIATE; end else if (column == 1) begin address_code = ADDR_MODE_ZP; end else if (column == 2 || column == 6) begin address_code = ADDR_MODE_IMPLIED; end else if (column == 3) begin address_code = ADDR_MODE_ABSOLUTE; end // column == 4 are invalid opcodes else if (column == 5) begin address_code = ADDR_MODE_INDEXED_ZP; end else if (column == 7) begin if (row == 5) address_code = ADDR_MODE_INDEXED_ABSOLUTE_Y; else address_code = ADDR_MODE_INDEXED_ABSOLUTE_X; end end end end `ifdef FORMAL reg f_past_valid; initial f_past_valid = 0; always_comb assume(rst == 0); always @(posedge clk) f_past_valid <= 1; always_comb if (instr == 8'h00) // BRK begin assert (decoded == I_BRK); end; always_comb if (instr == 8'h4C) // JMP abs begin assert (decoded == I_JMP); assert (address_code == ADDR_MODE_ABSOLUTE); end; always_comb if (instr == 8'h8D) // STA abs begin assert (decoded == I_STA); assert (address_code == ADDR_MODE_ABSOLUTE); end; always_comb if (instr == 8'hA2) // LDX imm begin assert (decoded == I_LDX); assert (address_code == ADDR_MODE_IMMEDIATE); end; always_comb if (instr == 8'hA9) // LDA imm begin assert (decoded == I_LDA); assert (address_code == ADDR_MODE_IMMEDIATE); end; always_comb if (instr == 8'hA0) // LDY imm begin assert (decoded == I_LDY); assert (address_code == ADDR_MODE_IMMEDIATE); end; always_comb if (instr == 8'hA4) // LDY zp begin assert (decoded == I_LDY); assert (address_code == ADDR_MODE_ZP); end; always_comb if (instr == 8'hB4) // LDY zp,X begin assert (decoded == I_LDY); assert (address_code == ADDR_MODE_INDEXED_ZP); end; always_comb if (instr == 8'hAC) // LDY abs begin assert (decoded == I_LDY); assert (address_code == ADDR_MODE_ABSOLUTE); end; always_comb if (instr == 8'hBC) // LDY abs,X begin assert (decoded == I_LDY); assert (address_code == ADDR_MODE_INDEXED_ABSOLUTE_X); end; always_comb if (instr == 8'hCA) // DEX begin assert (decoded == I_DEX); assert (address_code == ADDR_MODE_IMPLIED); end; always_comb if (instr == 8'hE0) // CPX begin assert (decoded == I_CPX); end; always_comb if (instr == 8'hE0) // CPX begin assert (decoded == I_CPX); end; `endif endmodule