passing diags
This commit is contained in:
88
rtl/NOTES.txt
Normal file
88
rtl/NOTES.txt
Normal file
@@ -0,0 +1,88 @@
|
||||
DEC-8I-H8NA-D KT8/I Time-Sharing Option Functional Description
|
||||
DEC-8I-HOCA-D KE8/I Extended Arithmetic Element
|
||||
|
||||
interrupt occurs here
|
||||
|
||||
510 00516 7141 CLL CIA
|
||||
511 00517 1155 TAD LASTV
|
||||
512 00520 7630 SZL CLA
|
||||
513 00521 4526 ERROR /STORAGE FILLED BY PUSHDOWN LIST
|
||||
|
||||
|
||||
6000 PWS The contents of the AC register are loaded into the SW
|
||||
register. This instruction performs no operation if the IM
|
||||
flag is 1.
|
||||
|
||||
6001 ION The IE flag is set to 1, enabling interrupts, after a one
|
||||
instruction delay.
|
||||
|
||||
6002 IOF The IE flag is set to 0, disabling interrupts.
|
||||
|
||||
6003 PSI Skip if the IE flag is 1. This instruction performs no
|
||||
operation if the IM flag is 1.
|
||||
|
||||
6004 PAI The contents of the IB register are loaded into the IF
|
||||
register, and the II flag is set to 0, just as if a JMP or
|
||||
JMS was executed when the IM flag is 1. This instruction
|
||||
performs no operation if the IM flag is 1.
|
||||
|
||||
6005 PAS The contents of the DF register are loaded into bits
|
||||
[03..05] of the SF register, and the contents of the IF
|
||||
register are loaded into bits [00..02] of the SF register,
|
||||
just as they would be loaded on an interrupt. This
|
||||
instruction performs no operation of the IM flag is 1.
|
||||
|
||||
6006 PDX The DM flag is set to 1 for the execution of the next
|
||||
instruction. This instruction executes normally if IM is 1,
|
||||
but since DM is 1 anytime IM is 1, it effectively performs
|
||||
no operation.
|
||||
|
||||
6007 PEX The IM flag is set to 1, switching the CPU into normal mode,
|
||||
after a one instruction delay. This instruction executes
|
||||
notmally if IM is 1, but effectively performs no operation.
|
||||
|
||||
62x1 CDF Bits [06..08] of the instruction are loaded into the DF
|
||||
register.
|
||||
62x2 CIF Bits [06..08] of the instruction are loaded into the IB
|
||||
register, and the II flag is set to 1. The contents of the
|
||||
IB register will be loaded into the IF register, and the II
|
||||
flag will be set to 0, when the next JMP or JMS instruction
|
||||
is executed. The reload happens after any instruction and/or
|
||||
indirect address words are read, but before the JMS writes
|
||||
its return address; the return address is written to the new
|
||||
instruction field. The II flag blocks interrupts between the
|
||||
CIF and the JMP/JMS (page 53 of the 1970 small computer
|
||||
handbook describes the effect of the II flag, even though
|
||||
the flag itself is not described clearly).
|
||||
|
||||
6214 RDF The contents of the DF register are logically ORed into
|
||||
bits [06..08] of the AC register.
|
||||
|
||||
6224 RIF The contents of the IF register are logically ORed into
|
||||
bits [06..08] of the AC register.
|
||||
|
||||
6234 RIB The contents of the SF register are logically ORed into
|
||||
bits [06..11] of the AC register; if the AC register is
|
||||
initially 0, then bits [09..11] of the AC register get the
|
||||
value which was in the DF register at the time of the last
|
||||
interrupt, and bits [06..08] of the AC register get the
|
||||
value which was in the IF register at the time of the last
|
||||
interrupt.
|
||||
|
||||
6244 RMF Bits [03..05] of the SF register are loaded into the DF
|
||||
register, bits [00..02] of the SF register are loaded into
|
||||
the IB register, and the II flag is set to 1. The next JMP
|
||||
or JMS instruction completes the restore.
|
||||
|
||||
-----
|
||||
|
||||
rf08
|
||||
|
||||
photocell
|
||||
DCIM - turn off photocell
|
||||
DIML - turn on photocell
|
||||
|
||||
DMAR, DMAW - schedule work; delta to new location in time
|
||||
|
||||
transfer in bursts
|
||||
|
||||
195
rtl/pdp8.v
195
rtl/pdp8.v
@@ -71,31 +71,77 @@
|
||||
//
|
||||
// cpu states
|
||||
//
|
||||
// F0 fetch
|
||||
// F0 fetch ram[IF,pc]
|
||||
// F1 incr pc
|
||||
// F2 write
|
||||
// F2 ?
|
||||
// F3 dispatch
|
||||
//
|
||||
// E0 read
|
||||
// E1 decode
|
||||
// E2 write
|
||||
// E3 load
|
||||
// then
|
||||
//
|
||||
// E0 read ram[ea]
|
||||
// E1 decode
|
||||
// E2 write ram
|
||||
// E3 load
|
||||
//
|
||||
// or
|
||||
//
|
||||
// D0 read
|
||||
// D1 wait
|
||||
// D2 write
|
||||
// D3 load
|
||||
// D0 read ram[ea]
|
||||
// D1 wait
|
||||
// D2 write ram
|
||||
// D3 load
|
||||
//
|
||||
// H0 halted
|
||||
//
|
||||
// ------
|
||||
// Rules for address calculation
|
||||
// 0 and
|
||||
// 1 tad
|
||||
// 2 isz
|
||||
// 3 dca
|
||||
//
|
||||
// // 11
|
||||
// 109876543210
|
||||
// cccIZooooooo
|
||||
//
|
||||
// bit 8 - indirect
|
||||
// bit 7 - page 0
|
||||
// bits 6:0 offset
|
||||
//
|
||||
// if 8:7 == 2'b00
|
||||
// ea = IF, pc[11:7], offset[6:0] ;; current page
|
||||
// if 8:7 == 2'b01
|
||||
// ea = IF, 5'b0, offset[6:0] ;; page 0
|
||||
// if 8:7 == 2'b10
|
||||
// ea = (DF, MA( IF, pc[11:7], offset[6:0] )) ;; *(current page)
|
||||
// if 8:7 == 2'b11
|
||||
// ea = (DF, MA( IF, 5'b0, offset[6:0] )) ;; *(page 0)
|
||||
|
||||
// 4 jms
|
||||
// 5 jmp
|
||||
//
|
||||
// ------
|
||||
//
|
||||
// ea <= if Z
|
||||
// if I
|
||||
// {DF, 5'b0, mb[6:0]};
|
||||
// else
|
||||
// {IF, 5'b0, mb[6:0]};
|
||||
// else
|
||||
// if I
|
||||
// {DF, pc[11:7], mb[6:0]};
|
||||
// else
|
||||
// {IF, pc[11:7], mb[6:0]};
|
||||
//
|
||||
// ------
|
||||
|
||||
// F0 fetch
|
||||
// ma = {IF,pc}
|
||||
// check for interrupt
|
||||
//
|
||||
// F1 incr pc
|
||||
// ma = 0
|
||||
// ea <= { IF, ir_z_flag ? pc[11:7] : 5'b0, mb[6:0] };
|
||||
//
|
||||
// if opr
|
||||
// group 1 processing
|
||||
// group 2 processing
|
||||
@@ -104,28 +150,39 @@
|
||||
//
|
||||
// incr pc or skip (incr pc by 2)
|
||||
//
|
||||
// F2 write
|
||||
// ma <= pc
|
||||
// F2 ??
|
||||
// ma = pc
|
||||
//
|
||||
// F3 dispatch
|
||||
// ma = ea
|
||||
// if opr
|
||||
// group1 processing
|
||||
//
|
||||
// if !opr && !iot
|
||||
// possible defer
|
||||
//
|
||||
//
|
||||
// D0
|
||||
// mb <= memory
|
||||
// ma = ea
|
||||
// mb <= ram[ma]
|
||||
// D1
|
||||
// D2
|
||||
// ma = 0
|
||||
// D2 write index reg
|
||||
// ma = index reg ? ea : {DF,mb}
|
||||
// ram_wr = 1
|
||||
// D3
|
||||
// ea <= mb
|
||||
// ma = 0
|
||||
//
|
||||
// E0
|
||||
// mb <= memory
|
||||
// ma = ea
|
||||
// mb <= ram[ma]
|
||||
// E1
|
||||
// E2 write isz value
|
||||
// ma = 0
|
||||
// E2 write isz value, dca value, jms return
|
||||
// ma = ea
|
||||
// ram_wr = 1
|
||||
// E3
|
||||
// ma = ea + 1 (only bottom 12 bits)
|
||||
//
|
||||
|
||||
//
|
||||
@@ -187,6 +244,9 @@ module pdp8(clk, reset,
|
||||
|
||||
// instruction register
|
||||
reg [2:0] ir;
|
||||
reg ir_z_flag;
|
||||
reg ir_i_flag;
|
||||
|
||||
|
||||
// extended memory - instruction field & data field
|
||||
reg [2:0] IF;
|
||||
@@ -317,6 +377,8 @@ module pdp8(clk, reset,
|
||||
|
||||
assign next_state = state == F0 ? F1 :
|
||||
state == F1 && (~iot | (iot & io_data_avail)) ? F2 :
|
||||
// xxx fix this
|
||||
// state == F1 && (iot & ~io_data_avail) ? F1 :
|
||||
state == F2 ? F3 :
|
||||
state == F3 ? (~run ? H0 :
|
||||
next_is_F0 ? F0 :
|
||||
@@ -343,10 +405,11 @@ module pdp8(clk, reset,
|
||||
pc <= 0;
|
||||
else
|
||||
begin
|
||||
if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
//if (state == F1)
|
||||
// $display("pc_incr %b pc_skip %b", pc_incr, pc_skip);
|
||||
//if (state == F1 || state == D3 || state == E3)
|
||||
//$display(" pc <- %o", pc_mux);
|
||||
pc <= pc_mux;
|
||||
//$display(" pc <- %o", pc_mux);
|
||||
pc <= pc_mux;
|
||||
end
|
||||
|
||||
assign pc_mux = (state == F1 && pc_skip) ? (pc + 12'd2) :
|
||||
@@ -383,13 +446,13 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
ea <= 0;
|
||||
else
|
||||
if (state == F1)
|
||||
ea <= {DF, mb[7] ? pc[11:7] : 5'b0, mb[6:0]};
|
||||
ea <= { IF, ir_z_flag ? pc[11:7] : 5'b0, mb[6:0] };
|
||||
else
|
||||
if (state == D3)
|
||||
ea <= mb;
|
||||
ea <= { (ir_i_flag && (!jmp && !jms)) ? DF : IF, mb };
|
||||
|
||||
wire is_index_reg;
|
||||
assign is_index_reg = ea[11:3] == 8'h01;
|
||||
assign is_index_reg = ea[11:3] == 9'o001;
|
||||
|
||||
//
|
||||
// ma
|
||||
@@ -412,7 +475,8 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
reg interrupt_inhibit_ion;
|
||||
|
||||
assign interrupt_inhibit = interrupt_inhibit_delay[0] |
|
||||
interrupt_inhibit_delay[1];
|
||||
interrupt_inhibit_delay[1] |
|
||||
interrupt_inhibit_ion;
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
@@ -457,7 +521,11 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
ac <= 0;
|
||||
mq <= 0;
|
||||
l <= 0;
|
||||
ir <= 0;
|
||||
|
||||
ir <= 3'b000;
|
||||
ir_z_flag <= 1'b0;
|
||||
ir_i_flag <= 1'b0;
|
||||
|
||||
run <= 1;
|
||||
interrupt_enable <= 0;
|
||||
interrupt_cycle <= 0;
|
||||
@@ -477,12 +545,16 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
F0:
|
||||
begin
|
||||
interrupt_skip <= 0;
|
||||
interrupt_inhibit_ion = 1'b0;
|
||||
|
||||
if (interrupt && interrupt_enable &&
|
||||
!interrupt_inhibit && !interrupt_cycle)
|
||||
begin
|
||||
$display("xxx interrupt, pc %o; %b %b %b",
|
||||
pc, interrupt, interrupt_enable, interrupt_cycle);
|
||||
if (0)
|
||||
$display("xxx interrupt, pc %o; %b %b %b; %b %b",
|
||||
pc,
|
||||
interrupt, interrupt_enable, interrupt_cycle,
|
||||
interrupt_inhibit, interrupt_inhibit_delay);
|
||||
interrupt_cycle <= 1;
|
||||
interrupt <= 0;
|
||||
interrupt_enable <= 0;
|
||||
@@ -490,6 +562,8 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
// simulate a jsr to 0
|
||||
mb <= 12'o4000;
|
||||
ir <= 3'o4;
|
||||
ir_i_flag <= 1'b0;
|
||||
ir_z_flag <= 1'b0;
|
||||
SF <= {UF,IF,DF};
|
||||
IF <= 3'b000;
|
||||
DF <= 3'b000;
|
||||
@@ -498,9 +572,11 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
begin
|
||||
interrupt_cycle <= 0;
|
||||
|
||||
//$display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
if (0) $display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
mb <= ram_data_in;
|
||||
ir <= ram_data_in[11:9];
|
||||
ir_i_flag <= ram_data_in[8];
|
||||
ir_z_flag <= ram_data_in[7];
|
||||
end
|
||||
end
|
||||
|
||||
@@ -527,13 +603,25 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
end
|
||||
|
||||
if (opr)
|
||||
case ({mb[8],mb[0]})
|
||||
casex ({mb[8],mb[0]})
|
||||
2'b0x: // group 1
|
||||
begin
|
||||
if (mb[7]) ac <= 0;
|
||||
if (mb[6]) l <= 0;
|
||||
if (mb[5]) ac <= ~ac;
|
||||
if (mb[4]) l <= ~l;
|
||||
case ({mb[7],mb[5]})
|
||||
2'b01: ac <= ~ac;
|
||||
2'b10: ac <= 12'o0;
|
||||
2'b11: ac <= 12'o7777;
|
||||
endcase
|
||||
|
||||
case ({mb[6],mb[4]})
|
||||
2'b01: l <= ~l;
|
||||
2'b10: l <= 1'b0;
|
||||
2'b11: l <= 1'b1;
|
||||
endcase
|
||||
|
||||
// if (mb[7]) ac <= 0;
|
||||
// if (mb[6]) l <= 0;
|
||||
// if (mb[5]) ac <= ~ac;
|
||||
// if (mb[4]) l <= ~l;
|
||||
end
|
||||
|
||||
2'b10: // group 2
|
||||
@@ -554,7 +642,7 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
|
||||
if (iot)
|
||||
begin
|
||||
case (io_select)
|
||||
casex (io_select)
|
||||
6'b000000: // ION, IOF
|
||||
case (mb[2:0])
|
||||
3'b001:
|
||||
@@ -583,9 +671,9 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
case (io_select[2:0])
|
||||
3'b000: UI <= 0; // CINT
|
||||
|
||||
3'b001: ac <= { 6'b0, DF, 3'b0 }; // RDF
|
||||
3'b010: ac <= { 6'b0, IF, 3'b0 }; // RIF
|
||||
3'b011: ac <= { 5'b0, SF }; // RIB
|
||||
3'b001: ac <= ac | { 6'b0, DF, 3'b0 }; // RDF
|
||||
3'b010: ac <= ac | { 6'b0, IF, 3'b0 }; // RIF
|
||||
3'b011: ac <= ac | { 5'b0, SF }; // RIB
|
||||
3'b100: begin // RMF
|
||||
UB <= SF[6];
|
||||
IB <= SF[5:3];
|
||||
@@ -626,7 +714,19 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
end // if (iot)
|
||||
|
||||
if (io_interrupt)
|
||||
interrupt <= 1;
|
||||
begin
|
||||
if (0)
|
||||
$display("F1 - set interrupt; (%b %b %b, %b %b %b)",
|
||||
interrupt_enable,
|
||||
interrupt_inhibit,
|
||||
interrupt_cycle,
|
||||
IB_pending, UB_pending,
|
||||
interrupt_inhibit_delay);
|
||||
|
||||
interrupt <= 1;
|
||||
end
|
||||
else
|
||||
interrupt <= 0;
|
||||
|
||||
end // case: F1
|
||||
|
||||
@@ -634,6 +734,10 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
begin
|
||||
if (opr)
|
||||
begin
|
||||
// group 1
|
||||
if (!mb[8] && mb[0]) /* IAC */
|
||||
{l,ac} <= {l,ac} + 13'o00001;
|
||||
|
||||
// group 3
|
||||
if (mb[8] & mb[0])
|
||||
case ({mb[6:4]})
|
||||
@@ -657,8 +761,8 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
// group 1
|
||||
if (!mb[8])
|
||||
begin
|
||||
if (mb[0]) // IAC
|
||||
{l,ac} <= {l,ac} + 1'b1;
|
||||
// if (mb[0]) // IAC
|
||||
// {l,ac} <= {l,ac} + 13'o00001;
|
||||
case (mb[3:1])
|
||||
3'b001: // BSW
|
||||
{l,ac} <= {l,ac[5:0],ac[11:6]};
|
||||
@@ -736,7 +840,7 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
|
||||
D0:
|
||||
begin
|
||||
$display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
if (0) $display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
mb <= ram_data_in;
|
||||
end
|
||||
|
||||
@@ -750,7 +854,8 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
D2:
|
||||
begin
|
||||
// write ram
|
||||
$display("write ram [%o] <- %o", ram_addr, ram_data_out);
|
||||
if (ram_wr)
|
||||
if (0) $display("write ram [%o] <- %o", ram_addr, ram_data_out);
|
||||
end
|
||||
|
||||
D3:
|
||||
@@ -772,7 +877,7 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
|
||||
E0:
|
||||
begin
|
||||
$display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
if (0) $display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
mb <= ram_data_in;
|
||||
end
|
||||
|
||||
@@ -795,7 +900,9 @@ if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
E2:
|
||||
begin
|
||||
// write ram
|
||||
$display("write ram [%o] <- %o", ram_addr, ram_data_out);
|
||||
if (ram_wr)
|
||||
if (0) $display("write ram [%o] <- %o (pc %o)",
|
||||
ram_addr, ram_data_out, pc);
|
||||
end
|
||||
|
||||
E3:
|
||||
|
||||
@@ -71,10 +71,7 @@ module pdp8_io(clk, reset, iot, state, mb,
|
||||
rf_io_selected ? rf_io_data_avail :
|
||||
1'b0;
|
||||
|
||||
assign io_interrupt =
|
||||
tt_io_selected ? tt_io_interrupt :
|
||||
rf_io_selected ? rf_io_interrupt :
|
||||
1'b0;
|
||||
assign io_interrupt = tt_io_interrupt | rf_io_selected;
|
||||
|
||||
assign io_skip =
|
||||
tt_io_selected ? tt_io_skip :
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
//
|
||||
|
||||
`include "ram_32kx12.v"
|
||||
|
||||
module pdp8_ram(clk, reset, addr, data_in, data_out, rd, wr);
|
||||
|
||||
input clk;
|
||||
|
||||
280
rtl/pdp8_rf.v
280
rtl/pdp8_rf.v
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
RF08
|
||||
|
||||
@@ -123,16 +122,18 @@ usually through the program interrupt facility. An interrupt is
|
||||
requested when the data transfer is completed and the service routine
|
||||
will process the information.
|
||||
|
||||
xxx:
|
||||
if (databreak_req)
|
||||
begin
|
||||
databreak_done <= 0;
|
||||
next_state <= DB0;
|
||||
end
|
||||
|
||||
|
||||
----------- ----------- ----------- -----------
|
||||
|
||||
external signals:
|
||||
|
||||
ma_out
|
||||
ram_write_req
|
||||
ram_read_req
|
||||
ram_done
|
||||
mb_in
|
||||
mb_out
|
||||
|
||||
DISK STATE MACHINE:
|
||||
|
||||
// setup
|
||||
@@ -144,20 +145,76 @@ will process the information.
|
||||
ide_block = {1'b0, track, 3'b0} + {8'b0, dma[11:8]}
|
||||
ide_block_index = dma[7:0];
|
||||
|
||||
read_block:
|
||||
read block
|
||||
start dma
|
||||
write block
|
||||
if dma-stopped-at-end-of-block
|
||||
goto read_block
|
||||
|
||||
// read block into buffer
|
||||
DR0:
|
||||
read[
|
||||
if (db_eob)
|
||||
dr_next_state =
|
||||
idle
|
||||
|
||||
start-xfer
|
||||
read wc
|
||||
read addr
|
||||
|
||||
if read
|
||||
goto check-xfer-read
|
||||
else
|
||||
goto begin-xfer-write
|
||||
|
||||
check-xfer-read
|
||||
if disk-addr-page == memory-buffer-addr-page
|
||||
read memory-buffer-page[offset]
|
||||
goto next-xfer-read
|
||||
else
|
||||
if memory-buffer-dirty == 0
|
||||
goto read-new-page
|
||||
else
|
||||
goto write-old-page
|
||||
|
||||
next-xfer-read
|
||||
write M[addr]
|
||||
goto next-xfer-incr
|
||||
|
||||
next-xfer-incr
|
||||
incr addr
|
||||
incr wc
|
||||
if wc == 0
|
||||
goto done-xfer
|
||||
if read
|
||||
goto check-xfer-read
|
||||
else
|
||||
goto begin-xfer-write
|
||||
|
||||
begin-xfer-write
|
||||
read data from memory
|
||||
goto check-xfer-write
|
||||
|
||||
check-xfer-write
|
||||
if disk-addr-page == memory-buffer-addr-page
|
||||
write memory-buffer-page[offset]
|
||||
set memory-buffer-dirty = 1
|
||||
goto next-xfer-incr
|
||||
else
|
||||
if memory-buffer-dirty == 0
|
||||
goto read-new-page
|
||||
else
|
||||
goto write-old-page
|
||||
|
||||
done-xfer
|
||||
write addr
|
||||
write wc
|
||||
set done/interrupt
|
||||
goto idle
|
||||
|
||||
read-new-page
|
||||
read block from ide
|
||||
set memory-buffer-addr-page
|
||||
set memory-buffer-dirty = 0
|
||||
if read
|
||||
goto check-xfer-read
|
||||
else
|
||||
goto check-xfer-write
|
||||
|
||||
write-old-page
|
||||
write block to ide
|
||||
set memory-buffer-dirty = 0
|
||||
goto read-new-page
|
||||
|
||||
----------- ----------- ----------- -----------
|
||||
|
||||
DMA STATE MACHINE:
|
||||
@@ -189,57 +246,113 @@ will process the information.
|
||||
databreak_notdone_req = 0;
|
||||
|
||||
// idle
|
||||
DB0:
|
||||
DB_idle:
|
||||
|
||||
// read word count
|
||||
DB1:
|
||||
DB_start_xfer1:
|
||||
ma_out = wc-address;
|
||||
databreak_notdone_req = 1;
|
||||
db_next_state = DB2;
|
||||
ram_read_req = 1;
|
||||
if ram_done db_next_state = DB_start_xfer2;
|
||||
|
||||
// write word count + 1
|
||||
DB2:
|
||||
mb_out = mb_in + 1;
|
||||
ram_write = 1;
|
||||
if (mb_in == 12'o7777)
|
||||
databreak_done_req = 1;
|
||||
db_next_state = DB3;
|
||||
|
||||
// finish write
|
||||
DB3:
|
||||
db_next_state = DB4;
|
||||
|
||||
// read current address
|
||||
DB4:
|
||||
// read addr
|
||||
DB_start_xfer2:
|
||||
wc = mb_in;
|
||||
ma_out = wc-address | 1;
|
||||
db_next_state = DB5;
|
||||
ram_read_req = 1;
|
||||
db_next_state = DB_start_xfer3;
|
||||
|
||||
DB_start_xfer3:
|
||||
ram_addr = mb_in
|
||||
db_next_state = DB_check_xfer_read;
|
||||
|
||||
// write current address + 1
|
||||
DB5:
|
||||
mb_out = mb_in + 1;
|
||||
ram_write = 1;
|
||||
db_next_state = DB6;
|
||||
// read buffer
|
||||
DB_check_xfer_read:
|
||||
buffer_addr = disk_addr_offset
|
||||
if disk-addr-page == memory-buffer-addr-page
|
||||
db_next_state = DB_next_xfer_read;
|
||||
else
|
||||
if buffer_dirty == 0
|
||||
db_next_state = DB_read_new_page;
|
||||
else
|
||||
db_next_state = DB_write_old_page;
|
||||
|
||||
// finish write
|
||||
DB6:
|
||||
db_next_state = DB7;
|
||||
// advance
|
||||
DB_next_xfer_read:
|
||||
ma_out = ram_addr
|
||||
mb_out = buffer_out
|
||||
ram_write_req = 1
|
||||
if ram_done db_next_state = DB_next_xfer_incr;
|
||||
|
||||
DB_next_xfer_incr:
|
||||
disk_addr <= disk_addr + 1
|
||||
new_da = {ema, dma} + 19'b1;
|
||||
|
||||
// set up read/write address
|
||||
DB7:
|
||||
ma_out = mb_in;
|
||||
db_next_state = DB8;
|
||||
ram_addr <= ram_addr + 1
|
||||
wc <= wc + 1
|
||||
done = wc == 07777
|
||||
if done
|
||||
db_next_state = DB_done_xfer;
|
||||
else
|
||||
if read
|
||||
db_next_state = DB_check_xfer_read;
|
||||
else
|
||||
db_next_state = DB_begin_xfer_write;
|
||||
|
||||
// do read or start write
|
||||
DB8:
|
||||
if (databreak_write)
|
||||
disk_buffer[disk_buffer_index] = memory_bus;
|
||||
else
|
||||
begin
|
||||
mb_out = disk_buffer[disk_buffer_index];
|
||||
ram_write = 1;
|
||||
end
|
||||
db_next_state = DB9;
|
||||
// write to ram
|
||||
DB7_begin_xfer_write:
|
||||
ma_out = ram_addr
|
||||
mb_out = buffer_out
|
||||
ram_read_req = 1
|
||||
if ram_done db_next_state = DB_check_xfer_write;
|
||||
|
||||
// read buffer
|
||||
DB_check_xfer_write:
|
||||
buffer_addr = disk_addr_offset
|
||||
if disk-addr-page == memory-buffer-addr-page
|
||||
buffer_wr = 1
|
||||
buffer-dirty <= 1
|
||||
db_next_state = DB_next_xfer_incr;
|
||||
else
|
||||
if buffer-dirty == 0
|
||||
db_next_state = DB_read_new_page
|
||||
else
|
||||
db_next_state = DB_write_old_page
|
||||
|
||||
// done
|
||||
DB_done_xfer:
|
||||
ma_out = wc-address;
|
||||
mb_out = ram_addr
|
||||
ram_write_req = 1;
|
||||
if ram_done db_next_state = DB_start_xfer1;
|
||||
|
||||
DB_done_xfer1:
|
||||
ma_out = wc-address | 1;
|
||||
mb_out = wc
|
||||
ram_write_req = 1;
|
||||
if ram_done db_next_state = DB_done_xfer2;
|
||||
|
||||
DB_done_xfer2:
|
||||
set done/interrupt
|
||||
db_next_state = DB_idle
|
||||
|
||||
DB_read_new_page:
|
||||
read block from ide
|
||||
set memory-buffer-addr-page
|
||||
buffer-dirty <= 0
|
||||
if read
|
||||
db_next_state = DB_check_xfer_read
|
||||
else
|
||||
db_next_state = DB_check_xfer_write
|
||||
|
||||
DB_write_old_page:
|
||||
write block to ide
|
||||
buffer-dirty <= 0
|
||||
db_next_state = DB_read-new-page
|
||||
|
||||
|
||||
|
||||
------
|
||||
|
||||
// finish read/write
|
||||
DB9:
|
||||
disk_buffer_index = disk_buffer_index + 1;
|
||||
@@ -249,12 +362,12 @@ will process the information.
|
||||
if (databreak_done)
|
||||
begin
|
||||
db_done = 1;
|
||||
db_next_state = DB0;
|
||||
db_next_state = DB_idle;
|
||||
end
|
||||
else
|
||||
if (disk_buffer_index == 8'b0)
|
||||
begin
|
||||
db_next_state = DB0;
|
||||
db_next_state = DB_idle;
|
||||
db_eob = 1;
|
||||
end
|
||||
else
|
||||
@@ -276,7 +389,7 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
output reg io_selected;
|
||||
output reg [11:0] io_data_out;
|
||||
output reg io_data_avail;
|
||||
output reg io_interrupt;
|
||||
output io_interrupt;
|
||||
output reg io_skip;
|
||||
|
||||
parameter F0 = 4'b0000;
|
||||
@@ -307,8 +420,7 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
assign DCF = 1'b0;
|
||||
assign ADC = DMA == /*DWA??*/0;
|
||||
|
||||
parameter IDLE = 4'b1111;
|
||||
parameter DB0 = 4'b0000;
|
||||
parameter DB_idle = 4'b0000;
|
||||
parameter DB1 = 4'b0001;
|
||||
parameter DB2 = 4'b0010;
|
||||
parameter DB3 = 4'b0011;
|
||||
@@ -322,7 +434,10 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
wire [3:0] db_next_state;
|
||||
reg [3:0] db_state;
|
||||
reg dma_start;
|
||||
|
||||
|
||||
//
|
||||
assign io_interrupt = 1'b0;
|
||||
|
||||
// combinatorial
|
||||
always @(state or
|
||||
ADC or DRL or PER or WLS or NXD or DCF)
|
||||
@@ -340,12 +455,12 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
begin
|
||||
io_selected = 1'b1;
|
||||
case (mb[2:0])
|
||||
3'o03: // DMAR
|
||||
6'o03: // DMAR
|
||||
begin
|
||||
io_data_out = 0;
|
||||
dma_start = 1;
|
||||
end
|
||||
3'o03: // DMAW
|
||||
6'o03: // DMAW
|
||||
begin
|
||||
io_data_out = 0;
|
||||
dma_start = 1;
|
||||
@@ -451,13 +566,14 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
F1:
|
||||
if (iot)
|
||||
begin
|
||||
if (io_select == 6'o60 || io_select == 6'o64)
|
||||
$display("iot2 %t, state %b, mb %o, io_select %o",
|
||||
$time, state, mb, io_select);
|
||||
|
||||
case (io_select)
|
||||
6'o60:
|
||||
case (mb[2:0])
|
||||
3'o03: // DMAR
|
||||
6'o03: // DMAR
|
||||
begin
|
||||
// clear ac
|
||||
DMA <= io_data_in;
|
||||
@@ -465,7 +581,7 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
rf08_rw <= 0;
|
||||
end
|
||||
|
||||
3'o03: // DMAW
|
||||
6'o03: // DMAW
|
||||
begin
|
||||
// clear ac
|
||||
DMA <= io_data_in;
|
||||
@@ -487,25 +603,25 @@ module pdp8_rf(clk, reset, iot, state, mb,
|
||||
|
||||
end // if (iot)
|
||||
|
||||
F2:
|
||||
begin
|
||||
if (io_interrupt)
|
||||
$display("iot2 %t, reset io_interrupt", $time);
|
||||
|
||||
// sampled during f0
|
||||
io_interrupt <= 0;
|
||||
end
|
||||
// F2:
|
||||
// begin
|
||||
// if (io_interrupt)
|
||||
// $display("iot2 %t, reset io_interrupt", $time);
|
||||
//
|
||||
// // sampled during f0
|
||||
// io_interrupt <= 0;
|
||||
// end
|
||||
|
||||
endcase // case(state)
|
||||
|
||||
//
|
||||
assign db_next_state =
|
||||
dma_start ? DB0 :
|
||||
IDLE;
|
||||
dma_start ? DB1 :
|
||||
DB_idle;
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
db_state <= IDLE;
|
||||
db_state <= DB_idle;
|
||||
else
|
||||
db_state <= db_next_state;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ module pdp8_tt(clk, reset, iot, state, mb,
|
||||
output reg io_selected;
|
||||
output reg [11:0] io_data_out;
|
||||
output reg io_data_avail;
|
||||
output reg io_interrupt;
|
||||
output io_interrupt;
|
||||
output reg io_skip;
|
||||
|
||||
|
||||
@@ -26,17 +26,21 @@ integer tx_delay;
|
||||
parameter F2 = 4'b0010;
|
||||
parameter F3 = 4'b0011;
|
||||
|
||||
|
||||
// interrupt output
|
||||
assign io_interrupt = rx_int || tx_int;
|
||||
|
||||
// combinatorial
|
||||
always @(state or
|
||||
rx_int or tx_int)
|
||||
always @(state or rx_int or tx_int)
|
||||
begin
|
||||
// sampled during f1
|
||||
io_skip = 1'b0;
|
||||
io_data_out = io_data_in;
|
||||
io_data_avail = 1'b1;
|
||||
io_selected = 1'b0;
|
||||
|
||||
|
||||
//if (state == F1 && iot)
|
||||
//$display("io_select %o", io_select);
|
||||
|
||||
if (state == F1 && iot)
|
||||
case (io_select)
|
||||
6'o03:
|
||||
@@ -68,6 +72,7 @@ integer tx_delay;
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
begin
|
||||
tx_int <= 0;
|
||||
end
|
||||
else
|
||||
case (state)
|
||||
@@ -80,8 +85,9 @@ integer tx_delay;
|
||||
F1:
|
||||
if (iot)
|
||||
begin
|
||||
$display("iot2 %t, state %b, mb %o, io_select %o",
|
||||
$time, state, mb, io_select);
|
||||
if (io_select == 6'o03 || io_select == 6'o04)
|
||||
if (0) $display("iot2 %t, state %b, mb %o, io_select %o",
|
||||
$time, state, mb, io_select);
|
||||
|
||||
case (io_select)
|
||||
6'o03:
|
||||
@@ -104,10 +110,9 @@ integer tx_delay;
|
||||
begin
|
||||
tx_data <= io_data_in;
|
||||
$display("xxx tx_data %o", io_data_in);
|
||||
tx_int <= 1;
|
||||
tx_delaying <= 1;
|
||||
tx_delay <= 98;
|
||||
$display("xxx set tx_int");
|
||||
// tx_delay <= 98;
|
||||
tx_delay <= 20;
|
||||
end
|
||||
end // case: 6'o04
|
||||
|
||||
@@ -115,15 +120,6 @@ integer tx_delay;
|
||||
|
||||
end // if (iot)
|
||||
|
||||
F2:
|
||||
begin
|
||||
if (io_interrupt)
|
||||
$display("iot2 %t, reset io_interrupt", $time);
|
||||
|
||||
// sampled during f0
|
||||
io_interrupt <= 0;
|
||||
end
|
||||
|
||||
F3:
|
||||
begin
|
||||
if (tx_delaying)
|
||||
@@ -132,9 +128,9 @@ integer tx_delay;
|
||||
//$display("xxx delay %d", tx_delay);
|
||||
if (tx_delay == 0)
|
||||
begin
|
||||
$display("iot2 %t, xxx set io_interrupt", $time);
|
||||
$display("xxx set tx_int");
|
||||
tx_delaying <= 0;
|
||||
io_interrupt <= 1;
|
||||
tx_int <= 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/* 32kx12 static ram */
|
||||
module ram_32kx12(A, DI, DO, CE_N, WE_N);
|
||||
|
||||
@@ -10,29 +9,50 @@ module ram_32kx12(A, DI, DO, CE_N, WE_N);
|
||||
reg[11:0] ram [0:32767];
|
||||
integer i;
|
||||
|
||||
// synthesis translate_off
|
||||
reg [11:0] v;
|
||||
integer file;
|
||||
reg [1023:0] str;
|
||||
reg [1023:0] testfilename;
|
||||
integer n;
|
||||
|
||||
initial
|
||||
begin
|
||||
for (i = 0; i < 32768; i=i+1)
|
||||
ram[i] = 12'b0;
|
||||
|
||||
ram[15'o0000] = 12'o5177;
|
||||
ram[15'o0200] = 12'o7300;
|
||||
ram[15'o0201] = 12'o1300;
|
||||
ram[15'o0202] = 12'o1301;
|
||||
ram[15'o0203] = 12'o3302;
|
||||
ram[15'o0204] = 12'o7402;
|
||||
ram[15'o0205] = 12'o5200;
|
||||
`ifdef verilator
|
||||
n = 0;
|
||||
`endif
|
||||
|
||||
`include "focal.v"
|
||||
ram[15'o0000] = 12'o5404;
|
||||
ram[15'o0004] = 12'o0200;
|
||||
`ifdef __ICARUS__
|
||||
n = $value$plusargs("test=%s", testfilename);
|
||||
`endif
|
||||
|
||||
`ifdef __CVER__
|
||||
n = $scan$plusargs("test=", testfilename);
|
||||
`endif
|
||||
if (n > 0)
|
||||
begin
|
||||
$display("ram: code filename: %s", testfilename);
|
||||
file = $fopen(testfilename, "r");
|
||||
|
||||
while ($fscanf(file, "%o %o\n", i, v) > 0)
|
||||
begin
|
||||
//$display("ram[%o] <- %o", i, v);
|
||||
ram[i] = v;
|
||||
end
|
||||
|
||||
$fclose(file);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(WE_N or CE_N or A or DI)
|
||||
begin
|
||||
if (WE_N == 0 && CE_N == 0)
|
||||
begin
|
||||
$display("ram: write [%o] <- %o", A, DI);
|
||||
//$display("ram: write [%o] <- %o", A, DI);
|
||||
ram[ A ] = DI;
|
||||
end
|
||||
end
|
||||
|
||||
11
rtl/top.v
11
rtl/top.v
@@ -3,13 +3,6 @@
|
||||
// copyright Brad Parker <brad@heeltoe.com> 2009
|
||||
//
|
||||
|
||||
`include "pdp8.v"
|
||||
`include "pdp8_tt.v"
|
||||
`include "pdp8_rf.v"
|
||||
`include "pdp8_io.v"
|
||||
`include "pdp8_ram.v"
|
||||
`include "debounce.v"
|
||||
|
||||
`timescale 1ns / 1ns
|
||||
|
||||
module top(rs232_txd, rs232_rxd,
|
||||
@@ -134,6 +127,7 @@ module top(rs232_txd, rs232_rxd,
|
||||
.io_data_avail(io_data_avail),
|
||||
.io_interrupt(io_interrupt),
|
||||
.io_skip(io_skip),
|
||||
.io_clear_ac(io_clear_ac),
|
||||
.iot(iot),
|
||||
.mb(mb),
|
||||
.switches(switches));
|
||||
@@ -148,7 +142,8 @@ module top(rs232_txd, rs232_rxd,
|
||||
.io_select(io_select),
|
||||
.io_data_avail(io_data_avail),
|
||||
.io_interrupt(io_interrupt),
|
||||
.io_skip(io_skip));
|
||||
.io_skip(io_skip),
|
||||
.io_clear_ac(io_clear_ac));
|
||||
|
||||
pdp8_ram ram(.clk(clk),
|
||||
.reset(reset),
|
||||
|
||||
Reference in New Issue
Block a user