505 lines
9.7 KiB
Verilog
505 lines
9.7 KiB
Verilog
// run_rf.v
|
|
// testing top end for pdp8_rf.v
|
|
//
|
|
|
|
`define debug 1
|
|
|
|
`include "../rtl/pdp8_rf.v"
|
|
`include "../rtl/ide_disk.v"
|
|
`include "../rtl/ide.v"
|
|
`include "../rtl/ram_256x12.v"
|
|
`include "../verif/fake_ram.v"
|
|
|
|
`timescale 1ns / 1ns
|
|
|
|
`ifdef use_fake_ide
|
|
`include "../verif/fake_ide.v"
|
|
`endif
|
|
|
|
module test;
|
|
|
|
reg clk, reset;
|
|
|
|
wire [11:0] io_data_out;
|
|
wire io_data_avail;
|
|
wire io_interrupt;
|
|
wire io_skip;
|
|
|
|
wire ram_read_req;
|
|
wire ram_write_req;
|
|
wire ram_done;
|
|
|
|
wire [14:0] ram_ma;
|
|
wire [11:0] ram_out;
|
|
wire [11:0] ram_in;
|
|
|
|
reg [5:0] io_select;
|
|
reg [11:0] io_data_in;
|
|
reg iot;
|
|
reg [3:0] state;
|
|
reg [11:0] mb_in;
|
|
|
|
wire ide_dior;
|
|
wire ide_diow;
|
|
wire [1:0] ide_cs;
|
|
wire [2:0] ide_da;
|
|
wire [15:0] ide_data_bus;
|
|
|
|
`ifdef use_fake_ide
|
|
fake_ide ide(.ide_dior(ide_dior),
|
|
.ide_diow(ide_diow),
|
|
.ide_cs(ide_cs),
|
|
.ide_da(ide_da),
|
|
.ide_data_bus(ide_data_bus));
|
|
`endif
|
|
|
|
pdp8_rf rf(.clk(clk),
|
|
.reset(reset),
|
|
.iot(iot),
|
|
.state(state),
|
|
.mb(mb_in),
|
|
.io_data_in(io_data_in),
|
|
.io_data_out(io_data_out),
|
|
.io_select(io_select),
|
|
.io_selected(io_selected),
|
|
.io_data_avail(io_data_avail),
|
|
.io_interrupt(io_interrupt),
|
|
.io_skip(io_skip),
|
|
.io_clear_ac(io_clear_ac),
|
|
.ram_read_req(ram_read_req),
|
|
.ram_write_req(ram_write_req),
|
|
.ram_done(ram_done),
|
|
.ram_ma(ram_ma),
|
|
.ram_in(ram_in),
|
|
.ram_out(ram_out),
|
|
.ide_dior(ide_dior),
|
|
.ide_diow(ide_diow),
|
|
.ide_cs(ide_cs),
|
|
.ide_da(ide_da),
|
|
.ide_data_bus(ide_data_bus));
|
|
|
|
fake_ram ram(.clk(clk),
|
|
.reset(reset),
|
|
.ram_read_req(ram_read_req),
|
|
.ram_write_req(ram_write_req),
|
|
.ram_done(ram_done),
|
|
.ram_ma(ram_ma),
|
|
.ram_in(ram_out),
|
|
.ram_out(ram_in));
|
|
|
|
|
|
//
|
|
task write_ram;
|
|
input [14:0] addr;
|
|
input [11:0] data;
|
|
|
|
begin
|
|
@(posedge clk);
|
|
force ram_ma = addr;
|
|
force ram_out = data;
|
|
force ram_write_req = 1;
|
|
@(posedge clk);
|
|
force ram_write_req = 0;
|
|
@(posedge clk);
|
|
release ram_ma;
|
|
release ram_out;
|
|
release ram_write_req;
|
|
@(posedge clk);
|
|
end
|
|
endtask
|
|
|
|
//
|
|
task read_ram;
|
|
input [14:0] addr;
|
|
output [11:0] data;
|
|
|
|
begin
|
|
@(posedge clk);
|
|
force ram_ma = addr;
|
|
force ram_read_req = 1;
|
|
@(posedge clk);
|
|
begin
|
|
data = ram_in;
|
|
force ram_read_req = 0;
|
|
end
|
|
@(posedge clk);
|
|
release ram_ma;
|
|
release ram_read_req;
|
|
@(posedge clk);
|
|
end
|
|
endtask
|
|
|
|
|
|
//
|
|
task write_rf_reg;
|
|
input [11:0] isn;
|
|
input [11:0] data;
|
|
|
|
begin
|
|
@(posedge clk);
|
|
begin
|
|
state = 4'h0;
|
|
mb_in = isn;
|
|
io_select = isn[8:3];
|
|
io_data_in = data;
|
|
iot = 1;
|
|
end
|
|
#20 state = 4'h1;
|
|
#20 state = 4'h2;
|
|
#20 state = 4'h3;
|
|
#20 begin
|
|
state = 4'h0;
|
|
iot = 0;
|
|
end
|
|
end
|
|
endtask
|
|
|
|
//
|
|
task read_rf_reg;
|
|
input [11:0] isn;
|
|
output [11:0] data;
|
|
|
|
begin
|
|
@(posedge clk);
|
|
begin
|
|
state = 4'h0;
|
|
mb_in = isn;
|
|
io_select = isn[8:3];
|
|
io_data_in = 0;
|
|
iot = 1;
|
|
end
|
|
#20 state = 4'h1;
|
|
#20 begin
|
|
data = io_data_out;
|
|
state = 4'h2;
|
|
end
|
|
#20 state = 4'h3;
|
|
#20 begin
|
|
state = 4'h0;
|
|
iot = 0;
|
|
end
|
|
end
|
|
endtask
|
|
|
|
//
|
|
task read_rf_skip;
|
|
input [11:0] isn;
|
|
output skip;
|
|
|
|
begin
|
|
@(posedge clk);
|
|
begin
|
|
state = 4'h0;
|
|
mb_in = isn;
|
|
io_select = isn[8:3];
|
|
io_data_in = 0;
|
|
iot = 1;
|
|
end
|
|
@(posedge clk);
|
|
state = 4'h1;
|
|
@(posedge clk);
|
|
begin
|
|
skip = io_skip;
|
|
state = 4'h2;
|
|
end
|
|
@(posedge clk);
|
|
state = 4'h3;
|
|
@(posedge clk);
|
|
begin
|
|
state = 4'h0;
|
|
iot = 0;
|
|
end
|
|
end
|
|
endtask
|
|
|
|
//
|
|
task wait_for_rf;
|
|
begin
|
|
while (rf.DCF == 1'b0)
|
|
begin
|
|
@(posedge clk);
|
|
begin
|
|
state = 4'h0;
|
|
mb_in = 0;
|
|
io_select = 0;
|
|
io_data_in = 0;
|
|
iot = 0;
|
|
end
|
|
@(posedge clk);
|
|
state = 4'h1;
|
|
@(posedge clk);
|
|
state = 4'h2;
|
|
@(posedge clk);
|
|
state = 4'h3;
|
|
@(posedge clk);
|
|
state = 4'h0;
|
|
end
|
|
end
|
|
endtask
|
|
|
|
task clear_ram;
|
|
integer a;
|
|
begin
|
|
ram.ram_debug = 0;
|
|
for (a = 0; a <= 12'o7777; a = a + 1)
|
|
write_ram(a, 0);
|
|
//ram.ram_debug = 1;
|
|
end
|
|
endtask
|
|
|
|
task failure;
|
|
input [14:0] addr;
|
|
input [11:0] got;
|
|
input [11:0] expected;
|
|
|
|
begin
|
|
$display("FAILURE addr %o, read %o, expected %o",
|
|
addr, got, expected);
|
|
$finish;
|
|
end
|
|
endtask
|
|
|
|
task fill_ram;
|
|
input [14:0] addr;
|
|
input [11:0] value;
|
|
input count;
|
|
|
|
integer count;
|
|
integer a;
|
|
begin
|
|
for (a = addr; count > 0; a = a + 1)
|
|
begin
|
|
write_ram(a, value);
|
|
count = count - 1;
|
|
end
|
|
end
|
|
endtask
|
|
|
|
task check_ram;
|
|
input [14:0] addr;
|
|
input [11:0] value;
|
|
integer a;
|
|
reg [11:0] rv;
|
|
|
|
begin
|
|
read_ram(addr, rv);
|
|
$display("check_ram: %o %o @ %o", rv, value, addr);
|
|
if (rv != value)
|
|
failure(addr, rv, value);
|
|
end
|
|
endtask
|
|
|
|
task check_fill_ram;
|
|
input [14:0] addr;
|
|
input [11:0] value;
|
|
input count;
|
|
integer count;
|
|
integer a;
|
|
reg [11:0] rv;
|
|
|
|
begin
|
|
for (a = addr; count > 0; a = a + 1)
|
|
begin
|
|
read_ram(a, rv);
|
|
if (rv != value)
|
|
failure(a, rv, value);
|
|
count = count - 1;
|
|
end
|
|
end
|
|
endtask
|
|
|
|
task write_rf;
|
|
input [17:0] da;
|
|
input [14:0] ma;
|
|
input count;
|
|
integer count;
|
|
|
|
reg [11:0] cw;
|
|
|
|
begin
|
|
cw = -count;
|
|
write_ram(14'o07750, cw); // word count
|
|
write_ram(14'o07751, ma[11:0]-1); // current addr
|
|
|
|
write_rf_reg(12'o6615, {6'b0, ma[14:12], 3'b0}); // DIML
|
|
write_rf_reg(12'o6643, {6'b0, da[17:12]}); // DXAL
|
|
write_rf_reg(12'o6605, da[11:0]); // DMAW
|
|
wait_for_rf;
|
|
end
|
|
endtask
|
|
|
|
task read_rf;
|
|
input [17:0] da;
|
|
input [14:0] ma;
|
|
input count;
|
|
integer count;
|
|
|
|
reg [11:0] cw;
|
|
|
|
begin
|
|
cw = -count;
|
|
write_ram(14'o07750, cw);
|
|
write_ram(14'o07751, ma[11:0]-1);
|
|
|
|
write_rf_reg(12'o6615, {6'b0, ma[14:12], 3'b0}); // DIML
|
|
write_rf_reg(12'o6643, {6'b0, da[17:12]}); // DXAL
|
|
write_rf_reg(12'o6603, da[11:0]); // DMAR
|
|
wait_for_rf;
|
|
end
|
|
endtask
|
|
|
|
initial
|
|
begin
|
|
$timeformat(-9, 0, "ns", 7);
|
|
|
|
$dumpfile("pdp8_rf.vcd");
|
|
$dumpvars(0, test.rf);
|
|
end
|
|
|
|
reg [11:0] data;
|
|
integer a;
|
|
|
|
initial
|
|
begin
|
|
clk = 0;
|
|
reset = 0;
|
|
|
|
#1 reset = 1;
|
|
#50 reset = 0;
|
|
|
|
//---
|
|
$display("* sanity");
|
|
clear_ram;
|
|
fill_ram(14'o00000, 12'o1111, 8);
|
|
check_fill_ram(14'o00000, 12'o1111, 8);
|
|
check_fill_ram(14'o00010, 12'o0000, 512);
|
|
check_fill_ram(14'o01010, 12'o0000, 512);
|
|
|
|
`ifdef xxx
|
|
//---
|
|
$display("* prep");
|
|
clear_ram;
|
|
write_rf(18'o000000, 14'o00000, 4096);
|
|
write_rf(18'o010000, 14'o00000, 4096);
|
|
write_rf(18'o020000, 14'o00000, 4096);
|
|
write_rf(18'o030000, 14'o00000, 4096);
|
|
write_rf(18'o040000, 14'o00000, 4096);
|
|
write_rf(18'o050000, 14'o00000, 4096);
|
|
write_rf(18'o060000, 14'o00000, 4096);
|
|
write_rf(18'o070000, 14'o00000, 4096);
|
|
`endif
|
|
|
|
`ifdef xxx
|
|
//---
|
|
$display("* write 8 words; cached");
|
|
clear_ram;
|
|
fill_ram(14'o00000, 12'o1111, 8);
|
|
write_rf(18'o000000, 14'o00000, 8);
|
|
clear_ram;
|
|
read_rf (18'o000000, 14'o01000, 8);
|
|
check_fill_ram(14'o00000, 12'o0000, 512);
|
|
check_fill_ram(14'o01000, 12'o1111, 8);
|
|
check_fill_ram(14'o01010, 12'o0000, 512);
|
|
|
|
//---
|
|
$display("* write 8 words; force write");
|
|
clear_ram;
|
|
read_rf (18'o010000, 14'o00000, 8);
|
|
|
|
//---
|
|
$display("* write 8 words; cached");
|
|
clear_ram;
|
|
fill_ram(14'o00000, 12'o2222, 8);
|
|
write_rf(18'o010000, 14'o00000, 8);
|
|
clear_ram;
|
|
read_rf (18'o010000, 14'o00000, 8);
|
|
check_fill_ram(14'o00000, 12'o2222, 8);
|
|
check_fill_ram(14'o00010, 12'o0000, 512);
|
|
read_rf (18'o000000, 14'o00000, 8);
|
|
|
|
//----
|
|
$display("* read/write 2 fields");
|
|
clear_ram;
|
|
fill_ram(14'o10000, 12'o3333, 4096);
|
|
write_rf(18'o000000, 14'o10000, 4032);
|
|
write_rf(18'o010000, 14'o00000, 4096);
|
|
read_rf (18'o000000, 14'o00000, 4032);
|
|
read_rf (18'o010000, 14'o10000, 4096);
|
|
$display("** checking");
|
|
check_fill_ram(14'o00000, 12'o3333, 4032);
|
|
check_fill_ram(14'o10000, 12'o0000, 4096);
|
|
`endif
|
|
|
|
//----
|
|
$display("* read/write individual words");
|
|
clear_ram;
|
|
read_rf (18'o000000, 14'o00000, 256);
|
|
write_ram(14'o00200, 12'o0000);
|
|
write_ram(14'o00201, 12'o1010);
|
|
write_ram(14'o00202, 12'o2020);
|
|
write_ram(14'o00203, 12'o3030);
|
|
$display("** write 4");
|
|
// rf.buffer.ram_debug = 1;
|
|
write_rf(18'o000200, 14'o00200, 4);
|
|
// rf.buffer.ram_debug = 0;
|
|
$display("** read to flush");
|
|
read_rf (18'o010000, 14'o10000, 256);
|
|
$display("** checking");
|
|
clear_ram;
|
|
read_rf (18'o000000, 14'o00000, 512);
|
|
check_ram(14'o00200, 12'o0000);
|
|
check_ram(14'o00201, 12'o1010);
|
|
check_ram(14'o00202, 12'o2020);
|
|
check_ram(14'o00203, 12'o3030);
|
|
|
|
//----
|
|
$display("* read/write individual words");
|
|
clear_ram;
|
|
read_rf (18'o000000, 14'o00000, 4032);
|
|
write_ram(14'o00204, 12'o4040);
|
|
write_ram(14'o00205, 12'o5050);
|
|
write_ram(14'o00206, 12'o6060);
|
|
write_ram(14'o00207, 12'o7070);
|
|
write_rf(18'o000204, 14'o00204, 4);
|
|
read_rf (18'o010000, 14'o10000, 4096);
|
|
$display("** checking");
|
|
clear_ram;
|
|
read_rf (18'o000000, 14'o00000, 4032);
|
|
check_ram(14'o00200, 12'o0000);
|
|
check_ram(14'o00201, 12'o1010);
|
|
check_ram(14'o00202, 12'o2020);
|
|
check_ram(14'o00203, 12'o3030);
|
|
check_ram(14'o00204, 12'o4040);
|
|
check_ram(14'o00205, 12'o5050);
|
|
check_ram(14'o00206, 12'o6060);
|
|
check_ram(14'o00207, 12'o7070);
|
|
$finish;
|
|
end
|
|
|
|
`ifndef use_fake_ide
|
|
always @(posedge clk)
|
|
begin
|
|
$pli_ide(ide_data_bus, ide_dior, ide_diow, ide_cs, ide_da);
|
|
end
|
|
`endif
|
|
|
|
always
|
|
begin
|
|
#10 clk = 0;
|
|
#10 clk = 1;
|
|
end
|
|
|
|
//----
|
|
integer cycle;
|
|
|
|
initial
|
|
cycle = 0;
|
|
|
|
always @(posedge rf.clk)
|
|
begin
|
|
cycle = cycle + 1;
|
|
end
|
|
|
|
endmodule
|
|
|