1
0
mirror of synced 2026-04-12 15:07:20 +00:00

added data break for rf disk

This commit is contained in:
brad
2010-04-10 19:26:42 +00:00
parent 2936993a82
commit 3ec05e8313
6 changed files with 530 additions and 277 deletions

View File

@@ -1,10 +1,13 @@
// PDP-8 in verilog
// Brad Parker brad@heeltoe.com
// PDP-8/I in verilog
// copyright Brad Parker <brad@heeltoe.com> 2005-2010
//
// Based on descriptions in "Computer Engineering" and various PDP-8/I manuals
// fully implements extended memory (IF & DF) and user mode (KT8/I)
//
// Mar 2010
// co-simulation with simh & behavioral model to boot TSS/8
// passes 8/I instruction and extended memory diags
// split out peripherals, added external dma
// Apr 2009
// major revamp for synthesis, removed latches, added muxes, new top
// Jan 2007
@@ -19,12 +22,6 @@
// initial work; runs focal a bit
//
// TODO:
// fully implement extended memory (IF & DF), user mode (KT8/I)
// add df32/rf08
// 6000 pws ac <= switches
//
//
// Instruction format:
//
@@ -71,7 +68,7 @@
//
// cpu states
//
// F0 fetch ram[IF,pc]
// F0 read ram[IF,pc]
// F1 incr pc
// F2 ?
// F3 dispatch
@@ -133,7 +130,9 @@
// {IF, pc[11:7], mb[6:0]};
//
// ------
//
// Actions take during each state:
//
// F0 fetch
// ma = {IF,pc}
// check for interrupt
@@ -157,7 +156,6 @@
// ma = ea
// if opr
// group1 processing
//
// if !opr && !iot
// possible defer
//
@@ -166,7 +164,7 @@
// mb <= ram[ma]
// D1
// ma = 0
// D2 write index reg
// D2 (write index reg)
// ma = index reg ? ea : {DF,mb}
// ram_wr = 1
// D3
@@ -178,7 +176,7 @@
// mb <= ram[ma]
// E1
// ma = 0
// E2 write isz value, dca value, jms return
// E2 (write isz value, dca value, jms return)
// ma = ea
// ram_wr = 1
// E3
@@ -201,7 +199,9 @@ module pdp8(clk, reset,
ram_addr, ram_data_out, ram_data_in, ram_rd, ram_wr,
io_select, io_data_out, io_data_in,
io_data_avail, io_interrupt, io_skip, io_clear_ac,
switches, iot, state, mb);
switches, iot, state, mb,
ext_ram_read_req, ext_ram_write_req, ext_ram_done,
ext_ram_ma, ext_ram_in, ext_ram_out);
input clk, reset;
input [11:0] ram_data_in;
@@ -225,6 +225,15 @@ module pdp8(clk, reset,
input [11:0] switches;
input ext_ram_read_req;
input ext_ram_write_req;
input [14:0] ext_ram_ma;
input [11:0] ext_ram_in;
output ext_ram_done;
output [11:0] ext_ram_out;
// memory buffer, holds data, instructions
reg [11:0] mb;
@@ -336,26 +345,25 @@ module pdp8(clk, reset,
assign pc_skip =
(opr && (mb[8] && !mb[0]) && (skip_condition ^ mb[3])) ||
(iot && (io_skip || interrupt_skip));
// (iot && mb[0] && io_skip);
// cpu states
parameter F0 = 4'b0000;
parameter F1 = 4'b0001;
parameter F2 = 4'b0010;
parameter F3 = 4'b0011;
parameter [3:0]
F0 = 4'b0000,
F1 = 4'b0001,
F2 = 4'b0010,
F3 = 4'b0011,
parameter D0 = 4'b0100;
parameter D1 = 4'b0101;
parameter D2 = 4'b0110;
parameter D3 = 4'b0111;
D0 = 4'b0100,
D1 = 4'b0101,
D2 = 4'b0110,
D3 = 4'b0111,
parameter E0 = 4'b1000;
parameter E1 = 4'b1001;
parameter E2 = 4'b1010;
parameter E3 = 4'b1011;
E0 = 4'b1000,
E1 = 4'b1001,
E2 = 4'b1010,
E3 = 4'b1011,
parameter H0 = 4'b1100;
H0 = 4'b1100;
//
// cpu state state machine
@@ -377,7 +385,6 @@ 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 :
@@ -405,10 +412,6 @@ module pdp8(clk, reset,
pc <= 0;
else
begin
//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;
end
@@ -425,13 +428,22 @@ module pdp8(clk, reset,
//
assign ram_rd = (state == F0) ||
(state == D0) ||
(state == E0);
(state == E0) ||
(state == F2 && ext_ram_read_req);
assign ram_wr = (state == D2 && is_index_reg) ||
(state == E2 && (isz || dca || jms));
(state == E2 && (isz || dca || jms)) ||
(state == F2 && ext_ram_write_req);
assign ram_addr = ma;
assign ram_data_out = mb;
/* peripherals get ram access during F2 */
wire ext_ram_req;
assign ext_ram_req = ext_ram_read_req | ext_ram_write_req;
assign ext_ram_done = state == F2 && ext_ram_req;
assign ext_ram_out = ext_ram_req ? ram_data_in : 12'b0;
assign ram_addr = ext_ram_req ? ext_ram_ma : ma;
assign ram_data_out = ext_ram_req ? ext_ram_in : mb;
assign io_select = mb[8:3];
assign io_data_out = ac;
@@ -541,7 +553,9 @@ module pdp8(clk, reset,
end
else
case (state)
//
// FETCH
//
F0:
begin
interrupt_skip <= 0;
@@ -617,11 +631,6 @@ module pdp8(clk, reset,
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
@@ -695,9 +704,9 @@ module pdp8(clk, reset,
UB <= 1;
interrupt_inhibit_ub = 1'b1;
end
endcase // case(io_select[2:0])
endcase
end // if (mb[2:0] == 3'b100)
end // case: endcase...
end
endcase // case(io_select)
if (io_data_avail)
@@ -761,8 +770,6 @@ module pdp8(clk, reset,
// group 1
if (!mb[8])
begin
// 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]};
@@ -808,36 +815,13 @@ module pdp8(clk, reset,
mq <= 0;
end
// ir <= 0;
// mb <= 0;
end // if (opr)
// if (iot)
// begin
// ir <= 0;
// mb <= 0;
// end
// if (!(opr || iot))
// begin
// if (!mb[8] & jmp)
// begin
// //pc <= ma;
// ir <= 0;
// mb <= 0;
// end
//
// if (mb[8])
// mb <= 0;
//
// if (!mb[8] & !jmp)
// mb <= 0;
// end
end // case: F3
//
// DEFER
//
D0:
begin
if (0) $display("read ram [%o] -> %o", ram_addr, ram_data_in);
@@ -860,21 +844,11 @@ module pdp8(clk, reset,
D3:
begin
// if (jmp)
// begin
// //pc <= mb;
// ir <= 0;
// mb <= 0;
// end
//
// if (!jmp)
// begin
// mb <= 0;
// end
end
//
// EXECUTE
//
E0:
begin
if (0) $display("read ram [%o] -> %o", ram_addr, ram_data_in);
@@ -915,9 +889,6 @@ module pdp8(clk, reset,
else
if (dca)
ac <= 0;
// pc <- ma
// ir <= 0;
end
endcase // case(state)

View File

@@ -5,13 +5,17 @@
module pdp8_io(clk, reset, iot, state, mb,
io_data_in, io_data_out, io_select,
io_data_avail, io_interrupt, io_skip, io_clear_ac);
io_data_avail, io_interrupt, io_skip, io_clear_ac,
io_ram_read_req, io_ram_write_req, io_ram_done,
io_ram_ma, io_ram_in, io_ram_out);
input clk, reset, iot;
input [11:0] io_data_in;
input [11:0] mb;
input [3:0] state;
input [5:0] io_select;
input wire io_ram_done;
input wire [11:0] io_ram_in;
output wire [11:0] io_data_out;
output wire io_data_avail;
@@ -19,6 +23,11 @@ module pdp8_io(clk, reset, iot, state, mb,
output wire io_skip;
output wire io_clear_ac;
output wire io_ram_read_req;
output wire io_ram_write_req;
output wire [14:0] io_ram_ma;
output wire [11:0] io_ram_out;
wire tt_io_selected;
wire [11:0] tt_io_data_out;
wire tt_io_data_avail;
@@ -32,7 +41,7 @@ module pdp8_io(clk, reset, iot, state, mb,
wire rf_io_interrupt;
wire rf_io_skip;
wire rf_io_clear_ac;
pdp8_tt tt(.clk(clk),
.reset(reset),
.iot(iot),
@@ -59,7 +68,14 @@ module pdp8_io(clk, reset, iot, state, mb,
.io_data_out(rf_io_data_out),
.io_data_avail(rf_io_data_avail),
.io_interrupt(rf_io_interrupt),
.io_skip(rf_io_skip));
.io_skip(rf_io_skip),
.ram_read_req(io_ram_read_req),
.ram_write_req(io_ram_write_req),
.ram_done(io_ram_done),
.ram_ma(io_ram_ma),
.ram_in(io_ram_in),
.ram_out(io_ram_out));
assign io_data_out =
tt_io_selected ? tt_io_data_out :

View File

@@ -1,9 +1,17 @@
/*
RF08
2048 words/track
128 tracks
2048 words/track 11 bits
128 tracks 7 bits
4 disks 2 bits
-------
20 bits
1 111
dma 98765432109876543210
ddtttttttwwwwwwwwwww
ema 876543210
mapped to IDE drive;
2048 x 12 bits -> 2048 x 16 bits = 8 blocks of 512 bytes
each track is 8 blocks
@@ -19,10 +27,6 @@
writes to dma trigger; adc is asserted after match w/disk
1 111
98765432109876543210
wwwwwwwwwww
-------------
memory:
@@ -85,7 +89,7 @@
uses 3 cycle data break
ac 7:0, ac 11:0 => 20 bit {EMA,DMA}
ac 8:0, ac 10:0 => 20 bit {EMA,DMA}
20 bit {EMA,DMA} = { disk-select, track-select 6:0, word-select 11:0 }
status
@@ -122,29 +126,10 @@ usually through the program interrupt facility. An interrupt is
requested when the data transfer is completed and the service routine
will process the information.
----------- ----------- ----------- -----------
external signals:
ma_out
ram_write_req
ram_read_req
ram_done
mb_in
mb_out
DISK STATE MACHINE:
HIGH LEVEL DISK STATE MACHINE:
// setup
wire [8:0] track;
wire [11:0] ide_block;
wire [7:0] ide_block_index;
track = {ema[7:0], dma[11]};
ide_block = {1'b0, track, 3'b0} + {8'b0, dma[11:8]}
ide_block_index = dma[7:0];
idle
start-xfer
@@ -157,17 +142,17 @@ will process the information.
goto begin-xfer-write
check-xfer-read
if disk-addr-page == memory-buffer-addr-page
read memory-buffer-page[offset]
if memory buffer contains disk page
read word from memory buffer at offset
goto next-xfer-read
else
if memory-buffer-dirty == 0
goto read-new-page
else
if memory buffer dirty
goto write-old-page
else
goto read-new-page
next-xfer-read
write M[addr]
write memory at addr
goto next-xfer-incr
next-xfer-incr
@@ -181,94 +166,100 @@ will process the information.
goto begin-xfer-write
begin-xfer-write
read data from memory
read from memory at addr
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
if memory buffer contains disk page
write word to memory buffer at offset
set memory buffer dirty
goto next-xfer-incr
else
if memory-buffer-dirty == 0
goto read-new-page
else
if memory buffer dirty
goto write-old-page
else
goto read-new-page
done-xfer
write addr
write wc
write addr to memory
write wc to memory
set done/interrupt
goto idle
read-new-page
read block from ide
set memory-buffer-addr-page
set memory-buffer-dirty = 0
read memory buffer from ide
remember memory buffer disk address
clear memory buffer dirty
if read
goto check-xfer-read
else
goto check-xfer-write
write-old-page
write block to ide
set memory-buffer-dirty = 0
write memory buffer to ide
clear memory buffer dirty
goto read-new-page
----------- ----------- ----------- -----------
DMA STATE MACHINE:
DISK / DMA STATE MACHINE:
wire [7:0] disk_buffer_index;
wire databreak_done_req;
wire databreak_notdone_req;
external signals:
reg databreak_done;
always @(posedge clk)
if (databreak_done_req)
databreak_done <= 1;
else
if (databreak_notdone_req)
databreak_done <= 0;
always @(posedge clk)
if (db_state == DB9)
begin
ema <= new_da[18:11];
dma <= new_da[10:0];
end
ma_out
ram_write_req
ram_read_req
ram_done
mb_in
mb_out
db_done = 0;
db_eob = 0;
ram_write = 0;
databreak_done_req = 0;
databreak_notdone_req = 0;
internal signals:
reg [19:0] disk_addr;
wire [8:0] track;
wire [11:0] ide_block;
wire [7:0] ide_block_index;
track = {ema[7:0], dma[11]};
ide_block = {1'b0, track, 3'b0} + {8'b0, dma[11:8]}
ide_block_index = dma[7:0];
db_done <= 0;
dma_done = 0;
ram_read_req = 0;
ram_write_req = 0;
// idle
DB_idle:
// read word count
DB_start_xfer1:
disk_addr <= {ema, dma};
ma_out = wc-address;
ram_read_req = 1;
dma_wc <= mb_in;
if ram_done db_next_state = DB_start_xfer2;
// read addr
DB_start_xfer2:
wc = mb_in;
ma_out = wc-address | 1;
ram_read_req = 1;
dma_addr <= mb_in
db_next_state = DB_start_xfer3;
DB_start_xfer3:
ram_addr = mb_in
db_next_state = DB_check_xfer_read;
if read
db_next_state = DB_check_xfer_read;
else
db_next_state = DB_begin_xfer_write;
// read buffer
// check buffer address
DB_check_xfer_read:
buffer_addr = disk_addr_offset
if disk-addr-page == memory-buffer-addr-page
buffer_rd = 1
db_next_state = DB_next_xfer_read;
else
if buffer_dirty == 0
@@ -276,21 +267,19 @@ will process the information.
else
db_next_state = DB_write_old_page;
// advance
// write to ram
DB_next_xfer_read:
ma_out = ram_addr
ma_out = dma_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;
ram_addr <= ram_addr + 1
wc <= wc + 1
done = wc == 07777
if done
dma_addr <= dma_addr + 1
dma_wc <= dma_wc + 1
dma_done = dma_wc == 07777
if dma_done
db_next_state = DB_done_xfer;
else
if read
@@ -298,104 +287,103 @@ will process the information.
else
db_next_state = DB_begin_xfer_write;
// write to ram
DB7_begin_xfer_write:
ma_out = ram_addr
// read from ram
DB_begin_xfer_write:
ma_out = dma_addr
mb_out = buffer_out
ram_read_req = 1
if ram_done db_next_state = DB_check_xfer_write;
// read buffer
// check buffer address
DB_check_xfer_write:
buffer_addr = disk_addr_offset
if disk-addr-page == memory-buffer-addr-page
buffer_wr = 1
buffer-dirty <= 1
buffer_dirty <= 1
db_next_state = DB_next_xfer_incr;
else
if buffer-dirty == 0
if buffer_dirty == 0
db_next_state = DB_read_new_page
else
db_next_state = DB_write_old_page
// done
DB_done_xfer:
ema <= disk_addr[18:11];
dma <= disk_addr[10:0];
ma_out = wc-address;
mb_out = ram_addr
mb_out = dma_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
mb_out = dma_wc
ram_write_req = 1;
if ram_done db_next_state = DB_done_xfer2;
DB_done_xfer2:
set done/interrupt
// wait for F2
if state == F2
db_next_state = DB_done_xfer3
else
db_next_state = DB_done_xfer2
DB_done_xfer3:
db_done <= 1
//interrupt
db_next_state = DB_idle
DB_read_new_page:
read block from ide
set memory-buffer-addr-page
buffer-dirty <= 0
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
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;
new_da = {ema, dma} + 19'b1;
if (databreak_done)
begin
db_done = 1;
db_next_state = DB_idle;
end
else
if (disk_buffer_index == 8'b0)
begin
db_next_state = DB_idle;
db_eob = 1;
end
else
db_next_state = DB1;
*/
----------- ----------- ----------- -----------
*/
module pdp8_rf(clk, reset, iot, state, mb,
io_data_in, io_data_out, io_select, io_selected,
io_data_avail, io_interrupt, io_skip);
io_data_avail, io_interrupt, io_skip,
ram_read_req, ram_write_req, ram_done,
ram_ma, ram_in, ram_out);
input clk, reset, iot;
input [11:0] io_data_in;
input [11:0] mb;
input [3:0] state;
input [5:0] io_select;
output reg io_selected;
input [11:0] mb;
input [3:0] state;
input [5:0] io_select;
input ram_done;
input [11:0] ram_in;
output reg [11:0] io_data_out;
output reg io_selected;
output reg io_data_avail;
output io_interrupt;
output reg io_skip;
parameter F0 = 4'b0000;
parameter F1 = 4'b0001;
parameter F2 = 4'b0010;
parameter F3 = 4'b0011;
output ram_read_req;
output ram_write_req;
output [11:0] ram_out;
output [14:0] ram_ma;
parameter [3:0]
F0 = 4'b0000,
F1 = 4'b0001,
F2 = 4'b0010,
F3 = 4'b0011;
parameter PCA_bit = 12'o4000; // photocell status
parameter DRE_bit = 12'o2000; // data req enable
@@ -408,36 +396,85 @@ module pdp8_rf(clk, reset, iot, state, mb,
parameter NXD_bit = 12'o0002; // non-existent disk
parameter PER_bit = 12'o0001; // parity error
parameter WC_ADDR = 15'o07750;
parameter CA_ADDR = 15'o07751;
wire ADC;
wire DCF;
wire PCA;
wire DRE;
wire DRL;
wire PER;
reg [11:0] DMA;
reg [7:0] EMA;
reg PEF;
reg rf08_rw;
reg rf08_start_io;
reg CIE, DRE, DRL, EIE, MEX, NXD, PCA, PER, PIE, WLS;
reg CIE, EIE, MEX, NXD, PIE, WLS;
assign DCF = 1'b0;
assign ADC = DMA == /*DWA??*/0;
parameter DB_idle = 4'b0000;
parameter DB1 = 4'b0001;
parameter DB2 = 4'b0010;
parameter DB3 = 4'b0011;
parameter DB4 = 4'b0100;
parameter DB5 = 4'b0101;
parameter DB6 = 4'b0110;
parameter DB7 = 4'b0111;
parameter DB8 = 4'b1000;
parameter DB9 = 4'b1001;
wire [3:0] db_next_state;
assign DRL = 1'b0;
assign PER = 1'b0;
reg [10:0] photocell_counter;
parameter [3:0]
DB_idle = 4'b0000,
DB_start_xfer1 = 4'b0001,
DB_start_xfer2 = 4'b0010,
DB_start_xfer3 = 4'b0011,
DB_check_xfer_read = 4'b0100,
DB_next_xfer_read = 4'b0101,
DB_next_xfer_incr = 4'b0110,
DB_begin_xfer_write = 4'b0111,
DB_check_xfer_write = 4'b1000,
DB_done_xfer = 4'b1001,
DB_done_xfer1 = 4'b1010,
DB_done_xfer2 = 4'b1011,
DB_done_xfer3 = 4'b1100,
DB_read_new_page = 4'b1101,
DB_write_old_page = 4'b1111;
reg [3:0] db_next_state;
reg [3:0] db_state;
wire active;
reg is_read;
reg is_write;
reg dma_start;
reg db_done;
wire dma_done;
reg [15:0] dma_addr;
reg [11:0] dma_wc;
reg [19:0] disk_addr;
wire [7:0] buffer_addr;
reg [19:8] buffer_disk_addr;
reg buffer_dirty;
reg [11:0] buffer_hold;
wire buffer_matches_DMA;
wire buffer_rd;
wire buffer_wr;
wire ide_read_req;
wire ide_write_req;
wire ide_done;
//
assign io_interrupt = 1'b0;
assign io_interrupt = (CIE & db_done) ||
(PIE & PCA) ||
(EIE & (WLS | DRL | NXD | PER));
assign active = is_read | is_write;
assign buffer_matches_DMA = buffer_disk_addr[19:8] == disk_addr[19:8];
assign buffer_addr = disk_addr[7:0];
assign ide_done = 1;
// combinatorial
always @(state or
ADC or DRL or PER or WLS or NXD or DCF)
@@ -455,15 +492,15 @@ module pdp8_rf(clk, reset, iot, state, mb,
begin
io_selected = 1'b1;
case (mb[2:0])
6'o03: // DMAR
3'o3: // DMAR
begin
io_data_out = 0;
dma_start = 1;
dma_start = 1'b1;
end
6'o03: // DMAW
3'o3: // DMAW
begin
io_data_out = 0;
dma_start = 1;
dma_start = 1'b1;
end
endcase
end // case: 6'o60
@@ -510,9 +547,9 @@ module pdp8_rf(clk, reset, iot, state, mb,
begin
io_selected = 1'b1;
case (mb[2:0])
3: // DXAL
3'o3: // DXAL
io_data_out = 0;
5: // DXAC
3'o5: // DXAC
io_data_out = EMA;
endcase // case(mb[2:0])
end
@@ -527,14 +564,18 @@ module pdp8_rf(clk, reset, iot, state, mb,
always @(posedge clk)
if (reset)
begin
is_read <= 1'b0;
is_write <= 1'b0;
EMA <= 0;
DMA <= 0;
PEF <= 0;
CIE <= 0;
end
else
case (state)
F0:
begin
// sampled during f1
io_data_avail <= 0;
if (iot)
case (io_select)
6'o60: // DCMA
@@ -542,22 +583,25 @@ module pdp8_rf(clk, reset, iot, state, mb,
begin
DMA <= 0;
PEF <= 0;
DRL <= 0;
end
6'o61:
case (mb[2:0])
3'o1: // DCIM
begin
MEX <= 0;
CIE <= 0;
EMA <= 0;
PIE <= 0;
EIE <= 0;
end
3'o2: // DSAC
begin
end
3'o5: // DIML
begin
CIE <= io_data_in[8];
EMA <= io_data_in[7:0];
begin
EIE <= io_data_in[8];
PIE <= io_data_in[7];
CIE <= io_data_in[6];
MEX <= io_data_in[5:3];
end
endcase // case(mb[2:0])
endcase
@@ -577,16 +621,14 @@ module pdp8_rf(clk, reset, iot, state, mb,
begin
// clear ac
DMA <= io_data_in;
rf08_start_io <= 1;
rf08_rw <= 0;
is_read <= 1'b1;
end
6'o03: // DMAW
begin
// clear ac
DMA <= io_data_in;
rf08_start_io <= 1;
rf08_rw <= 1;
is_write <= 1'b1;
end
endcase // case(mb[2:0])
@@ -612,18 +654,219 @@ module pdp8_rf(clk, reset, iot, state, mb,
// io_interrupt <= 0;
// end
// F3 is a convenient time to do this
// note that state machine waits when done till next F2
// to sync up DB_done_xfer3 and F3
F3:
if (db_state == DB_done_xfer3)
begin
EMA <= disk_addr[19:12];
DMA <= disk_addr[11:0];
is_read <= 1'b0;
is_write <= 1'b0;
end
endcase // case(state)
//
assign db_next_state =
dma_start ? DB1 :
DB_idle;
// comb logic for next state
always @(*)
begin
db_next_state = DB_idle;
case (db_state)
DB_idle:
if (dma_start)
db_next_state = DB_start_xfer1;
DB_start_xfer1:
db_next_state = ram_done ? DB_start_xfer2 : DB_start_xfer1;
DB_start_xfer2:
db_next_state = ram_done ? DB_start_xfer3 : DB_start_xfer2;
DB_start_xfer3:
db_next_state = is_read ? DB_check_xfer_read : DB_begin_xfer_write;
DB_check_xfer_read:
if (buffer_matches_DMA)
db_next_state = DB_next_xfer_read;
else
db_next_state = buffer_dirty ? DB_write_old_page:DB_read_new_page;
DB_next_xfer_read:
db_next_state = ram_done ? DB_next_xfer_incr : DB_next_xfer_read;
DB_next_xfer_incr:
if (dma_done)
db_next_state = DB_done_xfer;
else
db_next_state = is_read ? DB_check_xfer_read:DB_begin_xfer_write;
DB_begin_xfer_write:
db_next_state = ram_done ? DB_check_xfer_write:DB_begin_xfer_write;
DB_check_xfer_write:
if (buffer_matches_DMA)
db_next_state = DB_next_xfer_incr;
else
db_next_state = buffer_dirty ? DB_write_old_page:DB_read_new_page;
DB_done_xfer:
db_next_state = ram_done ? DB_done_xfer1 : DB_done_xfer;
DB_done_xfer1:
db_next_state = ram_done ? DB_done_xfer2 : DB_done_xfer1;
DB_done_xfer2:
db_next_state = state == F2 ? DB_done_xfer3 : DB_done_xfer2;
DB_done_xfer3:
db_next_state = DB_idle;
DB_read_new_page:
db_next_state = ide_done ?
(is_read ? DB_check_xfer_read:DB_check_xfer_write) :
DB_read_new_page;
DB_write_old_page:
db_next_state = ide_done ? DB_read_new_page : DB_write_old_page;
endcase
end
// db_state
always @(posedge clk)
if (reset)
db_state <= DB_idle;
else
db_state <= db_next_state;
assign dma_done = dma_wc == 12'o7777;
// general state
always @(posedge clk)
if (reset)
begin
db_done <= 1'b1;
dma_wc <= 12'b0;
dma_addr <= 15'b0;
disk_addr <= 20'b0;
buffer_disk_addr[19:8] <= 12'b111111111111;
buffer_dirty <= 1'b0;
buffer_hold <= 12'b0;
end
else
begin
case (db_state)
DB_idle:
begin
disk_addr <= {EMA, DMA};
db_done <= 0;
end
DB_start_xfer1:
begin
dma_wc <= ram_in;
end
DB_start_xfer2:
begin
dma_addr <= ram_in;
end
DB_start_xfer3:
begin
// this state might be not be needed
end
DB_begin_xfer_write:
begin
buffer_hold <= ram_in;
end
DB_next_xfer_incr:
begin
disk_addr <= disk_addr + 20'b1;
dma_addr <= dma_addr + 15'b1;
dma_wc <= dma_wc + 12'b1;
end
DB_check_xfer_write:
buffer_dirty <= 1;
DB_done_xfer2:
db_done <= 1;
DB_read_new_page:
begin
buffer_dirty <= 0;
buffer_disk_addr[19:8] <= disk_addr[19:8];
end
DB_write_old_page:
begin
buffer_dirty <= 0;
buffer_disk_addr[19:8] <= disk_addr[19:8];
end
endcase // case (db_state)
end // else: !if(reset)
//
// external ram control
//
assign ram_ma =
db_state == DB_start_xfer1 ? WC_ADDR :
db_state == DB_start_xfer2 ? CA_ADDR :
db_state == DB_next_xfer_read ? dma_addr :
db_state == DB_begin_xfer_write ? dma_addr :
db_state == DB_done_xfer ? WC_ADDR :
db_state == DB_done_xfer1 ? CA_ADDR :
15'b0;
assign ram_read_req =
(db_state == DB_start_xfer1) |
(db_state == DB_start_xfer2) |
(db_state == DB_begin_xfer_write);
assign ram_write_req =
(db_state == DB_next_xfer_read) |
(db_state == DB_done_xfer) |
(db_state == DB_done_xfer1);
assign ram_out =
db_state == DB_next_xfer_read ? buffer_hold :
db_state == DB_begin_xfer_write ? buffer_hold :
db_state == DB_done_xfer ? dma_addr :
db_state == DB_done_xfer1 ? dma_wc :
12'b0;
assign buffer_rd = db_state == DB_check_xfer_read && buffer_matches_DMA;
assign buffer_wr = db_state == DB_check_xfer_write && buffer_matches_DMA;
assign ide_read_req = db_state == DB_read_new_page;
assign ide_write = db_state == DB_write_old_page;
//
// RF08 state
//
assign ADC = buffer_matches_DMA;
always @(posedge clk)
if (reset)
photocell_counter <= 0;
else
photocell_counter <= photocell_counter + 1;
assign PCA = photocell_counter == 0;
assign DRE = PCA;
assign DCF = db_done;
always @(posedge clk)
if (reset)
begin
WLS <= 1'b0;
end
endmodule

View File

@@ -11,7 +11,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 io_data_avail;
output io_interrupt;
output reg io_skip;
@@ -28,6 +28,8 @@ integer tx_delay;
// interrupt output
assign io_interrupt = rx_int || tx_int;
assign io_data_avail = 1'b1;
// combinatorial
always @(state or rx_int or tx_int)
@@ -35,7 +37,6 @@ integer tx_delay;
// 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)
@@ -78,8 +79,6 @@ integer tx_delay;
case (state)
F0:
begin
// sampled during f1
io_data_avail <= 0;
end
F1:

View File

@@ -21,9 +21,7 @@ module ram_32kx12(A, DI, DO, CE_N, WE_N);
for (i = 0; i < 32768; i=i+1)
ram[i] = 12'b0;
`ifdef verilator
n = 0;
`endif
`ifdef __ICARUS__
n = $value$plusargs("test=%s", testfilename);
@@ -32,6 +30,13 @@ module ram_32kx12(A, DI, DO, CE_N, WE_N);
`ifdef __CVER__
n = $scan$plusargs("test=", testfilename);
`endif
if (n == 0)
begin
testfilename = "../verif/default.mem";
n = 1;
end
if (n > 0)
begin
$display("ram: code filename: %s", testfilename);

View File

@@ -1,6 +1,6 @@
//
// pdp-8/i in verilog - fpga top level
// copyright Brad Parker <brad@heeltoe.com> 2009
// copyright Brad Parker <brad@heeltoe.com> 2009-2010
//
`timescale 1ns / 1ns
@@ -105,6 +105,13 @@ module top(rs232_txd, rs232_rxd,
wire [3:0] state;
wire [11:0] mb;
wire ext_ram_read_req;
wire ext_ram_write_req;
wire [14:0] ext_ram_ma;
wire [11:0] ext_ram_in;
wire ext_ram_done;
wire [11:0] ext_ram_out;
debounce reset_sw(.clk(sysclk), .in(button[3]), .out(reset));
// display show_pc(.clk(sysclk), .reset(reset),
@@ -130,7 +137,13 @@ module top(rs232_txd, rs232_rxd,
.io_clear_ac(io_clear_ac),
.iot(iot),
.mb(mb),
.switches(switches));
.switches(switches),
.ext_ram_read_req(ext_ram_read_req),
.ext_ram_write(ext_ram_write_req),
.ext_ram_done(ext_ram_done),
.ext_ram_ma(ext_ram_ma),
.ext_ram_in(ext_ram_out),
.ext_ram_out(ext_ram_in));
pdp8_io io(.clk(clk),
.reset(reset),
@@ -143,7 +156,13 @@ 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));
.io_clear_ac(io_clear_ac),
.io_ram_read_req(ext_ram_read_req),
.io_ram_write(ext_ram_write_req),
.io_ram_done(ext_ram_done),
.io_ram_ma(ext_ram_ma),
.io_ram_in(ext_ram_in),
.io_ram_out(ext_ram_out));
pdp8_ram ram(.clk(clk),
.reset(reset),