diff --git a/src/alu.verilog b/src/alu.verilog index 88f3afd..ea8d2eb 100644 --- a/src/alu.verilog +++ b/src/alu.verilog @@ -1,89 +1,87 @@ module alu ( - input nrst, - input clk, - input [7:0] A, - input [7:0] B, - input C, - input [2:0] sel, - output [7:0] result, - output r_n, - output r_z, - output reg r_v, - output reg r_c + input logic [7:0] A, + input logic [7:0] B, + input logic C, + input logic [2:0] sel, + output logic [7:0] result, + output logic r_n, + output logic r_z, + output logic r_v, + output logic r_c ); - wire rst = !nrst; - reg [8:0] buffer; - wire [8:0] sum; - wire [8:0] diff; +`include "parameters.vh" - assign result[7:0] = buffer[7:0]; - assign r_z = buffer[7:0] == 0; - assign r_n = buffer[7]; - assign sum = A + B + C; - assign diff = A - B - (1 - C); + reg [8:0] buffer; + wire [8:0] sum; + wire [8:0] diff; - initial begin - buffer <= 0; - r_v <= 0; - r_c <= 0; - end +assign r_z = result[7:0] == 0; +assign r_n = result[7]; +assign sum = A + B + C; +assign diff = A - B - (1 - C); - always @(posedge clk) - begin - case (sel) - OP_OR: - begin - buffer <= A | B; - end - OP_AND: - begin - buffer <= A & B; - end - OP_EOR: - begin - buffer <= A ^ B; - end - OP_ADC: - begin - buffer <= sum; - r_c <= sum[8]; - r_v <= !(A[7] ^ B[7]) & (A[7] & sum[7]); - end - OP_SUB: - begin - buffer <= diff; - r_c <= diff[8]; - r_v <= !(A[7] ^ B[7]) & (A[7] & diff[7]); - end - OP_ROT: - begin - if (B == SHIFT_LEFT) begin - buffer[8:1] <= A[7:0]; - buffer[0] <= C; - r_c <= A[7]; - end - else begin - buffer[6:0] <= A[7:1]; - buffer[7] <= C; - r_c <= A[0]; - end - end - OP_SHF: - begin - if (B == SHIFT_LEFT) begin - buffer[8:1] <= A[7:0]; - buffer[0] <= 0; - r_c <= A[7]; - end - else begin - buffer[6:0] <= A[7:1]; - buffer[7] <= 0; - r_c <= A[0]; - end - end - endcase // case sel - end +always_comb + begin + case (sel) + OP_OR: + begin + result = A | B; + r_v = 0; + r_c = 0; + end + OP_AND: + begin + result = A & B; + r_v = 0; + r_c = 0; + end + OP_EOR: + begin + result = A ^ B; + r_v = 0; + r_c = 0; + end + OP_ADC: + begin + result = sum[7:0]; + r_c = sum[8]; + r_v = !(A[7] ^ B[7]) & (A[7] ^ sum[7]); + end + OP_SUB: + begin + result = diff; + r_c = diff[8]; + r_v = !(A[7] ^ B[7]) & (A[7] ^ diff[7]); + end + OP_ROT: + begin + if (B == SHIFT_LEFT) begin + result[7:1] = A[6:0]; + result[0] = C; + r_c = A[7]; + end + else begin + result[6:0] = A[7:1]; + result[7] = C; + r_c = A[0]; + end + end + OP_SHF: + begin + if (B == SHIFT_LEFT) begin + result[7:1] = A[6:0]; + result[0] = 0; + r_c = A[7]; + end + else begin + result[6:0] = A[7:1]; + result[7] = 0; + r_c = A[0]; + end + end + endcase // case sel + end endmodule diff --git a/src/decoder.verilog b/src/decoder.verilog index ad1223b..936871c 100644 --- a/src/decoder.verilog +++ b/src/decoder.verilog @@ -4,8 +4,8 @@ module decoder input clk, input rst, input [7:0] instr, - output reg [3:0] address_code, - output reg [7:0] decoded + output logic [4:0] address_code, + output logic [7:0] decoded ); `include "parameters.vh" @@ -18,152 +18,226 @@ module decoder wire sec_2_nop = (sector == 2) && ((column == 0 && (row == 4 || row == 6 || row == 7)) || (column == 6 && (row != 4 && row != 5))); -always @* begin +always_comb begin + address_code = 0; + decoded = 0; if (rst) begin - address_code <= 0; + address_code = 8'h0; end else 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_STA : I_NOP); - 5: decoded <= I_LDA; - 6: decoded <= I_CMP; - 7: decoded <= I_SBC; + 0: decoded = I_ORA; + 1: decoded = I_AND; + 2: decoded = I_EOR; + 3: decoded = I_ADC; + 4: decoded = (column == 2 ? I_STA : I_NOP); + 5: decoded = I_LDA; + 6: decoded = I_CMP; + 7: decoded = I_SBC; endcase - address_code <= column; + 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)); + 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 if (column > 0) begin - address_code <= column - end + address_code = column; + end else begin - address_code <= ADDR_MODE_IMMEDIATE; + address_code = ADDR_MODE_IMMEDIATE; end 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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 (column > 0) begin - address_code <= column; + 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 begin - if (row >= 4) begin - address_code <= ADDR_MODE_IMMEDIATE; + 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_ABSOLUTE; end else begin - address_code <= ADDR_MODE_ABSOLUTE; + address_code = ADDR_MODE_INDEXED_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; + 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 || column == 7) begin + address_code = ADDR_MODE_INDEXED_ABSOLUTE; + 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 + address_code = ADDR_MODE_INDEXED_ABSOLUTE; + end end end end diff --git a/src/parameters.vh b/src/parameters.vh index 9ac7abe..fef2968 100644 --- a/src/parameters.vh +++ b/src/parameters.vh @@ -1,12 +1,14 @@ -parameter ADDR_MODE_INDEXED_INDIRECT = 0; -parameter ADDR_MODE_ZP = 1; -parameter ADDR_MODE_IMMEDIATE = 2; -parameter ADDR_MODE_ABSOLUTE = 3; -parameter ADDR_MODE_INDIRECT_INDEXED = 4; -parameter ADDR_MODE_ZP_X = 5; -parameter ADDR_MODE_ABS_Y = 6; -parameter ADDR_MODE_ABS_X = 7; +parameter ADDR_MODE_IMPLIED = 0; +parameter ADDR_MODE_IMMEDIATE = 1; +parameter ADDR_MODE_ABSOLUTE = 2; +parameter ADDR_MODE_ZP = 3; +parameter ADDR_MODE_INDEXED_ABSOLUTE = 4; +parameter ADDR_MODE_INDEXED_ZP = 5; +parameter ADDR_MODE_INDIRECT = 6; +parameter ADDR_MODE_PREINDEXED_INDIRECT = 7; +parameter ADDR_MODE_POSTINDEXED_INDIRECT = 8; +parameter ADDR_MODE_RELATIVE = 9; parameter OP_OR = 0; parameter OP_AND = 1; diff --git a/tests/test_alu.verilog b/tests/test_alu.verilog index fe2f5d3..30b6b13 100644 --- a/tests/test_alu.verilog +++ b/tests/test_alu.verilog @@ -1,8 +1,8 @@ module test_alu; - initial begin - $dumpfile("test.vcd"); - $dumpvars(0, test_alu); - end +initial begin + $dumpfile("test.vcd"); + $dumpvars(0, test_alu); +end `define assert(signal, value) \ if (signal !== value) begin \ @@ -11,110 +11,122 @@ if (signal !== value) begin \ end - reg nrst = 1; - reg clk = 0; + reg [7:0] A; + reg [7:0] B; + reg C; + reg [2:0] op_sel; - reg [7:0] A; - reg [7:0] B; - reg C; - reg [2:0] op_sel; + wire [7:0] result; + wire r_z; + wire r_n; + wire r_c; + wire r_v; - wire [7:0] result; - wire r_z; - wire r_n; - wire r_c; - wire r_v; +`include "parameters.vh" - always #1 clk = !clk; +alu my_alu( + .A(A), + .B(B), + .C(C), + .sel(op_sel), + .result(result), + .r_z(r_z), + .r_n(r_n), + .r_c(r_c), + .r_v(r_v)); - alu my_alu( - .nrst(nrst), - .clk(clk), - .A(A), - .B(B), - .C(C), - .sel(op_sel), - .result(result), - .r_z(r_z), - .r_n(r_n), - .r_c(r_c), - .r_v(r_v)); +initial begin - initial begin - #10 A = 8'h11; - B = 8'h22; - C = 0; - op_sel = 0; // OR + // Testing OR + #10 A = 8'h11; + B = 8'h22; + C = 0; + op_sel = OP_OR; - #2 `assert (result, 8'h33); + #2 `assert (result, 8'h33); - #2 op_sel = 1; // AND + // Testing AND + #2 op_sel = OP_AND; - #2 `assert (result, 8'h00); + #2 `assert (result, 8'h00); - #2 op_sel = 2; // EOR + // Testing EOR + #2 op_sel = OP_EOR; - #2 `assert (result, 8'h33); + #2 `assert (result, 8'h33); - #2 A = 8'h22; - B = 8'h22; + #2 A = 8'h22; + B = 8'h22; - #2 `assert (result, 8'h00); + #2 `assert (result, 8'h00); - #2 op_sel = 3; // ADC + // Testing ADC + // Without carry + #2 op_sel = OP_ADC; - #2 A = 8'h22; - B = 8'h22; + #2 A = 8'h22; + B = 8'h22; + C = 0; - #2 `assert (result, 8'h44); + #2 `assert (result, 8'h44); - #2 C = 1; // ADD with CARRY + // With carry + #2 C = 1; - #2 `assert (result, 8'h45); + #2 `assert (result, 8'h45); - #2 A = 8'hf0; - B = 8'h10; - C = 0; + #2 A = 8'hf0; + B = 8'h10; + C = 0; - #2 `assert (r_c, 1); + #2 `assert (r_c, 1); - #2 op_sel = 4; - A = 8'hf0; - B = 8'h10; - C = 0; - #2 `assert (result, 8'hdf); + // Test SUB + #2 op_sel = OP_SUB; + A = 8'hf0; + B = 8'h10; + C = 0; + #2 `assert (result, 8'hdf); - #2 C = 1; + #2 C = 1; - #2 `assert (result, 8'he0); + #2 `assert (result, 8'he0); - #2 op_sel = 5; + // Test ROT + #2 op_sel = OP_ROT; - A = 8'hf0; - B = 8'h00; - C = 1; + A = 8'hf0; + B = SHIFT_LEFT; + C = 1; - #2 `assert (result, 8'he1); - `assert (r_c, 1); + #2 `assert (result, 8'he1); + `assert (r_c, 1); - #2 C = 0; + #2 C = 0; - #2 `assert (result, 8'he0); + #2 `assert (result, 8'he0); - #2 B = 1; - C = 0; + #2 B = SHIFT_RIGHT; + C = 0; - #2 `assert (result, 8'h78); + #2 `assert (result, 8'h78); - #2 A = 8'hf1; - C = 1; + #2 A = 8'hf1; + C = 1; - #2 `assert (result, 8'hf8); - `assert (r_c, 1); + #2 `assert (result, 8'hf8); + `assert (r_c, 1); - #2 op_sel = 6; + // Test SHF + #2 op_sel = OP_SHF; + A = 8'hf9; + B = SHIFT_LEFT; + #1 `assert (result, 8'hf2); - #500 $finish; - end + B = SHIFT_RIGHT; + #1 `assert (result, 8'h7c); + + #500 $finish; +end endmodule