You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
10 KiB
351 lines
10 KiB
`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
|
|
|