📄 a86_alu.v
字号:
// http://gforge.openchip.org/projects/a86
`include "timescale.v"
`include "a86_defines.v"
`include "a86_ADSU16_XILINX.v"
`include "a86_ADSU16_GENERIC.v"
module a86_alu(
icode,
ain,bin,
dout,
fin,fout,
aluop,dout_hi
);
input [`a86_icode_width-1:0] icode;
input [15:0] ain;
input [15:0] bin;
output [15:0] dout;
output [15:0] dout_hi;
input [15:0] fin;
output [15:0] fout;
reg [15:0] fout;
input [7:0] aluop;
reg [15:0] dout;
reg [15:0] dout_hi;
//
reg [15:0] add_result;
reg [15:0] sub_result;
reg [15:0] and_result;
reg [15:0] or_result;
reg [15:0] xor_result;
reg [31:0] mul_result;
reg [15:0] alu_result;
//
reg [15:0] aaa_result;
reg [15:0] aad_result;
reg [15:0] aam_result;
reg [15:0] aas_result;
// AND gates
reg [15:0] sela_anded;
reg [15:0] selb_anded;
reg [15:0] add_anded;
reg [15:0] and_anded;
reg [15:0] or_anded;
reg [15:0] xor_anded;
// or together
reg [15:0] res_ored;
reg zf;
reg cf;
wire adsu_result;
// todo: Xilinx use ADDSU16, and carry chain for add and sub
`ifdef a86_vendor_xilinx
a86_ADSU16_XILINX addsu16_0 (
.A(ain),
.ADD(1'b0),
.B(bin),
.CI(fin[`psf_cf]),
.CO( ),
.OFL(),
.S(adsu_result)
);
uu always @ (aluop,ain,bin,adsu_result) add_result <= adsu_result;
uuu always @ (aluop,ain,bin,adsu_result) sub_result <= adsu_result;
`endif
`ifdef a86_vendor_generic
//always @ (aluop,ain,bin) add_result = ain + bin + fin[`psf_cf];
//always @ (aluop,ain,bin) sub_result = ain - bin - fin[`psf_cf];
always @ (ain,bin) add_result = ain + bin;
always @ (ain,bin) sub_result = ain - bin;
`endif
// Logic Operations
always @ (ain,bin) or_result = ain | bin;
always @ (ain,bin) and_result = ain & bin;
always @ (ain,bin) xor_result = ain ^ bin;
// funny
always @ (aluop,ain) begin
/*
if (((AL = AL & 0x0F) > 9) || (AF == 1)) {
-- AL is not yet in BCD format note high nibble of AL is cleared either way) convert AL to decimal and unpack
AL = (AL + 6) & 0x0F;
AH = AH + 1;
set carry flags
CF = AF = 1;
}
else
-- clear carry flags
CF = AF = 0;
*/
aaa_result = {ain[15:8]+8'b00000001, (ain[7:0]+8'b00000110) & 8'b00001111 };
end
always @ (aluop,ain) begin
aad_result = {8'b00000000, ain[15:8] * 8'b00001010 + ain[7:0]};
end
always @ (aluop,ain) begin
//aam_result = {ain[7:0] / 10, ain[7:0] % 10};
// TODO!
aam_result = ain;
end
always @ (aluop,ain) begin
/*
if (((AL = AL & 0x0F) > 9) || (AF == 1)) {
AL is not yet decimal (note high nibble of AL is cleared either way convert AL to decimal and unpack
AL = (AL - 6) & 0x0F;
AH = AH - 1;
set carry flags
CF = AF = 1;
}
else
clear carry flags
CF = AF = 0;
*/
aas_result = {ain[15:8]-8'b00000001, (ain[7:0]-8'b00000110) & 8'b00001111 };
end
// XST uses embedded 18x18 multiply OK
always @ (aluop,ain,bin) mul_result = ain * bin;
/*
always @ (aluop)
case(aluop[7:0])
`alu_op_add: alu_result = add_result; // add, adc, inc
`alu_op_sub: alu_result = sub_result; // sub, sbb, dec
`alu_op_and: alu_result = and_result;
`alu_op_or: alu_result = or_result;
`alu_op_mul: alu_result = mul_result[15:0];
8'b11110111: alu_result = fin; // bypass PSF reg for "PUSH Flags" :)
default alu_result <= 16'h0000;
endcase
*/
// Muxin A
always @ (ain,icode)
if (icode[`a86_icode_alu_sela]) sela_anded = ain;
else sela_anded = 16'h0000;
// Muxin B
always @ (bin,icode)
if (icode[`a86_icode_alu_selb]) selb_anded = bin;
else selb_anded = 16'h0000;
// Muxin ADD result
always @ (add_result,icode)
if (icode[`a86_icode_incdec]) add_anded = add_result;
else add_anded = 16'h0000;
// Muxin AND result
always @ (and_result,icode)
if (icode[`a86_icode_alu_and]) and_anded = and_result;
else and_anded = 16'h0000;
// Muxin OR result
always @ (or_result,icode)
if (icode[`a86_icode_alu_or]) or_anded = or_result;
else or_anded = 16'h0000;
// Muxin XOR result
always @ (xor_result,icode)
if (icode[`a86_icode_alu_xor]) xor_anded = xor_result;
else xor_anded = 16'h0000;
// Muxin all in!
always @ (sela_anded,selb_anded,add_anded,and_anded,or_anded,xor_anded)
res_ored =
sela_anded | selb_anded
| add_anded
| and_anded | or_anded | xor_anded;
always @ (res_ored) dout = res_ored;
always @ (mul_result)
dout_hi = mul_result[31:16];
reg aluop_is16;
// calculate out flags
reg f_parity_lo;
reg f_parity_hi;
reg f_parity;
reg f_zero_lo;
reg f_zero_hi;
reg f_zero;
// Zero Flag!
always @(dout)
f_zero_lo = dout[7:0] == 8'b00000000;
always @(dout)
f_zero_hi = dout[15:8] == 8'b00000000; //) & aluop_is16;
always @(f_zero_lo,f_zero_hi)
f_zero = f_zero_lo | f_zero_hi;
// send the flags out ...
always @(f_zero)
fout[`psf_zf] = f_zero;
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -