1
0
Fork 0
2023-fpga-computer/src/sap3/alu.v

174 lines
3.1 KiB
Verilog

module alu(
input clk,
input rst,
input cs,
input flags_we,
input a_we,
input a_store,
input a_restore,
input tmp_we,
input[4:0] op,
input[7:0] bus,
output[7:0] flags,
output[7:0] out
);
reg carry;
wire flg_c;
wire flg_z;
wire flg_p;
wire flg_s;
reg[7:0] acc;
reg[7:0] flg;
reg[7:0] act; // Internal
reg[7:0] tmp; // Internal
localparam FLG_Z = 0;
localparam FLG_C = 1;
localparam FLG_P = 2;
localparam FLG_S = 3;
localparam OP_ADD = 5'b00000;
localparam OP_ADC = 5'b00001;
localparam OP_SUB = 5'b00010;
localparam OP_SBB = 5'b00011;
localparam OP_ANA = 5'b00100;
localparam OP_XRA = 5'b00101;
localparam OP_ORA = 5'b00110;
localparam OP_CMP = 5'b00111;
localparam OP_RLC = 5'b01000;
localparam OP_RRC = 5'b01001;
localparam OP_RAL = 5'b01010;
localparam OP_RAR = 5'b01011;
localparam OP_DAA = 5'b01100; // Unsupported
localparam OP_CMA = 5'b01101;
localparam OP_STC = 5'b01110;
localparam OP_CMC = 5'b01111;
localparam OP_INR = 5'b10000;
localparam OP_DCR = 5'b10001;
assign flg_c = (carry == 1'b1);
assign flg_z = (acc[7:0] == 8'b0);
assign flg_s = acc[7];
assign flg_p = ~^acc[7:0];
always @(posedge clk, posedge rst) begin
if (rst) begin
acc <= 8'b0;
act <= 8'b0;
tmp <= 8'b0;
carry <= 1'b0;
end else begin
if (a_we) begin
acc <= bus;
end else if (a_restore) begin
acc <= act;
end else if (cs) begin
case (op)
OP_ADD: begin
{carry, acc} <= acc + tmp;
end
OP_ADC: begin
{carry, acc} <= acc + tmp + flg[FLG_C];
end
OP_SUB: begin
{carry, acc} <= acc - tmp;
end
OP_SBB: begin
{carry, acc} <= acc - tmp - flg[FLG_C];
end
OP_ANA: begin
{carry, acc} <= acc & tmp;
end
OP_XRA: begin
{carry, acc} <= acc ^ tmp;
end
OP_ORA: begin
{carry, acc} <= acc | tmp;
end
OP_CMP: begin
act <= acc - tmp;
end
OP_RLC: begin
carry <= acc[7];
acc <= acc << 1;
end
OP_RRC: begin
carry <= acc[0];
acc <= acc >> 1;
end
OP_RAL: begin
carry <= acc[7];
acc <= (acc << 1 | {7'b0, flg[FLG_C]});
end
OP_RAR: begin
carry <= acc[0];
acc <= (acc >> 1 | {flg[FLG_C], 7'b0});
end
OP_CMA: begin
acc <= ~acc;
end
OP_STC: begin
carry <= 1'b1;
end
OP_CMC: begin
carry <= ~flg[FLG_C];
end
OP_INR: begin
acc <= acc + 1;
end
OP_DCR: begin
acc <= acc - 1;
end
endcase
end
if (a_store)
act <= acc;
if (tmp_we)
tmp <= bus;
end
end
always @(negedge clk, posedge rst) begin
if (rst) begin
flg <= 8'b0;
end else if (flags_we) begin
flg <= bus;
end else begin
if (cs) begin
case (op)
OP_ADD, OP_ADC, OP_SUB, OP_SBB, OP_ANA, OP_XRA, OP_ORA: begin
flg[FLG_C] <= flg_c;
flg[FLG_Z] <= flg_z;
flg[FLG_S] <= flg_s;
flg[FLG_P] <= flg_p;
end
OP_CMP: begin
flg[FLG_Z] <= (act == 8'b0);
end
OP_INR, OP_DCR: begin
flg[FLG_Z] <= flg_z;
flg[FLG_S] <= flg_s;
flg[FLG_P] <= flg_p;
end
OP_RLC, OP_RRC, OP_RAL, OP_RAR, OP_STC, OP_CMC: begin
flg[FLG_C] <= flg_c;
end
endcase
end
end
end
assign flags = flg;
assign out = acc;
endmodule