mirror of
https://github.com/aap/pdp6.git
synced 2026-01-20 01:54:24 +00:00
202 lines
4.7 KiB
Verilog
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
|