Browse Source

ALU,decoder: make combinatorial

master
Denis Tereshkin 1 month ago
parent
commit
0dd5d0341a
  1. 158
      src/alu.verilog
  2. 262
      src/decoder.verilog
  3. 18
      src/parameters.vh
  4. 164
      tests/test_alu.verilog

158
src/alu.verilog

@ -1,89 +1,87 @@
module alu module alu
( (
input nrst, input logic [7:0] A,
input clk, input logic [7:0] B,
input [7:0] A, input logic C,
input [7:0] B, input logic [2:0] sel,
input C, output logic [7:0] result,
input [2:0] sel, output logic r_n,
output [7:0] result, output logic r_z,
output r_n, output logic r_v,
output r_z, output logic r_c
output reg r_v,
output reg r_c
); );
wire rst = !nrst; `include "parameters.vh"
reg [8:0] buffer;
wire [8:0] sum;
wire [8:0] diff;
assign result[7:0] = buffer[7:0]; reg [8:0] buffer;
assign r_z = buffer[7:0] == 0; wire [8:0] sum;
assign r_n = buffer[7]; wire [8:0] diff;
assign sum = A + B + C;
assign diff = A - B - (1 - C);
initial begin assign r_z = result[7:0] == 0;
buffer <= 0; assign r_n = result[7];
r_v <= 0; assign sum = A + B + C;
r_c <= 0; assign diff = A - B - (1 - C);
end
always @(posedge clk) always_comb
begin begin
case (sel) case (sel)
OP_OR: OP_OR:
begin begin
buffer <= A | B; result = A | B;
end r_v = 0;
OP_AND: r_c = 0;
begin end
buffer <= A & B; OP_AND:
end begin
OP_EOR: result = A & B;
begin r_v = 0;
buffer <= A ^ B; r_c = 0;
end end
OP_ADC: OP_EOR:
begin begin
buffer <= sum; result = A ^ B;
r_c <= sum[8]; r_v = 0;
r_v <= !(A[7] ^ B[7]) & (A[7] & sum[7]); r_c = 0;
end end
OP_SUB: OP_ADC:
begin begin
buffer <= diff; result = sum[7:0];
r_c <= diff[8]; r_c = sum[8];
r_v <= !(A[7] ^ B[7]) & (A[7] & diff[7]); r_v = !(A[7] ^ B[7]) & (A[7] ^ sum[7]);
end end
OP_ROT: OP_SUB:
begin begin
if (B == SHIFT_LEFT) begin result = diff;
buffer[8:1] <= A[7:0]; r_c = diff[8];
buffer[0] <= C; r_v = !(A[7] ^ B[7]) & (A[7] ^ diff[7]);
r_c <= A[7]; end
end OP_ROT:
else begin begin
buffer[6:0] <= A[7:1]; if (B == SHIFT_LEFT) begin
buffer[7] <= C; result[7:1] = A[6:0];
r_c <= A[0]; result[0] = C;
end r_c = A[7];
end end
OP_SHF: else begin
begin result[6:0] = A[7:1];
if (B == SHIFT_LEFT) begin result[7] = C;
buffer[8:1] <= A[7:0]; r_c = A[0];
buffer[0] <= 0; end
r_c <= A[7]; end
end OP_SHF:
else begin begin
buffer[6:0] <= A[7:1]; if (B == SHIFT_LEFT) begin
buffer[7] <= 0; result[7:1] = A[6:0];
r_c <= A[0]; result[0] = 0;
end r_c = A[7];
end end
endcase // case sel else begin
end result[6:0] = A[7:1];
result[7] = 0;
r_c = A[0];
end
end
endcase // case sel
end
endmodule endmodule

262
src/decoder.verilog

@ -4,8 +4,8 @@ module decoder
input clk, input clk,
input rst, input rst,
input [7:0] instr, input [7:0] instr,
output reg [3:0] address_code, output logic [4:0] address_code,
output reg [7:0] decoded output logic [7:0] decoded
); );
`include "parameters.vh" `include "parameters.vh"
@ -18,152 +18,226 @@ module decoder
wire sec_2_nop = (sector == 2) && ((column == 0 && (row == 4 || row == 6 || row == 7)) wire sec_2_nop = (sector == 2) && ((column == 0 && (row == 4 || row == 6 || row == 7))
|| (column == 6 && (row != 4 && row != 5))); || (column == 6 && (row != 4 && row != 5)));
always @* begin always_comb begin
address_code = 0;
decoded = 0;
if (rst) begin if (rst) begin
address_code <= 0; address_code = 8'h0;
end end
else begin else begin
if (sector == 1) begin if (sector == 1) begin
case (row) case (row)
0: decoded <= I_ORA; 0: decoded = I_ORA;
1: decoded <= I_AND; 1: decoded = I_AND;
2: decoded <= I_EOR; 2: decoded = I_EOR;
3: decoded <= I_ADC; 3: decoded = I_ADC;
4: decoded <= (column == 2 ? I_STA : I_NOP); 4: decoded = (column == 2 ? I_STA : I_NOP);
5: decoded <= I_LDA; 5: decoded = I_LDA;
6: decoded <= I_CMP; 6: decoded = I_CMP;
7: decoded <= I_SBC; 7: decoded = I_SBC;
endcase endcase
address_code <= column; address_code = column;
end end
else if (sector == 2) begin else if (sector == 2) begin
case (row) case (row)
0: decoded <= (sec_2_stp ? I_STP : (sec_2_nop ? I_NOP : I_ASL)); 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)); 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)); 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)); 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))); 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))); 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))); 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)); 7: decoded = (sec_2_stp ? I_STP : ((sec_2_nop || column == 2) ? I_NOP : I_INC));
endcase endcase
if (column > 0) begin if (column > 0) begin
address_code <= column address_code = column;
end end
else begin else begin
address_code <= ADDR_MODE_IMMEDIATE; address_code = ADDR_MODE_IMMEDIATE;
end end
end end
else if (sector == 0) begin else if (sector == 0) begin
if (column == 0) begin if (column == 0) begin
case (row) case (row)
0: decoded <= I_BRK; 0: decoded = I_BRK;
1: decoded <= I_JSR; 1: decoded = I_JSR;
2: decoded <= I_RTI; 2: decoded = I_RTI;
3: decoded <= I_RTS; 3: decoded = I_RTS;
4: decoded <= I_NOP; 4: decoded = I_NOP;
5: decoded <= I_LDY; 5: decoded = I_LDY;
6: decoded <= I_CPY; 6: decoded = I_CPY;
7: decoded <= I_CPX; 7: decoded = I_CPX;
endcase endcase
end end
else if (column == 1) begin else if (column == 1) begin
case (row) case (row)
0: decoded <= I_NOP; 0: decoded = I_NOP;
1: decoded <= I_BIT; 1: decoded = I_BIT;
2: decoded <= I_NOP; 2: decoded = I_NOP;
3: decoded <= I_NOP; 3: decoded = I_NOP;
4: decoded <= I_STY; 4: decoded = I_STY;
5: decoded <= I_LDY; 5: decoded = I_LDY;
6: decoded <= I_CPY; 6: decoded = I_CPY;
7: decoded <= I_CPX; 7: decoded = I_CPX;
endcase endcase
end end
else if (column == 2) begin else if (column == 2) begin
case (row) case (row)
0: decoded <= I_PHP; 0: decoded = I_PHP;
1: decoded <= I_PLP; 1: decoded = I_PLP;
2: decoded <= I_PHA; 2: decoded = I_PHA;
3: decoded <= I_PLA; 3: decoded = I_PLA;
4: decoded <= I_DEY; 4: decoded = I_DEY;
5: decoded <= I_TAY; 5: decoded = I_TAY;
6: decoded <= I_INY; 6: decoded = I_INY;
7: decoded <= I_INX; 7: decoded = I_INX;
endcase endcase
end end
else if (column == 3) begin else if (column == 3) begin
case (row) case (row)
0: decoded <= I_NOP; 0: decoded = I_NOP;
1: decoded <= I_BIT; 1: decoded = I_BIT;
2: decoded <= I_JMP; 2: decoded = I_JMP;
3: decoded <= I_JMP; 3: decoded = I_JMP;
4: decoded <= I_STY; 4: decoded = I_STY;
5: decoded <= I_LDY; 5: decoded = I_LDY;
6: decoded <= I_CPY; 6: decoded = I_CPY;
7: decoded <= I_CPX; 7: decoded = I_CPX;
endcase endcase
end end
else if (column == 4) begin else if (column == 4) begin
case (row) case (row)
0: decoded <= I_BPL; 0: decoded = I_BPL;
1: decoded <= I_BMI; 1: decoded = I_BMI;
2: decoded <= I_BVC; 2: decoded = I_BVC;
3: decoded <= I_BVS; 3: decoded = I_BVS;
4: decoded <= I_BCC; 4: decoded = I_BCC;
5: decoded <= I_BCS; 5: decoded = I_BCS;
6: decoded <= I_BNE; 6: decoded = I_BNE;
7: decoded <= I_BEQ; 7: decoded = I_BEQ;
endcase endcase
end end
else if (column == 5) begin else if (column == 5) begin
case (row) case (row)
0: decoded <= I_NOP; 0: decoded = I_NOP;
1: decoded <= I_NOP; 1: decoded = I_NOP;
2: decoded <= I_NOP; 2: decoded = I_NOP;
3: decoded <= I_NOP; 3: decoded = I_NOP;
4: decoded <= I_STY; 4: decoded = I_STY;
5: decoded <= I_LDY; 5: decoded = I_LDY;
6: decoded <= I_NOP; 6: decoded = I_NOP;
7: decoded <= I_NOP; 7: decoded = I_NOP;
endcase endcase
end end
else if (column == 6) begin else if (column == 6) begin
case (row) case (row)
0: decoded <= I_CLC; 0: decoded = I_CLC;
1: decoded <= I_SEC; 1: decoded = I_SEC;
2: decoded <= I_CLI; 2: decoded = I_CLI;
3: decoded <= I_SEI; 3: decoded = I_SEI;
4: decoded <= I_TYA; 4: decoded = I_TYA;
5: decoded <= I_CLV; 5: decoded = I_CLV;
6: decoded <= I_CLD; 6: decoded = I_CLD;
7: decoded <= I_SED; 7: decoded = I_SED;
endcase endcase
end end
else if (column == 7) begin else if (column == 7) begin
case (row) case (row)
0: decoded <= I_NOP; 0: decoded = I_NOP;
1: decoded <= I_NOP; 1: decoded = I_NOP;
2: decoded <= I_NOP; 2: decoded = I_NOP;
3: decoded <= I_NOP; 3: decoded = I_NOP;
4: decoded <= I_SHY; 4: decoded = I_SHY;
5: decoded <= I_LDY; 5: decoded = I_LDY;
6: decoded <= I_NOP; 6: decoded = I_NOP;
7: decoded <= I_NOP; 7: decoded = I_NOP;
endcase endcase
end end
end
if (column > 0) begin if (sector == 0) begin
address_code <= column; 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 end
else begin else if(column == 1) begin
if (row >= 4) begin address_code = ADDR_MODE_ZP;
address_code <= ADDR_MODE_IMMEDIATE; 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 end
else begin else begin
address_code <= ADDR_MODE_ABSOLUTE; address_code = ADDR_MODE_INDEXED_ABSOLUTE;
end end
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 end
end end

18
src/parameters.vh

@ -1,12 +1,14 @@
parameter ADDR_MODE_INDEXED_INDIRECT = 0; parameter ADDR_MODE_IMPLIED = 0;
parameter ADDR_MODE_ZP = 1; parameter ADDR_MODE_IMMEDIATE = 1;
parameter ADDR_MODE_IMMEDIATE = 2; parameter ADDR_MODE_ABSOLUTE = 2;
parameter ADDR_MODE_ABSOLUTE = 3; parameter ADDR_MODE_ZP = 3;
parameter ADDR_MODE_INDIRECT_INDEXED = 4; parameter ADDR_MODE_INDEXED_ABSOLUTE = 4;
parameter ADDR_MODE_ZP_X = 5; parameter ADDR_MODE_INDEXED_ZP = 5;
parameter ADDR_MODE_ABS_Y = 6; parameter ADDR_MODE_INDIRECT = 6;
parameter ADDR_MODE_ABS_X = 7; parameter ADDR_MODE_PREINDEXED_INDIRECT = 7;
parameter ADDR_MODE_POSTINDEXED_INDIRECT = 8;
parameter ADDR_MODE_RELATIVE = 9;
parameter OP_OR = 0; parameter OP_OR = 0;
parameter OP_AND = 1; parameter OP_AND = 1;

164
tests/test_alu.verilog

@ -1,8 +1,8 @@
module test_alu; module test_alu;
initial begin initial begin
$dumpfile("test.vcd"); $dumpfile("test.vcd");
$dumpvars(0, test_alu); $dumpvars(0, test_alu);
end end
`define assert(signal, value) \ `define assert(signal, value) \
if (signal !== value) begin \ if (signal !== value) begin \
@ -11,110 +11,122 @@ if (signal !== value) begin \
end end
reg nrst = 1; reg [7:0] A;
reg clk = 0; reg [7:0] B;
reg C;
reg [2:0] op_sel;
reg [7:0] A; wire [7:0] result;
reg [7:0] B; wire r_z;
reg C; wire r_n;
reg [2:0] op_sel; wire r_c;
wire r_v;
wire [7:0] result; `include "parameters.vh"
wire r_z;
wire r_n;
wire r_c;
wire r_v;
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( initial begin
.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 // Testing OR
#10 A = 8'h11; #10 A = 8'h11;
B = 8'h22; B = 8'h22;
C = 0; C = 0;
op_sel = 0; // OR 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; #2 A = 8'h22;
B = 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; #2 A = 8'h22;
B = 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; #2 A = 8'hf0;
B = 8'h10; B = 8'h10;
C = 0; C = 0;
#2 `assert (r_c, 1); #2 `assert (r_c, 1);
#2 op_sel = 4; // Test SUB
A = 8'hf0; #2 op_sel = OP_SUB;
B = 8'h10; A = 8'hf0;
C = 0; B = 8'h10;
#2 `assert (result, 8'hdf); 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; A = 8'hf0;
B = 8'h00; B = SHIFT_LEFT;
C = 1; C = 1;
#2 `assert (result, 8'he1); #2 `assert (result, 8'he1);
`assert (r_c, 1); `assert (r_c, 1);
#2 C = 0; #2 C = 0;
#2 `assert (result, 8'he0); #2 `assert (result, 8'he0);
#2 B = 1; #2 B = SHIFT_RIGHT;
C = 0; C = 0;
#2 `assert (result, 8'h78); #2 `assert (result, 8'h78);
#2 A = 8'hf1; #2 A = 8'hf1;
C = 1; C = 1;
#2 `assert (result, 8'hf8); #2 `assert (result, 8'hf8);
`assert (r_c, 1); `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; B = SHIFT_RIGHT;
end #1 `assert (result, 8'h7c);
#500 $finish;
end
endmodule endmodule

Loading…
Cancel
Save