Vous êtes sur la page 1sur 9

Design an 8-bit Processor with Verilog

at Behavioral Level

We use the Intel 8085 all time popular 8-bit processor as an


example.

A complete functional Verilog model for the Intel 8085 will be


presented.

Lecture outline
1. review the architecture, chip layout, pin definition
2. instruction set
3. 8085 Verilog models
4. 8085 Verilog test bench.

1 2

Architecture of the 8085


The 8085 has:
A 16-bit program counter (PC)
A 16-bit stack pointer (SP)
An 8-bit instruction register
An 8-bit accumulator
Six 8-bit general purpose registers, B, C, D, E, H, L
BC, DE, HL can be accessed in pairs or individually.
A temporary register pair: W, Z
Instructions are 1 to 3 bytes in length and the first byte is the OPCODE

Seven different machine cycles


(each machine cycle may take up to 4 clock cycles)
1. opcode fetch
2. memory read
3. memory write
4. I/O read
5. I/O write
6. interrupt acknowledge
7. bus idle
3 4

1
S0, S1 (Output) READY (Input)

Data Bus Status. Encoded status of the bus cycle: If Ready is high during a read or write cycle, it indicates that the memory
or peripheral is ready to send or receive data.
S1 S0 If Ready is low, the CPU will wait for Ready to go high before
0 0 HALT completing the read or write cycle.
0 1 WRITE
1 0 READ
1 1 FETCH HOLD (Input)

RD (Output 3state) HOLD; indicates that another Master is requesting the use of the Address
and Data Buses. The CPU, upon receiving the Hold request. will relinquish
READ; indicates the selected memory or I/O device is to be read the use of buses as soon as the completion of the current machine cycle.
and that the Data Bus is available for the data transfer. Internal processing can continue. The processor can regain the buses only
3stated during Hold and Halt. after the Hold is removed.
When the Hold is acknowledged, the Address, Data, RD, WR, and IO/M lines
WR (Output 3state) are 3stated.

WRITE; indicates the data on the Data Bus is to be written into


the selected memory or I/O location. 3stated during Hold and Halt modes.

5 6

HLDA (Output) TRAP (Input)

HOLD ACKNOWLEDGE; indicates that the CPU has received the Hold request Trap interrupt is a nonmaskable restart interrupt.
and that it will relinquish thebuses in the next clock cycle. It is recognized at the same time as INTR.
HLDA goes low after the Hold request is removed. It is unaffected by any mask or Interrupt Enable.
The CPU takes the buses one half clock cycle after HLDA goes low. It has the highest priority of any interrupt.

RESTART INTERRUPTS; Name RESTART Address (Hex)


These three inputs have the same timing as INTR except they cause
an internal RESTART to be automatically inserted. TRAP 2416
RST 5.5 2C16
RST 7.5 Highest Priority RST 6.5 3416
RST 6.5 RST 7.5 3C16
RST 5.5 Lowest Priority

The priority of these interrupts is ordered as shown above. RESET IN (Input)


These interrupts have a higher priority than the INTR.
Reset sets the Program Counter to zero and resets the Interrupt Enable
and HLDA flip flops.

7 8

2
IO/M (Output) module s85; // simulation testbench module

IO/M indicates whether the Read/Write is to memory or l/O reg [8:1] dflags;
Tristated during Hold and Halt modes. initial dflags = 0;
// diag flags:
// 1 = printmem
RESET OUT (Output)
// 2 = dump state at end
// 3 = test reset control
Indicates CPU is being reset. Can be used as a system RESET.
// 4 = monitor the transmit and receive lines
The signal is synchronized to the processor clock.
wire s0, ale, rxd, txd, clock;
X1, X2 (Input)
tri[7:0] ad, a;
Crystal or R/C network connections to set the internal clock generator tri1 read, write, iomout;
X1 can also be an external clock input instead of a crystal.
The input frequency is divided by 2 to give the internal operating frequency. reg trap, rst7p5, rst6p5, rst5p5,
intr, ready, nreset, hold, pclock;

CLK (Output)

Clock Output for use as a system clock


9 10

module intel_8085a
//instantiate the clock (clock, x2, resetff, sodff, sid, trap,
osc timebase(clock); rst7p5, rst6p5, rst5p5, intr, intaff,
ad, a, s0, aleff, writeout, readout, s1,
//instantiate the RAM module iomout, ready, nreset,
ram85a r0(ale, ad, a, write, read, iomout); clockff, hldaff, hold);

