/*
|
/*
|
* (c) 2013 Alejandro Paz
|
* (c) 2013 Alejandro Paz
|
*
|
*
|
*
|
*
|
* An alu core
|
* An alu core
|
*
|
*
|
* ADD, ADC, DAA, SUB, SBC, COM, NEG, CMP, ASR, ASL, ROR, ROL, RCR, RCL
|
* ADD, ADC, DAA, SUB, SBC, COM, NEG, CMP, ASR, ASL, ROR, ROL, RCR, RCL
|
*
|
*
|
*
|
*
|
*
|
*
|
*/
|
*/
|
`include "defs.v"
|
`include "defs.v"
|
|
|
|
|
module alu(
|
module alu(
|
input wire clk_in,
|
input wire clk_in,
|
input wire [15:0] a_in,
|
input wire [15:0] a_in,
|
input wire [15:0] b_in,
|
input wire [15:0] b_in,
|
input wire [7:0] CCR, /* condition code register */
|
input wire [7:0] CCR, /* condition code register */
|
input wire [4:0] opcode_in, /* ALU opcode */
|
input wire [4:0] opcode_in, /* ALU opcode */
|
input wire sz_in, /* size, low 8 bit, high 16 bit */
|
input wire sz_in, /* size, low 8 bit, high 16 bit */
|
output reg [15:0] q_out, /* ALU result */
|
output reg [15:0] q_out, /* ALU result */
|
output reg [7:0] CCRo
|
output reg [7:0] CCRo
|
);
|
);
|
|
|
wire [7:0] ccr8_out, q8_out;
|
wire [7:0] ccr8_out, q8_out;
|
wire [15:0] q16_out;
|
wire [15:0] q16_out;
|
wire [3:0] ccr16_out;
|
wire [3:0] ccr16_out;
|
|
wire [15:0] q16_mul;
|
reg [15:0] ra_in, rb_in;
|
reg [15:0] ra_in, rb_in;
|
reg [4:0] rop_in;
|
reg [4:0] rop_in;
|
|
|
|
|
|
mul8x8 mulu(clk_in, a_in[7:0], b_in[7:0], q16_mul);
|
alu8 alu8(clk_in, ra_in[7:0], rb_in[7:0], CCR, rop_in, q8_out, ccr8_out);
|
alu8 alu8(clk_in, ra_in[7:0], rb_in[7:0], CCR, rop_in, q8_out, ccr8_out);
|
alu16 alu16(clk_in, ra_in, rb_in, CCR, rop_in, q16_out, ccr16_out);
|
alu16 alu16(clk_in, ra_in, rb_in, CCR, rop_in, q16_mul, q16_out, ccr16_out);
|
|
|
|
|
always @(posedge clk_in)
|
always @(posedge clk_in)
|
begin
|
begin
|
ra_in <= a_in;
|
ra_in <= a_in;
|
rb_in <= b_in;
|
rb_in <= b_in;
|
rop_in <= opcode_in;
|
rop_in <= opcode_in;
|
end
|
end
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
if (sz_in)
|
if (sz_in)
|
begin
|
begin
|
q_out = q16_out;
|
q_out = q16_out;
|
CCRo = { CCR[7:4], ccr16_out };
|
CCRo = { CCR[7:4], ccr16_out };
|
end
|
end
|
else
|
else
|
begin
|
begin
|
q_out = { 8'h0, q8_out };
|
q_out = { 8'h0, q8_out };
|
CCRo = ccr8_out;
|
CCRo = ccr8_out;
|
end
|
end
|
end
|
end
|
|
|
|
|
endmodule
|
endmodule
|
/**
|
/**
|
* Simple 3 functions logic
|
* Simple 3 functions logic
|
*
|
*
|
*/
|
*/
|
module logic8(
|
module logic8(
|
input wire [7:0] a_in,
|
input wire [7:0] a_in,
|
input wire [7:0] b_in,
|
input wire [7:0] b_in,
|
input wire [1:0] opcode_in, /* ALU opcode */
|
input wire [1:0] opcode_in, /* ALU opcode */
|
output reg [7:0] q_out /* ALU result */
|
output reg [7:0] q_out /* ALU result */
|
);
|
);
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
case (opcode_in)
|
case (opcode_in)
|
2'b00: q_out = b_in;
|
2'b00: q_out = b_in;
|
2'b01: q_out = a_in & b_in;
|
2'b01: q_out = a_in & b_in;
|
2'b10: q_out = a_in | b_in;
|
2'b10: q_out = a_in | b_in;
|
2'b11: q_out = a_in ^ b_in;
|
2'b11: q_out = a_in ^ b_in;
|
endcase
|
endcase
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
/**
|
/**
|
* Simple ADD/SUB module
|
* Simple ADD/SUB module
|
*
|
*
|
*/
|
*/
|
module arith8(
|
module arith8(
|
input wire [7:0] a_in,
|
input wire [7:0] a_in,
|
input wire [7:0] b_in,
|
input wire [7:0] b_in,
|
input wire carry_in, /* condition code register */
|
input wire carry_in, /* condition code register */
|
input wire half_c_in,
|
input wire half_c_in,
|
input wire [1:0] opcode_in, /* ALU opcode */
|
input wire [1:0] opcode_in, /* ALU opcode */
|
output reg [7:0] q_out, /* ALU result */
|
output reg [7:0] q_out, /* ALU result */
|
output reg carry_out,
|
output reg carry_out,
|
output reg overflow_out,
|
output reg overflow_out,
|
output reg half_c_out
|
output reg half_c_out
|
);
|
);
|
|
|
wire carry;
|
wire carry;
|
assign carry = opcode_in[1] ? carry_in:1'b0;
|
assign carry = opcode_in[1] ? carry_in:1'b0;
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
case (opcode_in[0])
|
case (opcode_in[0])
|
1'b0: { carry_out, q_out } = { 1'b0, a_in } + { 1'b0, b_in } + { 8'h0, carry }; // ADD/ADC
|
1'b0: { carry_out, q_out } = { 1'b0, a_in } + { 1'b0, b_in } + { 8'h0, carry }; // ADD/ADC
|
1'b1: { carry_out, q_out } = { 1'b0, a_in } - { 1'b0, b_in } - { 8'h0, carry }; // SUB/SBC
|
1'b1: { carry_out, q_out } = { 1'b0, a_in } - { 1'b0, b_in } - { 8'h0, carry }; // SUB/SBC
|
endcase
|
endcase
|
end
|
end
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
case (opcode_in[0])
|
case (opcode_in[0])
|
1'b0: overflow_out = (a_in[7] & b_in[7] & (~q_out[7])) | ((~a_in[7]) & (~b_in[7]) & q_out[7]);
|
1'b0: overflow_out = (a_in[7] & b_in[7] & (~q_out[7])) | ((~a_in[7]) & (~b_in[7]) & q_out[7]);
|
1'b1: overflow_out = (a_in[7] & (~b_in[7]) & (~q_out[7])) | ((~a_in[7]) & b_in[7] & q_out[7]);
|
1'b1: overflow_out = (a_in[7] & (~b_in[7]) & (~q_out[7])) | ((~a_in[7]) & b_in[7] & q_out[7]);
|
endcase
|
endcase
|
end
|
end
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
case (opcode_in[0])
|
case (opcode_in[0])
|
1'b0: half_c_out = (a_in[3] & b_in[3] & (~q_out[3])) | ((~a_in[3]) & (~b_in[3]) & q_out[3]);
|
1'b0: half_c_out = (a_in[4] ^ b_in[4] ^ q_out[4]);
|
1'b1: half_c_out = half_c_in;
|
1'b1: half_c_out = half_c_in;
|
endcase
|
endcase
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
/**
|
/**
|
* Simple ADD/SUB module
|
* Simple ADD/SUB module
|
*
|
*
|
*/
|
*/
|
module arith16(
|
module arith16(
|
input wire [15:0] a_in,
|
input wire [15:0] a_in,
|
input wire [15:0] b_in,
|
input wire [15:0] b_in,
|
input wire carry_in, /* condition code register */
|
input wire carry_in, /* condition code register */
|
input wire [1:0] opcode_in, /* ALU opcode */
|
input wire [1:0] opcode_in, /* ALU opcode */
|
output reg [15:0] q_out, /* ALU result */
|
output reg [15:0] q_out, /* ALU result */
|
output reg carry_out,
|
output reg carry_out,
|
output reg overflow_out
|
output reg overflow_out
|
);
|
);
|
always @(*)
|
always @(*)
|
begin
|
begin
|
case (opcode_in)
|
case (opcode_in)
|
2'b00: { carry_out, q_out } = { 1'b0, a_in } + { 1'b0, b_in }; // ADD
|
2'b00: { carry_out, q_out } = { 1'b0, a_in } + { 1'b0, b_in }; // ADD
|
2'b01: { carry_out, q_out } = { 1'b0, a_in } - { 1'b0, b_in }; // SUB
|
2'b01: { carry_out, q_out } = { 1'b0, a_in } - { 1'b0, b_in }; // SUB
|
2'b10: { carry_out, q_out } = { 1'b0, a_in } + { 1'b0, b_in } + { 8'h0, carry_in }; // ADC
|
2'b10: { carry_out, q_out } = { 1'b0, a_in } + { 1'b0, b_in } + { 8'h0, carry_in }; // ADC
|
2'b11: { carry_out, q_out } = { 1'b0, a_in } - { 1'b0, b_in } - { 8'h0, carry_in }; // SBC
|
2'b11: { carry_out, q_out } = { 1'b0, a_in } - { 1'b0, b_in } - { 8'h0, carry_in }; // SBC
|
endcase
|
endcase
|
end
|
end
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
case (opcode_in)
|
case (opcode_in)
|
2'b00, 2'b10: overflow_out = (a_in[15] & b_in[15] & (~q_out[15])) | ((~a_in[15]) & (~b_in[15]) & q_out[7]);
|
2'b00, 2'b10: overflow_out = (a_in[15] & b_in[15] & (~q_out[15])) | ((~a_in[15]) & (~b_in[15]) & q_out[7]);
|
2'b01, 2'b11: overflow_out = (a_in[15] & (~b_in[15]) & (~q_out[15])) | ((~a_in[15]) & b_in[15] & q_out[7]);
|
2'b01, 2'b11: overflow_out = (a_in[15] & (~b_in[15]) & (~q_out[15])) | ((~a_in[15]) & b_in[15] & q_out[7]);
|
endcase
|
endcase
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
module shift8(
|
module shift8(
|
input wire [7:0] a_in,
|
input wire [7:0] a_in,
|
input wire [7:0] b_in,
|
input wire [7:0] b_in,
|
input wire carry_in, /* condition code register */
|
input wire carry_in, /* condition code register */
|
input wire overflow_in, /* condition code register */
|
input wire overflow_in, /* condition code register */
|
input wire [2:0] opcode_in, /* ALU opcode */
|
input wire [2:0] opcode_in, /* ALU opcode */
|
output reg [7:0] q_out, /* ALU result */
|
output reg [7:0] q_out, /* ALU result */
|
output wire carry_out,
|
output wire carry_out,
|
output reg overflow_out
|
output reg overflow_out
|
);
|
);
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
q_out = { a_in[7], a_in[7:1] }; // ASR
|
q_out = { a_in[7], a_in[7:1] }; // ASR
|
case (opcode_in)
|
case (opcode_in)
|
3'b000: q_out = { 1'b0, a_in[7:1] }; // LSR
|
3'b000: q_out = { 1'b0, a_in[7:1] }; // LSR
|
3'b001: q_out = { a_in[6:0], 1'b0 }; // LSL
|
3'b001: q_out = { a_in[6:0], 1'b0 }; // LSL
|
3'b010: q_out = { carry_in, a_in[7:1] }; // ROR
|
3'b010: q_out = { carry_in, a_in[7:1] }; // ROR
|
3'b011: q_out = { a_in[6:0], carry_in }; // ROL
|
3'b011: q_out = { a_in[6:0], carry_in }; // ROL
|
3'b100: q_out = { a_in[7], a_in[7:1] }; // ASR
|
3'b100: q_out = { a_in[7], a_in[7:1] }; // ASR
|
endcase
|
endcase
|
end
|
end
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
overflow_out = overflow_in;
|
overflow_out = overflow_in;
|
case (opcode_in)
|
case (opcode_in)
|
3'b000: overflow_out = overflow_in; // LSR
|
3'b000: overflow_out = overflow_in; // LSR
|
3'b001: overflow_out = a_in[7] ^ a_in[6]; // LSL
|
3'b001: overflow_out = a_in[7] ^ a_in[6]; // LSL
|
3'b010: overflow_out = overflow_in; // ROR
|
3'b010: overflow_out = overflow_in; // ROR
|
3'b011: overflow_out = a_in[7] ^ a_in[6]; // ROL
|
3'b011: overflow_out = a_in[7] ^ a_in[6]; // ROL
|
3'b100: overflow_out = overflow_in; // ASR
|
3'b100: overflow_out = overflow_in; // ASR
|
endcase
|
endcase
|
end
|
end
|
|
|
assign carry_out = opcode_in[0] ? a_in[0]:a_in[7];
|
assign carry_out = opcode_in[0] ? a_in[7]:a_in[0];
|
|
|
endmodule
|
endmodule
|
|
|
|
|
module alu8(
|
module alu8(
|
input wire clk_in,
|
input wire clk_in,
|
input wire [7:0] a_in,
|
input wire [7:0] a_in,
|
input wire [7:0] b_in,
|
input wire [7:0] b_in,
|
input wire [7:0] CCR, /* condition code register */
|
input wire [7:0] CCR, /* condition code register */
|
input wire [4:0] opcode_in, /* ALU opcode */
|
input wire [4:0] opcode_in, /* ALU opcode */
|
output reg [7:0] q_out, /* ALU result */
|
output reg [7:0] q_out, /* ALU result */
|
output reg [7:0] CCRo
|
output reg [7:0] CCRo
|
);
|
);
|
|
|
wire c_in, n_in, v_in, z_in, h_in;
|
wire c_in, n_in, v_in, z_in, h_in;
|
assign c_in = CCR[0]; /* carry flag */
|
assign c_in = CCR[0]; /* carry flag */
|
assign n_in = CCR[3]; /* neg flag */
|
assign n_in = CCR[3]; /* neg flag */
|
assign v_in = CCR[1]; /* overflow flag */
|
assign v_in = CCR[1]; /* overflow flag */
|
assign z_in = CCR[2]; /* zero flag */
|
assign z_in = CCR[2]; /* zero flag */
|
assign h_in = CCR[5]; /* halb-carry flag */
|
assign h_in = CCR[5]; /* halb-carry flag */
|
|
|
wire [7:0] com8_r, neg8_r;
|
wire [7:0] com8_r, neg8_r, daa_p0_r;
|
wire [3:0] daa8l_r, daa8h_r;
|
wire [3:0] daa8h_r;
|
wire daa_lnm9;
|
|
|
|
wire [7:0] com8_w, neg8_w;
|
wire [7:0] com8_w, neg8_w;
|
|
|
wire ccom8_r, cneg8_r, cdaa8_r;
|
wire ccom8_r, cneg8_r, cdaa8_r;
|
|
|
wire vcom8_r, vneg8_r;
|
wire vcom8_r, vneg8_r;
|
|
|
assign com8_w = ~a_in[7:0];
|
assign com8_w = ~a_in[7:0];
|
assign neg8_w = 8'h0 - a_in[7:0];
|
assign neg8_w = 8'h0 - a_in[7:0];
|
// COM
|
// COM
|
assign com8_r = com8_w;
|
assign com8_r = com8_w;
|
assign ccom8_r = com8_w != 8'h0 ? 1'b1:1'b0;
|
assign ccom8_r = com8_w != 8'h0 ? 1'b1:1'b0;
|
assign vcom8_r = 1'b0;
|
assign vcom8_r = 1'b0;
|
// NEG
|
// NEG
|
assign neg8_r = neg8_w;
|
assign neg8_r = neg8_w;
|
assign cneg8_r = neg8_w[7] | neg8_w[6] | neg8_w[5] | neg8_w[4] | neg8_w[3] | neg8_w[2] | neg8_w[1] | neg8_w[0];
|
assign cneg8_r = neg8_w[7] | neg8_w[6] | neg8_w[5] | neg8_w[4] | neg8_w[3] | neg8_w[2] | neg8_w[1] | neg8_w[0];
|
assign vneg8_r = neg8_w[7] & (~neg8_w[6]) & (~neg8_w[5]) & (~neg8_w[4]) & (~neg8_w[3]) & (~neg8_w[2]) & (~neg8_w[1]) & (~neg8_w[0]);
|
assign vneg8_r = neg8_w[7] & (~neg8_w[6]) & (~neg8_w[5]) & (~neg8_w[4]) & (~neg8_w[3]) & (~neg8_w[2]) & (~neg8_w[1]) & (~neg8_w[0]);
|
// DAA
|
|
assign daa_lnm9 = (a_in[3:0] > 9);
|
|
assign daa8l_r = (daa_lnm9 | h_in ) ? a_in[3:0] + 4'h6:a_in[3:0];
|
|
assign daa8h_r = ((a_in[7:4] > 9) || (c_in == 1'b1) || (a_in[7] & daa_lnm9)) ? a_in[7:4] + 4'h6:a_in[7:4];
|
|
assign cdaa8_r = daa8h_r < a_in[7:4];
|
|
|
|
reg c8, h8, n8, v8, z8;
|
reg c8, h8, n8, v8, z8;
|
reg [7:0] q8;
|
reg [7:0] q8;
|
|
|
wire [7:0] logic_q, arith_q, shift_q;
|
wire [7:0] logic_q, arith_q, shift_q;
|
wire arith_c, arith_v, arith_h;
|
wire arith_c, arith_v, arith_h;
|
wire shift_c, shift_v;
|
wire shift_c, shift_v;
|
|
|
logic8 l8(a_in, b_in, opcode_in[1:0], logic_q);
|
logic8 l8(a_in, b_in, opcode_in[1:0], logic_q);
|
arith8 a8(a_in, b_in, c_in, h_in, opcode_in[1:0], arith_q, arith_c, arith_v, arith_h);
|
arith8 a8(a_in, b_in, c_in, h_in, opcode_in[1:0], arith_q, arith_c, arith_v, arith_h);
|
shift8 s8(a_in, b_in, c_in, v_in, opcode_in[2:0], shift_q, shift_c, shift_v);
|
shift8 s8(a_in, b_in, c_in, v_in, opcode_in[2:0], shift_q, shift_c, shift_v);
|
|
// DAA
|
|
assign daa_p0_r = ((a_in[3:0] > 4'h9) | h_in ) ? a_in[7:0] + 8'h6:a_in[7:0];
|
|
assign { cdaa8_r, daa8h_r } = ((daa_p0_r[7:4] > 9) || (c_in == 1'b1)) ? { 1'b0, daa_p0_r[7:4] } + 5'h6:{ 1'b0, daa_p0_r[7:4] };
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
q8 = 8'h0;
|
q8 = 8'h0;
|
c8 = c_in;
|
c8 = c_in;
|
h8 = h_in;
|
h8 = h_in;
|
v8 = v_in;
|
v8 = v_in;
|
case (opcode_in)
|
case (opcode_in)
|
|
`SEXT:
|
|
begin
|
|
q8 = a_in[7] ? 8'hff:8'h00;
|
|
end
|
`ADD, `ADC, `SUB, `SBC:
|
`ADD, `ADC, `SUB, `SBC:
|
begin
|
begin
|
q8 = arith_q;
|
q8 = arith_q;
|
c8 = arith_c;
|
c8 = arith_c;
|
v8 = arith_v;
|
v8 = arith_v;
|
h8 = arith_h;
|
h8 = arith_h;
|
end
|
end
|
|
`DEC, `INC:
|
|
begin
|
|
q8 = arith_q;
|
|
v8 = arith_v;
|
|
end
|
`COM:
|
`COM:
|
begin
|
begin
|
q8 = com8_r;
|
q8 = com8_r;
|
c8 = com8_r;
|
c8 = com8_r;
|
v8 = vcom8_r;
|
v8 = vcom8_r;
|
end
|
end
|
`NEG:
|
`NEG:
|
begin
|
begin
|
q8 = neg8_r;
|
q8 = neg8_r;
|
c8 = cneg8_r;
|
c8 = cneg8_r;
|
v8 = vneg8_r;
|
v8 = vneg8_r;
|
end
|
end
|
`LSR, `LSL, `ROL, `ROR,`ASR:
|
`LSR, `LSL, `ROL, `ROR,`ASR:
|
begin
|
begin
|
q8 = shift_q;
|
q8 = shift_q;
|
c8 = shift_c;
|
c8 = shift_c;
|
v8 = shift_v;
|
v8 = shift_v;
|
end
|
end
|
`AND, `OR, `EOR, `LD:
|
`AND, `OR, `EOR, `LD:
|
begin
|
begin
|
q8 = logic_q;
|
q8 = logic_q;
|
v8 = 1'b0;
|
v8 = 1'b0;
|
end
|
end
|
`DAA:
|
`DAA:
|
begin // V is undefined, so we don't touch it
|
begin // V is undefined, so we don't touch it
|
q8 = { daa8h_r, daa8l_r };
|
q8 = { daa8h_r, daa_p0_r[3:0] };
|
c8 = cdaa8_r;
|
c8 = cdaa8_r;
|
end
|
end
|
`ST:
|
`ST:
|
begin
|
begin
|
q8 = a_in[7:0];
|
q8 = a_in[7:0];
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
/*
|
reg [7:0] regq8;
|
reg [7:0] regq8;
|
/* register before second mux */
|
// register before second mux
|
always @(posedge clk_in)
|
always @(posedge clk_in)
|
begin
|
begin
|
regq8 <= q8;
|
regq8 <= q8;
|
end
|
end
|
|
*/
|
always @(*)
|
always @(*)
|
begin
|
begin
|
q_out[7:0] = q8; //regq8;
|
q_out[7:0] = q8; //regq8;
|
case (opcode_in)
|
CCRo = { CCR[7:6], h8, CCR[4], q8[7], (q8 == 8'h0), v8, c8 };
|
`ORCC:
|
|
CCRo = CCR | b_in[7:0];
|
|
`ANDCC:
|
|
CCRo = CCR & b_in[7:0];
|
|
default:
|
|
CCRo = { CCR[7:6], CCR[5], h8, q8[7], (q8 == 8'h0), v8, c8 };
|
|
endcase
|
|
end
|
end
|
|
|
initial
|
initial
|
begin
|
begin
|
end
|
end
|
endmodule
|
endmodule
|
|
|
/* ALU for 16 bit operations */
|
/* ALU for 16 bit operations */
|
module alu16(
|
module alu16(
|
input wire clk_in,
|
input wire clk_in,
|
input wire [15:0] a_in,
|
input wire [15:0] a_in,
|
input wire [15:0] b_in,
|
input wire [15:0] b_in,
|
input wire [7:0] CCR, /* condition code register */
|
input wire [7:0] CCR, /* condition code register */
|
input wire [4:0] opcode_in, /* ALU opcode */
|
input wire [4:0] opcode_in, /* ALU opcode */
|
|
input wire [15:0] q_mul_in,
|
output reg [15:0] q_out, /* ALU result */
|
output reg [15:0] q_out, /* ALU result */
|
output reg [3:0] CCRo
|
output reg [3:0] CCRo
|
);
|
);
|
|
|
wire c_in, n_in, v_in, z_in;
|
wire c_in, n_in, v_in, z_in;
|
assign c_in = CCR[0]; /* carry flag */
|
assign c_in = CCR[0]; /* carry flag */
|
assign n_in = CCR[3]; /* neg flag */
|
assign n_in = CCR[3]; /* neg flag */
|
assign v_in = CCR[1]; /* overflow flag */
|
assign v_in = CCR[1]; /* overflow flag */
|
assign z_in = CCR[2]; /* zero flag */
|
assign z_in = CCR[2]; /* zero flag */
|
|
|
`ifdef HD6309
|
`ifdef HD6309
|
wire [15:0] com16_r, neg16_r;
|
wire [15:0] com16_r, neg16_r;
|
wire [15:0] asr16_r, shr16_r, shl16_r, ror16_r, rol16_r, and16_r, or16_r, eor16_r;
|
wire [15:0] asr16_r, shr16_r, shl16_r, ror16_r, rol16_r, and16_r, or16_r, eor16_r;
|
|
|
wire [15:0] com16_w, neg16_w;
|
wire [15:0] com16_w, neg16_w;
|
wire [15:0] asr16_w, shr16_w, shl16_w, ror16_w, rol16_w, and16_w, or16_w, eor16_w;
|
wire [15:0] asr16_w, shr16_w, shl16_w, ror16_w, rol16_w, and16_w, or16_w, eor16_w;
|
|
|
wire ccom16_r, cneg16_r;
|
wire ccom16_r, cneg16_r;
|
wire casr16_r, cshr16_r, cshl16_r, cror16_r, crol16_r, cand16_r;
|
wire casr16_r, cshr16_r, cshl16_r, cror16_r, crol16_r, cand16_r;
|
|
|
wire vadd16_r, vadc16_r, vsub16_r, vsbc16_r, vcom16_r, vneg16_r;
|
wire vadd16_r, vadc16_r, vsub16_r, vsbc16_r, vcom16_r, vneg16_r;
|
wire vasr16_r, vshr16_r, vshl16_r, vror16_r, vrol16_r, vand16_r;
|
wire vasr16_r, vshr16_r, vshl16_r, vror16_r, vrol16_r, vand16_r;
|
|
|
assign com16_w = ~a_in[15:0];
|
assign com16_w = ~a_in[15:0];
|
assign neg16_w = 16'h0 - a_in[15:0];
|
assign neg16_w = 16'h0 - a_in[15:0];
|
assign asr16_w = { a_in[15], a_in[15:1] };
|
assign asr16_w = { a_in[15], a_in[15:1] };
|
assign shr16_w = { 1'b0, a_in[15:1] };
|
assign shr16_w = { 1'b0, a_in[15:1] };
|
assign shl16_w = { a_in[14:0], 1'b0 };
|
assign shl16_w = { a_in[14:0], 1'b0 };
|
assign ror16_w = { c_in, a_in[15:1] };
|
assign ror16_w = { c_in, a_in[15:1] };
|
assign rol16_w = { a_in[14:0], c_in };
|
assign rol16_w = { a_in[14:0], c_in };
|
assign and16_w = a_in[15:0] & b_in[15:0];
|
assign and16_w = a_in[15:0] & b_in[15:0];
|
assign or16_w = a_in[15:0] | b_in[15:0];
|
assign or16_w = a_in[15:0] | b_in[15:0];
|
assign eor16_w = a_in[15:0] ^ b_in[15:0];
|
assign eor16_w = a_in[15:0] ^ b_in[15:0];
|
|
|
// COM
|
// COM
|
assign com16_r = com16_w;
|
assign com16_r = com16_w;
|
assign ccom16_r = com16_w != 16'h0 ? 1'b1:1'b0;
|
assign ccom16_r = com16_w != 16'h0 ? 1'b1:1'b0;
|
assign vcom16_r = 1'b0;
|
assign vcom16_r = 1'b0;
|
// NEG
|
// NEG
|
assign neg16_r = neg16_w;
|
assign neg16_r = neg16_w;
|
assign vneg16_r = neg16_w[15] & (~neg16_w[14]) & (~neg16_w[13]) & (~neg16_w[12]) & (~neg16_w[11]) & (~neg16_w[10]) & (~neg16_w[9]) & (~neg16_w[8]) & (~neg16_w[7]) & (~neg16_w[6]) & (~neg16_w[5]) & (~neg16_w[4]) & (~neg16_w[3]) & (~neg16_w[2]) & (~neg16_w[1]) & (~neg16_w[0]);
|
assign vneg16_r = neg16_w[15] & (~neg16_w[14]) & (~neg16_w[13]) & (~neg16_w[12]) & (~neg16_w[11]) & (~neg16_w[10]) & (~neg16_w[9]) & (~neg16_w[8]) & (~neg16_w[7]) & (~neg16_w[6]) & (~neg16_w[5]) & (~neg16_w[4]) & (~neg16_w[3]) & (~neg16_w[2]) & (~neg16_w[1]) & (~neg16_w[0]);
|
assign cneg16_r = neg16_w[15] | neg16_w[14] | neg16_w[13] | neg16_w[12] | neg16_w[11] | neg16_w[10] | neg16_w[9] & neg16_w[8] | neg16_w[7] | neg16_w[6] | neg16_w[5] | neg16_w[4] | neg16_w[3] | neg16_w[2] | neg16_w[1] | neg16_w[0];
|
assign cneg16_r = neg16_w[15] | neg16_w[14] | neg16_w[13] | neg16_w[12] | neg16_w[11] | neg16_w[10] | neg16_w[9] & neg16_w[8] | neg16_w[7] | neg16_w[6] | neg16_w[5] | neg16_w[4] | neg16_w[3] | neg16_w[2] | neg16_w[1] | neg16_w[0];
|
// ASR
|
// ASR
|
assign asr16_r = asr16_w;
|
assign asr16_r = asr16_w;
|
assign casr16_r = a_in[0];
|
assign casr16_r = a_in[0];
|
assign vasr16_r = a_in[0] ^ asr16_w[15];
|
assign vasr16_r = a_in[0] ^ asr16_w[15];
|
// SHR
|
// SHR
|
assign shr16_r = shr16_w;
|
assign shr16_r = shr16_w;
|
assign cshr16_r = a_in[0];
|
assign cshr16_r = a_in[0];
|
assign vshr16_r = a_in[0] ^ shr16_w[15];
|
assign vshr16_r = a_in[0] ^ shr16_w[15];
|
// SHL
|
// SHL
|
assign shl16_r = shl16_w;
|
assign shl16_r = shl16_w;
|
assign cshl16_r = a_in[15];
|
assign cshl16_r = a_in[15];
|
assign vshl16_r = a_in[15] ^ shl16_w[15];
|
assign vshl16_r = a_in[15] ^ shl16_w[15];
|
// ROR
|
// ROR
|
assign ror16_r = ror16_w;
|
assign ror16_r = ror16_w;
|
assign cror16_r = a_in[0];
|
assign cror16_r = a_in[0];
|
assign vror16_r = a_in[0] ^ ror16_w[15];
|
assign vror16_r = a_in[0] ^ ror16_w[15];
|
// ROL
|
// ROL
|
assign rol16_r = rol16_w;
|
assign rol16_r = rol16_w;
|
assign crol16_r = a_in[15];
|
assign crol16_r = a_in[15];
|
assign vrol16_r = a_in[15] ^ rol16_w[15];
|
assign vrol16_r = a_in[15] ^ rol16_w[15];
|
// AND
|
// AND
|
assign and16_r = and16_w;
|
assign and16_r = and16_w;
|
assign cand16_r = c_in;
|
assign cand16_r = c_in;
|
assign vand16_r = 1'b0;
|
assign vand16_r = 1'b0;
|
// OR
|
// OR
|
assign or16_r = or16_w;
|
assign or16_r = or16_w;
|
// EOR
|
// EOR
|
assign eor16_r = eor16_w;
|
assign eor16_r = eor16_w;
|
`endif
|
`endif
|
|
|
wire [15:0] q16_mul;
|
|
|
|
mul8x8 mulu(clk_in, a_in[7:0], b_in[7:0], q16_mul);
|
|
|
|
reg c16, n16, v16, z16;
|
reg c16, n16, v16, z16;
|
reg [15:0] q16;
|
reg [15:0] q16;
|
|
|
wire [15:0] arith_q;
|
wire [15:0] arith_q;
|
wire arith_c, arith_v, arith_h;
|
wire arith_c, arith_v, arith_h;
|
|
|
arith16 a16(a_in, b_in, c_in, opcode_in[1:0], arith_q, arith_c, arith_v);
|
arith16 a16(a_in, b_in, c_in, opcode_in[1:0], arith_q, arith_c, arith_v);
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
q16 = 16'h0;
|
q16 = 16'h0;
|
c16 = c_in;
|
c16 = c_in;
|
v16 = v_in;
|
v16 = v_in;
|
case (opcode_in)
|
case (opcode_in)
|
`ADD, `ADC, `SUB, `SBC:
|
`ADD, `ADC, `SUB, `SBC:
|
begin
|
begin
|
q16 = arith_q;
|
q16 = arith_q;
|
c16 = arith_c;
|
c16 = arith_c;
|
v16 = arith_v;
|
v16 = arith_v;
|
end
|
end
|
`ifdef HD6309
|
`ifdef HD6309
|
`COM:
|
`COM:
|
begin
|
begin
|
q16 = com16_r;
|
q16 = com16_r;
|
c16 = ccom16_r;
|
c16 = ccom16_r;
|
v16 = vcom16_r;
|
v16 = vcom16_r;
|
end
|
end
|
`NEG:
|
`NEG:
|
begin
|
begin
|
q16 = neg16_r;
|
q16 = neg16_r;
|
c16 = cneg16_r;
|
c16 = cneg16_r;
|
v16 = vneg16_r;
|
v16 = vneg16_r;
|
end
|
end
|
`ASR:
|
`ASR:
|
begin
|
begin
|
q16 = asr16_r;
|
q16 = asr16_r;
|
c16 = casr16_r;
|
c16 = casr16_r;
|
v16 = vasr16_r;
|
v16 = vasr16_r;
|
end
|
end
|
`LSR:
|
`LSR:
|
begin
|
begin
|
q16 = shr16_r;
|
q16 = shr16_r;
|
c16 = cshr16_r;
|
c16 = cshr16_r;
|
v16 = vshr16_r;
|
v16 = vshr16_r;
|
end
|
end
|
`LSL:
|
`LSL:
|
begin
|
begin
|
q16 = shl16_r;
|
q16 = shl16_r;
|
c16 = cshl16_r;
|
c16 = cshl16_r;
|
v16 = vshl16_r;
|
v16 = vshl16_r;
|
end
|
end
|
`ROR:
|
`ROR:
|
begin
|
begin
|
q16 = ror16_r;
|
q16 = ror16_r;
|
c16 = cror16_r;
|
c16 = cror16_r;
|
v16 = vror16_r;
|
v16 = vror16_r;
|
end
|
end
|
`ROL:
|
`ROL:
|
begin
|
begin
|
q16 = rol16_r;
|
q16 = rol16_r;
|
c16 = crol16_r;
|
c16 = crol16_r;
|
v16 = vrol16_r;
|
v16 = vrol16_r;
|
end
|
end
|
`AND:
|
`AND:
|
begin
|
begin
|
q16 = and16_r;
|
q16 = and16_r;
|
c16 = cand16_r;
|
c16 = cand16_r;
|
v16 = vand16_r;
|
v16 = vand16_r;
|
end
|
end
|
`OR:
|
`OR:
|
begin
|
begin
|
q16 = or16_r;
|
q16 = or16_r;
|
c16 = cand16_r;
|
c16 = cand16_r;
|
v16 = vand16_r;
|
v16 = vand16_r;
|
end
|
end
|
`EOR:
|
`EOR:
|
begin
|
begin
|
q16 = eor16_r;
|
q16 = eor16_r;
|
c16 = cand16_r;
|
c16 = cand16_r;
|
v16 = vand16_r;
|
v16 = vand16_r;
|
end
|
end
|
`endif
|
`endif
|
`MUL:
|
`MUL:
|
begin
|
begin
|
q16 = q16_mul;
|
q16 = q_mul_in;
|
c16 = q16_mul[7];
|
c16 = q_mul_in[7];
|
end
|
end
|
`LD:
|
`LD:
|
begin
|
begin
|
v16 = 0;
|
v16 = 0;
|
q16 = b_in[15:0];
|
q16 = b_in[15:0];
|
end
|
end
|
`ST:
|
`ST:
|
begin
|
begin
|
q16 = a_in[15:0];
|
q16 = a_in[15:0];
|
end
|
end
|
`SEXT: // sign extend
|
`SEXT: // sign extend
|
begin
|
begin
|
q16 = { b_in[7] ? 8'hff:8'h00, b_in[7:0] };
|
q16 = { b_in[7] ? 8'hff:8'h00, b_in[7:0] };
|
end
|
end
|
`LEA:
|
`LEA:
|
begin
|
begin
|
q16 = a_in[15:0];
|
q16 = a_in[15:0];
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
reg [15:0] regq16;
|
reg [15:0] regq16;
|
reg reg_n_in, reg_z_in;
|
reg reg_n_in, reg_z_in;
|
/* register before second mux */
|
/* register before second mux */
|
always @(posedge clk_in)
|
always @(posedge clk_in)
|
begin
|
begin
|
regq16 <= q16;
|
regq16 <= q16;
|
reg_n_in <= n_in;
|
reg_n_in <= n_in;
|
reg_z_in <= z_in;
|
reg_z_in <= z_in;
|
end
|
end
|
|
|
/* Negative & zero flags */
|
/* Negative & zero flags */
|
always @(*)
|
always @(*)
|
begin
|
begin
|
n16 = q16[15];
|
n16 = q16[15];
|
z16 = q16 == 16'h0;
|
z16 = q16 == 16'h0;
|
case (opcode_in)
|
case (opcode_in)
|
`ADD:
|
`ADD:
|
begin
|
begin
|
end
|
end
|
`ADC:
|
`ADC:
|
begin
|
begin
|
end
|
end
|
`SUB: // for CMP no register result is written back
|
`SUB: // for CMP no register result is written back
|
begin
|
begin
|
end
|
end
|
`SBC:
|
`SBC:
|
begin
|
begin
|
end
|
end
|
`COM:
|
`COM:
|
begin
|
begin
|
end
|
end
|
`NEG:
|
`NEG:
|
begin
|
begin
|
end
|
end
|
`ASR:
|
`ASR:
|
begin
|
begin
|
end
|
end
|
`LSR:
|
`LSR:
|
begin
|
begin
|
end
|
end
|
`LSL:
|
`LSL:
|
begin
|
begin
|
end
|
end
|
`ROR:
|
`ROR:
|
begin
|
begin
|
end
|
end
|
`ROL:
|
`ROL:
|
begin
|
begin
|
end
|
end
|
`AND:
|
`AND:
|
begin
|
begin
|
end
|
end
|
`OR:
|
`OR:
|
begin
|
begin
|
end
|
end
|
`EOR:
|
`EOR:
|
begin
|
begin
|
end
|
end
|
`MUL:
|
`MUL:
|
begin
|
begin
|
n16 = reg_n_in;
|
n16 = reg_n_in;
|
end
|
end
|
`LD:
|
`LD:
|
begin
|
begin
|
end
|
end
|
`ST:
|
`ST:
|
begin
|
begin
|
end
|
end
|
`SEXT: // sign extend
|
`SEXT: // sign extend
|
begin
|
begin
|
n16 = reg_n_in;
|
n16 = reg_n_in;
|
z16 = reg_z_in;
|
z16 = reg_z_in;
|
end
|
end
|
`LEA: // only Z will be affected
|
`LEA: // only Z will be affected
|
begin
|
begin
|
n16 = reg_n_in;
|
n16 = reg_n_in;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
|
|
always @(*)
|
always @(*)
|
begin
|
begin
|
q_out = q16;
|
q_out = q16;
|
CCRo = { n16, z16, v16, c16 };
|
CCRo = { n16, z16, v16, c16 };
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
module mul8x8(
|
module mul8x8(
|
input wire clk_in,
|
input wire clk_in,
|
input wire [7:0] a,
|
input wire [7:0] a,
|
input wire [7:0] b,
|
input wire [7:0] b,
|
output wire [15:0] q
|
output wire [15:0] q
|
);
|
);
|
|
|
reg [15:0] pipe0, pipe1;//, pipe2, pipe3;
|
reg [15:0] pipe0, pipe1;//, pipe2, pipe3;
|
assign q = pipe1;
|
assign q = pipe1;
|
|
|
always @(posedge clk_in)
|
always @(posedge clk_in)
|
begin
|
begin
|
pipe0 <= (a[0] ? {8'h0, b}:16'h0) + (a[1] ? { 7'h0, b, 1'h0}:16'h0) +
|
pipe0 <= (a[0] ? {8'h0, b}:16'h0) + (a[1] ? { 7'h0, b, 1'h0}:16'h0) +
|
(a[2] ? {6'h0, b, 2'h0}:16'h0) + (a[3] ? { 5'h0, b, 3'h0}:16'h0);
|
(a[2] ? {6'h0, b, 2'h0}:16'h0) + (a[3] ? { 5'h0, b, 3'h0}:16'h0);
|
pipe1 <= (a[4] ? {4'h0, b, 4'h0}:16'h0) + (a[5] ? { 3'h0, b, 5'h0}:16'h0) +
|
pipe1 <= (a[4] ? {4'h0, b, 4'h0}:16'h0) + (a[5] ? { 3'h0, b, 5'h0}:16'h0) +
|
(a[6] ? {2'h0, b, 6'h0}:16'h0) + (a[7] ? { 1'h0, b, 7'h0}:16'h0) + pipe0;
|
(a[6] ? {2'h0, b, 6'h0}:16'h0) + (a[7] ? { 1'h0, b, 7'h0}:16'h0) + pipe0;
|
/*
|
/*
|
pipe0 <= (a[0] ? {8'h0, b}:16'h0) + (a[1] ? { 7'h0, b, 1'h0}:16'h0);
|
pipe0 <= (a[0] ? {8'h0, b}:16'h0) + (a[1] ? { 7'h0, b, 1'h0}:16'h0);
|
pipe1 <= (a[2] ? {6'h0, b, 2'h0}:16'h0) + (a[3] ? { 5'h0, b, 3'h0}:16'h0) + pipe0;
|
pipe1 <= (a[2] ? {6'h0, b, 2'h0}:16'h0) + (a[3] ? { 5'h0, b, 3'h0}:16'h0) + pipe0;
|
pipe2 <= (a[4] ? {4'h0, b, 4'h0}:16'h0) + (a[5] ? { 3'h0, b, 5'h0}:16'h0) + pipe1;
|
pipe2 <= (a[4] ? {4'h0, b, 4'h0}:16'h0) + (a[5] ? { 3'h0, b, 5'h0}:16'h0) + pipe1;
|
pipe3 <= (a[6] ? {2'h0, b, 6'h0}:16'h0) + (a[7] ? { 1'h0, b, 7'h0}:16'h0) + pipe2;
|
pipe3 <= (a[6] ? {2'h0, b, 6'h0}:16'h0) + (a[7] ? { 1'h0, b, 7'h0}:16'h0) + pipe2;
|
*/
|
*/
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|