URL
https://opencores.org/ocsvn/i650/i650/trunk
Subversion Repositories i650
[/] [i650/] [trunk/] [rtl/] [operator_ctl.v] - Rev 12
Go to most recent revision | Compare with Previous | Blame | View Log
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // IBM 650 Reconstruction in Verilog (i650) // // This file is part of the IBM 650 Reconstruction in Verilog (i650) project // http:////www.opencores.org/project,i650 // // Description: Operator console and external control interface. // // Additional Comments: See US 2959351, Fig. 75, 76, 76 and 77. Also implements // a simple command-based control interface. // // Copyright (c) 2015 Robert Abeles // // This source file is free software; you can redistribute it // and/or modify it under the terms of the GNU Lesser General // Public License as published by the Free Software Foundation; // either version 2.1 of the License, or (at your option) any // later version. // // This source is distributed in the hope that it will be // useful, but WITHOUT ANY WARRANTY; without even the implied // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the GNU Lesser General Public License for more // details. // // You should have received a copy of the GNU Lesser General // Public License along with this source; if not, download it // from http://www.opencores.org/lgpl.shtml ////////////////////////////////////////////////////////////////////////////////// `include "defines.v" module operator_ctl ( input rst, clk, input ap, dp, input dx, d0, d1, d2, d3, d4, d5, d6, d10, input wu, hp, input [0:3] early_idx, ontime_idx, input [0:6] cmd_digit_in, io_buffer_in, gs_in, input [0:5] command, output reg[0:6] data_out, addr_out, console_out, output reg console_to_addr, output reg[0:14] gs_ram_addr, output reg read_gs, write_gs, output reg pgm_start, pgm_stop, err_reset, err_sense_reset, output run_control, half_or_pgm_stop, ri_storage, ro_storage, storage_control, output reg man_pgm_reset, man_acc_reset, set_8000, reset_8000, hard_reset, output reg[0:6] cmd_digit_out, output reg busy, digit_ready, output reg punch_card, read_card, card_digit_ready ); //----------------------------------------------------------------------------- // Operator console switch settings and their control signals. //----------------------------------------------------------------------------- reg pgm_sw_stop, pgm_sw_run, half_cycle_sw_run, half_cycle_sw_half, ctl_sw_addr_stop, ctl_sw_run, ctl_sw_manual, disp_sw_lacc, disp_sw_uacc, disp_sw_dist, disp_sw_pgm, disp_sw_ri, disp_sw_ro, ovflw_sw_stop, ovflw_sw_sense, err_sw_stop, err_sw_sense; reg [0:6] storage_entry_sw [0:15]; reg [0:6] addr_sel_sw [0:3]; assign run_control = disp_sw_lacc | disp_sw_uacc | disp_sw_dist | disp_sw_pgm; assign half_or_pgm_stop = half_cycle_sw_half | pgm_stop; assign ri_storage = disp_sw_ri; assign ro_storage = disp_sw_ro; assign storage_control = run_control | disp_sw_ro; //----------------------------------------------------------------------------- // Calculate the RAM address of the general storage word at address gs_addr_. //----------------------------------------------------------------------------- reg [0:6] gs_addr_th, gs_addr_h, gs_addr_t, gs_addr_u; wire [0:14] gs_band_addr; wire [0:9] gs_word_offset; ram_band_addr rba(gs_addr_th, gs_addr_h, gs_addr_t, gs_band_addr); ram_word_offset rwo(gs_addr_t, gs_addr_u, gs_word_offset); wire [0:14] gs_word_addr = gs_band_addr + gs_word_offset; //----------------------------------------------------------------------------- // Operator console state machine //----------------------------------------------------------------------------- reg do_power_on_reset, do_reset_console, do_err_reset, do_err_sense_reset, do_pgm_reset, do_acc_reset, do_hard_reset, do_clear_drum; reg [0:5] state; `define state_idle 6'd0 `define state_reset_console_1 6'd1 `define state_reset_console_2 6'd2 `define state_pgm_reset_1 6'd3 `define state_pgm_reset_2 6'd4 `define state_acc_reset_1 6'd5 `define state_acc_reset_2 6'd6 `define state_err_reset_1 6'd7 `define state_err_reset_2 6'd8 `define state_err_sense_reset_1 6'd9 `define state_err_sense_reset_2 6'd10 `define state_hard_reset_1 6'd11 `define state_storage_entry_sw_1 6'd12 `define state_storage_entry_sw_2 6'd13 `define state_addr_sel_sw_1 6'd14 `define state_addr_sel_sw_2 6'd15 `define state_xfer_key_1 6'd16 `define state_xfer_key_2 6'd17 `define state_pgm_start_key_1 6'd18 `define state_pgm_start_key_2 6'd19 `define state_pgm_stop_key_1 6'd20 `define state_pgm_stop_key_2 6'd21 `define state_read_gs_1 6'd30 `define state_read_gs_2 6'd31 `define state_read_gs_3 6'd32 `define state_read_gs_4 6'd33 `define state_read_gs_5 6'd34 `define state_read_gs_6 6'd35 `define state_clear_drum_1 6'd50 `define state_clear_drum_2 6'd51 `define state_clear_drum_3 6'd52 always @(posedge clk) begin if (rst) begin console_to_addr <= 0; pgm_start <= 0; pgm_stop <= 0; err_reset <= 0; err_sense_reset <= 0; man_pgm_reset <= 0; man_acc_reset <= 0; set_8000 <= 0; reset_8000 <= 0; hard_reset <= 0; // reset console switches pgm_sw_stop <= 0; pgm_sw_run <= 1; half_cycle_sw_run <= 1; half_cycle_sw_half <= 0; ctl_sw_addr_stop <= 0; ctl_sw_run <= 1; ctl_sw_manual <= 0; disp_sw_lacc <= 0; disp_sw_uacc <= 0; disp_sw_dist <= 1; disp_sw_pgm <= 0; disp_sw_ri <= 0; disp_sw_ro <= 0; ovflw_sw_stop <= 1; ovflw_sw_sense <= 0; err_sw_stop <= 1; err_sw_sense <= 0; state <= `state_idle; busy <= 1; digit_ready <= 0; cmd_digit_out <= `biq_blank; do_power_on_reset <= 1; do_reset_console <= 0; do_err_reset <= 0; do_err_sense_reset <= 0; do_pgm_reset <= 0; do_acc_reset <= 0; do_hard_reset <= 0; do_clear_drum <= 0; gs_ram_addr <= 15'd0; read_gs <= 0; write_gs <= 0; console_out <= `biq_blank; end else if (dp) begin case (state) `state_idle: begin case (command) `cmd_none: begin if (do_power_on_reset) begin do_power_on_reset <= 0; do_reset_console <= 1; do_pgm_reset <= 1; do_acc_reset <= 1; do_err_reset <= 1; do_err_sense_reset <= 1; do_hard_reset <= 1; do_clear_drum <= 1; end else if (do_hard_reset) begin do_hard_reset <= 0; hard_reset <= 1; state <= `state_hard_reset_1; end else if (do_reset_console) begin do_reset_console <= 0; state <= `state_reset_console_1; end else if (do_clear_drum) begin do_clear_drum <= 0; gs_ram_addr <= 15'd0; state <= `state_clear_drum_1; end else if (do_pgm_reset) begin do_pgm_reset <= 0; state <= `state_pgm_reset_1; end else if (do_acc_reset) begin do_acc_reset <= 0; man_acc_reset <= 1; state <= `state_acc_reset_1; end else if (do_err_reset) begin do_err_reset <= 0; err_reset <= 1; state <= `state_err_reset_1; end else if (do_err_sense_reset) begin do_err_sense_reset <= 0; err_sense_reset <= 1; state <= `state_err_sense_reset_1; end else begin busy <= 0; digit_ready <= 0; end end `cmd_pgm_sw_stop: begin busy <= 1; pgm_sw_stop <= 1; pgm_sw_run <= 0; end `cmd_pgm_sw_run: begin busy <= 1; pgm_sw_stop <= 0; pgm_sw_run <= 1; end `cmd_half_cycle_sw_run: begin busy <= 1; half_cycle_sw_run <= 1; half_cycle_sw_half <= 0; end `cmd_half_cycle_sw_half: begin busy <= 1; half_cycle_sw_run <= 0; half_cycle_sw_half <= 1; end `cmd_ctl_sw_addr_stop: begin busy <= 1; ctl_sw_addr_stop <= 1; ctl_sw_run <= 0; ctl_sw_manual <= 0; end `cmd_ctl_sw_run: begin busy <= 1; ctl_sw_addr_stop <= 0; ctl_sw_run <= 1; ctl_sw_manual <= 0; end `cmd_ctl_sw_manual: begin busy <= 1; ctl_sw_addr_stop <= 0; ctl_sw_run <= 0; ctl_sw_manual <= 1; end `cmd_disp_sw_lacc: begin busy <= 1; disp_sw_lacc <= 1; disp_sw_uacc <= 0; disp_sw_dist <= 0; disp_sw_pgm <= 0; disp_sw_ri <= 0; disp_sw_ro <= 0; end `cmd_disp_sw_uacc: begin busy <= 1; disp_sw_lacc <= 0; disp_sw_uacc <= 1; disp_sw_dist <= 0; disp_sw_pgm <= 0; disp_sw_ri <= 0; disp_sw_ro <= 0; end `cmd_disp_sw_dist: begin busy <= 1; disp_sw_lacc <= 0; disp_sw_uacc <= 0; disp_sw_dist <= 1; disp_sw_pgm <= 0; disp_sw_ri <= 0; disp_sw_ro <= 0; end `cmd_disp_sw_prog: begin busy <= 1; disp_sw_lacc <= 0; disp_sw_uacc <= 0; disp_sw_dist <= 0; disp_sw_pgm <= 1; disp_sw_ri <= 0; disp_sw_ro <= 0; end `cmd_disp_sw_ri: begin busy <= 1; disp_sw_lacc <= 0; disp_sw_uacc <= 0; disp_sw_dist <= 0; disp_sw_pgm <= 0; disp_sw_ri <= 1; disp_sw_ro <= 0; end `cmd_disp_sw_ro: begin busy <= 1; disp_sw_lacc <= 0; disp_sw_uacc <= 0; disp_sw_dist <= 0; disp_sw_pgm <= 0; disp_sw_ri <= 0; disp_sw_ro <= 1; end `cmd_ovflw_sw_stop: begin busy <= 1; ovflw_sw_stop <= 1; ovflw_sw_sense <= 0; end `cmd_ovflw_sw_sense: begin busy <= 1; ovflw_sw_stop <= 0; ovflw_sw_sense <= 1; end `cmd_err_sw_stop: begin busy <= 1; err_sw_stop <= 1; err_sw_sense <= 0; end `cmd_err_sw_sense: begin busy <= 1; err_sw_stop <= 0; err_sw_sense <= 1; end `cmd_storage_entry_sw: begin busy <= 1; state <= `state_storage_entry_sw_1; end `cmd_addr_sel_sw: begin busy <= 1; state <= `state_addr_sel_sw_1; end `cmd_xfer_key: begin if (ctl_sw_manual) begin busy <= 1; state <= `state_xfer_key_1; end end `cmd_pgm_start_key: begin busy <= 1; state <= `state_pgm_start_key_1; end `cmd_pgm_stop_key: begin busy <= 1; pgm_stop <= 1; state <= `state_pgm_stop_key_1; end `cmd_pgm_reset_key: begin busy <= 1; do_pgm_reset <= 1; do_err_reset <= 1; end `cmd_comp_reset_key: begin busy <= 1; do_pgm_reset <= 1; do_acc_reset <= 1; do_err_reset <= 1; end `cmd_acc_reset_key: begin busy <= 1; do_acc_reset <= 1; do_err_reset <= 1; end `cmd_err_reset_key: begin busy <= 1; do_err_reset <= 1; end `cmd_err_sense_reset_key: begin busy <= 1; do_err_sense_reset <= 1; end //-------------------------------------------------------------- // Read from general storage: // --> 4 digits address, little-endian // <-- 1 digit sign, 10 digits, little-endian // 0 : Ignore if CPU not stopped // Accept low-order address digit // 1 : Accept remaining address digits // 2 : Calculate word origin in gs RAM // Validate address // console_read_gs <= 1; // 3 : Send gs-early digit to out // digit_ready <= 1; // 4 : digit_ready <= 0; //-------------------------------------------------------------- `cmd_read_gs: begin if (ctl_sw_manual) begin busy <= 1; state <= `state_read_gs_1; end end `cmd_write_gs: begin end `cmd_read_acc: begin end `cmd_read_dist: begin end `cmd_read_prog: begin end // 0 : Ignore if not in manual // Clear gs_ram_addr // 1 : Synchronize with d10 // Turn on console_write_gs // 2 : Put a digit: // dx: blank // d0: minus // d1-d10: zero // gs_ram_addr++ `cmd_clear_gs: begin if (ctl_sw_manual) begin busy <= 1; do_clear_drum <= 1; end end `cmd_load_gs: begin end `cmd_dump_gs: begin end `cmd_power_on_reset: begin end `cmd_reset_console: begin end `cmd_hard_reset: begin busy <= 1; do_hard_reset <= 1; end endcase; end // Reset console `state_reset_console_1: begin if (d10) state <= `state_reset_console_2; end `state_reset_console_2: begin storage_entry_sw[ontime_idx] <= dx? `biq_blank : d0? `biq_plus : `biq_0; addr_sel_sw[ontime_idx[2:3]] <= `biq_0; if (d10) state <= `state_idle; end // Program reset key press `state_pgm_reset_1: begin if (wu & d10) begin man_pgm_reset <= 1; state <= `state_pgm_reset_2; end end `state_pgm_reset_2: begin if (wu & d10) begin man_pgm_reset <= 0; state <= `state_idle; end end // Accumulator reset key press `state_acc_reset_1: begin if (wu & d10) begin man_acc_reset <= 1; state <= `state_acc_reset_2; end end `state_acc_reset_2: begin if (wu & d10) begin man_acc_reset <= 0; state <= `state_idle; end end // Error reset key press `state_err_reset_1: begin if (wu & d10) begin err_reset <= 1; state <= `state_err_reset_2; end end `state_err_reset_2: begin if (wu & d10) begin err_reset <= 0; state <= `state_idle; end end // Error sense reset key press `state_err_sense_reset_1: begin if (wu & d10) begin err_sense_reset <= 1; state <= `state_err_sense_reset_2; end end `state_err_sense_reset_2: begin if (wu & d10) begin err_sense_reset <= 0; state <= `state_idle; end end // Hard reset `state_hard_reset_1: begin hard_reset <= 0; state <= `state_idle; end // Set storage entry switches `state_storage_entry_sw_1: begin if (d0) begin state <= `state_storage_entry_sw_2; digit_ready <= 1; storage_entry_sw[ontime_idx] <= cmd_digit_in; end end `state_storage_entry_sw_2: begin storage_entry_sw[ontime_idx] <= cmd_digit_in; if (d10) begin state <= `state_idle; digit_ready <= 0; end end // Set address selection switches `state_addr_sel_sw_1: begin if (dx) begin state <= `state_addr_sel_sw_2; digit_ready <= 1; addr_sel_sw[ontime_idx[2:3]] <= cmd_digit_in; end end `state_addr_sel_sw_2: begin addr_sel_sw[ontime_idx[2:3]] <= cmd_digit_in; if (d2) begin state <= `state_idle; digit_ready <= 0; end end // Transfer key press `state_xfer_key_1: begin if (d10) begin console_to_addr <= 1; state <= `state_xfer_key_2; end end `state_xfer_key_2: begin if (d10) begin console_to_addr <= 0; state <= `state_idle; end end // Start key press `state_pgm_start_key_1: begin if (wu & d10) begin pgm_start <= 1; state <= `state_pgm_start_key_2; end end `state_pgm_start_key_2: begin if (wu & d10) begin pgm_start <= 0; state <= `state_idle; end end // Stop key press `state_pgm_stop_key_1: begin if (hp) state <= `state_pgm_stop_key_2; end `state_pgm_stop_key_2: begin if (hp) begin pgm_stop <= 0; state <= `state_idle; end end // Read word from general storage // --> 4 digits address, little-endian // <-- 1 digit sign, 10 digits, little-endian // 0 : Ignore if CPU not stopped // 1 : Accept first address digit // 2 : Accept remaining address digits // 2 : Calculate word origin in gs RAM // Validate address // console_read_gs <= 1; // 3 : Send gs-early digit to out // digit_ready <= 1; // 4 : digit_ready <= 0; `state_read_gs_1: begin if (dx) begin state <= `state_read_gs_2; digit_ready <= 1; gs_addr_u <= cmd_digit_in; end end `state_read_gs_2: begin if (d0) gs_addr_t <= cmd_digit_in; else if (d1) gs_addr_h <= cmd_digit_in; else if (d2) begin gs_addr_th <= cmd_digit_in; state <= `state_read_gs_3; digit_ready <= 0; end end `state_read_gs_3: begin if (d10) begin gs_ram_addr <= gs_word_addr; read_gs <= 1; state <= `state_read_gs_4; end end `state_read_gs_4: begin state <= `state_read_gs_5; gs_ram_addr <= gs_ram_addr + 1; end `state_read_gs_5: begin digit_ready <= 1; cmd_digit_out <= gs_in; gs_ram_addr <= gs_ram_addr + 1; if (dx) begin state <= `state_read_gs_6; read_gs <= 0; end end `state_read_gs_6: begin digit_ready <= 0; state <= `state_idle; end // 0 : Ignore if not in manual // Clear gs_ram_addr // 1 : Synchronize with d10 // Turn on console_write_gs // 2 : Put a digit: // dx: blank // d0: minus // d1-d10: zero // gs_ram_addr++ `state_clear_drum_1: begin if (d10) begin state <= `state_clear_drum_2; end end `state_clear_drum_2: begin write_gs <= 1; console_out <= dx? `biq_blank : d0? `biq_minus : `biq_0; if (write_gs) gs_ram_addr <= gs_ram_addr + 1; if (gs_ram_addr == 15'd23999) begin write_gs <= 0; state <= `state_idle; end end endcase; end end; always @(posedge ap) begin if (hard_reset) begin data_out <= `biq_blank; addr_out <= `biq_blank; end else begin data_out <= d10? `biq_blank : storage_entry_sw[early_idx]; addr_out <= (d3 | d4 | d5 | d6)? addr_sel_sw[early_idx[2:3]] : `biq_blank; end end; always @(posedge ap) begin if (hard_reset) begin punch_card <= 0; read_card <= 0; card_digit_ready <= 0; end end; endmodule
Go to most recent revision | Compare with Previous | Blame | View Log