Browse Source

Add ALU

master
Denis Tereshkin 2 years ago
commit
8ccea9566e
  1. BIN
      doc/w65c02s.pdf
  2. 94
      src/alu.verilog
  3. 120
      tests/test_alu.verilog

BIN
doc/w65c02s.pdf

Binary file not shown.

94
src/alu.verilog

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
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
);
localparam OP_OR = 0;
localparam OP_AND = 1;
localparam OP_EOR = 2;
localparam OP_ADC = 3;
localparam OP_SUB = 4;
localparam OP_ROT = 5;
localparam OP_SHF = 6;
localparam SHIFT_LEFT = 0;
localparam SHIFT_RIGHT = 1;
wire rst = !nrst;
reg [8:0] buffer;
wire [8:0] sum;
wire [8:0] diff;
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);
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
endmodule

120
tests/test_alu.verilog

@ -0,0 +1,120 @@ @@ -0,0 +1,120 @@
module test_alu;
initial begin
$dumpfile("test.vcd");
$dumpvars(0, test_alu);
end
`define assert(signal, value) \
if (signal !== value) begin \
$display("ASSERTION FAILED in %m: signal != value"); \
$finish; \
end
reg nrst = 1;
reg clk = 0;
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;
always #1 clk = !clk;
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
#10 A = 8'h11;
B = 8'h22;
C = 0;
op_sel = 0; // OR
#2 `assert (result, 8'h33);
#2 op_sel = 1; // AND
#2 `assert (result, 8'h00);
#2 op_sel = 2; // EOR
#2 `assert (result, 8'h33);
#2 A = 8'h22;
B = 8'h22;
#2 `assert (result, 8'h00);
#2 op_sel = 3; // ADC
#2 A = 8'h22;
B = 8'h22;
#2 `assert (result, 8'h44);
#2 C = 1; // ADD with CARRY
#2 `assert (result, 8'h45);
#2 A = 8'hf0;
B = 8'h10;
C = 0;
#2 `assert (r_c, 1);
#2 op_sel = 4;
A = 8'hf0;
B = 8'h10;
C = 0;
#2 `assert (result, 8'hdf);
#2 C = 1;
#2 `assert (result, 8'he0);
#2 op_sel = 5;
A = 8'hf0;
B = 8'h00;
C = 1;
#2 `assert (result, 8'he1);
`assert (r_c, 1);
#2 C = 0;
#2 `assert (result, 8'he0);
#2 B = 1;
C = 0;
#2 `assert (result, 8'h78);
#2 A = 8'hf1;
C = 1;
#2 `assert (result, 8'hf8);
`assert (r_c, 1);
#2 op_sel = 6;
#500 $finish;
end
endmodule
Loading…
Cancel
Save