//instantiate the 8085a processor module reg [8:1] dflags;


intel_8085a i85(clock, , , , , trap, initial dflags = 'b000;
rst7p5, rst6p5, rst5p5, intr, , // diag flags:
ad, a, s0, ale, write, read, , // 1 = trace instructions
iomout, ready, nreset, // 2 = trace IN and OUT instructions
, , hold); // 3 = trace instruction count

initial output
begin resetff, sodff, intaff, s0, aleff,
$write("\n"); writeout, readout, s1, iomout, clockff, hldaff;

inout[7:0] ad, a; // a is address bus low byte output only


….. input
….. clock, x2, sid, trap,
endmodule rst7p5, rst6p5, rst5p5,
11 intr, ready, nreset, hold; 12

3
reg[15:0]
pc, // program counter intaff, // interrupt acknowledge
sp, // stack pointer trapff, // trap interrupt request
addr; // address output trapi, // trap execution for RIM instruction (RIM:read interrupt mask)
inte, // previous state of interrupt enable flag
reg[8:0] int, // interrupt acknowledge in progress
intmask; // interrupt mask and status validint, // interrupt pending
haltff, // halt request
reg[7:0] resetff, // reset output
acc, // accumulator clockff, // clock output
regb, // general sodff, // serial output data
regc, // general read, // read request signal
regd, // general write, // write request signal
rege, // general iomff, // i/o memory select
regh, // general acontrol, // address output control
regl, // general dcontrol, // data output control
ir, // instruction s, // data source control
data; // data output cs, // sign condition code
reg cz, // zero condition code
aleff, // address latch enable cac, // aux carry condition code
s0ff, // status line 0 cp, // parity condition code
s1ff, // status line 1 cc; // carry condition code
hldaff, // hold acknowledge
13 14
holdff, // internal hold

The condition flags


Z Zero Overview of Instruction set
S Sign
P Parity 1. Data Transfer Group
C Carry 2. Logic Group
A Auxiliary carry 3. Branch Group
4. Stack and Machine Control Group
Registers: A, B, C, D, E, H, L 5. Arithmetic Group
Register pairs: BC, DE, HL
Data Transfer Instructions
Symbols and abbreviations used in Assembly language
accumulator Register A
IN port // move data at port to Accumulator
addr 16-bit address
(A) Å (port) // two byte instruction, first byte is OPCODE
data 8-bit data
//second byte is port address
data 16 16-bit data
OUT port //move data from A to port
byte 2 the second byte of the instruction
(port) Å (A)
byte 3 the third byte of the instruction
port 8-bit address of an I/O device
For examples
r, r1, r2 one of the registers A, B, C, D, E, H, L
IN 5
DDD, SSS destination, source
OUT 1
rp register pair
( ) the contents of the memory location or register
enclosed in the parentheses 15 16

4
LDA addr //load accumulator direct
(A) Å ((byte 3) (byte 2)) MOV M, r //store r in memory

STA addr //store accumulator direct LDAX rp //load accumulator indirect


((byte 3)(byte 2)) Å (A) (A) Å ((rp))

example: STAX rp //store accumulator indirect


LDA First // First is a 16-bit address ((rp)) Å (A)
STA First
MVI r, data //move immediate
LHLD addr //load H and L direct (r) Å (byte 2)
(L) Å ((byte3) (byte 2))
(H) Å ((byte 3) (byte 2) + 1) LXI rp, data 16 //load register pair immediate
(rl) Å (byte 2)
SHLD addr //store H and L direct (rh) Å (byte 3)
((byte 3)(byte 2)) Å (L)
((byte 3)(byte 2) + 1) Å (H) MVI M, data //move to memory immediate
((H)(L)) Å (byte 2)
MOV r, M //move from memory specified by HL
(r) Å ((H)(L)) //to a register r
example
MOV B, M
17 18

Verilog Model Examples for Data Transfer Instructions


/* enabled only by move */
/* move register to register */
task rmov;
task move;
input[7:0] fromreg;
case(ir[2:0])
case(ir[5:3])
0: rmov(regb); // MOV -,B
0: regb = fromreg; // MOV B,-
1: rmov(regc); // MOV -,C
1: regc = fromreg; // MOV C,-
2: rmov(regd); // MOV -,D
2: regd = fromreg; // MOV D,-
3: rmov(rege); // MOV -,E
3: rege = fromreg; // MOV E,-
4: rmov(regh); // MOV -,H
4: regh = fromreg; // MOV H,-
5: rmov(regl); // MOV -,L
5: regl = fromreg; // MOV L,-
6:
6: memwrite(fromreg, {regh, regl}); // MOV M,-
if(ir[5:3] == 6)
7: acc = fromreg; // MOV A,-
begin
endcase
haltff = 1; // HLT
endtask
end
else begin // MOV -,M
memread(data, {regh, regl});
rmov(data);
end
7: rmov(acc); // MOV -,A
endcase
endtask 19 20

