1
0
mirror of https://github.com/aap/pdp6.git synced 2026-01-20 01:54:24 +00:00
2019-11-04 09:33:03 +01:00

202 lines
4.7 KiB
Verilog

module ptr(
input wire clk,
input wire reset,
/* IO bus */
input wire iobus_iob_poweron,
input wire iobus_iob_reset,
input wire iobus_datao_clear,
input wire iobus_datao_set,
input wire iobus_cono_clear,
input wire iobus_cono_set,
input wire iobus_iob_fm_datai,
input wire iobus_iob_fm_status,
input wire iobus_rdi_pulse, // unused on 6
input wire [3:9] iobus_ios,
input wire [0:35] iobus_iob_in,
output wire [1:7] iobus_pi_req,
output wire [0:35] iobus_iob_out,
output wire iobus_dr_split,
output wire iobus_rdi_data, // unused on 6
/* Console panel */
input wire key_start,
input wire key_stop,
input wire key_tape_feed,
output wire [35:0] ptr_ind,
output wire [6:0] status_ind, // also includes motor on
/* Avalon slave */
input wire s_write,
input wire [31:0] s_writedata,
output wire fe_data_rq
);
assign iobus_dr_split = 0;
assign iobus_rdi_data = 0;
assign ptr_ind = ptr;
assign status_ind = { motor_on, ptr_b, ptr_busy, ptr_flag, ptr_pia };
wire ptr_sel = iobus_ios == 7'b001_000_1;
wire [8:1] stb_hole = ptr_b ? { 2'b0, hole[6:1] } : hole[8:1];
wire ptr_data_clr;
wire ptr_data_set;
wire ptr_ic_clr;
wire ptr_ic_set;
wire iob_reset;
wire ptr_datai = ptr_sel & iobus_iob_fm_datai;
wire ptr_status = ptr_sel & iobus_iob_fm_status;
wire ptr_start_clr, ptr_stop_clr;
wire ptr_busy_set;
pa ptr_pa0(clk, reset, ptr_sel & iobus_datao_clear, ptr_data_clr);
pa ptr_pa1(clk, reset, ptr_sel & iobus_datao_set, ptr_data_set);
pa ptr_pa2(clk, reset, ptr_sel & iobus_cono_clear | iob_reset, ptr_ic_clr);
pa ptr_pa3(clk, reset, ptr_sel & iobus_cono_set, ptr_ic_set);
pa ptr_pa4(clk, reset, iobus_iob_reset, iob_reset);
pg ptr_pg0(clk, reset, motor_on, ptr_start_clr);
pg ptr_pg1(clk, reset, ~motor_on, ptr_stop_clr);
pa ptr_pa5(clk, reset, ~ptr_datai, ptr_busy_set); // CDG actually
wire ptr_clr;
pa ptr_pa6(clk, reset, ptr_busy, ptr_clr);
reg [36:31] ptr_sr; // actually 36,30,24,18,12,6
reg [35:0] ptr;
reg motor_on = 0;
wire ptr_lead;
wire ptr_mid; // mid hole, this is where the strobe happens.
// normally 400μs after leading edge of feed hole
wire ptr_strobe = ptr_mid & (~ptr_b | hole[8]);
wire ptr_trail;
assign iobus_iob_out =
ptr_datai ? ptr :
ptr_status ? { 27'b0, motor_on, 2'b0, ptr_b, ptr_busy, ptr_flag, ptr_pia } :
36'b0;
wire [1:7] ptr_req = { ptr_flag, 7'b0 } >> ptr_pia;
assign iobus_pi_req = ptr_req;
reg [33:35] ptr_pia;
reg ptr_busy;
reg ptr_flag;
reg ptr_b;
`ifdef simulation
initial begin
ptr_busy <= 0;
ptr_flag <= 0;
ptr_b <= 0;
end
`endif
always @(posedge clk) begin
if(ptr_ic_clr) begin
ptr_pia <= 0;
ptr_busy <= 0;
ptr_flag <= 0;
ptr_b <= 0;
end
if(ptr_ic_set) begin
ptr_pia <= iobus_iob_in[33:35];
if(iobus_iob_in[32])
ptr_flag <= 1;
if(iobus_iob_in[31])
ptr_busy <= 1;
if(iobus_iob_in[30])
ptr_b <= 1;
end
if(ptr_busy_set)
ptr_busy <= 1;
if(ptr_start_clr)
ptr_busy <= 0;
if(ptr_start_clr | ptr_stop_clr)
ptr_flag <= 1;
if(ptr_datai)
ptr_flag <= 0;
if(ptr_trail & ptr_busy & (~ptr_b | ptr_sr[36])) begin
ptr_busy <= 0;
ptr_flag <= 1;
end
if(ptr_clr) begin
ptr <= 0;
ptr_sr <= 0;
end
if(ptr_strobe) begin
ptr_sr <= { ptr_sr[35:31], 1'b1 };
ptr <= { ptr[29:0], 6'b0 } | stb_hole;
end
if(key_start)
motor_on <= 1;
if(key_stop | reset)
motor_on <= 0;
end
// front end interface
assign fe_data_rq = fe_req;
wire moving = motor_on & (key_tape_feed | ptr_busy);
reg fe_req; // requesting data from FE
reg fe_rs; // FE responded with data
reg [8:1] hole; // FE data
reg mid_sync; // set when mid hole
reg trail_sync; // set when trailing edge of feed hole would happen
wire start_signal = ~moving | ptr_trail;
wire start_pulse;
dly50ns fe_dly3(clk, reset, start_signal, start_pulse);
wire fe_mid_pulse, fe_trail_pulse;
`ifdef simulation
dly200ns fe_dly0(clk, reset, start_signal, ptr_lead);
dly800ns fe_dly1(clk, reset, start_signal, fe_mid_pulse);
dly1us fe_dly2(clk, reset, start_signal, fe_trail_pulse);
`else
dly1us fe_dly0(clk, reset, start_signal, ptr_lead);
dly2_1ms fe_dly1(clk, reset, start_signal, fe_mid_pulse);
dly2_5ms fe_dly2(clk, reset, start_signal, fe_trail_pulse);
`endif
pa fe_pa0(clk, reset, fe_rs & mid_sync & ptr_busy, ptr_mid);
pa fe_pa1(clk, reset, fe_rs & trail_sync, ptr_trail);
always @(posedge clk) begin
if(~moving | start_pulse) begin
fe_req <= 0;
fe_rs <= 0;
hole <= 0;
mid_sync <= 0;
trail_sync <= 0;
end
// start FE request
if(ptr_lead)
fe_req <= 1;
// got response from FE
if(s_write & fe_req) begin
hole <= s_writedata[7:0];
fe_req <= 0;
fe_rs <= 1;
end
if(fe_mid_pulse)
mid_sync <= 1;
if(fe_trail_pulse)
trail_sync <= 1;
// all done
if(ptr_trail)
fe_rs <= 0;
end
endmodule