1 |
27 |
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: Control commutator.
|
9 |
|
|
//
|
10 |
|
|
// Additional Comments: See US 2959351, Fig. 81.
|
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 ctl_commutator (
|
33 |
|
|
input rst,
|
34 |
|
|
input ap, bp, cp, dp,
|
35 |
|
|
input dx, d1, d3, d7, d9, d10,
|
36 |
|
|
input dxu, dxl,
|
37 |
|
|
input wu, wl,
|
38 |
|
|
|
39 |
|
|
input invalid_addr,
|
40 |
|
|
input man_prog_reset, run_control_sw, program_start_sw, manual_ri_storage_sw,
|
41 |
|
|
input manual_ro_storage_sw, manual_error_reset_sw,
|
42 |
|
|
input half_or_pgm_stop,
|
43 |
|
|
|
44 |
|
|
input prog_restart, error_stop, error_sense_restart, arith_restart,
|
45 |
|
|
input stop_code, code_69, start_10s_60s, end_shift_cntrl, tlu_on,
|
46 |
|
|
input end_of_operation, turn_on_op_intlk, decode_restarts,
|
47 |
|
|
|
48 |
|
|
input use_d_for_i, dist_back_signal,
|
49 |
|
|
input error_stop_ed0u, divide_overflow_stop,
|
50 |
|
|
exceed_address_or_stor_select_light,
|
51 |
|
|
input [0:6] opreg_t, opreg_u,
|
52 |
|
|
input addr_no_800x, addr_8001,
|
53 |
|
|
input dynamic_addr_hit,
|
54 |
|
|
|
55 |
|
|
output reg restart_a, restart_b,
|
56 |
|
|
output reg i_alt, d_alt,
|
57 |
|
|
output reg manual_stop_start, run_latch,
|
58 |
|
|
output reg enable_ri,
|
59 |
|
|
output manual_ri_storage, manual_ro_storage,
|
60 |
|
|
output reg manual_start_ri_dist_latch,
|
61 |
|
|
output i_control_pulse,
|
62 |
|
|
output i_control, d_control, d_control_no_8001,
|
63 |
|
|
output reg start_ri,
|
64 |
|
|
output reg rips_ri_dist_intlk_a, rips_ri_dist_intlk_b, op_intlk, single_intlk,
|
65 |
|
|
output rips, ri_dist,
|
66 |
|
|
output reg acc_to_dist_ri_latch,
|
67 |
|
|
output start_acc_to_dist_ri, end_acc_to_dist_ri,
|
68 |
|
|
output reg rigs,
|
69 |
|
|
output end_rigs
|
70 |
|
|
);
|
71 |
|
|
|
72 |
|
|
//-----------------------------------------------------------------------------
|
73 |
|
|
// Restart control
|
74 |
|
|
//-----------------------------------------------------------------------------
|
75 |
|
|
wire ri_dist_restart, arith_codes_restart;
|
76 |
|
|
assign all_restarts = decode_restarts
|
77 |
|
|
| prog_restart
|
78 |
|
|
| ri_dist_restart
|
79 |
|
|
| arith_codes_restart;
|
80 |
|
|
|
81 |
|
|
always @(posedge ap)
|
82 |
|
|
if (rst) begin
|
83 |
|
|
restart_a <= 0;
|
84 |
|
|
end else if (~invalid_addr & all_restarts & ~restart_b) begin
|
85 |
|
|
restart_a <= 1;
|
86 |
|
|
end else if (man_prog_reset | (restart_b & dx)) begin
|
87 |
|
|
restart_a <= 0;
|
88 |
|
|
end;
|
89 |
|
|
|
90 |
|
|
always @(posedge ap)
|
91 |
|
|
if (rst) begin
|
92 |
|
|
restart_b <= 0;
|
93 |
|
|
end else if (restart_a & dx) begin
|
94 |
|
|
restart_b <= 1;
|
95 |
|
|
end else if (restart_b & dx) begin
|
96 |
|
|
restart_b <= 0;
|
97 |
|
|
end;
|
98 |
|
|
|
99 |
|
|
//-----------------------------------------------------------------------------
|
100 |
|
|
// I / D alternation
|
101 |
|
|
//-----------------------------------------------------------------------------
|
102 |
|
|
assign run_control = run_control_sw & run_latch;
|
103 |
|
|
assign d_control_no_8001 = opreg_t[`biq_q1] & d_control & ~addr_8001;
|
104 |
|
|
wire d_control_8001 = opreg_t[`biq_q1] & d_control & addr_8001;
|
105 |
|
|
assign i_control = i_alt & ~restart_b & run_latch;
|
106 |
|
|
assign d_control = d_alt & ~op_intlk & ~restart_b & run_control;
|
107 |
|
|
|
108 |
|
|
always @(posedge dp)
|
109 |
|
|
if (rst) begin
|
110 |
|
|
i_alt <= 0;
|
111 |
|
|
d_alt <= 1;
|
112 |
|
|
end else if (man_prog_reset | use_d_for_i ) begin
|
113 |
|
|
i_alt <= 0;
|
114 |
|
|
d_alt <= 1;
|
115 |
|
|
end else if (dx & restart_b & run_control) begin
|
116 |
|
|
i_alt <= d_alt;
|
117 |
|
|
d_alt <= i_alt;
|
118 |
|
|
end;
|
119 |
|
|
|
120 |
|
|
//-----------------------------------------------------------------------------
|
121 |
|
|
// 8uS i_control_pulse is emited at the rising edge of (ap & i_control)
|
122 |
|
|
//-----------------------------------------------------------------------------
|
123 |
|
|
digit_pulse i_ctl (rst, ap, (i_control | manual_ro_storage | d_control_no_8001), 1'b0, i_control_pulse);
|
124 |
|
|
|
125 |
|
|
//-----------------------------------------------------------------------------
|
126 |
|
|
// CPU running control
|
127 |
|
|
//-----------------------------------------------------------------------------
|
128 |
|
|
assign manual_ri_storage = manual_ri_storage_sw & run_latch;
|
129 |
|
|
assign manual_ro_storage = manual_ro_storage_sw & run_latch;
|
130 |
|
|
|
131 |
|
|
always @(posedge ap)
|
132 |
|
|
if (rst) begin
|
133 |
|
|
manual_stop_start <= 0;
|
134 |
|
|
end else if (dxl) begin
|
135 |
|
|
manual_stop_start <= 0;
|
136 |
|
|
end else if (program_start_sw & dxu & ~error_stop) begin
|
137 |
|
|
manual_stop_start <= 1;
|
138 |
|
|
end;
|
139 |
|
|
|
140 |
|
|
wire turn_off_run_latch = half_or_pgm_stop & ~invalid_addr & all_restarts & ~restart_b;
|
141 |
|
|
|
142 |
|
|
always @(posedge bp)
|
143 |
|
|
if (rst) begin
|
144 |
|
|
run_latch <= 0;
|
145 |
|
|
end else if ( (manual_ri_storage & end_rigs)
|
146 |
|
|
| (manual_ro_storage & dist_back_signal)
|
147 |
|
|
| manual_error_reset_sw
|
148 |
|
|
| error_stop_ed0u
|
149 |
|
|
| divide_overflow_stop
|
150 |
|
|
| exceed_address_or_stor_select_light
|
151 |
|
|
| stop_code
|
152 |
|
|
| turn_off_run_latch ) begin
|
153 |
|
|
run_latch <= 0;
|
154 |
|
|
end else if (manual_stop_start | error_sense_restart) begin
|
155 |
|
|
run_latch <= 1;
|
156 |
|
|
end;
|
157 |
|
|
|
158 |
|
|
|
159 |
|
|
//-----------------------------------------------------------------------------
|
160 |
|
|
// Accumulator to distributor read-in control
|
161 |
|
|
//-----------------------------------------------------------------------------
|
162 |
|
|
|
163 |
|
|
//-----------------------------------------------------------------------------
|
164 |
|
|
// Predicates for accumulator to distributor read-in. Instructions decoded:
|
165 |
|
|
// 20 STL Store Lower in Memory
|
166 |
|
|
// 21 STU Store Upper in Memory
|
167 |
|
|
// 22 STDA Store Lower Data Address
|
168 |
|
|
// 23 STIA Store Lower Inst Address
|
169 |
|
|
// 24 STD Store Distributor
|
170 |
|
|
//-----------------------------------------------------------------------------
|
171 |
|
|
assign op_20_24_d_p = opreg_t[`biq_b0] & opreg_t[`biq_q2] & opreg_u[`biq_q0] & d_control;
|
172 |
|
|
|
173 |
|
|
assign op_20_24_d_intlk_p = op_20_24_d_p & ~single_intlk;
|
174 |
|
|
|
175 |
|
|
assign op_20_d_intlk_d10u_p = op_20_24_d_intlk_p & opreg_u[`biq_q0] & wu & d10;
|
176 |
|
|
assign op_21_d_intlk_d10l_p = op_20_24_d_intlk_p & opreg_u[`biq_q1] & wl & d10;
|
177 |
|
|
assign op_22_d_intlk_d3l_p = op_20_24_d_intlk_p & opreg_u[`biq_q2] & wl & d3;
|
178 |
|
|
assign op_23_d_intlk_dxl_p = op_20_24_d_intlk_p & opreg_u[`biq_q3] & wl & dx;
|
179 |
|
|
assign acc_to_dist_ri_on_p = op_20_d_intlk_d10u_p | op_21_d_intlk_d10l_p | op_22_d_intlk_d3l_p | op_23_d_intlk_dxl_p;
|
180 |
|
|
|
181 |
|
|
assign op_20_d_intlk_d9_p = op_20_24_d_intlk_p & opreg_u[`biq_q0] & d9;
|
182 |
|
|
|
183 |
|
|
assign op_21_d_intlk_d9u_p = op_20_24_d_intlk_p & opreg_u[`biq_q1] & wu & d9;
|
184 |
|
|
|
185 |
|
|
assign op_22_d_intlk_d7_p = op_20_24_d_intlk_p & opreg_u[`biq_q2] & d7;
|
186 |
|
|
|
187 |
|
|
assign op_23_d_intlk_d3_p = op_20_24_d_intlk_p & opreg_u[`biq_q3] & d3;
|
188 |
|
|
assign acc_to_dist_ri_off_p = op_20_d_intlk_d9_p | op_21_d_intlk_d9u_p | op_22_d_intlk_d7_p | op_23_d_intlk_d3_p;
|
189 |
|
|
|
190 |
|
|
assign op_24_d_intlk_p = op_20_24_d_intlk_p & opreg_u[`biq_q4];
|
191 |
|
|
|
192 |
|
|
always @(posedge bp)
|
193 |
|
|
if (rst) begin
|
194 |
|
|
acc_to_dist_ri_latch <= 0;
|
195 |
|
|
end else if (acc_to_dist_ri_off_p) begin
|
196 |
|
|
acc_to_dist_ri_latch <= 0;
|
197 |
|
|
end else if (acc_to_dist_ri_on_p) begin
|
198 |
|
|
acc_to_dist_ri_latch <= 1;
|
199 |
|
|
end;
|
200 |
|
|
digit_pulse a2d_ri_on (rst, cp, acc_to_dist_ri_latch, 1'b0, start_acc_to_dist_ri);
|
201 |
|
|
digit_pulse a2d_ri_off(rst, cp, ~acc_to_dist_ri_latch, 1'b1, end_acc_to_dist_ri);
|
202 |
|
|
|
203 |
|
|
//-----------------------------------------------------------------------------
|
204 |
|
|
// Manual read-in control
|
205 |
|
|
//-----------------------------------------------------------------------------
|
206 |
|
|
wire man_start_ri_dist_sig;
|
207 |
|
|
digit_pulse ri_dist_sig (rst, ap, manual_ri_storage, 1'b0, man_start_ri_dist_sig);
|
208 |
|
|
|
209 |
|
|
always @(posedge bp)
|
210 |
|
|
if (rst) begin
|
211 |
|
|
manual_start_ri_dist_latch <= 0;
|
212 |
|
|
end
|
213 |
|
|
|
214 |
|
|
//-----------------------------------------------------------------------------
|
215 |
|
|
// Read-in control
|
216 |
|
|
//-----------------------------------------------------------------------------
|
217 |
|
|
always @(posedge dp)
|
218 |
|
|
if (rst) begin
|
219 |
|
|
enable_ri <= 0;
|
220 |
|
|
end else if (man_prog_reset | start_ri) begin
|
221 |
|
|
enable_ri <= 0;
|
222 |
|
|
end else if ( start_acc_to_dist_ri
|
223 |
|
|
| man_start_ri_dist_sig
|
224 |
|
|
| i_control_pulse
|
225 |
|
|
| op_24_d_intlk_p ) begin
|
226 |
|
|
enable_ri <= 1;
|
227 |
|
|
end;
|
228 |
|
|
|
229 |
|
|
always @(posedge cp)
|
230 |
|
|
if (rst) begin
|
231 |
|
|
start_ri <= 0;
|
232 |
|
|
end else if (d1) begin
|
233 |
|
|
start_ri <= 0;
|
234 |
|
|
end else if (d9 & addr_no_800x & enable_ri & dynamic_addr_hit) begin
|
235 |
|
|
start_ri <= 1;
|
236 |
|
|
end;
|
237 |
|
|
|
238 |
|
|
//-----------------------------------------------------------------------------
|
239 |
|
|
// Read-in general storage
|
240 |
|
|
//-----------------------------------------------------------------------------
|
241 |
|
|
always @(posedge bp)
|
242 |
|
|
if (rst) begin
|
243 |
|
|
rigs <= 0;
|
244 |
|
|
end else if (d10 & ~start_ri) begin
|
245 |
|
|
rigs <= 0;
|
246 |
|
|
end else if ((d10 & manual_ri_storage & start_ri) | (d10 & op_20_24_d_p & start_ri)) begin
|
247 |
|
|
rigs <= 1;
|
248 |
|
|
end;
|
249 |
|
|
|
250 |
|
|
digit_pulse end_rigs_sig (rst, cp, ~rigs, 1'b1, end_rigs);
|
251 |
|
|
|
252 |
|
|
//-----------------------------------------------------------------------------
|
253 |
|
|
// Read-in distributor
|
254 |
|
|
//-----------------------------------------------------------------------------
|
255 |
|
|
assign ri_dist = (dx & start_ri & ~rips_ri_dist_intlk_b & (manual_ro_storage | d_control_no_8001)) | man_start_ri_dist_sig;
|
256 |
|
|
assign ri_dist_restart = dist_back_sig_latch & end_rigs;
|
257 |
|
|
reg dist_back_sig_latch;
|
258 |
|
|
|
259 |
|
|
always @(posedge bp)
|
260 |
|
|
if (rst) begin
|
261 |
|
|
dist_back_sig_latch <= 0;
|
262 |
|
|
end else if (man_prog_reset | dist_back_signal) begin
|
263 |
|
|
dist_back_sig_latch <= 1;
|
264 |
|
|
end else if (ri_dist | start_acc_to_dist_ri) begin
|
265 |
|
|
dist_back_sig_latch <= 0;
|
266 |
|
|
end;
|
267 |
|
|
|
268 |
|
|
//-----------------------------------------------------------------------------
|
269 |
|
|
// Read-in program step
|
270 |
|
|
//-----------------------------------------------------------------------------
|
271 |
|
|
assign rips = dx & start_ri & i_control & ~rips_ri_dist_intlk_b;
|
272 |
|
|
|
273 |
|
|
//-----------------------------------------------------------------------------
|
274 |
|
|
// Enable arithmetic codes latch
|
275 |
|
|
//-----------------------------------------------------------------------------
|
276 |
|
|
reg enable_arith_codes_latch;
|
277 |
|
|
wire d_control_8001_sig;
|
278 |
|
|
|
279 |
|
|
digit_pulse ac_on_sig (rst, ap, d_control_8001, 1'b0, d_control_8001_sig);
|
280 |
|
|
|
281 |
|
|
always @(posedge bp)
|
282 |
|
|
if (rst) begin
|
283 |
|
|
enable_arith_codes_latch <= 0;
|
284 |
|
|
end else if ((arith_restart & dist_back_sig_latch) | code_69) begin
|
285 |
|
|
enable_arith_codes_latch <= 0;
|
286 |
|
|
end else if (d_control_8001_sig | (d_control_no_8001 & dist_back_signal)) begin
|
287 |
|
|
enable_arith_codes_latch <= 1;
|
288 |
|
|
end;
|
289 |
|
|
|
290 |
|
|
digit_pulse ac_restart (rst, cp, ~arith_restart, 1'b1, arith_codes_restart);
|
291 |
|
|
|
292 |
|
|
//-----------------------------------------------------------------------------
|
293 |
|
|
// Interlocks
|
294 |
|
|
//-----------------------------------------------------------------------------
|
295 |
|
|
|
296 |
|
|
// RIPS-RID interlock A and B latches: These latches provide an interlock to
|
297 |
|
|
// insure that only one RIPS or storage to distributor RI signal will be
|
298 |
|
|
// developed on any commutator half cycle. Interlock B must be off to obtain
|
299 |
|
|
// either RIPS or storage to distributor RI. Either signal when developed
|
300 |
|
|
// turns on interlock A which turns off with the next D1 and turns interlock
|
301 |
|
|
// B on. With interlock B on, one of the conditions necessary for RIPS or
|
302 |
|
|
// storage to distributor RI is removed. Interlock B is reset by any restart,
|
303 |
|
|
// program reset, or manual RI.
|
304 |
|
|
always @(posedge bp)
|
305 |
|
|
if (rst) begin
|
306 |
|
|
rips_ri_dist_intlk_a <= 0;
|
307 |
|
|
rips_ri_dist_intlk_b <= 0;
|
308 |
|
|
end else begin
|
309 |
|
|
if (d1) begin
|
310 |
|
|
rips_ri_dist_intlk_a <= 0;
|
311 |
|
|
end else if (ri_dist | rips) begin
|
312 |
|
|
rips_ri_dist_intlk_a <= 1;
|
313 |
|
|
end
|
314 |
|
|
if (all_restarts | man_prog_reset) begin
|
315 |
|
|
rips_ri_dist_intlk_b <= 0;
|
316 |
|
|
end else if (d1 & rips_ri_dist_intlk_a) begin
|
317 |
|
|
rips_ri_dist_intlk_b <= 1;
|
318 |
|
|
end
|
319 |
|
|
end;
|
320 |
|
|
|
321 |
|
|
// Operation interlock latch (791, Fig 81i): The off output of this latch is
|
322 |
|
|
// one of the conditions needed for the development of the "D" control signal
|
323 |
|
|
// and for the turning of the start RI latch on an 800X address. The arith-
|
324 |
|
|
// metic and shift operations make use of the accumulator and distributor and
|
325 |
|
|
// may require several word times for their completion. The restart signal on
|
326 |
|
|
// these operations is developed during the first operation word interval.
|
327 |
|
|
// Thus the commutator can advance concurrently with the performance of the
|
328 |
|
|
// operation and allow the next instruction to be located, read into program
|
329 |
|
|
// step storage, restart to "D" and transfer the new Op. code and "D" address
|
330 |
|
|
// to the registers. At this point further advance of the commutator cannot
|
331 |
|
|
// be allowed until the preceeding operation is completed. This interlocking
|
332 |
|
|
// is done by allowing arithmetic and shift signals to turn on the operation
|
333 |
|
|
// interlock latch, removing one of the necessary conditions for "D" control.
|
334 |
|
|
// When an arithmetic or shift instruction has an 800X "I" address, the
|
335 |
|
|
// location of the next instruction must be prevented until the preceeding
|
336 |
|
|
// operation is complete, since the instruction itself is in the process of
|
337 |
|
|
// being developed by the operation. This is accomplished by the Op.
|
338 |
|
|
// interlock off condition necessary for turning on the start RI.
|
339 |
|
|
wire set_op_intlk_sig;
|
340 |
|
|
wire set_op_intlk_p = wl & opreg_t[`biq_q1] & enable_arith_codes_latch & ~single_intlk;
|
341 |
|
|
digit_pulse op_ilk_sig (rst, ap, ~set_op_intlk_p, 1'b1, set_op_intlk_sig);
|
342 |
|
|
always @(posedge bp)
|
343 |
|
|
if (rst) begin
|
344 |
|
|
op_intlk <= 0;
|
345 |
|
|
end else if (man_prog_reset | end_of_operation) begin
|
346 |
|
|
op_intlk <= 0;
|
347 |
|
|
end else if (set_op_intlk_sig | turn_on_op_intlk) begin
|
348 |
|
|
op_intlk <= 1;
|
349 |
|
|
end;
|
350 |
|
|
|
351 |
|
|
// Single interlock latch (857, Fig 81i): This latch when off, conditions
|
352 |
|
|
// the development of arithmetic code signals, store code signals, shift
|
353 |
|
|
// code signals and TLU signals. When any of these signals are developed
|
354 |
|
|
// they cause the single interlock latch to be turned on thus preventing
|
355 |
|
|
// further development of the same signals during successive word intervals
|
356 |
|
|
// of the same commutator half cycle. The latch is turned off by any
|
357 |
|
|
// restart or by program reset.
|
358 |
|
|
wire single_intlk_set_p = (enable_ri & op_24_d_intlk_p)
|
359 |
|
|
| start_10s_60s
|
360 |
|
|
| end_shift_cntrl
|
361 |
|
|
| end_acc_to_dist_ri
|
362 |
|
|
| tlu_on;
|
363 |
|
|
always @(posedge dp)
|
364 |
|
|
if (rst) begin
|
365 |
|
|
single_intlk <= 0;
|
366 |
|
|
end else if (man_prog_reset | all_restarts) begin
|
367 |
|
|
single_intlk <= 0;
|
368 |
|
|
end else if (single_intlk_set_p) begin
|
369 |
|
|
single_intlk <= 1;
|
370 |
|
|
end;
|
371 |
|
|
|
372 |
|
|
endmodule
|