5
/* increment register and memory contents */
/* move register and memory immediate */ task inr;
task movi; case(ir[5:3])
begin 0: doinc(regb); // INR B
case(ir[5:3]) 1: doinc(regc); // INR C
0: memread(regb, pc); // MVI B, -- 2: doinc(regd); // INR D
1: memread(regc, pc); // MVI C, -- 3: doinc(rege); // INR E
2: memread(regd, pc); // MVI D, -- 4: doinc(regh); // INR H
3: memread(rege, pc); // MVI E, -- 5: doinc(regl); // INR L
4: memread(regh, pc); // MVI H, -- 6: // INR M
5: memread(regl, pc); // MVI L, -- begin
6: // MVI M, -- ; ((H)(L)) <-- (byte 2) memread(data, {regh, regl});
begin doinc(data);
memread(data, pc); memwrite(data, {regh, regl});
memwrite(data, {regh, regl}); end
end
7: doinc(acc); // INR A
7: memread(acc, pc); // MVI A endcase
endcase endtask
pc = pc + 1;
end
endtask
21 22

/* enabled only from incrm */


/* store and load instruction */
task doinc;
task sta_lda;
inout[7:0] sr;
reg[15:0] ra;
begin
case(ir[5:3])
cac = sr[3:0] == 'b1111;//auxiliary carry is set least 4 bits = 1111
0: memwrite(acc, {regb, regc}); // STAX B
// i.e., ac is 1 when ----1111 is incremented
1: memread(acc, {regb, regc}); // LDAX B
//by one
2: memwrite(acc, {regd, rege}); // STAX D
sr = sr + 1;
3: memread(acc, {regd, rege}); // LDAX D
calpsz(sr);
end
4: // SHLD
endtask
begin
adread(ra);
/* calculate cp cs and cz */ memwrite(regl, ra);
task calpsz; memwrite(regh, ra + 1);
input[7:0] tr; end
begin 5: // LHLD
cp = ^tr; //parity, ^Exclusive or all bits of tr begin
cz = tr == 0; //zero flag adread(ra);
cs = tr[7]; //sign flag memread(regl, ra);
end memread(regh, ra + 1);
endtask end
23 24

6
6: // STA
begin
adread(ra); /* memory read */ @(posedge clock)
memwrite(acc, ra); task memread; dcontrol = 0;
end output[7:0] rdata; if(int)
7: // LDA input[15:0] raddr; intaff = 0;
begin begin else
adread(ra); @(posedge clock) read = 0;
memread(acc, ra); addr = raddr; @(posedge clock)
end s = 0; ready_hold;
endcase acontrol = 1; checkint;
endtask dcontrol = 1;
iomff = int; @(posedge clock)
/* fetch address from pc+1, pc+2 */
s0ff = int; intaff = 1;
task adread;
s1ff = 1; read = 1;
output[15:0] address;
aleff = 1; rdata = ad;
begin
@(posedge clock) if(holdff) holdit;
memread(address[7:0], pc);
aleff = 0; end
pc = pc + 1;
endtask
memread(address[15:8], pc);
if(!int) pc = pc + 1; // if interrupt is not true, pc = pc+1
end
endtask 25 26

Logic and Arithmetic operations

/* memory write */ CMA // complement the accumulator


task memwrite; (A) Å (A)
input[7:0] wdata; CMC // complement the carry flag
@(posedge clock) (CY) Å (CY)
input[15:0] waddr;
data = wdata;
begin STC // set the carry flag
write = 0;
@(posedge clock) ANI data // AND immediate, A and with byte 2
s = 1;
aleff = 1; ANA r // A and with register r
@(posedge clock)
s0ff = 1; ANA M // A and with memory
ready_hold;
s1ff = 0; ORI // OR immediate, A or with byte 2
checkint;
s = 0; ORA r // A or with register r
iomff = 0; ORA M // A or with memory
@(posedge clock)
addr = waddr; XRI data // Exclusive_OR immediate
write = 1;
acontrol = 1; XRA r // A xor with register r
if(holdff) holdit;
dcontrol = 1; XRA M // A xor with memory
end
@(posedge clock) CPI data // compare immediate
endtask
aleff = 0; CMP r // compare register
CMP M // compare memory

