This commit is contained in:
818
rtl/pdp8.v
Normal file
818
rtl/pdp8.v
Normal file
@@ -0,0 +1,818 @@
|
||||
// PDP-8 in verilog
|
||||
// Brad Parker brad@heeltoe.com
|
||||
//
|
||||
// Based on descriptions in "Computer Engineering" and various PDP-8/I manuals
|
||||
//
|
||||
// Mar 2010
|
||||
// co-simulation with simh & behavioral model to boot TSS/8
|
||||
// Apr 2009
|
||||
// major revamp for synthesis, removed latches, added muxes, new top
|
||||
// Jan 2007
|
||||
// cleaned up state machines for synthesis
|
||||
// finished extended memory (IF & DF), user mode (KT8/I)
|
||||
// added rf08 registers
|
||||
// Dec 2006
|
||||
// cleaned up a little; now runs focal to prompt
|
||||
// moved i/o out to pdp8_io.v
|
||||
// added IF, DF, user mode
|
||||
// Nov 2005 Brad Parker brad@heeltoe.com
|
||||
// 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:
|
||||
//
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
// 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
// |--op--|
|
||||
// 0 and
|
||||
// 1 tad
|
||||
// 2 isz
|
||||
// 3 dca
|
||||
// 4 jms
|
||||
// 5 jmp
|
||||
// 6 iot
|
||||
// 7 opr
|
||||
// 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
// group 1
|
||||
// 0
|
||||
// |cla|clf| | |
|
||||
// | | |cma cml| |
|
||||
// |bsw 001 |
|
||||
// |ral 010 |
|
||||
// |rtl 011 |
|
||||
// |rar 100 |
|
||||
// |rtr 101 |
|
||||
// | |iac
|
||||
//
|
||||
// 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
// group 2
|
||||
// 1 0
|
||||
// |sma|sza|snl|skp| |
|
||||
// |cla|
|
||||
// |osr|hlt
|
||||
//
|
||||
// group 3
|
||||
// 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
// eae
|
||||
// 1 1
|
||||
// |cla|
|
||||
// |mqa|sca|mql|
|
||||
// |isn |
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// cpu states
|
||||
//
|
||||
// F0 fetch
|
||||
// F1 incr pc
|
||||
// F2 write
|
||||
// F3 dispatch
|
||||
//
|
||||
// E0 read
|
||||
// E1 decode
|
||||
// E2 write
|
||||
// E3 load
|
||||
//
|
||||
// or
|
||||
//
|
||||
// D0 read
|
||||
// D1 wait
|
||||
// D2 write
|
||||
// D3 load
|
||||
//
|
||||
// H0 halted
|
||||
//
|
||||
// ------
|
||||
//
|
||||
// F0 fetch
|
||||
// check for interrupt
|
||||
//
|
||||
// F1 incr pc
|
||||
// if opr
|
||||
// group 1 processing
|
||||
// group 2 processing
|
||||
//
|
||||
// if iot
|
||||
//
|
||||
// incr pc or skip (incr pc by 2)
|
||||
//
|
||||
// F2 write
|
||||
// ma <= pc
|
||||
//
|
||||
// F3 dispatch
|
||||
// if opr
|
||||
// group1 processing
|
||||
//
|
||||
// if !opr && !iot
|
||||
// possible defer
|
||||
//
|
||||
//
|
||||
// D0
|
||||
// mb <= memory
|
||||
// D1
|
||||
// D2
|
||||
// D3
|
||||
//
|
||||
// E0
|
||||
// mb <= memory
|
||||
// E1
|
||||
// E2 write isz value
|
||||
// E3
|
||||
//
|
||||
|
||||
//
|
||||
// extended memory
|
||||
//
|
||||
// 62n1 cdf change data field; df <= mb[5:3]
|
||||
// 62n2 cif change instruction field; if <= mb[5:3], after next jmp or jms
|
||||
// 6214 rdf read df into ac[5:3]
|
||||
// 6224 rif read if into ac[5:3]
|
||||
// 6234 rib read sf into ac[5:0], which is {if,df}
|
||||
// 6244 rmf restore memory field, sf => ib, df
|
||||
// (remember that on interrupt, sf <= {if,df})
|
||||
//
|
||||
|
||||
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);
|
||||
|
||||
input clk, reset;
|
||||
input [11:0] ram_data_in;
|
||||
output ram_rd;
|
||||
output ram_wr;
|
||||
output [11:0] ram_data_out;
|
||||
output [14:0] ram_addr;
|
||||
|
||||
output [5:0] io_select;
|
||||
input [11:0] io_data_in;
|
||||
output [11:0] io_data_out;
|
||||
|
||||
input io_data_avail;
|
||||
input io_interrupt;
|
||||
input io_skip;
|
||||
input io_clear_ac;
|
||||
|
||||
output iot;
|
||||
output [3:0] state;
|
||||
output [11:0] mb;
|
||||
|
||||
input [11:0] switches;
|
||||
|
||||
// memory buffer, holds data, instructions
|
||||
reg [11:0] mb;
|
||||
|
||||
// generate address of work in memory being accessed
|
||||
wire [14:0] ma;
|
||||
|
||||
// accumulator & link
|
||||
reg [11:0] ac;
|
||||
reg l;
|
||||
|
||||
// MQ
|
||||
reg [11:0] mq;
|
||||
|
||||
// program counter
|
||||
reg [11:0] pc;
|
||||
wire pc_incr, pc_skip;
|
||||
|
||||
// instruction register
|
||||
reg [2:0] ir;
|
||||
|
||||
// extended memory - instruction field & data field
|
||||
reg [2:0] IF;
|
||||
reg [2:0] DF;
|
||||
reg [2:0] IB;
|
||||
reg [6:0] SF; // { UF, IF[2:0], DF[2:0] }
|
||||
reg IB_pending;
|
||||
|
||||
// user mode
|
||||
reg UB; // user_buffer
|
||||
reg UF; // user_flag
|
||||
reg UI; // user_interrupt
|
||||
reg UB_pending;
|
||||
|
||||
// processor state
|
||||
reg [3:0] state;
|
||||
wire [3:0] next_state;
|
||||
|
||||
reg run;
|
||||
reg interrupt_enable;
|
||||
reg interrupt_cycle;
|
||||
reg [1:0] interrupt_inhibit_delay;
|
||||
reg interrupt_skip;
|
||||
|
||||
reg interrupt;
|
||||
|
||||
wire interrupt_inhibit;
|
||||
wire skip_condition;
|
||||
|
||||
wire fetch; // memory cycle to fetch instruction
|
||||
wire deferred;// memory cycle to get address of operand
|
||||
wire execute;// memory cycle to getch (store) operand and execute isn
|
||||
|
||||
assign {fetch, deferred, execute} =
|
||||
(state[3:2] == 2'b00) ? 3'b100 :
|
||||
(state[3:2] == 2'b01) ? 3'b010 :
|
||||
(state[3:2] == 2'b10) ? 3'b001 :
|
||||
3'b000 ;
|
||||
|
||||
// instruction op decode
|
||||
wire i_and,tad,isz,dca,jms,jmp,iot,opr;
|
||||
|
||||
assign {i_and,tad,isz,dca,jms,jmp,iot,opr} =
|
||||
(ir == 3'b000) ? 8'b10000000 :
|
||||
(ir == 3'b001) ? 8'b01000000 :
|
||||
(ir == 3'b010) ? 8'b00100000 :
|
||||
(ir == 3'b011) ? 8'b00010000 :
|
||||
(ir == 3'b100) ? 8'b00001000 :
|
||||
(ir == 3'b101) ? 8'b00000100 :
|
||||
(ir == 3'b110) ? 8'b00000010 :
|
||||
8'b00000001 ;
|
||||
|
||||
|
||||
//-------------
|
||||
|
||||
/*
|
||||
* note: bit numbering is opposite that used in "Computer Engineering"
|
||||
*
|
||||
* F1
|
||||
* if opr
|
||||
* if MB[8] and !MB[0]
|
||||
* begin
|
||||
* if skip.conditions ^ MB[3]
|
||||
* pc <= pc + 2
|
||||
* if skip.conditions == MB[3]
|
||||
* pc <= pc + 1 next
|
||||
* if MB[7]
|
||||
* ac <= 0
|
||||
*
|
||||
* skip conditions are only valid during F1
|
||||
*
|
||||
*/
|
||||
assign skip_condition = (mb[6] && ac[11]) ||
|
||||
(mb[5] && (ac == 12'b0)) ||
|
||||
(mb[4] && l);
|
||||
|
||||
assign pc_incr =
|
||||
/* group 1 */
|
||||
(opr & !mb[8]) ||
|
||||
/* group 2 */
|
||||
(opr && (mb[8] && !mb[0]) && (skip_condition == mb[3])) ||
|
||||
/* group 3? */
|
||||
(opr && (mb[8] && mb[0])) ||
|
||||
iot ||
|
||||
(!(opr || iot) && !interrupt_cycle);
|
||||
|
||||
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 D0 = 4'b0100;
|
||||
parameter D1 = 4'b0101;
|
||||
parameter D2 = 4'b0110;
|
||||
parameter D3 = 4'b0111;
|
||||
|
||||
parameter E0 = 4'b1000;
|
||||
parameter E1 = 4'b1001;
|
||||
parameter E2 = 4'b1010;
|
||||
parameter E3 = 4'b1011;
|
||||
|
||||
parameter H0 = 4'b1100;
|
||||
|
||||
//
|
||||
// cpu state state machine
|
||||
//
|
||||
// clock next cpu state at rising edge of clock
|
||||
//
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
state <= 0;
|
||||
else
|
||||
state <= next_state;
|
||||
|
||||
wire next_is_F0;
|
||||
wire next_is_E0;
|
||||
|
||||
assign next_is_F0 = opr | iot | (!mb[8] & jmp);
|
||||
assign next_is_E0 = !mb[8] & !jmp;
|
||||
|
||||
assign next_state = state == F0 ? F1 :
|
||||
state == F1 && (~iot | (iot & io_data_avail)) ? F2 :
|
||||
state == F2 ? F3 :
|
||||
state == F3 ? (~run ? H0 :
|
||||
next_is_F0 ? F0 :
|
||||
next_is_E0 ? E0 :
|
||||
D0) :
|
||||
state == D0 ? D1 :
|
||||
state == D1 ? D2 :
|
||||
state == D2 ? D3 :
|
||||
state == D3 ? (jmp ? F0 : E0) :
|
||||
state == E0 ? E1 :
|
||||
state == E1 ? E2 :
|
||||
state == E2 ? E3 :
|
||||
state == E3 ? F0 :
|
||||
state == H0 ? H0 :
|
||||
F0;
|
||||
|
||||
//
|
||||
// pc
|
||||
//
|
||||
wire [11:0] pc_mux;
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
pc <= 0;
|
||||
else
|
||||
begin
|
||||
if (state == F1) $display("pc_skip %b", pc_skip);
|
||||
//if (state == F1 || state == D3 || state == E3)
|
||||
//$display(" pc <- %o", pc_mux);
|
||||
pc <= pc_mux;
|
||||
end
|
||||
|
||||
assign pc_mux = (state == F1 && pc_skip) ? (pc + 12'd2) :
|
||||
(state == F1 && pc_incr) ? (pc + 12'd1) :
|
||||
(state == F3 && !(opr || iot) && (!mb[8] & jmp)) ? ma :
|
||||
(state == D3 && jmp) ? mb :
|
||||
(state == E3 && jms) ? ma :
|
||||
(state == E3 && isz && mb == 12'b0) ? (pc + 12'd1) :
|
||||
pc;
|
||||
|
||||
//
|
||||
// ram
|
||||
//
|
||||
assign ram_rd = (state == F0) ||
|
||||
(state == D0) ||
|
||||
(state == E0);
|
||||
|
||||
assign ram_wr = (state == D2 && is_index_reg) ||
|
||||
(state == E2 && (isz || dca || jms));
|
||||
|
||||
assign ram_addr = ma;
|
||||
assign ram_data_out = mb;
|
||||
|
||||
assign io_select = mb[8:3];
|
||||
assign io_data_out = ac;
|
||||
|
||||
//
|
||||
// ea calculation
|
||||
//
|
||||
reg [14:0] ea;
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ea <= 0;
|
||||
else
|
||||
if (state == F1)
|
||||
ea <= {DF, mb[7] ? pc[11:7] : 5'b0, mb[6:0]};
|
||||
else
|
||||
if (state == D3)
|
||||
ea <= mb;
|
||||
|
||||
wire is_index_reg;
|
||||
assign is_index_reg = ea[11:3] == 8'h01;
|
||||
|
||||
//
|
||||
// ma
|
||||
//
|
||||
assign ma = (state == F0) ? {IF,pc} :
|
||||
(state == F2 && (opr || iot)) ? {IF,pc} :
|
||||
((state == F3 || state == D0 || state == E0) &&
|
||||
(!opr && !iot)) ? ea :
|
||||
(state == D2) ? (is_index_reg ? ea : {DF,mb}) :
|
||||
(state == E2 ) ? ea :
|
||||
(state == E3 && jms) ? {ea[14:12], ea[11:0] + 12'b1} :
|
||||
15'b0;
|
||||
|
||||
//
|
||||
// interrupt defer logic
|
||||
//
|
||||
reg interrupt_inhibit_clear;
|
||||
reg interrupt_inhibit_ib;
|
||||
reg interrupt_inhibit_ub;
|
||||
reg interrupt_inhibit_ion;
|
||||
|
||||
assign interrupt_inhibit = interrupt_inhibit_delay[0] |
|
||||
interrupt_inhibit_delay[1];
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
begin
|
||||
interrupt_inhibit_delay <= 2'b00;
|
||||
IB_pending <= 0;
|
||||
UB_pending <= 0;
|
||||
end
|
||||
else
|
||||
if (interrupt_inhibit_clear)
|
||||
begin
|
||||
interrupt_inhibit_delay <= 2'b00;
|
||||
IB_pending <= 1'b0;
|
||||
UB_pending <= 1'b0;
|
||||
end
|
||||
else
|
||||
if (interrupt_inhibit_ib)
|
||||
begin
|
||||
IB_pending <= 1;
|
||||
interrupt_inhibit_delay <= 2'b10;
|
||||
end
|
||||
else
|
||||
if (interrupt_inhibit_ub)
|
||||
begin
|
||||
UB_pending <= 1;
|
||||
interrupt_inhibit_delay <= 2'b10;
|
||||
end
|
||||
else
|
||||
if (~IB_pending && ~UB_pending)
|
||||
begin
|
||||
interrupt_inhibit_delay[1] <= interrupt_inhibit_delay[0];
|
||||
interrupt_inhibit_delay[0] <= interrupt_inhibit_ion;
|
||||
end
|
||||
|
||||
//
|
||||
// registers
|
||||
//
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
begin
|
||||
mb <= 0;
|
||||
ac <= 0;
|
||||
mq <= 0;
|
||||
l <= 0;
|
||||
ir <= 0;
|
||||
run <= 1;
|
||||
interrupt_enable <= 0;
|
||||
interrupt_cycle <= 0;
|
||||
interrupt_skip <= 0;
|
||||
interrupt <= 0;
|
||||
UI <= 0;
|
||||
IF <= 0;
|
||||
DF <= 0;
|
||||
IB <= 0;
|
||||
SF <= 0;
|
||||
UF <= 0;
|
||||
UB <= 0;
|
||||
end
|
||||
else
|
||||
case (state)
|
||||
// FETCH
|
||||
F0:
|
||||
begin
|
||||
interrupt_skip <= 0;
|
||||
|
||||
if (interrupt && interrupt_enable &&
|
||||
!interrupt_inhibit && !interrupt_cycle)
|
||||
begin
|
||||
$display("xxx interrupt, pc %o; %b %b %b",
|
||||
pc, interrupt, interrupt_enable, interrupt_cycle);
|
||||
interrupt_cycle <= 1;
|
||||
interrupt <= 0;
|
||||
interrupt_enable <= 0;
|
||||
|
||||
// simulate a jsr to 0
|
||||
mb <= 12'o4000;
|
||||
ir <= 3'o4;
|
||||
SF <= {UF,IF,DF};
|
||||
IF <= 3'b000;
|
||||
DF <= 3'b000;
|
||||
end
|
||||
else
|
||||
begin
|
||||
interrupt_cycle <= 0;
|
||||
|
||||
//$display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
mb <= ram_data_in;
|
||||
ir <= ram_data_in[11:9];
|
||||
end
|
||||
end
|
||||
|
||||
F1:
|
||||
begin
|
||||
/* defaults - these should be comb logic */
|
||||
interrupt_inhibit_clear = 1'b0;
|
||||
interrupt_inhibit_ion = 1'b0;
|
||||
interrupt_inhibit_ib = 1'b0;
|
||||
interrupt_inhibit_ub = 1'b0;
|
||||
|
||||
/* defered loading of IF from IB at next jmp/jms */
|
||||
if ((jmp || jms) && IB_pending)
|
||||
begin
|
||||
//$display("loading IF %o", IB);
|
||||
IF <= IB;
|
||||
interrupt_inhibit_clear = 1'b1;
|
||||
end
|
||||
|
||||
if ((jmp || jms) && UB_pending)
|
||||
begin
|
||||
UF <= UB;
|
||||
interrupt_inhibit_clear = 1'b1;
|
||||
end
|
||||
|
||||
if (opr)
|
||||
case ({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;
|
||||
end
|
||||
|
||||
2'b10: // group 2
|
||||
begin
|
||||
if (mb[7])
|
||||
ac <= 0;
|
||||
end
|
||||
|
||||
2'b11: // group 3
|
||||
begin
|
||||
if (mb[7])
|
||||
ac <= 0;
|
||||
end
|
||||
|
||||
default:
|
||||
;
|
||||
endcase
|
||||
|
||||
if (iot)
|
||||
begin
|
||||
case (io_select)
|
||||
6'b000000: // ION, IOF
|
||||
case (mb[2:0])
|
||||
3'b001:
|
||||
begin
|
||||
interrupt_enable <= 1;
|
||||
interrupt_inhibit_ion = 1'b1;
|
||||
end
|
||||
3'b010: interrupt_enable <= 0;
|
||||
3'b011: if (interrupt_enable)
|
||||
interrupt_skip <= 1;
|
||||
endcase
|
||||
|
||||
6'b010xxx: // CDF..RMF
|
||||
begin
|
||||
if (mb[0])
|
||||
DF <= mb[5:3]; // CDF
|
||||
|
||||
if (mb[1])
|
||||
begin // CIF
|
||||
IB <= mb[5:3];
|
||||
interrupt_inhibit_ib = 1'b1;
|
||||
end
|
||||
|
||||
if (mb[2:0] == 3'b100)
|
||||
begin
|
||||
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'b100: begin // RMF
|
||||
UB <= SF[6];
|
||||
IB <= SF[5:3];
|
||||
DF <= SF[2:0];
|
||||
end
|
||||
|
||||
3'b101: // SINT
|
||||
if (UI)
|
||||
interrupt_skip <= 1;
|
||||
|
||||
3'b110: // CUF
|
||||
begin
|
||||
UB <= 0;
|
||||
interrupt_inhibit_ub = 1'b1;
|
||||
end
|
||||
|
||||
3'b111: // SUF
|
||||
begin
|
||||
UB <= 1;
|
||||
interrupt_inhibit_ub = 1'b1;
|
||||
end
|
||||
endcase // case(io_select[2:0])
|
||||
end // if (mb[2:0] == 3'b100)
|
||||
end // case: endcase...
|
||||
endcase // case(io_select)
|
||||
|
||||
if (io_data_avail)
|
||||
begin
|
||||
//$display("io_data clock %o", io_data_in);
|
||||
ac <= io_data_in;
|
||||
end
|
||||
|
||||
if (io_clear_ac)
|
||||
begin
|
||||
ac <= 0;
|
||||
end
|
||||
|
||||
end // if (iot)
|
||||
|
||||
if (io_interrupt)
|
||||
interrupt <= 1;
|
||||
|
||||
end // case: F1
|
||||
|
||||
F2:
|
||||
begin
|
||||
if (opr)
|
||||
begin
|
||||
// group 3
|
||||
if (mb[8] & mb[0])
|
||||
case ({mb[6:4]})
|
||||
3'b001: /* MQL */
|
||||
begin
|
||||
mq <= ac;
|
||||
ac <= 0;
|
||||
end
|
||||
3'b100: ac <= ac | mq;
|
||||
//3'b101: tmq <= mq;
|
||||
3'b100: ac <= mq; /* MQA */
|
||||
3'b101: ac <= mq;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
F3:
|
||||
begin
|
||||
if (opr)
|
||||
begin
|
||||
// group 1
|
||||
if (!mb[8])
|
||||
begin
|
||||
if (mb[0]) // IAC
|
||||
{l,ac} <= {l,ac} + 1'b1;
|
||||
case (mb[3:1])
|
||||
3'b001: // BSW
|
||||
{l,ac} <= {l,ac[5:0],ac[11:6]};
|
||||
3'b010: // RAL
|
||||
{l,ac} <= {ac[11:0],l};
|
||||
3'b011: // RTL
|
||||
{l,ac} <= {ac[10:0],l,ac[11]};
|
||||
3'b100: // RAR
|
||||
{l,ac} <= {ac[0],l,ac[11:1]};
|
||||
3'b101: // RTR
|
||||
{l,ac} <= {ac[1:0],l,ac[11:2]};
|
||||
endcase
|
||||
end
|
||||
|
||||
if (!UF)
|
||||
begin
|
||||
// group 2
|
||||
if (mb[8] & !mb[0])
|
||||
begin
|
||||
if (mb[2])
|
||||
ac <= ac | switches;
|
||||
if (mb[1])
|
||||
run <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
if (UF)
|
||||
begin
|
||||
// group 2 - user mode (halt & osr)
|
||||
if (mb[8] & !mb[0])
|
||||
begin
|
||||
if (mb[2])
|
||||
UI <= 1;
|
||||
if (mb[1])
|
||||
UI <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
// group 3
|
||||
if (mb[8] & mb[0])
|
||||
begin
|
||||
if (mb[7:4] == 4'b1101)
|
||||
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
|
||||
$display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
mb <= ram_data_in;
|
||||
end
|
||||
|
||||
D1:
|
||||
begin
|
||||
// auto increment locations
|
||||
if (is_index_reg)
|
||||
mb <= mb + 1;
|
||||
end
|
||||
|
||||
D2:
|
||||
begin
|
||||
// write ram
|
||||
$display("write ram [%o] <- %o", ram_addr, ram_data_out);
|
||||
end
|
||||
|
||||
D3:
|
||||
begin
|
||||
// if (jmp)
|
||||
// begin
|
||||
// //pc <= mb;
|
||||
// ir <= 0;
|
||||
// mb <= 0;
|
||||
// end
|
||||
//
|
||||
// if (!jmp)
|
||||
// begin
|
||||
// mb <= 0;
|
||||
// end
|
||||
end
|
||||
|
||||
// EXECUTE
|
||||
|
||||
E0:
|
||||
begin
|
||||
$display("read ram [%o] -> %o", ram_addr, ram_data_in);
|
||||
mb <= ram_data_in;
|
||||
end
|
||||
|
||||
E1:
|
||||
begin
|
||||
if (i_and)
|
||||
begin
|
||||
end
|
||||
|
||||
if (isz)
|
||||
mb <= mb + 1;
|
||||
else
|
||||
if (dca)
|
||||
mb <= ac;
|
||||
else
|
||||
if (jms)
|
||||
mb <= pc;
|
||||
end
|
||||
|
||||
E2:
|
||||
begin
|
||||
// write ram
|
||||
$display("write ram [%o] <- %o", ram_addr, ram_data_out);
|
||||
end
|
||||
|
||||
E3:
|
||||
begin
|
||||
if (i_and)
|
||||
ac <= ac & mb;
|
||||
else
|
||||
if (tad)
|
||||
{l,ac} <= {l,ac} + {1'b0,mb};
|
||||
else
|
||||
if (dca)
|
||||
ac <= 0;
|
||||
|
||||
// pc <- ma
|
||||
// ir <= 0;
|
||||
end
|
||||
endcase // case(state)
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -186,7 +186,7 @@ will process the information.
|
||||
|
||||
module pdp8_io(clk, reset, iot, state, mb,
|
||||
io_data_in, io_data_out, io_select,
|
||||
io_data_avail, io_interrupt, io_skip);
|
||||
io_data_avail, io_interrupt, io_skip, io_clear_ac);
|
||||
|
||||
input clk, reset, iot;
|
||||
input [11:0] io_data_in;
|
||||
@@ -197,7 +197,8 @@ module pdp8_io(clk, reset, iot, state, mb,
|
||||
output reg [11:0] io_data_out;
|
||||
output reg io_data_avail;
|
||||
output reg io_interrupt;
|
||||
output reg io_skip;
|
||||
output wire io_skip;
|
||||
output wire io_clear_ac;
|
||||
|
||||
|
||||
reg rx_int, tx_int;
|
||||
@@ -237,8 +238,8 @@ integer tx_delay;
|
||||
reg [11:0] DMA;
|
||||
reg [7:0] EMA;
|
||||
reg PEF;
|
||||
reg rf08_rw;
|
||||
reg rf08_start_io;
|
||||
reg rf08_rw;
|
||||
reg rf08_start_io;
|
||||
reg CIE, DRE, DRL, EIE, MEX, NXD, PCA, PER, PIE, WLS;
|
||||
|
||||
assign DCF = 1'b0;
|
||||
@@ -252,7 +253,7 @@ integer tx_delay;
|
||||
// sampled during f1
|
||||
io_skip = 0;
|
||||
io_data_out = io_data_in;
|
||||
io_data_avail = 1;
|
||||
io_clear_ac = 0;
|
||||
|
||||
if (state == F1 && iot)
|
||||
case (io_select)
|
||||
@@ -287,11 +288,15 @@ integer tx_delay;
|
||||
begin
|
||||
io_skip = 1;
|
||||
io_data_out = 0;
|
||||
io_clear_ac = 1;
|
||||
end
|
||||
3'o6: // DIMA
|
||||
io_data_out = { PCA, DRE,WLS,EIE, PIE,CIE,MEX, DRL,NXD,PER };
|
||||
3'o5: // DIML
|
||||
io_data_out = 0;
|
||||
begin
|
||||
io_data_out = 0;
|
||||
io_clear_ac = 1;
|
||||
end
|
||||
|
||||
endcase
|
||||
|
||||
@@ -313,7 +318,10 @@ integer tx_delay;
|
||||
6'o64:
|
||||
case (mb[2:0])
|
||||
3: // DXAL
|
||||
io_data_out = 0;
|
||||
begin
|
||||
io_data_out = 0;
|
||||
io_clear_ac = 1;
|
||||
end
|
||||
5: // DXAC
|
||||
io_data_out = EMA;
|
||||
endcase
|
||||
@@ -328,6 +336,8 @@ integer tx_delay;
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
begin
|
||||
rf08_rw <= 0;
|
||||
rf08_start_io <= 0;
|
||||
end
|
||||
else
|
||||
case (state)
|
||||
@@ -367,6 +377,8 @@ integer tx_delay;
|
||||
F1:
|
||||
if (iot)
|
||||
begin
|
||||
io_data_avail <= 1;
|
||||
|
||||
$display("iot2 %t, state %b, mb %o, io_select %o",
|
||||
$time, state, mb, io_select);
|
||||
|
||||
|
||||
22
rtl/pdp8_ram.v
Normal file
22
rtl/pdp8_ram.v
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
|
||||
`include "ram_32kx12.v"
|
||||
|
||||
module pdp8_ram(clk, reset, addr, data_in, data_out, rd, wr);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
input [14:0] addr;
|
||||
input [11:0] data_in;
|
||||
output [11:0] data_out;
|
||||
input rd;
|
||||
input wr;
|
||||
|
||||
|
||||
ram_32kx12 ram(.A(addr),
|
||||
.DI(data_in),
|
||||
.DO(data_out),
|
||||
.CE_N(1'b0),
|
||||
.WE_N(~wr));
|
||||
|
||||
endmodule
|
||||
49
rtl/ram_32kx12.v
Normal file
49
rtl/ram_32kx12.v
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
/* 32kx12 static ram */
|
||||
module ram_32kx12(A, DI, DO, CE_N, WE_N);
|
||||
|
||||
input[14:0] A;
|
||||
input[11:0] DI;
|
||||
input CE_N, WE_N;
|
||||
output[11:0] DO;
|
||||
|
||||
reg[11:0] ram [0:32767];
|
||||
integer i;
|
||||
|
||||
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;
|
||||
|
||||
`include "focal.v"
|
||||
ram[15'o0000] = 12'o5404;
|
||||
ram[15'o0004] = 12'o0200;
|
||||
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);
|
||||
ram[ A ] = DI;
|
||||
end
|
||||
end
|
||||
|
||||
//always @(A)
|
||||
// begin
|
||||
// $display("ram: ce %b, we %b [%o] -> %o", CE_N, WE_N, A, ram[A]);
|
||||
// end
|
||||
|
||||
// assign DO = ram[ A ];
|
||||
assign DO = (^A === 1'bX || A === 1'bz) ? ram[0] : ram[A];
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user