/****************************************************************

* 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 */