27 28

7
RLC rotate accumulator left
(CY) ÅA7; A0 ÅA7; An+1 Å An SBI data subtract immediate with borrow

RRC rotate accumulator right INR r increment register


(CY) ÅA0; A7 ÅA0; An ÅAn+1 INR M increment memory
DCR r decrement register
RAL rotate left through carry DCR M decrement memory
RAR rotate right through carry INX rp increment register pair
DCX rp decrement register pair
ADD r add register
(A) Å(A) + (r) DAD rp add register pair to H and L
DAA decimal adjust accumulator
ADD M add memory
ADI data add immediate
ADC r add register with carry
ADC M add memory with carry
ACI data add immediate with carry
SUB r subtract register
SUB M subtract memory
SUI data subtract immediate
SBB r subtract register with borrow
SBB M subtract memory with borrow
29 30

5: // XRA XRI
2: // SUB SUI
/* operate on accumulator */ begin
begin
task doacci; acc = acc ^ sr;
{cac, null4} = acc - sr;
input[7:0] sr; cac = 0;
{cc, acc} = {1'b0, acc} - sr;
reg[3:0] null4; cc = 0;
calpsz(acc);
reg[7:0] null8; calpsz(acc);
end
case(ir[5:3]) end
0: // ADD ADI
3: // SBB SBI
begin 6: // ORA ORI
begin
{cac, null4} = acc + sr; begin
{cac, null4} = acc - sr - cc;
{cc, acc} = {1'b0, acc} + sr; acc = acc | sr;
{cc, acc} = {1'b0, acc} - sr - cc;
calpsz(acc); cac = 0;
calpsz(acc);
end cc = 0;
end
calpsz(acc);
1: // ADC ACI end
4: // ANA ANI
begin
begin
{cac, null4} = acc + sr + cc; 7: // CMP CPI
acc = acc & sr;
{cc, acc} = {1'b0, acc} + sr + cc; begin
cac = 1;
calpsz(acc); {cac, null4} = acc - sr;
cc = 0;
end {cc, null8} = {1'b0, acc} - sr;
calpsz(acc);
calpsz(null8);
end
end
endcase
31 32
endtask

8
/* rotate acc and special instructions */ 3: // RAR
task racc_spec; {acc, cc} = {cc, acc};
case(ir[5:3])
0: // RLC 4: // DAA, decimal adjust
begin begin
acc = {acc[6:0], acc[7]}; if((acc[3:0] > 9) || cac) acc = acc + 6;
cc = acc[7]; if((acc[7:4] > 9) || cc) {cc, acc} = {1'b0, acc} + 'h60;
end end

1: // RRC 5: // CMA
begin acc = ~acc;
acc = {acc[0], acc[7:1]};
cc = acc[0]; 6: // STC
end cc = 1;

2: // RAL 7: // CMC
{cc, acc} = {acc, cc}; cc = ~cc;
endcase
endtask

33 34

/* increment and decrement register pair */


task inx_dcx;
case(ir[5:3]) /* add into regh, regl pair */
0: {regb, regc} = {regb, regc} + 1; // INX B task addhl;
1: {regb, regc} = {regb, regc} - 1; // DCX B begin
2: {regd, rege} = {regd, rege} + 1; // INX D case(ir[5:4])
3: {regd, rege} = {regd, rege} - 1; // DCX D 0: {cc, regh, regl} = {1'b0, regh, regl} + {regb, regc}; // DAD B
4: {regh, regl} = {regh, regl} + 1; // INX H 1: {cc, regh, regl} = {1'b0, regh, regl} + {regd, rege}; // DAD D
5: {regh, regl} = {regh, regl} - 1; // DCX H 2: {cc, regh, regl} = {1'b0, regh, regl} + {regh, regl}; // DAD H
6: sp = sp + 1; // INX SP 3: {cc, regh, regl} = {1'b0, regh, regl} + sp; // DAD SP
7: sp = sp - 1; // DCX SP endcase
endcase end
endtask endtask

/* load register pair immediate */


task lrpi;
case(ir[5:4])
0: adread({regb, regc}); // LXI B
1: adread({regd, rege}); // LXI D
2: adread({regh, regl}); // LXI H
3: adread(sp); // LXI SP
endcase
35 36
endtask

Vous aimerez peut-être aussi