1 |
21 |
eightycc |
`timescale 1ns / 1ps
|
2 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
3 |
|
|
// IBM 650 Reconstruction in Verilog (i650)
|
4 |
|
|
//
|
5 |
|
|
// This file is part of the IBM 650 Reconstruction in Verilog (i650) project
|
6 |
|
|
// http:////www.opencores.org/project,i650
|
7 |
|
|
//
|
8 |
|
|
// Description: Bi-quinary adder.
|
9 |
|
|
//
|
10 |
|
|
// Additional Comments:
|
11 |
|
|
//
|
12 |
|
|
// Copyright (c) 2015 Robert Abeles
|
13 |
|
|
//
|
14 |
|
|
// This source file is free software; you can redistribute it
|
15 |
|
|
// and/or modify it under the terms of the GNU Lesser General
|
16 |
|
|
// Public License as published by the Free Software Foundation;
|
17 |
|
|
// either version 2.1 of the License, or (at your option) any
|
18 |
|
|
// later version.
|
19 |
|
|
//
|
20 |
|
|
// This source is distributed in the hope that it will be
|
21 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
22 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
23 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more
|
24 |
|
|
// details.
|
25 |
|
|
//
|
26 |
|
|
// You should have received a copy of the GNU Lesser General
|
27 |
|
|
// Public License along with this source; if not, download it
|
28 |
|
|
// from http://www.opencores.org/lgpl.shtml
|
29 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
30 |
|
|
`include "defines.v"
|
31 |
|
|
|
32 |
|
|
module adder (
|
33 |
|
|
input rst,
|
34 |
22 |
eightycc |
input ap, bp, dp,
|
35 |
|
|
dxu, dx, d0u, d1, d1l, d10, d10u, wl,
|
36 |
21 |
eightycc |
input [0:6] entry_a, entry_b,
|
37 |
|
|
input tlu_on, left_shift_off, left_shift_on,
|
38 |
|
|
input no_carry_insert, no_carry_blank, carry_insert, carry_blank,
|
39 |
|
|
input zero_insert,
|
40 |
|
|
|
41 |
|
|
input error_reset,
|
42 |
|
|
input quotient_digit_on, overflow_stop_sw, overflow_sense_sw,
|
43 |
|
|
input mult_div_off, dist_true_add_gate, acc_true_add_latch,
|
44 |
|
|
input shift_overflow,
|
45 |
|
|
|
46 |
|
|
output reg[0:6] adder_out,
|
47 |
22 |
eightycc |
output reg carry_test, no_carry_test, d0l_carry_sig, overflow_stop,
|
48 |
21 |
eightycc |
|
49 |
22 |
eightycc |
output overflow_light, overflow_sense_sig
|
50 |
21 |
eightycc |
);
|
51 |
|
|
|
52 |
|
|
//-----------------------------------------------------------------------------
|
53 |
22 |
eightycc |
// The 650 bi-quinary adder accepts its inputs early (i.e., one clock ahead),
|
54 |
|
|
// producing a result during the next digit time. This implementation retains
|
55 |
|
|
// sum and carries in _hold flip-flops, the 650 used other tricky means.
|
56 |
21 |
eightycc |
//-----------------------------------------------------------------------------
|
57 |
|
|
reg [0:6] sum_hold;
|
58 |
|
|
reg carry_hold, no_carry_hold, carry_test_hold, no_carry_test_hold;
|
59 |
22 |
eightycc |
reg reset_ctl;
|
60 |
|
|
reg carry, no_carry;
|
61 |
21 |
eightycc |
|
62 |
|
|
//-----------------------------------------------------------------------------
|
63 |
|
|
// Bi-quinary adder, forms biq sum of two biq digits with carry in and out.
|
64 |
22 |
eightycc |
// Hand captured from 650 patent fig. 68.
|
65 |
|
|
//
|
66 |
|
|
// By design, this logic produces a sum of all zeroes with zero carry_out and
|
67 |
|
|
// no_carry_out whenever entry_a or entry_b or both carry and no_carry are
|
68 |
|
|
// zero.
|
69 |
21 |
eightycc |
//-----------------------------------------------------------------------------
|
70 |
|
|
wire b0_and_b5 = (entry_a[`biq_b0] & entry_b[`biq_b5])
|
71 |
|
|
| (entry_a[`biq_b5] & entry_b[`biq_b0]);
|
72 |
|
|
wire q4_a_or_b = entry_a[`biq_q4] | entry_b[`biq_q4];
|
73 |
|
|
wire q3_a_or_b = entry_a[`biq_q3] | entry_b[`biq_q3];
|
74 |
|
|
wire q2_a_or_b = entry_a[`biq_q2] | entry_b[`biq_q2];
|
75 |
|
|
wire q1_a_or_b = entry_a[`biq_q1] | entry_b[`biq_q1];
|
76 |
|
|
wire q0_a_or_b = entry_a[`biq_q0] | entry_b[`biq_q0];
|
77 |
|
|
wire qsum_8 = entry_a[`biq_q4] & entry_b[`biq_q4];
|
78 |
|
|
wire qsum_7 = q4_a_or_b & q3_a_or_b;
|
79 |
|
|
wire qsum_6 = (entry_a[`biq_q3] & entry_b[`biq_q3])
|
80 |
|
|
| (q4_a_or_b & q2_a_or_b);
|
81 |
|
|
wire qsum_5 = (q4_a_or_b & q3_a_or_b)
|
82 |
|
|
| (q3_a_or_b & q2_a_or_b);
|
83 |
|
|
wire qsum_4 = (entry_a[`biq_q2] & entry_b[`biq_q2])
|
84 |
|
|
| (q3_a_or_b & q1_a_or_b)
|
85 |
|
|
| (q4_a_or_b & q0_a_or_b);
|
86 |
|
|
wire qsum_3 = (q3_a_or_b & q0_a_or_b)
|
87 |
|
|
| (q2_a_or_b & q1_a_or_b);
|
88 |
|
|
wire qsum_2 = (entry_a[`biq_q1] & entry_b[`biq_q1])
|
89 |
|
|
| (q2_a_or_b & q0_a_or_b);
|
90 |
|
|
wire qsum_1 = q1_a_or_b & q0_a_or_b;
|
91 |
|
|
wire qsum_0 = (entry_a[`biq_q0] & entry_b[`biq_q0]);
|
92 |
|
|
wire three_or_eight = qsum_3 | qsum_8;
|
93 |
|
|
wire two_or_seven = qsum_2 | qsum_7;
|
94 |
|
|
wire six_or_one = qsum_6 | qsum_1;
|
95 |
|
|
wire zero_or_five = qsum_0 | qsum_5;
|
96 |
|
|
wire five_and_up = qsum_8 | qsum_7 | qsum_6 | qsum_5 | (qsum_4 & carry);
|
97 |
|
|
wire below_five = (qsum_4 & no_carry) | qsum_3 | qsum_2 | qsum_1 | qsum_0;
|
98 |
|
|
wire b5_carry = five_and_up & entry_a[`biq_b5] & entry_b[`biq_b5];
|
99 |
|
|
wire b5_no_carry = (five_and_up & entry_a[`biq_b0] & entry_b[`biq_b0])
|
100 |
|
|
| (below_five & b0_and_b5);
|
101 |
|
|
wire b0_carry = (five_and_up & b0_and_b5)
|
102 |
|
|
| (below_five & entry_a[`biq_b5] & entry_b[`biq_b5]);
|
103 |
|
|
wire b0_no_carry = below_five & entry_a[`biq_b0] & entry_b[`biq_b0];
|
104 |
|
|
wire sum_q0 = (carry & qsum_4) | (no_carry & zero_or_five);
|
105 |
|
|
wire sum_q1 = (carry & zero_or_five) | (no_carry & six_or_one);
|
106 |
|
|
wire sum_q2 = (carry & six_or_one) | (no_carry & two_or_seven);
|
107 |
|
|
wire sum_q3 = (carry & two_or_seven) | (no_carry & three_or_eight);
|
108 |
|
|
wire sum_q4 = (carry & three_or_eight) | (no_carry & qsum_4);
|
109 |
|
|
wire sum_b0 = b0_no_carry | b0_carry;
|
110 |
|
|
wire sum_b5 = b5_no_carry | b5_carry;
|
111 |
|
|
wire [0:6] sum_out = {sum_b5, sum_b0, sum_q4, sum_q3, sum_q2, sum_q1, sum_q0};
|
112 |
|
|
wire carry_out = b0_carry | b5_carry;
|
113 |
|
|
wire no_carry_out = b0_no_carry | b5_no_carry;
|
114 |
22 |
eightycc |
|
115 |
21 |
eightycc |
//-----------------------------------------------------------------------------
|
116 |
22 |
eightycc |
// A : Supply sum and carries from previous digit time
|
117 |
21 |
eightycc |
//-----------------------------------------------------------------------------
|
118 |
22 |
eightycc |
always @(posedge ap)
|
119 |
21 |
eightycc |
if (rst) begin
|
120 |
22 |
eightycc |
adder_out <= `biq_blank;
|
121 |
|
|
carry_test <= 0;
|
122 |
21 |
eightycc |
no_carry_test <= 0;
|
123 |
22 |
eightycc |
carry <= 0;
|
124 |
|
|
no_carry <= 0;
|
125 |
21 |
eightycc |
end else begin
|
126 |
22 |
eightycc |
adder_out <= sum_hold;
|
127 |
|
|
carry_test <= carry_test_hold;
|
128 |
21 |
eightycc |
no_carry_test <= no_carry_test_hold;
|
129 |
22 |
eightycc |
carry <= carry_hold;
|
130 |
|
|
no_carry <= no_carry_hold;
|
131 |
21 |
eightycc |
end
|
132 |
|
|
|
133 |
22 |
eightycc |
wire reset_ctl_on_p = (wl & d10 & left_shift_off) | (dxu & left_shift_on);
|
134 |
|
|
wire reset_ctl_off_p = tlu_on | (d1 & left_shift_on) | (d0u & left_shift_off);
|
135 |
|
|
always @(posedge ap)
|
136 |
21 |
eightycc |
if (rst) begin
|
137 |
22 |
eightycc |
reset_ctl <= 0;
|
138 |
|
|
end else if (reset_ctl_on_p) begin
|
139 |
|
|
reset_ctl <= 1;
|
140 |
|
|
end else if (reset_ctl_off_p) begin
|
141 |
|
|
reset_ctl <= 0;
|
142 |
|
|
end;
|
143 |
|
|
|
144 |
|
|
wire overflow = shift_overflow
|
145 |
|
|
| (carry_test & d10u & dist_true_add_gate
|
146 |
|
|
& acc_true_add_latch & mult_div_off);
|
147 |
|
|
assign overflow_sense_sig = overflow & overflow_sense_sw;
|
148 |
|
|
wire overflow_stop_p = (d1l & carry_test & quotient_digit_on)
|
149 |
|
|
| (overflow & overflow_stop_sw);
|
150 |
|
|
assign overflow_light = overflow_stop;
|
151 |
|
|
always @(posedge bp)
|
152 |
|
|
if (rst) begin
|
153 |
|
|
overflow_stop <= 1;
|
154 |
|
|
end else if (error_reset) begin
|
155 |
|
|
overflow_stop <= 0;
|
156 |
|
|
end else if (overflow_stop_p) begin
|
157 |
|
|
overflow_stop <= 1;
|
158 |
|
|
end;
|
159 |
|
|
|
160 |
|
|
always @(posedge dp)
|
161 |
|
|
if (rst) d0l_carry_sig <= 0;
|
162 |
|
|
else if (wl & d1) d0l_carry_sig <= 0;
|
163 |
|
|
else if (wl & dx & carry_out) d0l_carry_sig <= 1;
|
164 |
|
|
|
165 |
|
|
always @(posedge dp)
|
166 |
|
|
if (rst) begin
|
167 |
21 |
eightycc |
sum_hold <= `biq_blank;
|
168 |
|
|
carry_hold <= 0;
|
169 |
|
|
no_carry_hold <= 0;
|
170 |
|
|
carry_test_hold <= 0;
|
171 |
|
|
no_carry_test_hold <= 0;
|
172 |
|
|
end else begin
|
173 |
22 |
eightycc |
sum_hold <= zero_insert? `biq_0
|
174 |
|
|
: reset_ctl? sum_hold
|
175 |
21 |
eightycc |
: sum_out;
|
176 |
22 |
eightycc |
carry_hold <= (reset_ctl | carry_blank)? 1'b0
|
177 |
21 |
eightycc |
: carry_insert? 1'b1
|
178 |
|
|
: carry_out;
|
179 |
22 |
eightycc |
no_carry_hold <= (reset_ctl | no_carry_blank)? 1'b0
|
180 |
21 |
eightycc |
: no_carry_insert? 1'b1
|
181 |
|
|
: no_carry_out;
|
182 |
22 |
eightycc |
carry_test_hold <= reset_ctl? 1'b0 : carry_out;
|
183 |
|
|
no_carry_test_hold <= reset_ctl? 1'b0 : no_carry_out;
|
184 |
|
|
end;
|
185 |
21 |
eightycc |
|
186 |
|
|
|
187 |
|
|
endmodule
|