/****************************************************************
* mp8085 DEMONSTRATION *
* Simulation demonstration of the Intel 8085a microprocessor *
* with program in RAM, *
* *
****************************************************************/
module s85; // simulation control module
reg [8:1] dflags;
initial dflags = 0;
// diag flags:
// 1 = printmem
// 2 = dump state at end
// 3 = test reset control
// 4 = monitor the transmit and receive lines
wire s0, ale, rxd, txd, clock;
tri[7:0] ad, a;
tri1 read, write, iomout;
reg trap, rst7p5, rst6p5, rst5p5,
intr, ready, nreset, hold, pclock;
//instantiate the clock
osc timebase(clock);
//instantiate the RAM module
ram85a r0(ale, ad, a, write, read, iomout);
//instantiate the 8085a processor module
intel_8085a i85(clock, , , , , trap,
rst7p5, rst6p5, rst5p5, intr, ,
ad, a, s0, ale, write, read, ,
iomout, ready, nreset,
, , hold);
initial
begin
$write("\n");
$write(" current test program sorting an array beginning");
$write(" at ram[h30], no of elements is in ram[h2F] \n");
r0.printmem;
$write("\n after sorting \n");
$write(" \n");
if(dflags[4])
$monitor($time,,txd,,rxd);
// clock = 0;
pclock = 0;
nreset = 0;
trap = 0;
rst7p5 = 0;
rst6p5 = 0;
rst5p5 = 0;
intr = 0;
ready = 0;
hold = 0;
#500
begin
nreset = 1;
ready = 1;
end
@(posedge i85.haltff) @(posedge timebase.clock);
r0.printmem;
$finish;//disable clockwave;
//disable pclockwave;
disable i85.run_processor;
if(dflags[1]) r0.printmem;
if(dflags[2]) i85.dumpstate;
end
/* test reset control */
initial if(dflags[3])
begin
# 5000 nreset = 0; #500 nreset = 1;
# 6000 nreset = 0; #500 nreset = 1;
#10000 nreset = 0; #500 nreset = 1;
#20000 nreset = 0; #1000 nreset = 1;
end
endmodule // s85
/* ram module for 8085a */
module ram85a(ale, ad, a, write, read, iomout);
reg [8:1] dflags;
initial dflags = 'b00000000;
// diag flags:
// 1 = trace read and writes
// 2 = dump ram after loading
inout[7:0] ad;
input[7:0] a;
input ale, write, read, iomout;
reg[7:0] ad_reg;
tri[7:0] ad = (read || iomout) ? 'bz : ad_reg;
parameter ramsize = 'h7A;
reg[7:0] ram[ramsize-1:0];
reg[15:0] address;
always @(negedge ale) begin
address = {a, ad};
if(dflags[1])
$display("Reading %h into ram address", address);
end
always @(negedge read) begin
if(dflags[1])
$display("Reading %h = ram[%h]", ram[address], address);
ad_reg = ram[address];
end
always @(negedge write) begin
if(dflags[1])
$display("Writing ram[%h] = %h", address, ad);
ram[address] = ad;
end
//define contents of RAM
//sorting data ram['h30]; no of elements in the array,
//array begins at ram['h31]
initial begin
ram['h0]='h06; ram['h1]='h00; ram['h2]='h21; ram['h3]='h2F;
ram['h4]='h00; ram['h5]='h4E; ram['h6]='h0D; ram['h7]='h23;
ram['h8]='h7E; ram['h9]='h23; ram['ha]='hBE; ram['hb]='hD2;
ram['hc]='h15; ram['hd]='h00; ram['he]='h56; ram['hf]='h77;
ram['h10]='h2B; ram['h11]='h72; ram['h12]='h23; ram['h13]='h06;
ram['h14]='h01; ram['h15]='h0D; ram['h16]='hC2; ram['h17]='h08;
ram['h18]='h00; ram['h19]='h05; ram['h1a]='hCA; ram['h1b]='h00;
ram['h1c]='h00; ram['h1d]='h76; ram['h1e]='h00; ram['h1f]='hDB;
ram['h20]='hF0; ram['h21]='h77; ram['h22]='hC9; ram['h23]='h7E;
ram['h24]='h0F; ram['h25]='h0F; ram['h26]='h0F; ram['h27]='h0F;
ram['h28]='hCD; ram['h29]='h30; ram['h2a]='h00; ram['h2b]='h7E;
ram['h2c]='hCD; ram['h2d]='h30; ram['h2e]='h00; ram['h2f]='h09;
ram['h30]='h08; ram['h31]='h0F; ram['h32]='hFE; ram['h33]='h0A;
ram['h34]='hD2; ram['h35]='h3C; ram['h36]='h00; ram['h37]='hFF;
ram['h38]='h30; ram['h39]='hC3; ram['h3a]='h3E; ram['h3b]='h00;
ram['h3c]='hC6; ram['h3d]='h37; ram['h3e]='h47; ram['h3f]='hDB;
ram['h40]='hF1; ram['h41]='hE6; ram['h42]='h01; ram['h43]='hCA;
ram['h44]='h3E; ram['h45]='h00; ram['h46]='h78; ram['h47]='hD3;
ram['h48]='hF0; ram['h49]='hC9;
/* last address of this program is 007AH (STACK) */
if(dflags[2])
printmem;
end
//print out the contents of the RAM
task printmem;
integer i;
reg[7:0] data;
begin
$write("dump of ram");
for(i = 0; i < ramsize; i = i + 1)
begin
data = ram[i];
if((i % 4) == 0) $write(" ");
if((i % 16) == 0) $write("\n%h: ", i);
$write("%h", data);
$write(" ");
end
$write("\n\n");
end
endtask
endmodule
/* Behavioral description of the Intel 8085a microprocessor */
module intel_8085a
(clock, x2, resetff, sodff, sid, trap,
rst7p5, rst6p5, rst5p5, intr, intaff,
ad, a, s0, aleff, writeout, readout, s1,
iomout, ready, nreset,
clockff, hldaff, hold);
reg [8:1] dflags;
initial dflags = 'b000;
// diag flags:
// 1 = trace instructions
// 2 = trace IN and OUT instructions
// 3 = trace instruction count
output
resetff, sodff, intaff, s0, aleff,
writeout, readout, s1, iomout, clockff, hldaff;
inout[7:0] ad, a;
input
clock, x2, sid, trap,
rst7p5, rst6p5, rst5p5,
intr, ready, nreset, hold;
reg[15:0]
pc, // program counter
sp, // stack pointer
addr; // address output
reg[8:0]
intmask; // interrupt mask and status
reg[7:0]
acc, // accumulator
regb, // general
regc, // general
regd, // general
rege, // general
regh, // general
regl, // general
ir, // instruction
data; // data output
reg
aleff, // address latch enable
s0ff, // status line 0
s1ff, // status line 1
hldaff, // hold acknowledge
holdff, // internal hold
intaff, // interrupt acknowledge
trapff, // trap interrupt request
trapi, // trap execution for RIM instruction
inte, // previous state of interrupt enable flag
int, // interrupt acknowledge in progress
validint, // interrupt pending
haltff, // halt request
resetff, // reset output
clockff, // clock output
sodff, // serial output data
read, // read request signal
write, // write request signal
iomff, // i/o memory select
acontrol, // address output control
dcontrol, // data output control
s, // data source control
cs, // sign condition code
cz, // zero condition code
cac, // aux carry condition code
cp, // parity condition code
cc; // carry condition code
wire
s0 = s0ff & ~haltff,
s1 = s1ff & ~haltff;
tri[7:0]
ad = dcontrol ? (s ? data : addr[7:0]) : 'bz,
a = acontrol ? addr[15:8] : 'bz;
tri
readout = acontrol ? read : 'bz,
writeout = acontrol ? write : 'bz,
iomout = acontrol ? iomff : 'bz;
integer instruction; // instruction count
initial instruction = 0;
always begin:run_processor
#1 reset_sequence;
fork
execute_instructions; // Instructions executed
wait(!nreset) // in parallel with reset
@(posedge clock) disable run_processor; // control. Reset will
join // disable run_processor
end // and all tasks and
// functions enabled from
// it when nreset set to 0.
task reset_sequence;
begin
wait(!nreset)
fork
begin
$display("Performing 8085(%m) reset sequence");
read = 1;
write = 1;
resetff = 1;
dcontrol = 0;
@(posedge clock) // synchronized with clock 1 event
pc = 0;
ir = 0;
intmask[3:0] = 7;
intaff = 1;
acontrol = 0;
aleff = 0;
intmask[7:5] = 0;
sodff = 0;
trapff = 0;
trapi = 0;
iomff = 0;
haltff = 0;
holdff = 0;
hldaff = 0;
validint = 0;
int = 0;
disable check_reset;
end
begin:check_reset
wait(nreset) // Check, in parallel with the
disable run_processor; // reset sequence, that nreset
end // remains at 0.
join
wait(nreset) @(posedge clock) @(posedge clock) resetff = 0;
end
endtask
/* fetch and execute instructions */
task execute_instructions;
forever begin
instruction = instruction + 1;
if(dflags[3])
$display("executing instruction %d", instruction);
@(posedge clock) // clock cycle 1
addr = pc;
s = 0;
iomff = 0;
read = 1;
write = 1;
acontrol = 1;
dcontrol = 1;
aleff = 1;
if(haltff) begin
haltff = 1;
s0ff = 0;
s1ff = 0;
haltreq;
end
else begin
s0ff = 1;
s1ff = 1;
end
@(posedge clock)
aleff = 0;
@(posedge clock) // clock cycle 2
read = 0;
dcontrol = 0;
@(posedge clock)
ready_hold;
@(posedge clock) // clock cycle 3
read = 1;
data = ad;
ir = ad;
@(posedge clock) // clock cycle 4
if(do6cycles(ir)) begin
// do a 6-cycle instruction fetch
@(posedge clock) // conditional clock cycle 5
if(hold) begin
holdff =1 ;
acontrol = 0;
dcontrol = 0;
@(posedge clock) hldaff = 1;
end
else begin
holdff = 0;
hldaff = 0;
end
@(posedge clock); // conditional clock cycle 6
end
if(holdff) holdit;
checkint;
do_instruction;
while(hold) @(posedge clock) begin
acontrol = 0;
dcontrol = 0;
end
holdff = 0;
hldaff = 0;
if(validint) interrupt;
end
endtask
function do6cycles;
input[7:0] ireg;
begin
do6cycles = 0;
case(ireg[2:0])
0, 4, 5, 7: if(ireg[7:6] == 3) do6cycles = 1;
1: if((ireg[3] == 1) & (ireg[7:5] == 7)) do6cycles = 1;
3: if(ireg[7:6] == 0) do6cycles = 1;
endcase
end
endfunction
task checkint;
begin
if(rst6p5)
if((intmask[3] == 1) & (intmask[1] == 0)) intmask[6] = 1;
else
intmask[6] = 0;
if(rst5p5)
if((intmask[3] == 1) & (intmask[0] == 0)) intmask[5] = 1;
else
intmask[5] = 0;
if({intmask[7], intmask[3:2]} == 6)
intmask[4] = 1;
else
intmask[4] = 0;
validint = (intmask[6:4] == 7) | trapff | intr;
end
endtask
// concurently with executing instructions,
// process primary inputs for processor interrupt
always @(posedge trap) trapff = 1;
always @(negedge trap) trapff = 0;
always @(posedge rst7p5) intmask[7] = 1;
/* check condition of ready and hold inputs */
task ready_hold;
begin
while(!ready) @(posedge clock);
@(posedge clock)
if(hold) begin
holdff = 1;
@(posedge clock) hldaff = 1;
end
end
endtask
/* hold */
task holdit;
begin
while(hold) @(posedge clock) begin
acontrol = 0;
dcontrol = 0;
end
holdff = 0;
@(posedge clock) hldaff = 0;
end
endtask
/* halt request */
task haltreq;
forever begin
@(posedge clock)
if(validint) begin
haltff = 0;
interrupt;
disable haltreq;
end
else begin
while(hold) @(posedge clock) hldaff = 1;
hldaff = 0;
@(posedge clock);
end
@(posedge clock) #10
dcontrol = 0;
acontrol = 0;
checkint;
end
endtask
/* memory read */
task memread;
output[7:0] rdata;
input[15:0] raddr;
begin
@(posedge clock)
addr = raddr;
s = 0;
acontrol = 1;
dcontrol = 1;
iomff = int;
s0ff = int;
s1ff = 1;
aleff = 1;
@(posedge clock)
aleff = 0;
@(posedge clock)
dcontrol = 0;
if(int)
intaff = 0;
else
read = 0;
@(posedge clock)
ready_hold;
checkint;
@(posedge clock)
intaff = 1;
read = 1;
rdata = ad;
if(holdff) holdit;
end
endtask
/* memory write */
task memwrite;
input[7:0] wdata;
input[15:0] waddr;
begin
@(posedge clock)
aleff = 1;
s0ff = 1;
s1ff = 0;
s = 0;
iomff = 0;
addr = waddr;
acontrol = 1;
dcontrol = 1;
@(posedge clock)
aleff = 0;
@(posedge clock)
data = wdata;
write = 0;
s = 1;
@(posedge clock)
ready_hold;
checkint;
@(posedge clock)
write = 1;
if(holdff) holdit;
end
endtask
/* reads from an i/o port */
task ioread;
input[7:0] sa;
begin
@(posedge clock)
aleff = 1;
s0ff = 0;
s1ff = 1;
s = 0;
iomff = 1;
addr = {sa, sa};
acontrol = 1;
dcontrol = 1;
@(posedge clock)
aleff = 0;
@(posedge clock)
dcontrol = 0;
if(int)
intaff = 0;
else
read = 0;
@(posedge clock)
ready_hold;
checkint;
@(posedge clock)
intaff = 1;
read = 1;
acc = ad;
if(dflags[2])
$display("IN %h data = %h", sa, acc);
end
endtask
/* writes into i/o port */
task iowrite;
input[7:0] sa;
begin
@(posedge clock)
addr = {sa, sa};
aleff = 1;
s0ff = 1;
s1ff = 0;
s = 0;
iomff = 1;
acontrol = 1;
dcontrol = 1;
@(posedge clock)
aleff = 0;
@(posedge clock)
data = acc;
write = 0;
s = 1;
if(dflags[2])
$display("OUT %h data = %h", sa, acc);
@(posedge clock)
ready_hold;
checkint;
@(posedge clock)
write = 1;
if(holdff) holdit;
end
endtask
task interrupt;
begin
@(posedge clock)
if(hold) begin
holdff = 1;
holdit;
@(posedge clock) hldaff = 1;
end
if(trapff) begin
inte = intmask[3];
trapi = 1;
intic;
pc = 'h24;
trapi = 1;
trapff = 0;
end
else if(intmask[7]) begin
intic;
pc = 'h3c;
intmask[7] = 0;
end
else if(intmask[6]) begin
intic;
pc = 'h34;
intmask[6] = 0;
end
else if(intmask[5]) begin
intic;
pc = 'h2c;
intmask[5] = 0;
end
else if(intr) begin
//?
end
end
endtask
task intic;
begin
aleff = 1;
s0ff = 1;
s1ff = 1;
s = 0;
iomff = 1;
addr = pc;
read = 1;
write = 1;
acontrol = 1;
dcontrol = 1;
@(posedge clock) aleff = 0;
@(posedge clock) dcontrol = 0;
repeat(4) @(posedge clock);
push2b(pc[15:8], pc[7:0]);
end
endtask
/* execute instruction */
task do_instruction;
begin
if(dflags[1])
$display(
"C%bZ%bM%bE%bI%b A=%h B=%h%h D=%h%h H=%h%h S=%h P=%h IR=%h",
cc, cz, cs, cp, cac,
acc, regb,regc, regd,rege, regh,regl,
sp, pc, ir);
pc = pc + 1;
@(posedge clock) // instruction decode synchronized with clock 2 event
case(ir[7:6])
0:
case(ir[2:0])
0: newops;
1: begin
if(ir[3]) addhl; else lrpi;
end
2: sta_lda;
3: inx_dcx;
4: inr;
5: dcr;
6: movi;
7: racc_spec;
endcase
1:
move;
2:
rmop;
3:
case(ir[2:0])
0,
2,
4: condjcr;
1: if(ir[3]) decode1; else pop;
3: decode2;
5: if(ir[3]) decode3; else push;
6: immacc;
7: restart;
endcase
endcase
end
endtask
/* move register to register */
task move;
case(ir[2:0])
0: rmov(regb); // MOV -,B
1: rmov(regc); // MOV -,C
2: rmov(regd); // MOV -,D
3: rmov(rege); // MOV -,E
4: rmov(regh); // MOV -,H
5: rmov(regl); // MOV -,L
6:
if(ir[5:3] == 6)
begin
haltff = 1; // HLT
end
else begin // MOV -,M
memread(data, {regh, regl});
rmov(data);
end
7: rmov(acc); // MOV -,A
endcase
endtask
/* enabled only by move */
task rmov;
input[7:0] fromreg;
case(ir[5:3])
0: regb = fromreg; // MOV B,-
1: regc = fromreg; // MOV C,-
2: regd = fromreg; // MOV D,-
3: rege = fromreg; // MOV E,-
4: regh = fromreg; // MOV H,-
5: regl = fromreg; // MOV L,-
6: memwrite(fromreg, {regh, regl}); // MOV M,-
7: acc = fromreg; // MOV A,-
endcase
endtask
/* move register and memory immediate */
task movi;
begin
case(ir[5:3])
0: memread(regb, pc); // MVI B
1: memread(regc, pc); // MVI C
2: memread(regd, pc); // MVI D
3: memread(rege, pc); // MVI E
4: memread(regh, pc); // MVI H
5: memread(regl, pc); // MVI L
6: // MVI M
begin
memread(data, pc);
memwrite(data, {regh, regl});
end
7: memread(acc, pc); // MVI A
endcase
pc = pc + 1;
end
endtask
/* increment register and memory contents */