OpenCores
URL https://opencores.org/ocsvn/plasma/plasma/trunk

Subversion Repositories plasma

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /plasma/tags/V2_1
    from Rev 350 to Rev 352
    Reverse comparison

Rev 350 → Rev 352

/tools/makefile
0,0 → 1,66
# NOTE: CC is for the x86 compiler to compile the PC based tools.
# Gcc is for the MIPS test code.
# If you get an error using GNU make.exe try a different make utility.
# The MIPS gcc compiler libraries cause problems with GNU make.
 
CC = cl /O1
#CC = gcc_x86 -O
 
all: convert.exe mlite.exe tracehex.exe bintohex.exe
@echo make targets = count, opcodes, pi, test, run, tohex
 
convert.exe: convert.c
@$(CC) -o convert.exe convert.c
 
mlite.exe: mlite.c
@$(CC) -o mlite.exe mlite.c
 
tracehex.exe: tracehex.c
@$(CC) -o tracehex.exe tracehex.c
 
bintohex.exe: bintohex.c
@$(CC) -o bintohex.exe bintohex.c
 
tohex:
bintohex test2.exe
copy code*.hex ..\vhdl
 
opcodes: all
as -o opcodes.o opcodes.asm
ld -Ttext 0 -eentry -Map test.map -s -N -o test.exe opcodes.o
-@objdump --disassemble test.exe > test.lst
@convert
-@mlite test2.exe BD > test.txt
@copy code.txt ..\vhdl
 
test: all
as -o boot.o boot.asm
gcc -O -DMLITE -Dmain=main2 -Wall -c -s test.c
ld -Ttext 0 -eentry -Map test.map -s -N -o test.exe boot.o test.o
-@objdump --disassemble test.exe > test.lst
@convert
-@mlite test2.exe BD > test.txt
@copy code.txt ..\vhdl
 
count: all
as -o boot.o boot.asm
gcc -O -DMLITE -Dmain=main2 -Wall -c -s count.c
ld -Ttext 0 -eentry -Map test.map -s -N -o test.exe boot.o count.o
-objdump --disassemble test.exe > test.lst
convert
-mlite test2.exe BD > test.txt
copy code.txt ..\vhdl
 
pi: all
as -o boot.o boot.asm
gcc -O -DMLITE -Dmain=main2 -Wall -c -s pi.c
ld -Ttext 0 -eentry -Map test.map -s -N -o test.exe boot.o pi.o
@objdump --disassemble test.exe > test.lst
@convert
-@mlite test2.exe BD > test.txt
@copy code.txt ..\vhdl
 
run: mlite.exe
@mlite test2.exe B
 
 
/tools/opcodes.asm
0,0 → 1,1039
##################################################################
# TITLE: Opcode Tester
# AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
# DATE CREATED: 1/10/02
# FILENAME: opcodes.asm
# PROJECT: Plasma CPU core
# COPYRIGHT: Software placed into the public domain by the author.
# Software 'as is' without warranty. Author liable for nothing.
# DESCRIPTION:
# This assembly file tests all of the opcodes supported by the
# Plasma core.
# This test assumes that address 0xffff is the UART write register
# Successful tests will print out "A" or "AB" or "ABC" or ....
# Missing letters or letters out of order indicate a failure.
##################################################################
.text
.align 2
.globl entry
.ent entry
entry:
.set noreorder
 
#These four instructions must be the first instructions
#convert.exe will correctly initialize $gp
lui $gp,0
ori $gp,$gp,0
#convert.exe will set $4=.sbss_start $5=.bss_end
lui $4,0
ori $4,$4,0
lui $5,0
ori $5,$5,0
lui $sp,0
ori $sp,$sp,0xfff0
 
mtc0 $0,$12 #disable interrupts
ori $20,$0,0xffff #serial port write address
ori $21,$0,'\n' #<CR> letter
ori $22,$0,'X' #'X' letter
ori $23,$0,'\r'
ori $24,$0,0x0f80 #temp memory
 
######################################
#Arithmetic Instructions
######################################
ori $2,$0,'A'
sb $2,0($20)
ori $2,$0,'r'
sb $2,0($20)
ori $2,$0,'i'
sb $2,0($20)
ori $2,$0,'t'
sb $2,0($20)
ori $2,$0,'h'
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#a: ADD
ori $2,$0,'a'
sb $2,0($20)
ori $3,$0,5
ori $4,$0,60
add $2,$3,$4
sb $2,0($20) #A
sb $23,0($20)
sb $21,0($20)
 
#b: ADDI
ori $2,$0,'b'
sb $2,0($20)
ori $4,$0,60
addi $2,$4,5
sb $2,0($20) #A
sb $23,0($20)
sb $21,0($20)
 
#c: ADDIU
ori $2,$0,'c'
sb $2,0($20)
ori $4,$0,50
addiu $5,$4,15
sb $5,0($20) #A
sb $23,0($20)
sb $21,0($20)
 
#d: ADDU
ori $2,$0,'d'
sb $2,0($20)
ori $3,$0,5
ori $4,$0,60
add $2,$3,$4
sb $2,0($20) #A
sb $23,0($20)
sb $21,0($20)
 
#e: DIV
ori $2,$0,'e'
sb $2,0($20)
ori $2,$0,65*117+41
ori $3,$0,117
div $2,$3
nop
mflo $4
sb $4,0($20) #A
mfhi $4
addi $4,$4,66-41
sb $4,0($20) #B
li $2,-67*19
ori $3,$0,19
div $2,$3
nop
mflo $4
sub $4,$0,$4
sb $4,0($20) #C
ori $2,$0,68*23
li $3,-23
div $2,$3
nop
mflo $4
sub $4,$0,$4
sb $4,0($20) #D
li $2,-69*13
li $3,-13
div $2,$3
mflo $4
sb $4,0($20) #E
sb $23,0($20)
sb $21,0($20)
 
#f: DIVU
ori $2,$0,'f'
sb $2,0($20)
ori $2,$0,65*13
ori $3,$0,13
divu $2,$3
nop
mflo $4
sb $4,0($20) #A
sb $23,0($20)
sb $21,0($20)
 
#g: MULT
ori $2,$0,'g'
sb $2,0($20)
ori $2,$0,5
ori $3,$0,13
mult $2,$3
nop
mflo $4
sb $4,0($20) #A
li $2,-5
ori $3,$0,13
mult $2,$3
mfhi $5
mflo $4
sub $4,$0,$4
addu $4,$4,$5
addi $4,$4,2
sb $4,0($20) #B
ori $2,$0,5
li $3,-13
mult $2,$3
mfhi $5
mflo $4
sub $4,$0,$4
addu $4,$4,$5
addi $4,$4,3
sb $4,0($20) #C
li $2,-5
li $3,-13
mult $2,$3
mfhi $5
mflo $4
addu $4,$4,$5
addi $4,$4,3
sb $4,0($20) #D
lui $4,0xfe98
ori $4,$4,0x62e5
lui $5,0x6
ori $5,0x8db8
mult $4,$5
mfhi $6
addiu $7,$6,2356+1+'E' #E
sb $7,0($20)
sb $23,0($20)
sb $21,0($20)
 
#h: MULTU
ori $2,$0,'h'
sb $2,0($20)
ori $2,$0,5
ori $3,$0,13
multu $2,$3
nop
mflo $4
sb $4,0($20) #A
sb $23,0($20)
sb $21,0($20)
 
#i: SLT
ori $2,$0,'i'
sb $2,0($20)
ori $2,$0,10
ori $3,$0,12
slt $4,$2,$3
addi $5,$4,64
sb $5,0($20) #A
slt $4,$3,$2
addi $5,$4,66
sb $5,0($20) #B
li $2,0xfffffff0
slt $4,$2,$3
addi $5,$4,66
sb $5,0($20) #C
slt $4,$3,$2
addi $5,$4,68
sb $5,0($20) #D
li $3,0xffffffff
slt $4,$2,$3
addi $5,$4,68
sb $5,0($20) #E
slt $4,$3,$2
addi $5,$4,70
sb $5,0($20) #F
sb $23,0($20)
sb $21,0($20)
 
#j: SLTI
ori $2,$0,'j'
sb $2,0($20)
ori $2,$0,10
slti $4,$2,12
addi $5,$4,64
sb $5,0($20) #A
slti $4,$2,8
addi $5,$4,66
sb $5,0($20) #B
sb $23,0($20)
sb $21,0($20)
 
#k: SLTIU
ori $2,$0,'k'
sb $2,0($20)
ori $2,$0,10
sltiu $4,$2,12
addi $5,$4,64
sb $5,0($20) #A
sltiu $4,$2,8
addi $5,$4,66
sb $5,0($20) #B
sb $23,0($20)
sb $21,0($20)
 
#l: SLTU
ori $2,$0,'l'
sb $2,0($20)
ori $2,$0,10
ori $3,$0,12
slt $4,$2,$3
addi $5,$4,64
sb $5,0($20) #A
slt $4,$3,$2
addi $5,$4,66
sb $5,0($20) #B
sb $23,0($20)
sb $21,0($20)
 
#m: SUB
ori $2,$0,'m'
sb $2,0($20)
ori $3,$0,70
ori $4,$0,5
sub $2,$3,$4
sb $2,0($20) #A
sb $23,0($20)
sb $21,0($20)
 
#n: SUBU
ori $2,$0,'n'
sb $2,0($20)
ori $3,$0,70
ori $4,$0,5
sub $2,$3,$4
sb $2,0($20) #A
sb $23,0($20)
sb $21,0($20)
 
######################################
#Branch and Jump Instructions
######################################
ori $2,$0,'B'
sb $2,0($20)
ori $2,$0,'r'
sb $2,0($20)
ori $2,$0,'a'
sb $2,0($20)
ori $2,$0,'n'
sb $2,0($20)
ori $2,$0,'c'
sb $2,0($20)
ori $2,$0,'h'
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#a: B
ori $2,$0,'a'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
b $B1
sb $10,0($20)
sb $22,0($20)
$B1:
sb $11,0($20)
sb $23,0($20)
sb $21,0($20)
 
#b: BAL
ori $2,$0,'b'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $14,$0,'E'
ori $15,$0,'X'
bal $BAL1
sb $10,0($20)
sb $13,0($20)
b $BAL2
sb $14,0($20)
sb $15,0($20)
$BAL1:
sb $11,0($20)
jr $31
sb $12,0($20)
sb $22,0($20)
$BAL2:
sb $23,0($20)
sb $21,0($20)
 
#c: BEQ
ori $2,$0,'c'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $2,$0,100
ori $3,$0,123
ori $4,$0,123
beq $2,$3,$BEQ1
sb $10,0($20)
sb $11,0($20)
beq $3,$4,$BEQ1
sb $12,0($20)
sb $22,0($20)
$BEQ1:
sb $13,0($20)
sb $23,0($20)
sb $21,0($20)
 
#d: BGEZ
ori $2,$0,'d'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
or $15,$0,'X'
ori $2,$0,100
li $3,0xffff1234
ori $4,$0,123
bgez $3,$BGEZ1
sb $10,0($20)
sb $11,0($20)
bgez $2,$BGEZ1
sb $12,0($20)
sb $22,0($20)
$BGEZ1:
bgez $0,$BGEZ2
nop
sb $15,0($20)
$BGEZ2:
sb $13,0($20)
sb $23,0($20)
sb $21,0($20)
 
#e: BGEZAL
ori $2,$0,'e'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $14,$0,'E'
ori $15,$0,'X'
li $3,0xffff1234
bgezal $3,$BGEZAL1
nop
sb $10,0($20)
bgezal $0,$BGEZAL1
nop
sb $13,0($20)
b $BGEZAL2
sb $14,0($20)
sb $15,0($20)
$BGEZAL1:
sb $11,0($20)
jr $31
sb $12,0($20)
sb $22,0($20)
$BGEZAL2:
sb $23,0($20)
sb $21,0($20)
 
#f: BGTZ
ori $2,$0,'f'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $2,$0,100
li $3,0xffff1234
bgtz $3,$BGTZ1
sb $10,0($20)
sb $11,0($20)
bgtz $2,$BGTZ1
sb $12,0($20)
sb $22,0($20)
$BGTZ1:
sb $13,0($20)
sb $23,0($20)
sb $21,0($20)
 
#g: BLEZ
ori $2,$0,'g'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $2,$0,100
li $3,0xffff1234
blez $2,$BLEZ1
sb $10,0($20)
sb $11,0($20)
blez $3,$BLEZ1
sb $12,0($20)
sb $22,0($20)
$BLEZ1:
blez $0,$BLEZ2
nop
sb $22,0($20)
$BLEZ2:
sb $13,0($20)
sb $23,0($20)
sb $21,0($20)
 
#h: BLTZ
ori $2,$0,'h'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $14,$0,'E'
ori $2,$0,100
li $3,0xffff1234
ori $4,$0,0
bltz $2,$BLTZ1
sb $10,0($20)
sb $11,0($20)
bltz $3,$BLTZ1
sb $12,0($20)
sb $22,0($20)
$BLTZ1:
bltz $4,$BLTZ2
nop
sb $13,0($20)
$BLTZ2:
sb $14,0($20)
sb $23,0($20)
sb $21,0($20)
 
#i: BLTZAL
ori $2,$0,'i'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $14,$0,'E'
ori $15,$0,'X'
li $3,0xffff1234
bltzal $0,$BLTZAL1
nop
sb $10,0($20)
bltzal $3,$BLTZAL1
nop
sb $13,0($20)
b $BLTZAL2
sb $14,0($20)
sb $15,0($20)
$BLTZAL1:
sb $11,0($20)
jr $31
sb $12,0($20)
sb $22,0($20)
$BLTZAL2:
sb $23,0($20)
sb $21,0($20)
 
#j: BNE
ori $2,$0,'j'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $2,$0,100
ori $3,$0,123
ori $4,$0,123
bne $3,$4,$BNE1
sb $10,0($20)
sb $11,0($20)
bne $2,$3,$BNE1
sb $12,0($20)
sb $22,0($20)
$BNE1:
sb $13,0($20)
sb $23,0($20)
sb $21,0($20)
 
#k: J
ori $2,$0,'k'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $15,$0,'X'
j $J1
sb $10,0($20)
sb $15,0($20)
$J1:
sb $11,0($20)
sb $23,0($20)
sb $21,0($20)
 
#l: JAL
ori $2,$0,'l'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $14,$0,'E'
ori $15,$0,'X'
jal $JAL1
sb $10,0($20)
sb $13,0($20)
b $JAL2
sb $14,0($20)
sb $15,0($20)
$JAL1:
sb $11,0($20)
jr $31
sb $12,0($20)
sb $22,0($20)
$JAL2:
sb $23,0($20)
sb $21,0($20)
 
#m: JALR
ori $2,$0,'m'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $12,$0,'C'
ori $13,$0,'D'
ori $14,$0,'E'
ori $15,$0,'X'
la $3,$JALR1
jalr $3
sb $10,0($20)
sb $13,0($20)
b $JALR2
sb $14,0($20)
sb $15,0($20)
$JALR1:
sb $11,0($20)
jr $31
sb $12,0($20)
sb $22,0($20)
$JALR2:
sb $23,0($20)
sb $21,0($20)
 
#n: JR
ori $2,$0,'n'
sb $2,0($20)
ori $10,$0,'A'
ori $11,$0,'B'
ori $15,$0,'X'
la $3,$JR1
jr $3
sb $10,0($20)
sb $15,0($20)
$JR1:
sb $11,0($20)
sb $23,0($20)
sb $21,0($20)
 
#o: NOP
ori $2,$0,'o'
sb $2,0($20)
ori $2,$0,65
nop
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
######################################
#Load, Store, and Memory Control Instructions
######################################
ori $2,$0,'L'
sb $2,0($20)
ori $2,$0,'o'
sb $2,0($20)
ori $2,$0,'a'
sb $2,0($20)
ori $2,$0,'d'
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#a: LB
ori $2,$0,'a'
sb $2,0($20)
or $2,$0,$24
li $3,0x41424344
sw $3,16($2)
lb $4,16($2)
sb $4,0($20)
lb $4,17($2)
sb $4,0($20)
lb $4,18($2)
sb $4,0($20)
lb $2,19($2)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#b: LBU
ori $2,$0,'b'
sb $2,0($20)
or $2,$0,$24
li $3,0x41424344
sw $3,16($2)
lb $4,16($2)
sb $4,0($20)
lb $4,17($2)
sb $4,0($20)
lb $4,18($2)
sb $4,0($20)
lb $2,19($2)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#c: LH
ori $2,$0,'c'
sb $2,0($20)
or $2,$0,$24
li $3,0x00410042
sw $3,16($2)
lh $4,16($2)
sb $4,0($20)
lh $2,18($2)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#d: LHU
ori $2,$0,'d'
sb $2,0($20)
or $2,$0,$24
li $3,0x00410042
sw $3,16($2)
lh $4,16($2)
sb $4,0($20)
lh $2,18($2)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#e: LW
ori $2,$0,'e'
sb $2,0($20)
or $2,$0,$24
li $3,'A'
sw $3,16($2)
ori $3,$0,0
lw $2,16($2)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#f: LWL & LWR
ori $2,$0,'f'
sb $2,0($20)
or $2,$0,$24
li $3,'A'
sw $3,16($2)
ori $3,$0,0
lwl $2,16($2)
lwr $2,16($2)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#g: SB
ori $2,$0,'g'
sb $2,0($20)
ori $2,$0,'A'
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#h: SH
ori $2,$0,'h'
sb $2,0($20)
or $4,$0,$24
ori $2,$0,0x4142
sh $2,16($4)
lb $3,16($4)
sb $3,0($20)
lb $2,17($4)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#i: SW
ori $2,$0,'i'
sb $2,0($20)
or $2,$0,$24
li $3,0x41424344
sw $3,16($2)
lb $4,16($2)
sb $4,0($20)
lb $4,17($2)
sb $4,0($20)
lb $4,18($2)
sb $4,0($20)
lb $2,19($2)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#j: SWL & SWR
ori $2,$0,'j'
sb $2,0($20)
or $2,$0,$24
li $3,0x41424344
swl $3,16($2)
swr $3,16($2)
lb $4,16($2)
sb $4,0($20)
lb $4,17($2)
sb $4,0($20)
lb $4,18($2)
sb $4,0($20)
lb $2,19($2)
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
 
######################################
#Logical Instructions
######################################
ori $2,$0,'L'
sb $2,0($20)
ori $2,$0,'o'
sb $2,0($20)
ori $2,$0,'g'
sb $2,0($20)
ori $2,$0,'i'
sb $2,0($20)
ori $2,$0,'c'
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#a: AND
ori $2,$0,'a'
sb $2,0($20)
ori $2,$0,0x0741
ori $3,$0,0x60f3
and $4,$2,$3
sb $4,0($20)
sb $23,0($20)
sb $21,0($20)
 
#b: ANDI
ori $2,$0,'b'
sb $2,0($20)
ori $2,$0,0x0741
andi $4,$2,0x60f3
sb $4,0($20)
sb $23,0($20)
sb $21,0($20)
 
#c: LUI
ori $2,$0,'c'
sb $2,0($20)
lui $2,0x41
srl $3,$2,16
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#d: NOR
ori $2,$0,'d'
sb $2,0($20)
li $2,0xf0fff08e
li $3,0x0f0f0f30
nor $4,$2,$3
sb $4,0($20)
sb $23,0($20)
sb $21,0($20)
 
#e: OR
ori $2,$0,'e'
sb $2,0($20)
ori $2,$0,0x40
ori $3,$0,0x01
or $4,$2,$3
sb $4,0($20)
sb $23,0($20)
sb $21,0($20)
 
#f: ORI
ori $2,$0,'f'
sb $2,0($20)
ori $2,$0,0x40
ori $4,$2,0x01
sb $4,0($20)
sb $23,0($20)
sb $21,0($20)
 
#g: XOR
ori $2,$0,'g'
sb $2,0($20)
ori $2,$0,0xf043
ori $3,$0,0xf002
xor $4,$2,$3
sb $4,0($20)
sb $23,0($20)
sb $21,0($20)
 
#h: XORI
ori $2,$0,'h'
sb $2,0($20)
ori $2,$0,0xf043
xor $4,$2,0xf002
sb $4,0($20)
sb $23,0($20)
sb $21,0($20)
 
######################################
#Move Instructions
######################################
ori $2,$0,'M'
sb $2,0($20)
ori $2,$0,'o'
sb $2,0($20)
ori $2,$0,'v'
sb $2,0($20)
ori $2,$0,'e'
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#a: MFHI
ori $2,$0,'a'
sb $2,0($20)
ori $2,$0,65
mthi $2
mfhi $3
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#b: MFLO
ori $2,$0,'b'
sb $2,0($20)
ori $2,$0,65
mtlo $2
mflo $3
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#c: MTHI
ori $2,$0,'c'
sb $2,0($20)
ori $2,$0,65
mthi $2
mfhi $3
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#d: MTLO
ori $2,$0,'d'
sb $2,0($20)
ori $2,$0,65
mtlo $2
mflo $3
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
 
######################################
#Shift Instructions
######################################
ori $2,$0,'S'
sb $2,0($20)
ori $2,$0,'h'
sb $2,0($20)
ori $2,$0,'i'
sb $2,0($20)
ori $2,$0,'f'
sb $2,0($20)
ori $2,$0,'t'
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
#a: SLL
ori $2,$0,'a'
sb $2,0($20)
li $2,0x40414243
sll $3,$2,8
srl $3,$3,24
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#b: SLLV
ori $2,$0,'b'
sb $2,0($20)
li $2,0x40414243
ori $3,$0,8
sllv $3,$2,$3
srl $3,$3,24
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#c: SRA
ori $2,$0,'c'
sb $2,0($20)
li $2,0x40414243
sra $3,$2,16
sb $3,0($20)
li $2,0x84000000
sra $3,$2,25
sub $3,$3,0x80
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#d: SRAV
ori $2,$0,'d'
sb $2,0($20)
li $2,0x40414243
ori $3,$0,16
srav $3,$2,$3
sb $3,0($20)
ori $3,$0,25
li $2,0x84000000
srav $3,$2,$3
sub $3,$3,0x80
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#e: SRL
ori $2,$0,'e'
sb $2,0($20)
li $2,0x40414243
srl $3,$2,16
sb $3,0($20)
li $2,0x84000000
srl $3,$2,25
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
#f: SRLV
ori $2,$0,'f'
sb $2,0($20)
li $2,0x40414243
ori $3,$0,16
srlv $4,$2,$3
sb $4,0($20)
ori $3,$0,25
li $2,0x84000000
srlv $3,$2,$3
sb $3,0($20)
sb $23,0($20)
sb $21,0($20)
 
 
ori $2,$0,'D'
sb $2,0($20)
ori $2,$0,'o'
sb $2,0($20)
ori $2,$0,'n'
sb $2,0($20)
ori $2,$0,'e'
sb $2,0($20)
sb $23,0($20)
sb $21,0($20)
 
 
$DONE:
j $DONE
nop
 
.set reorder
.end entry
 
/tools/boot.asm
0,0 → 1,106
##################################################################
# TITLE: Boot Up Code
# AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
# DATE CREATED: 1/12/02
# FILENAME: boot.asm
# PROJECT: Plasma CPU core
# COPYRIGHT: Software placed into the public domain by the author.
# Software 'as is' without warranty. Author liable for nothing.
# DESCRIPTION:
# Initializes the stack pointer and jumps to main2().
##################################################################
.text
.align 2
.globl entry
.ent entry
entry:
.set noreorder
 
#These eight instructions must be the first instructions.
#convert.exe will correctly initialize $gp
lui $gp,0
ori $gp,$gp,0
#convert.exe will set $4=.sbss_start $5=.bss_end
lui $4,0
ori $4,$4,0
lui $5,0
ori $5,$5,0
lui $sp,0
ori $sp,$sp,0xfff0 #initialize stack pointer
$BSS_CLEAR:
sw $0,0($4)
slt $3,$4,$5
bnez $3,$BSS_CLEAR
addiu $4,$4,4
 
jal main2
nop
$L1:
j $L1
 
#address 0x3c
interrupt_service_routine:
#registers $26 and $27 are reserved for the OS
ori $26,$0,0xffff
ori $27,$0,46
sb $27,0($26) #echo out '.'
#normally clear the interrupt source here
 
#return and re-enable interrupts
ori $26,$0,0x1
mfc0 $27,$14 #C0_EPC=14
jr $27
mtc0 $26,$12 #STATUS=1; enable interrupts
.set reorder
.end entry
 
 
###################################################
.globl isr_enable
.ent isr_enable
isr_enable:
.set noreorder
jr $31
mtc0 $4,$12 #STATUS=1; enable interrupts
.set reorder
.end isr_enable
 
 
###################################################
.globl putchar
.ent putchar
putchar:
.set noreorder
li $5,0xffff
 
#Uncomment to make each character on a seperate line
#The VHDL simulator buffers the lines
# sb $4,0($5)
# ori $4,$0,'\n'
 
jr $31
sb $4,0($5)
.set reorder
.end putchar
 
 
###################################################
.globl puts
.ent puts
puts:
.set noreorder
ori $5,$0,0xffff
PUTS1:
lb $6,0($4)
beqz $6,PUTS2
addiu $4,$4,1
b PUTS1
sb $6,0($5)
PUTS2:
jr $31
ori $2,$0,0
.set reorder
.end puts
 
 
/tools/convert.c
0,0 → 1,207
//convert.c by Steve Rhoads 4/26/01
//Now uses the ELF format (get gccmips_elf.zip)
//set $gp and zero .sbss and .bss
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define BUF_SIZE (1024*1024)
/*Assumes running on PC little endian*/
#define ntohl(A) (((A)>>24)|(((A)&0x00ff0000)>>8)|(((A)&0xff00)<<8)|((A)<<24))
#define ntohs(A) ((((A)&0xff00)>>8)|((A)<<8))
 
#define EI_NIDENT 16
#define SHT_PROGBITS 1
#define SHT_STRTAB 3
#define SHT_NOBITS 8
 
typedef struct {
unsigned char e_ident[EI_NIDENT];
unsigned short e_e_type;
unsigned short e_machine;
unsigned long e_version;
unsigned long e_entry;
unsigned long e_phoff;
unsigned long e_shoff;
unsigned long e_flags;
unsigned short e_ehsize;
unsigned short e_phentsize;
unsigned short e_phnum;
unsigned short e_shentsize;
unsigned short e_shnum;
unsigned short e_shstrndx;
} ElfHeader;
 
typedef struct {
unsigned long p_type;
unsigned long p_offset;
unsigned long p_vaddr;
unsigned long p_paddr;
unsigned long p_filesz;
unsigned long p_memsz;
unsigned long p_flags;
unsigned long p_align;
} Elf32_Phdr;
 
typedef struct {
unsigned long sh_name;
unsigned long sh_type;
unsigned long sh_flags;
unsigned long sh_addr;
unsigned long sh_offset;
unsigned long sh_size;
unsigned long sh_link;
unsigned long sh_info;
unsigned long sh_addralign;
unsigned long sh_entsize;
} Elf32_Shdr;
 
#if 0
unsigned long load(unsigned char *ptr,unsigned long address)
{
unsigned long value;
value=*(unsigned long*)(ptr+address);
value=ntohl(value);
return value;
}
 
unsigned short load_short(unsigned char *ptr,unsigned long address)
{
return (ptr[address]<<8)+ptr[address+1];
}
#endif
 
void set_low(char *ptr,unsigned long address,unsigned long value)
{
unsigned long opcode;
opcode=*(unsigned long*)(ptr+address);
opcode=ntohl(opcode);
opcode=(opcode&0xffff0000)|(value&0xffff);
opcode=ntohl(opcode);
*(unsigned long*)(ptr+address)=opcode;
}
 
int main(int argc,char *argv[])
{
FILE *infile,*outfile,*txtfile;
unsigned char *buf,*code;
long size,stack_pointer;
unsigned long length,d,i,gp_ptr=0;
unsigned long bss_start=0,bss_end=0;
 
ElfHeader *elfHeader;
Elf32_Phdr *elfProgram;
Elf32_Shdr *elfSection;
 
printf("test.exe -> code.txt & test2.exe\n");
infile=fopen("test.exe","rb");
if(infile==NULL) {
printf("Can't open test.exe");
return 0;
}
buf=(unsigned char*)malloc(BUF_SIZE);
size=fread(buf,1,BUF_SIZE,infile);
fclose(infile);
code=(unsigned char*)malloc(BUF_SIZE);
memset(code,0,BUF_SIZE);
 
elfHeader=(ElfHeader*)buf;
if(strncmp(elfHeader->e_ident+1,"ELF",3)) {
printf("Error: Not an ELF file!\n");
printf("Use the gccmips_elf.zip from opencores/projects/plasma!\n");
return -1;
}
 
elfHeader->e_entry=ntohl(elfHeader->e_entry);
elfHeader->e_phoff=ntohl(elfHeader->e_phoff);
elfHeader->e_shoff=ntohl(elfHeader->e_shoff);
elfHeader->e_phentsize=ntohs(elfHeader->e_phentsize);
elfHeader->e_phnum=ntohs(elfHeader->e_phnum);
elfHeader->e_shentsize=ntohs(elfHeader->e_shentsize);
elfHeader->e_shnum=ntohs(elfHeader->e_shnum);
length=0;
 
for(i=0;i<elfHeader->e_phnum;++i) {
elfProgram=(Elf32_Phdr*)(buf+elfHeader->e_phoff+elfHeader->e_phentsize*i);
elfProgram->p_offset=ntohl(elfProgram->p_offset);
elfProgram->p_vaddr=ntohl(elfProgram->p_vaddr);
elfProgram->p_filesz=ntohl(elfProgram->p_filesz);
elfProgram->p_memsz=ntohl(elfProgram->p_memsz);
// printf("[0x%x,0x%x,0x%x]\n",elfProgram->p_vaddr,elfProgram->p_offset,elfProgram->p_filesz);
memcpy(code+elfProgram->p_vaddr,buf+elfProgram->p_offset,elfProgram->p_filesz);
length=elfProgram->p_vaddr+elfProgram->p_memsz;
}
 
for(i=0;i<elfHeader->e_shnum;++i) {
elfSection=(Elf32_Shdr*)(buf+elfHeader->e_shoff+elfHeader->e_shentsize*i);
elfSection->sh_name=ntohl(elfSection->sh_name);
elfSection->sh_type=ntohl(elfSection->sh_type);
elfSection->sh_addr=ntohl(elfSection->sh_addr);
elfSection->sh_offset=ntohl(elfSection->sh_offset);
elfSection->sh_size=ntohl(elfSection->sh_size);
#if 0
printf("{0x%x,0x%x:0x%x,0x%x,0x%x}\n",
elfSection->sh_name,elfSection->sh_type,elfSection->sh_addr,
elfSection->sh_offset,elfSection->sh_size);
#endif
#if 0
if(elfSection->sh_type==SHT_PROGBITS||elfSection->sh_type==SHT_STRTAB) {
// memcpy(code+elfSection->sh_addr,buf+elfSection->sh_offset,elfSection->sh_size);
length=elfSection->sh_addr+elfSection->sh_size;
bss_start=length;
}
#endif
if(elfSection->sh_type==SHT_PROGBITS) {
gp_ptr=elfSection->sh_addr;
}
if(elfSection->sh_type==SHT_NOBITS) {
if(bss_start==0) {
bss_start=elfSection->sh_addr;
}
bss_end=elfSection->sh_addr+elfSection->sh_size;
}
}
 
if(bss_start==length) {
bss_start=length;
bss_end=length+4;
}
 
/*Initialize the $gp register for sdata and sbss*/
gp_ptr+=0x7ff0;
printf("gp_ptr=0x%x ",gp_ptr);
/*modify the first opcodes in boot.asm*/
/*modify the lui opcode*/
set_low(code,0,gp_ptr>>16);
/*modify the ori opcode*/
set_low(code,4,gp_ptr&0xffff);
 
/*Clear .sbss and .bss*/
printf(".sbss=0x%x .bss_end=0x%x\n",bss_start,bss_end);
set_low(code,8,bss_start>>16);
set_low(code,12,bss_start&0xffff);
set_low(code,16,bss_end>>16);
set_low(code,20,bss_end&0xffff);
 
/*Set stack pointer*/
stack_pointer=bss_end+512;
printf("Stack pointer=0x%x\n",stack_pointer);
set_low(code,24,stack_pointer>>16);
set_low(code,28,stack_pointer&0xffff);
 
/*write out code.txt*/
outfile=fopen("test2.exe","wb");
fwrite(code,length,1,outfile);
fclose(outfile);
 
txtfile=fopen("code.txt","w");
for(i=0;i<=length;i+=4) {
d=ntohl(*(unsigned long*)(code+i));
fprintf(txtfile,"%8.8x\n",d);
}
fclose(txtfile);
free(buf);
 
return 0;
}
 
/tools/mlite.c
0,0 → 1,436
/*-------------------------------------------------------------------
-- TITLE: Plasma CPU in software. Executes MIPS(tm) opcodes.
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 1/31/01
-- FILENAME: mlite.c
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Plasma CPU simulator in C code.
-- This file served as the starting point for the VHDL code.
--------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
 
#define MEM_SIZE (1024*1024*2)
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
#define htons(A) ntohs(A)
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
#define htonl(A) ntohl(A)
 
// int getch(void);
#define getch getchar
 
typedef struct {
long r[32];
long pc,pc_next;
long hi;
long lo;
long skip;
char *mem;
long wakeup;
long big_endian;
} State;
 
static char *opcode_string[]={
"SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
"ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
"COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
"?","?","?","?","?","?","?","?",
"LB","LH","LWL","LW","LBU","LHU","LWR","?",
"SB","SH","SWL","SW","?","?","SWR","CACHE",
"LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
"SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
};
 
static char *special_string[]={
"SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
"JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
"MFHI","MTHI","MFLO","MTLO","?","?","?","?",
"MULT","MULTU","DIV","DIVU","?","?","?","?",
"ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
"?","?","SLT","SLTU","?","DADDU","?","?",
"TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
"?","?","?","?","?","?","?","?"
};
 
static char *regimm_string[]={
"BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
"TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
"BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
"?","?","?","?","?","?","?","?"
};
 
static long big_endian=0;
 
static long mem_read(State *s,long size,unsigned long address)
{
unsigned long value=0,ptr;
address%=MEM_SIZE;
ptr=(long)s->mem+address;
switch(size) {
case 4: value=*(long*)ptr;
if(big_endian) value=ntohl(value);
break;
case 2:
value=*(unsigned short*)ptr;
if(big_endian) value=ntohs((unsigned short)value);
break;
case 1:
value=*(unsigned char*)ptr;
break;
default: printf("ERROR");
}
return(value);
}
 
static void mem_write(State *s,long size,long unsigned address,unsigned long value)
{
static char_count=0;
unsigned long ptr;
if(address==0xffff) { //UART write register at 0xffff
value&=0xff;
if(isprint(value)) {
printf("%c",value);
if(++char_count>=72) {
printf("\n");
char_count=0;
}
} else if(value=='\n') {
printf("\n");
char_count=0;
} else {
printf(".");
}
}
address%=MEM_SIZE;
ptr=(long)s->mem+address;
switch(size) {
case 4: if(big_endian) value=htonl(value);
*(long*)ptr=value;
break;
case 2:
if(big_endian) {
value=htons((unsigned short)value);
}
*(short*)ptr=(unsigned short)value;
break;
case 1:
*(char*)ptr=(unsigned char)value;
break;
default: printf("ERROR");
}
}
 
void mult_big(unsigned long a,unsigned long b,
unsigned long *hi,unsigned long *lo)
{
unsigned long ahi,alo,bhi,blo;
unsigned long c0,c1,c2,c3;
unsigned long c1_a,c1_b,c2_a,c2_b;
ahi=a>>16;
alo=a&0xffff;
bhi=b>>16;
blo=b&0xffff;
 
c0=alo*blo;
c1_a=ahi*blo;
c1_b=alo*bhi;
c2=ahi*bhi;
 
 
c2+=(c1_a>>16)+(c1_b>>16);
c1=(c1_a&0xffff)+(c1_b&0xffff)+(c0>>16);
c0&=0xffff;
c2+=(c1>>16);
c1&=0xffff;
*hi=c2;
*lo=(c1<<16)+c0;
}
 
//execute one cycle of a Plasma CPU
void cycle(State *s,int show_mode)
{
unsigned long opcode;
unsigned long op,rs,rt,rd,re,func,imm,target;
long imm_shift,branch=0,lbranch=2;
long *r=s->r;
unsigned long *u=(unsigned long*)s->r;
unsigned long ptr;
opcode=mem_read(s,4,s->pc);
op=(opcode>>26)&0x3f;
rs=(opcode>>21)&0x1f;
rt=(opcode>>16)&0x1f;
rd=(opcode>>11)&0x1f;
re=(opcode>>6)&0x1f;
func=opcode&0x3f;
imm=opcode&0xffff;
imm_shift=(((long)(short)imm)<<2)-4;
target=(opcode<<6)>>4;
ptr=(short)imm+r[rs];
r[0]=0;
if(show_mode) {
printf("%8.8lx %8.8lx ",s->pc,opcode);
if(op==0) printf("%8s ",special_string[func]);
else if(op==1) printf("%8s ",regimm_string[rt]);
else printf("%8s ",opcode_string[op]);
printf("$%2.2ld $%2.2ld $%2.2ld $%2.2ld ",rs,rt,rd,re);
printf("%4.4lx\n",imm);
}
if(show_mode>5) return;
s->pc=s->pc_next;
s->pc_next=s->pc_next+4;
if(s->skip) {
s->skip=0;
return;
}
switch(op) {
case 0x00:/*SPECIAL*/
switch(func) {
case 0x00:/*SLL*/ r[rd]=r[rt]<<re; break;
case 0x02:/*SRL*/ r[rd]=u[rt]>>re; break;
case 0x03:/*SRA*/ r[rd]=r[rt]>>re; break;
case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs]; break;
case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs]; break;
case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs]; break;
case 0x08:/*JR*/ s->pc_next=r[rs]; break;
case 0x09:/*JALR*/ r[rd]=s->pc_next; s->pc_next=r[rs]; break;
case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs]; break; /*IV*/
case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs]; break; /*IV*/
case 0x0c:/*SYSCALL*/ break;
case 0x0d:/*BREAK*/ s->wakeup=1; break;
case 0x0f:/*SYNC*/ s->wakeup=1; break;
case 0x10:/*MFHI*/ r[rd]=s->hi; break;
case 0x11:/*FTHI*/ s->hi=r[rs]; break;
case 0x12:/*MFLO*/ r[rd]=s->lo; break;
case 0x13:/*MTLO*/ s->lo=r[rs]; break;
case 0x18:/*MULT*/
case 0x19:/*MULTU*/ //s->lo=r[rs]*r[rt]; s->hi=0; break;
mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
case 0x1a:/*DIV*/ s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
case 0x20:/*ADD*/ r[rd]=r[rs]+r[rt]; break;
case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt]; break;
case 0x22:/*SUB*/ r[rd]=r[rs]-r[rt]; break;
case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt]; break;
case 0x24:/*AND*/ r[rd]=r[rs]&r[rt]; break;
case 0x25:/*OR*/ r[rd]=r[rs]|r[rt]; break;
case 0x26:/*XOR*/ r[rd]=r[rs]^r[rt]; break;
case 0x27:/*NOR*/ r[rd]=~(r[rs]|r[rt]); break;
case 0x2a:/*SLT*/ r[rd]=r[rs]<r[rt]; break;
case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt]; break;
case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt]; break;
case 0x31:/*TGEU*/ break;
case 0x32:/*TLT*/ break;
case 0x33:/*TLTU*/ break;
case 0x34:/*TEQ*/ break;
case 0x36:/*TNE*/ break;
default: printf("ERROR0(*0x%x~0x%x)\n",s->pc,opcode);
s->wakeup=1;
}
break;
case 0x01:/*REGIMM*/
switch(rt) {
case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
case 0x00:/*BLTZ*/ branch=r[rs]<0; break;
case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
case 0x01:/*BGEZ*/ branch=r[rs]>=0; break;
case 0x12:/*BLTZALL*/r[31]=s->pc_next;
case 0x02:/*BLTZL*/ lbranch=r[rs]<0; break;
case 0x13:/*BGEZALL*/r[31]=s->pc_next;
case 0x03:/*BGEZL*/ lbranch=r[rs]>=0; break;
default: printf("ERROR1\n"); s->wakeup=1;
}
break;
case 0x03:/*JAL*/ r[31]=s->pc_next;
case 0x02:/*J*/ s->pc_next=(s->pc&0xf0000000)|target; break;
case 0x04:/*BEQ*/ branch=r[rs]==r[rt]; break;
case 0x05:/*BNE*/ branch=r[rs]!=r[rt]; break;
case 0x06:/*BLEZ*/ branch=r[rs]<=0; break;
case 0x07:/*BGTZ*/ branch=r[rs]>0; break;
case 0x08:/*ADDI*/ r[rt]=r[rs]+(short)imm; break;
case 0x09:/*ADDIU*/ u[rt]=u[rs]+(short)imm; break;
case 0x0a:/*SLTI*/ r[rt]=r[rs]<(short)imm; break;
case 0x0b:/*SLTIU*/ u[rt]=u[rs]<(unsigned long)(short)imm; break;
case 0x0c:/*ANDI*/ r[rt]=r[rs]&imm; break;
case 0x0d:/*ORI*/ r[rt]=r[rs]|imm; break;
case 0x0e:/*XORI*/ r[rt]=r[rs]^imm; break;
case 0x0f:/*LUI*/ r[rt]=(imm<<16); break;
case 0x10:/*COP0*/ break;
// case 0x11:/*COP1*/ break;
// case 0x12:/*COP2*/ break;
// case 0x13:/*COP3*/ break;
case 0x14:/*BEQL*/ lbranch=r[rs]==r[rt]; break;
case 0x15:/*BNEL*/ lbranch=r[rs]!=r[rt]; break;
case 0x16:/*BLEZL*/ lbranch=r[rs]<=0; break;
case 0x17:/*BGTZL*/ lbranch=r[rs]>0; break;
// case 0x1c:/*MAD*/ break; /*IV*/
case 0x20:/*LB*/ r[rt]=(signed char)mem_read(s,1,ptr); break;
case 0x21:/*LH*/ r[rt]=(signed short)mem_read(s,2,ptr); break;
case 0x22:/*LWL*/ rt=rt; //fixme fall through
case 0x23:/*LW*/ r[rt]=mem_read(s,4,ptr); break;
case 0x24:/*LBU*/ r[rt]=(unsigned char)mem_read(s,1,ptr); break;
case 0x25:/*LHU*/ r[rt]=(unsigned short)mem_read(s,2,ptr); break;
case 0x26:/*LWR*/ break; //fixme
case 0x28:/*SB*/ mem_write(s,1,ptr,r[rt]); break;
case 0x29:/*SH*/ mem_write(s,2,ptr,r[rt]); break;
case 0x2a:/*SWL*/ rt=rt; //fixme fall through
case 0x2b:/*SW*/ mem_write(s,4,ptr,r[rt]); break;
case 0x2e:/*SWR*/ break; //fixme
case 0x2f:/*CACHE*/break;
case 0x30:/*LL*/ r[rt]=mem_read(s,4,ptr); break;
// case 0x31:/*LWC1*/ break;
// case 0x32:/*LWC2*/ break;
// case 0x33:/*LWC3*/ break;
// case 0x35:/*LDC1*/ break;
// case 0x36:/*LDC2*/ break;
// case 0x37:/*LDC3*/ break;
// case 0x38:/*SC*/ *(long*)ptr=r[rt]; r[rt]=1; break;
case 0x38:/*SC*/ mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
// case 0x39:/*SWC1*/ break;
// case 0x3a:/*SWC2*/ break;
// case 0x3b:/*SWC3*/ break;
// case 0x3d:/*SDC1*/ break;
// case 0x3e:/*SDC2*/ break;
// case 0x3f:/*SDC3*/ break;
default: printf("ERROR2 address=0x%x opcode=0x%x\n",
s->pc,opcode); s->wakeup=1;
// exit(0);
}
s->pc_next+=branch|(lbranch==1)?imm_shift:0;
s->skip=(lbranch==0);
}
 
void show_state(State *s)
{
long i,j;
for(i=0;i<4;++i) {
printf("%2.2ld ",i*8);
for(j=0;j<8;++j) {
printf("%8.8lx ",s->r[i*8+j]);
}
printf("\n");
}
printf("%8.8lx %8.8lx %8.8lx %8.8lx\n",s->pc,s->pc_next,s->hi,s->lo);
j=s->pc;
for(i=-4;i<=8;++i) {
printf("%c",i==0?'*':' ');
s->pc=j+i*4;
cycle(s,10);
}
s->pc=j;
}
 
void do_debug(State *s)
{
int ch;
long i,j=0,watch=0,addr;
s->pc_next=s->pc+4;
s->skip=0;
s->wakeup=0;
show_state(s);
for(;;) {
if(watch) printf("0x%8.8lx=0x%8.8lx\n",watch,mem_read(s,4,watch));
printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
printf("7=Watch 8=Jump 9=Quit> ");
ch=getch();
printf("\n");
switch(ch) {
case '1': case 'd': case ' ': cycle(s,0); show_state(s); break;
case '2': case 't': cycle(s,0); printf("*"); cycle(s,10); break;
case '3': case 's':
printf("Count> ");
scanf("%ld",&j);
for(i=0;i<j;++i) cycle(s,0);
show_state(s);
break;
case '4': case 'b':
printf("Line> ");
scanf("%lx",&j);
break;
case '5': case 'g':
s->wakeup=0;
while(s->wakeup==0) {
if(s->pc==j) break;
cycle(s,0);
}
show_state(s);
break;
case '6': case 'm':
printf("Memory> ");
scanf("%lx",&j);
for(i=0;i<8;++i) {
printf("%8.8lx ",mem_read(s,4,j+i*4));
}
printf("\n");
break;
case '7': case 'w':
printf("Watch> ");
scanf("%lx",&watch);
break;
case '8': case 'j':
printf("Jump> ");
scanf("%lx",&addr);
s->pc=addr;
s->pc_next=addr+4;
show_state(s);
break;
case '9': case 'q': return;
}
}
}
/************************************************************/
 
int main(int argc,char *argv[])
{
State state,*s=&state;
FILE *in;
long bytes,index;
printf("Plasma emulator\n");
memset(s,0,sizeof(State));
s->big_endian=0;
s->mem=malloc(MEM_SIZE);
if(argc<=1) {
printf(" Usage: mlite file.exe\n");
printf(" mlite file.exe B {for big_endian}\n");
printf(" mlite file.exe DD {disassemble}\n");
printf(" mlite file.exe BD {disassemble big_endian}\n");
return 0;
}
in=fopen(argv[1],"rb");
if(in==NULL) { printf("Can't open file %s!\n",argv[1]); getch(); return(0); }
bytes=fread(s->mem,1,MEM_SIZE,in);
fclose(in);
printf("Read %ld bytes.\n",bytes);
if(argc==3&&argv[2][0]=='B') {
printf("Big Endian\n");
s->big_endian=1;
big_endian=1;
}
if(argc==3&&argv[2][0]=='S') { /*make big endian*/
printf("Big Endian\n");
for(index=0;index<bytes+3;index+=4) {
*(unsigned long*)&s->mem[index]=htonl(*(unsigned long*)&s->mem[index]);
}
in=fopen("big.exe","wb");
fwrite(s->mem,bytes,1,in);
fclose(in);
return(0);
}
if(argc==3&&argv[2][1]=='D') { /*dump image*/
for(index=0;index<bytes;index+=4) {
s->pc=index;
cycle(s,10);
}
free(s->mem);
return(0);
}
s->pc=0x0;
do_debug(s);
free(s->mem);
return(0);
}
 
/tools/count.c
0,0 → 1,136
/*count.c*/
void putchar(int);
int puts(const char*);
 
char *name[]={
"","one","two","three","four","five","six","seven","eight","nine",
"ten","eleven","twelve","thirteen","fourteen","fifteen",
"sixteen","seventeen","eighteen","nineteen",
"","ten","twenty","thirty","forty","fifty","sixty","seventy",
"eighty","ninety"
};
 
#ifndef MLITE
int puts(const char *ptr)
{
while(*ptr) {
putchar(*ptr++);
}
return 0;
}
#endif
 
#if 0
char *xtoa(unsigned long num)
{
static char buf[12];
int i,digit;
buf[8]=0;
for(i=7;i>=0;--i) {
digit=num&0xf;
buf[i]=digit+(digit<10?'0':'A'-10);
num>>=4;
}
return buf;
}
#endif
 
char *itoa(unsigned long num)
{
static char buf[12];
int i;
buf[10]=0;
for(i=9;i>=0;--i) {
buf[i]=(char)((num%10)+'0');
num/=10;
}
return buf;
}
 
void number_text(unsigned long number)
{
int digit;
puts(itoa(number));
puts(": ");
if(number>=1000000000) {
digit=number/1000000000;
puts(name[digit]);
puts(" billion ");
number%=1000000000;
}
if(number>=100000000) {
digit=number/100000000;
puts(name[digit]);
puts(" hundred ");
number%=100000000;
if(number<1000000) {
puts("million ");
}
}
if(number>=20000000) {
digit=number/10000000;
puts(name[digit+20]);
putchar(' ');
number%=10000000;
if(number<1000000) {
puts("million ");
}
}
if(number>=1000000) {
digit=number/1000000;
puts(name[digit]);
puts(" million ");
number%=1000000;
}
if(number>=100000) {
digit=number/100000;
puts(name[digit]);
puts(" hundred ");
number%=100000;
if(number<1000) {
puts("thousand ");
}
}
if(number>=20000) {
digit=number/10000;
puts(name[digit+20]);
putchar(' ');
number%=10000;
if(number<1000) {
puts("thousand ");
}
}
if(number>=1000) {
digit=number/1000;
puts(name[digit]);
puts(" thousand ");
number%=1000;
}
if(number>=100) {
digit=number/100;
puts(name[digit]);
puts(" hundred ");
number%=100;
}
if(number>=20) {
digit=number/10;
puts(name[digit+20]);
putchar(' ');
number%=10;
}
puts(name[number]);
putchar('\r');
putchar('\n');
}
 
void main()
{
unsigned long number,i;
puts("Mult by 3\r\n");
number=3;
for(i=0;;++i) {
number_text(number);
number*=3;
}
}
 
/tools/tracehex.c
0,0 → 1,176
/***********************************************************
| tracehex by Steve Rhoads 12/25/01
| This tool modifies trace files from the free VHDL simulator
| http://www.symphonyeda.com/.
| The binary numbers are converted to hex values.
************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
 
#define BUF_SIZE (1024*1024*4)
#define LINE_SIZE 10000
 
char drop_char[10000];
 
int main(int argc, char *argv[])
{
FILE *file;
char *buf,*ptr_in,*ptr_out,*line_store,*line;
char *line_start,*source_start;
int bytes,digits,value,isbinary,col,col_num,row,drop_cnt;
int col_index,line_index,back_count,drop_start=0;
int digits_length=0;
(void)argc,argv;
 
printf("tracehex\n");
 
/* Reading trace.txt */
file=fopen("trace.txt","r");
if(file==NULL) {
printf("Can't open file\n");
return -1;
}
line_store=(char*)malloc(LINE_SIZE);
line_store[0]=' ';
line=line_store+1;
buf=(char*)malloc(BUF_SIZE*2);
if(buf==NULL) {
printf("Can't malloc!\n");
return -1;
}
ptr_out=buf+BUF_SIZE;
bytes=fread(buf,1,BUF_SIZE-1,file);
buf[bytes]=0;
fclose(file);
 
digits=0;
value=0;
isbinary=0;
col=0;
col_num=0;
row=0;
line_start=ptr_out;
source_start=buf;
for(ptr_in=strstr(buf,"=");*ptr_in;++ptr_in) {
++col;
if(drop_start==0&&*ptr_in==' ') {
for(drop_start=3;drop_start<30;++drop_start) {
if(ptr_in[drop_start]!=' ') {
break;
}
}
for(;drop_start<30;++drop_start) {
if(ptr_in[drop_start]==' ') {
break;
}
}
drop_start-=2;
}
if(col<4) {
drop_char[col]=1;
continue;
}
if(drop_start<=col&&col<=drop_start+2) {
drop_char[col]=1;
continue;
}
if(col<drop_start) {
*ptr_out++=*ptr_in;
continue;
}
/* convert binary number to hex */
if(isbinary&&(*ptr_in=='0'||*ptr_in=='1')) {
value=value*2+*ptr_in-'0';
++digits;
drop_char[col_num++]=1;
} else if(isbinary&&*ptr_in=='Z') {
value=1000;
++digits;
drop_char[col_num++]=1;
} else if(isbinary&&(*ptr_in=='U'||*ptr_in=='X')) {
value=10000;
++digits;
drop_char[col_num++]=1;
} else {
if(*ptr_in=='\n') {
col=0;
isbinary=0;
++row;
}
if(isspace(*ptr_in)) {
if(col>10) {
isbinary=1;
col_num=col;
for(digits_length=1;!isspace(ptr_in[digits_length]);++digits_length) ;
--digits_length;
}
} else {
isbinary=0;
}
*ptr_out++=*ptr_in;
digits=0;
value=0;
}
/* convert every four binary digits to a hex digit */
if(digits&&(digits_length%4)==0) {
drop_char[--col_num]=0;
if(value<100) {
*ptr_out++=value<10?value+'0':value-10+'A';
} else if(value<5000) {
*ptr_out++='Z';
} else {
*ptr_out++='U';
}
digits=0;
value=0;
}
--digits_length;
}
*ptr_out=0;
 
/* now process the header */
file=fopen("trace2.txt","w");
col=0;
line[0]=0;
for(ptr_in=buf;*ptr_in;++ptr_in) {
if(*ptr_in=='=') {
break;
}
line[col++]=*ptr_in;
if(*ptr_in=='\n') {
line[col]=0;
line_index=0;
for(col_index=0;col_index<col;++col_index) {
if(drop_char[col_index]) {
back_count=0;
while(line[line_index-back_count]!=' '&&back_count<10) {
++back_count;
}
if(line[line_index-back_count-1]!=' ') {
--back_count;
}
strcpy(line+line_index-back_count,line+line_index-back_count+1);
} else {
++line_index;
}
}
fprintf(file,"%s",line);
col=0;
}
}
drop_cnt=0;
for(col_index=13;col_index<sizeof(drop_char);++col_index) {
if(drop_char[col_index]) {
++drop_cnt;
}
}
fprintf(file,"%s",buf+BUF_SIZE+drop_cnt);
 
fclose(file);
free(line_store);
free(buf);
return 0;
}
/tools/bintohex.c
0,0 → 1,55
/*bintohex by Steve Rhoads 5/29/02*/
#include <stdio.h>
#include <string.h>
 
#define BUF_SIZE (1024*1024)
 
int main(int argc,char *argv[])
{
FILE *file;
unsigned char *buf;
unsigned long size,mem_size=1024*4,i,j,k,sum;
char filename[80];
 
if(argc<2) {
printf("usage: bintohex infile\n");
return -1;
}
file=fopen(argv[1],"rb");
if(file==NULL) {
printf("Can't open %s\n",argv[1]);
return -1;
}
buf=(unsigned char*)malloc(BUF_SIZE);
memset(buf,0,BUF_SIZE);
size=fread(buf,1,BUF_SIZE,file);
mem_size=size;
if(size>mem_size) {
printf("FILE TOO LARGE!!!!!!!!!!!\n");
return -1;
}
fclose(file);
strcpy(filename,"codeX.hex");
for(i=0;i<4;++i) {
filename[4]='0'+i;
file=fopen(filename,"wb");
for(j=0;i+j*4*16<mem_size;++j) {
k=j*16;
fprintf(file,":10%4.4x00",k);
sum=0x10+(k>>8)+(k&0xff);
for(k=0;k<16;++k) {
fprintf(file,"%2.2x",buf[i+j*4*16+k*4]);
sum+=buf[i+j*4*16+k*4];
}
sum&=0xff;
sum=0x100-sum;
sum&=0xff;
fprintf(file,"%2.2x\n",sum);
}
fprintf(file,":00000001ff\n");
fclose(file);
}
free(buf);
return 0;
}
 
/tools/test.c
0,0 → 1,254
/*-------------------------------------------------------------------
-- TITLE: Plasma CPU test code
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 4/21/01
-- FILENAME: test.c
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- The executable image of this file is used as input to the VHDL.
--
-- This file must not contain any global or static data since
-- there isn't a loader to relocate the .data segment and since
-- having static data causes the opcodes to begin at a different
-- location in the resulting executable file.
--
-- Save the opcodes in "code.txt".
--
-- The interrupt vector is set to address 0x30.
--------------------------------------------------------------------*/
#ifdef MLITE
#undef putchar
// The Plasma CPU VHDL supports a virtual UART. All character writes
// to address 0xffff will be stored in the file "output.txt".
#define putchar(C) *(volatile unsigned char*)0xffff=(unsigned char)(C)
void isr_enable(int);
#else
#define isr_enable(A)
#endif
 
char text[]="Testing the Plasma core.\n";
char buf[20];
int xyz=0xbadbeef;
int abc;
 
char *strcpy2(char *s, const char *t)
{
char *tmp=s;
while((int)(*s++=*t++)) ;
return(tmp);
}
 
static void itoa2(long n, char *s, int base, long *digits)
{
long i,j,sign;
unsigned long n2;
char number[20];
for(i=0;i<15;++i) {
number[i]=' ';
}
number[15]=0;
if(n>=0||base!=10) {
sign=1;
} else {
sign=-1;
}
n2=n*sign;
for(j=14;j>=0;--j) {
i=n2%base;
n2/=base;
number[j]=i<10?'0'+i:'a'+i-10;
if(n2==0&&15-j>=*digits) break;
}
if(sign==-1) {
number[--j]='-';
}
if(*digits==0||*digits<15-j) {
strcpy2(s,&number[j]);
*digits=15-j;
} else {
strcpy2(s,&number[15-*digits]);
}
}
 
void print(long num,long base,long digits)
{
char *ptr,buffer[128];
itoa2(num,buffer,base,&digits);
ptr=buffer;
while(*ptr) {
putchar(*ptr++); /* Put the character out */
if(ptr[-1]=='\n') *--ptr='\r';
}
}
 
void print_hex(unsigned long num)
{
long i;
unsigned long j;
for(i=28;i>=0;i-=4) {
j=((num>>i)&0xf);
if(j<10) putchar('0'+j);
else putchar('a'-10+j);
}
}
 
void print_string(char *p)
{
int i;
for(i=0;p[i];++i) {
putchar(p[i]);
}
}
 
int prime()
{
int i,j;
//show all prime numbers less than 1000
for(i=3;i<1000;i+=2) {
for(j=3;j<i;j+=2) {
if(i%j==0) {
j=0;
break;
}
}
if(j) {
print(i,10,0);
putchar(' ');
}
}
putchar('\n');
return 0;
}
 
int main2()
{
long i,j;
char char_buf[16];
short short_buf[16];
long long_buf[16];
 
//Uncomment to test interrupts
// isr_enable(1);
 
#if 1
//test shift
j=0x12345678;
for(i=0;i<32;++i) {
print_hex(j>>i);
putchar(' ');
}
putchar('\n');
j=0x92345678;
for(i=0;i<32;++i) {
print_hex(j>>i);
putchar(' ');
}
putchar('\n');
j=0x12345678;
for(i=0;i<32;++i) {
print_hex(j<<i);
putchar(' ');
}
putchar('\n');
putchar('\n');
#endif
#if 1
//test multiply and divide
j=7;
for(i=0;i<=10;++i) {
print(j*i,10,0);
putchar(' ');
}
putchar('\n');
j=0x321;
for(i=0;i<=5;++i) {
print_hex(j*(i+0x12345));
putchar(' ');
}
putchar('\n');
j=0x54321;
for(i=0;i<=5;++i) {
print_hex(j*(i+0x123));
putchar(' ');
}
putchar('\n');
j=0x12345;
for(i=1;i<10;++i) {
print_hex(j/i);
putchar(' ');
}
putchar('\n');
for(i=1;i<10;++i) {
print_hex(j%i);
putchar(' ');
}
putchar('\n');
putchar('\n');
#endif
 
#if 1
//test addition and subtraction
j=0x1234;
for(i=0;i<10;++i) {
print_hex(j+i);
putchar(' ');
}
putchar('\n');
for(i=0;i<10;++i) {
print_hex(j-i);
putchar(' ');
}
putchar('\n');
putchar('\n');
#endif
#if 1
//test bit operations
i=0x1234;
j=0x4321;
print_hex(i&j);
putchar(' ');
print_hex(i|j);
putchar(' ');
print_hex(i^j);
putchar(' ');
print_hex(~i);
putchar(' ');
print_hex(i+0x12);
putchar(' ');
print_hex(i-0x12);
putchar('\n');
putchar('\n');
#endif
#if 1
//test memory access
for(i=0;i<10;++i) {
char_buf[i]=i;
short_buf[i]=i;
long_buf[i]=i;
}
for(i=0;i<10;++i) {
j=char_buf[i];
print(j,10,0);
putchar(' ');
j=short_buf[i];
print(j,10,0);
putchar(' ');
j=long_buf[i];
print(j,10,0);
putchar('\n');
}
putchar('\n');
#endif
prime();
putchar('d'); putchar('o'); putchar('n'); putchar('e'); putchar('\n');
 
for(;;) ;
}
 
/tools/pi.c
0,0 → 1,23
/*Calculate the value of PI. Takes a long time!*/
void putchar(char);
 
void print_num(unsigned long num)
{
unsigned long digit,offset;
for(offset=1000;offset;offset/=10) {
digit=num/offset;
putchar(digit+'0');
num-=digit*offset;
}
}
 
long a=10000,b,c=56,d,e,f[57],g;
void main()
{
long a5=a/5;
for(;b-c;) f[b++]=a5;
for(;d=0,g=c*2;c-=14,print_num(e+d/a),e=d%a)for(b=c;d+=f[b]*a,
f[b]=d%--g,d/=g--,--b;d*=b);
putchar('\n');
}
 
/vhdl/mlite_pack.vhd
0,0 → 1,590
---------------------------------------------------------------------
-- TITLE: Plasma Misc. Package
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 2/15/01
-- FILENAME: mlite_pack.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Data types, constants, and add functions needed for the Plasma CPU.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
 
package mlite_pack is
constant ZERO : std_logic_vector(31 downto 0) :=
"00000000000000000000000000000000";
constant ONES : std_logic_vector(31 downto 0) :=
"11111111111111111111111111111111";
--make HIGH_Z equal to ZERO if compiler complains
constant HIGH_Z : std_logic_vector(31 downto 0) :=
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract,
-- alu_less_than, alu_less_than_signed,
-- alu_or, alu_and, alu_xor, alu_nor);
subtype alu_function_type is std_logic_vector(3 downto 0);
constant alu_nothing : alu_function_type := "0000";
constant alu_add : alu_function_type := "0001";
constant alu_subtract : alu_function_type := "0010";
constant alu_less_than : alu_function_type := "0011";
constant alu_less_than_signed : alu_function_type := "0100";
constant alu_or : alu_function_type := "0101";
constant alu_and : alu_function_type := "0110";
constant alu_xor : alu_function_type := "0111";
constant alu_nor : alu_function_type := "1000";
 
-- type shift_function_type is (
-- shift_nothing, shift_left_unsigned,
-- shift_right_signed, do_right_unsigned);
subtype shift_function_type is std_logic_vector(1 downto 0);
constant shift_nothing : shift_function_type := "00";
constant shift_left_unsigned : shift_function_type := "01";
constant shift_right_signed : shift_function_type := "11";
constant shift_right_unsigned : shift_function_type := "10";
 
-- type mult_function_type is (
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo,
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide);
subtype mult_function_type is std_logic_vector(3 downto 0);
constant mult_nothing : mult_function_type := "0000";
constant mult_read_lo : mult_function_type := "0001";
constant mult_read_hi : mult_function_type := "0010";
constant mult_write_lo : mult_function_type := "0011";
constant mult_write_hi : mult_function_type := "0100";
constant mult_mult : mult_function_type := "0101";
constant mult_signed_mult : mult_function_type := "0110";
constant mult_divide : mult_function_type := "0111";
constant mult_signed_divide : mult_function_type := "1000";
 
-- type a_source_type is (from_reg_source, from_imm10_6);
subtype a_source_type is std_logic_vector(1 downto 0);
constant a_from_reg_source : a_source_type := "00";
constant a_from_imm10_6 : a_source_type := "01";
constant a_from_pc : a_source_type := "10";
 
-- type b_source_type is (from_reg_target, from_imm, from_signed_imm);
subtype b_source_type is std_logic_vector(1 downto 0);
constant b_from_reg_target : b_source_type := "00";
constant b_from_imm : b_source_type := "01";
constant b_from_signed_imm : b_source_type := "10";
constant b_from_immX4 : b_source_type := "11";
 
-- type c_source_type is (from_null, from_alu, from_shift,
-- from_mult, from_memory, from_pc, from_imm_shift16,
-- from_reg_source_nez, from_reg_source_eqz);
subtype c_source_type is std_logic_vector(2 downto 0);
constant c_from_null : c_source_type := "000";
constant c_from_alu : c_source_type := "001";
constant c_from_shift : c_source_type := "001"; --same as alu
constant c_from_mult : c_source_type := "001"; --same as alu
constant c_from_memory : c_source_type := "010";
constant c_from_pc : c_source_type := "011";
constant c_from_pc_plus4 : c_source_type := "100";
constant c_from_imm_shift16: c_source_type := "101";
constant c_from_reg_sourcen: c_source_type := "110";
 
-- type pc_source_type is (from_inc4, from_opcode25_0, from_branch, from_lbranch);
subtype pc_source_type is std_logic_vector(1 downto 0);
constant from_inc4 : pc_source_type := "00";
constant from_opcode25_0 : pc_source_type := "01";
constant from_branch : pc_source_type := "10";
constant from_lbranch : pc_source_type := "11";
 
subtype branch_function_type is std_logic_vector(2 downto 0);
constant branch_ltz : branch_function_type := "000";
constant branch_lez : branch_function_type := "001";
constant branch_eq : branch_function_type := "010";
constant branch_ne : branch_function_type := "011";
constant branch_gez : branch_function_type := "100";
constant branch_gtz : branch_function_type := "101";
constant branch_yes : branch_function_type := "110";
 
-- mode(32=1,16=2,8=3), signed, write
subtype mem_source_type is std_logic_vector(3 downto 0);
constant mem_fetch : mem_source_type := "0000";
constant mem_read32 : mem_source_type := "0100";
constant mem_write32 : mem_source_type := "0101";
constant mem_read16 : mem_source_type := "1000";
constant mem_read16s : mem_source_type := "1010";
constant mem_write16 : mem_source_type := "1001";
constant mem_read8 : mem_source_type := "1100";
constant mem_read8s : mem_source_type := "1110";
constant mem_write8 : mem_source_type := "1101";
 
function bv_to_integer(bv: in std_logic_vector) return integer;
function bv_adder(a : in std_logic_vector(32 downto 0);
b : in std_logic_vector(32 downto 0);
do_add: in std_logic) return std_logic_vector;
function bv_adder_lookahead(
a : in std_logic_vector(32 downto 0);
b : in std_logic_vector(32 downto 0);
do_add: in std_logic) return std_logic_vector;
function bv_negate(a : in std_logic_vector) return std_logic_vector;
function bv_increment(a : in std_logic_vector(31 downto 2)
) return std_logic_vector;
function bv_inc6(a : in std_logic_vector
) return std_logic_vector;
 
-- For Altera
COMPONENT lpm_add_sub
GENERIC (
lpm_width : NATURAL;
lpm_direction : STRING := "UNUSED";
lpm_type : STRING;
lpm_hint : STRING);
PORT (
dataa : IN STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0);
add_sub : IN STD_LOGIC ;
datab : IN STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0);
result : OUT STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0));
END COMPONENT;
 
-- For Altera
COMPONENT lpm_ram_dp
GENERIC (
lpm_width : NATURAL;
lpm_widthad : NATURAL;
rden_used : STRING;
intended_device_family : STRING;
lpm_indata : STRING;
lpm_wraddress_control : STRING;
lpm_rdaddress_control : STRING;
lpm_outdata : STRING;
use_eab : STRING;
lpm_type : STRING);
PORT (
wren : IN STD_LOGIC ;
wrclock : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0);
data : IN STD_LOGIC_VECTOR (lpm_width-1 DOWNTO 0);
rdaddress : IN STD_LOGIC_VECTOR (lpm_widthad-1 DOWNTO 0);
wraddress : IN STD_LOGIC_VECTOR (lpm_widthad-1 DOWNTO 0));
END COMPONENT;
 
-- For Altera
component LPM_RAM_DQ
generic (
LPM_WIDTH : natural; -- MUST be greater than 0
LPM_WIDTHAD : natural; -- MUST be greater than 0
LPM_NUMWORDS : natural := 0;
LPM_INDATA : string := "REGISTERED";
LPM_ADDRESS_CONTROL: string := "REGISTERED";
LPM_OUTDATA : string := "REGISTERED";
LPM_FILE : string := "UNUSED";
LPM_TYPE : string := "LPM_RAM_DQ";
USE_EAB : string := "OFF";
INTENDED_DEVICE_FAMILY : string := "UNUSED";
LPM_HINT : string := "UNUSED");
port (
DATA : in std_logic_vector(LPM_WIDTH-1 downto 0);
ADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
INCLOCK : in std_logic := '0';
OUTCLOCK : in std_logic := '0';
WE : in std_logic;
Q : out std_logic_vector(LPM_WIDTH-1 downto 0));
end component;
 
-- For Xilinx
component ramb4_s16_s16
port (
clka : in std_logic;
rsta : in std_logic;
addra : in std_logic_vector;
dia : in std_logic_vector;
ena : in std_logic;
wea : in std_logic;
doa : out std_logic_vector;
 
clkb : in std_logic;
rstb : in std_logic;
addrb : in std_logic_vector;
dib : in std_logic_vector;
enb : in std_logic;
web : in std_logic);
end component;
 
-- For Xilinx
component reg_file_dp_ram
port (
addra : IN std_logic_VECTOR(4 downto 0);
addrb : IN std_logic_VECTOR(4 downto 0);
clka : IN std_logic;
clkb : IN std_logic;
dinb : IN std_logic_VECTOR(31 downto 0);
douta : OUT std_logic_VECTOR(31 downto 0);
web : IN std_logic);
end component;
 
-- For Xilinx
component reg_file_dp_ram_xc4000xla
port (
A : IN std_logic_vector(4 DOWNTO 0);
DI : IN std_logic_vector(31 DOWNTO 0);
WR_EN : IN std_logic;
WR_CLK : IN std_logic;
DPRA : IN std_logic_vector(4 DOWNTO 0);
SPO : OUT std_logic_vector(31 DOWNTO 0);
DPO : OUT std_logic_vector(31 DOWNTO 0));
end component;
component pc_next
port(clk : in std_logic;
reset_in : in std_logic;
pc_new : in std_logic_vector(31 downto 2);
take_branch : in std_logic;
pause_in : in std_logic;
opcode25_0 : in std_logic_vector(25 downto 0);
pc_source : in pc_source_type;
pc_out : out std_logic_vector(31 downto 0);
pc_out_plus4 : out std_logic_vector(31 downto 0));
end component;
 
component mem_ctrl
generic(ACCURATE_TIMING : boolean := false);
port(clk : in std_logic;
reset_in : in std_logic;
pause_in : in std_logic;
nullify_op : in std_logic;
address_pc : in std_logic_vector(31 downto 0);
opcode_out : out std_logic_vector(31 downto 0);
 
address_data : in std_logic_vector(31 downto 0);
mem_source : in mem_source_type;
data_write : in std_logic_vector(31 downto 0);
data_read : out std_logic_vector(31 downto 0);
pause_out : out std_logic;
mem_address : out std_logic_vector(31 downto 0);
mem_data_w : out std_logic_vector(31 downto 0);
mem_data_r : in std_logic_vector(31 downto 0);
mem_byte_sel : out std_logic_vector(3 downto 0);
mem_write : out std_logic);
end component;
 
component control
port(opcode : in std_logic_vector(31 downto 0);
intr_signal : in std_logic;
rs_index : out std_logic_vector(5 downto 0);
rt_index : out std_logic_vector(5 downto 0);
rd_index : out std_logic_vector(5 downto 0);
imm_out : out std_logic_vector(15 downto 0);
alu_func : out alu_function_type;
shift_func : out shift_function_type;
mult_func : out mult_function_type;
branch_func : out branch_function_type;
a_source_out : out a_source_type;
b_source_out : out b_source_type;
c_source_out : out c_source_type;
pc_source_out: out pc_source_type;
mem_source_out:out mem_source_type);
end component;
 
component reg_bank
generic(memory_type : string := "TRI_PORT");
port(clk : in std_logic;
reset_in : in std_logic;
pause : in std_logic;
rs_index : in std_logic_vector(5 downto 0);
rt_index : in std_logic_vector(5 downto 0);
rd_index : in std_logic_vector(5 downto 0);
reg_source_out : out std_logic_vector(31 downto 0);
reg_target_out : out std_logic_vector(31 downto 0);
reg_dest_new : in std_logic_vector(31 downto 0);
intr_enable : out std_logic);
end component;
 
component bus_mux
port(imm_in : in std_logic_vector(15 downto 0);
reg_source : in std_logic_vector(31 downto 0);
a_mux : in a_source_type;
a_out : out std_logic_vector(31 downto 0);
 
reg_target : in std_logic_vector(31 downto 0);
b_mux : in b_source_type;
b_out : out std_logic_vector(31 downto 0);
 
c_bus : in std_logic_vector(31 downto 0);
c_memory : in std_logic_vector(31 downto 0);
c_pc : in std_logic_vector(31 downto 0);
c_pc_plus4 : in std_logic_vector(31 downto 0);
c_mux : in c_source_type;
reg_dest_out : out std_logic_vector(31 downto 0);
 
branch_func : in branch_function_type;
take_branch : out std_logic);
end component;
 
component alu
generic(adder_type : string := "GENERIC";
alu_type : string := "GENERIC");
port(a_in : in std_logic_vector(31 downto 0);
b_in : in std_logic_vector(31 downto 0);
alu_function : in alu_function_type;
c_alu : out std_logic_vector(31 downto 0));
end component;
 
component shifter
generic( shifter_type : string := "GENERIC" );
port(value : in std_logic_vector(31 downto 0);
shift_amount : in std_logic_vector(4 downto 0);
shift_func : in shift_function_type;
c_shift : out std_logic_vector(31 downto 0));
end component;
 
component mult
generic (
adder_type : string := "GENERIC";
mult_type : string := "GENERIC");
port (
clk : in std_logic;
a, b : in std_logic_vector(31 downto 0);
mult_func : in mult_function_type;
c_mult : out std_logic_vector(31 downto 0);
pause_out : out std_logic);
end component;
 
component pipeline
port(clk : in std_logic;
reset : in std_logic;
a_bus : in std_logic_vector(31 downto 0);
a_busD : out std_logic_vector(31 downto 0);
b_bus : in std_logic_vector(31 downto 0);
b_busD : out std_logic_vector(31 downto 0);
alu_func : in alu_function_type;
alu_funcD : out alu_function_type;
shift_func : in shift_function_type;
shift_funcD : out shift_function_type;
mult_func : in mult_function_type;
mult_funcD : out mult_function_type;
reg_dest : in std_logic_vector(31 downto 0);
reg_destD : out std_logic_vector(31 downto 0);
rd_index : in std_logic_vector(5 downto 0);
rd_indexD : out std_logic_vector(5 downto 0);
 
rs_index : in std_logic_vector(5 downto 0);
rt_index : in std_logic_vector(5 downto 0);
pc_source : in pc_source_type;
mem_source : in mem_source_type;
a_source : in a_source_type;
b_source : in b_source_type;
c_source : in c_source_type;
c_bus : in std_logic_vector(31 downto 0);
pause_any : in std_logic;
pause_pipeline : out std_logic);
end component;
 
component mlite_cpu
generic(memory_type : string := "ALTERA";
mult_type : string := "GENERIC";
shifter_type : string := "GENERIC";
pipeline_stages : natural := 3);
port(clk : in std_logic;
reset_in : in std_logic;
intr_in : in std_logic;
 
mem_address : out std_logic_vector(31 downto 0);
mem_data_w : out std_logic_vector(31 downto 0);
mem_data_r : in std_logic_vector(31 downto 0);
mem_byte_sel: out std_logic_vector(3 downto 0);
mem_write : out std_logic;
mem_pause : in std_logic);
end component;
 
component ram
generic(memory_type : string := "GENERIC");
port(clk : in std_logic;
mem_byte_sel : in std_logic_vector(3 downto 0);
mem_write : in std_logic;
mem_address : in std_logic_vector(31 downto 0);
mem_data_w : in std_logic_vector(31 downto 0);
mem_data_r : out std_logic_vector(31 downto 0));
end component; --ram
 
component uart
generic(log_file : string := "UNUSED");
port(clk : in std_logic;
reset : in std_logic;
uart_sel : in std_logic;
data : in std_logic_vector(7 downto 0);
uart_read : in std_logic;
uart_write : out std_logic;
pause : out std_logic);
end component; --uart
 
component plasma
generic(memory_type : string := "GENERIC";
log_file : string := "UNUSED");
port(clk_in : in std_logic;
reset_in : in std_logic;
intr_in : in std_logic;
 
uart_read : in std_logic;
uart_write : out std_logic;
 
mem_address_out : out std_logic_vector(31 downto 0);
mem_data : out std_logic_vector(31 downto 0);
mem_byte_sel_out : out std_logic_vector(3 downto 0);
mem_write_out : out std_logic;
mem_pause_in : in std_logic);
end component; --plasma
 
component plasma_if
generic(memory_type : string := "ALTERA";
log_file : string := "UNUSED");
port(clk_in : in std_logic;
reset_n : in std_logic;
uart_read : in std_logic;
uart_write : out std_logic;
 
address : out std_logic_vector(31 downto 0);
data : out std_logic_vector(31 downto 0);
we_n : out std_logic;
oe_n : out std_logic;
be_n : out std_logic_vector(3 downto 0);
sram0_cs_n : out std_logic;
sram1_cs_n : out std_logic);
end component; --plasma_if
 
end; --package mlite_pack
 
package body mlite_pack is
 
function bv_to_integer(bv: in std_logic_vector) return integer is
variable result : integer;
variable b : integer;
begin
result := 0;
b := 0;
for index in bv'range loop
if bv(index) = '1' then
b := 1;
else
b := 0;
end if;
result := result * 2 + b;
end loop;
return result;
end; --function bv_to_integer
 
 
function bv_adder(a : in std_logic_vector(32 downto 0);
b : in std_logic_vector(32 downto 0);
do_add: in std_logic) return std_logic_vector is
variable carry_in : std_logic;
variable bb : std_logic_vector(32 downto 0);
variable result : std_logic_vector(32 downto 0);
begin
result := '0' & ZERO;
if do_add = '1' then
bb := b;
carry_in := '0';
else
bb := not b;
carry_in := '1';
end if;
for index in 0 to 32 loop
result(index) := a(index) xor bb(index) xor carry_in;
carry_in := (carry_in and (a(index) or bb(index))) or
(a(index) and bb(index));
end loop;
return result;
end; --function
 
 
function bv_adder_lookahead(
a : in std_logic_vector(32 downto 0);
b : in std_logic_vector(32 downto 0);
do_add: in std_logic) return std_logic_vector is
variable carry : std_logic_vector(32 downto 0);
variable p, g : std_logic_vector(32 downto 0);
variable bb : std_logic_vector(32 downto 0);
variable result : std_logic_vector(32 downto 0);
variable i : natural;
begin
carry := '0' & ZERO;
if do_add = '1' then
bb := b;
carry(0) := '0';
else
bb := not b;
carry(0) := '1';
end if;
 
p := a or bb; --propogate
g := a and bb; --generate
for index in 0 to 7 loop
i := index*4;
carry(i+1) := g(i) or
(p(i) and carry(i));
i := index*4+1;
carry(i+1) := g(i) or
(p(i) and g(i-1)) or
((p(i) and p(i-1)) and carry(i-1));
i := index*4+2;
carry(i+1) := g(i) or
(p(i) and g(i-1)) or
(p(i) and p(i-1) and g(i-2)) or
((p(i) and p(i-1) and p(i-2)) and carry(i-2));
i := index*4+3;
carry(i+1) := g(i) or
(p(i) and g(i-1)) or
(p(i) and p(i-1) and g(i-2)) or
(p(i) and p(i-1) and p(i-2) and g(i-3)) or
(((p(i) and p(i-1)) and (p(i-2) and p(i-3)))
and carry(i-3));
end loop;
result := (a xor bb) xor carry;
return result;
end; --function
 
 
function bv_negate(a : in std_logic_vector) return std_logic_vector is
variable carry_in : std_logic;
variable not_a : std_logic_vector(31 downto 0);
variable result : std_logic_vector(31 downto 0);
begin
result := ZERO;
not_a := not a;
carry_in := '1';
for index in a'reverse_range loop
result(index) := not_a(index) xor carry_in;
carry_in := carry_in and not_a(index);
end loop;
return result;
end; --function
 
 
function bv_increment(a : in std_logic_vector(31 downto 2)
) return std_logic_vector is
variable carry_in : std_logic;
variable result : std_logic_vector(31 downto 2);
begin
result := ZERO(31 downto 2);
carry_in := '1';
for index in 2 to 31 loop
result(index) := a(index) xor carry_in;
carry_in := a(index) and carry_in;
end loop;
return result;
end; --function
 
 
function bv_inc6(a : in std_logic_vector
) return std_logic_vector is
variable carry_in : std_logic;
variable result : std_logic_vector(5 downto 0);
begin
result := "000000";
carry_in := '1';
for index in 0 to 5 loop
result(index) := a(index) xor carry_in;
carry_in := a(index) and carry_in;
end loop;
return result;
end; --function
 
end; --package body
 
 
/vhdl/mlite_cpu.vhd
0,0 → 1,341
---------------------------------------------------------------------
-- TITLE: Plasma CPU core
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 2/15/01
-- FILENAME: mlite_cpu.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- NOTE: MIPS(tm) and MIPS I(tm) are registered trademarks of MIPS
-- Technologies. MIPS Technologies does not endorse and is not
-- associated with this project.
-- DESCRIPTION:
-- Top level VHDL document that ties the nine other entities together.
--
-- Executes all MIPS I(tm) opcodes but exceptions and non-aligned
-- memory accesses. Based on information found in:
-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
-- and "The Designer's Guide to VHDL" by Peter J. Ashenden
--
-- The CPU is implemented as a two or three stage pipeline.
-- An add instruction would take the following steps (see cpu.gif):
-- Stage #1:
-- 1. The "pc_next" entity passes the program counter (PC) to the
-- "mem_ctrl" entity which fetches the opcode from memory.
-- Stage #2:
-- 2. "Mem_ctrl" passes the opcode to the "control" entity.
-- 3. "Control" converts the 32-bit opcode to a 60-bit VLWI opcode
-- and sends control signals to the other entities.
-- 4. Based on the rs_index and rt_index control signals, "reg_bank"
-- sends the 32-bit reg_source and reg_target to "bus_mux".
-- 5. Based on the a_source and b_source control signals, "bus_mux"
-- multiplexes reg_source onto a_bus and reg_target onto b_bus.
-- Stage #3:
-- 6. Based on the alu_func control signals, "alu" adds the values
-- from a_bus and b_bus and places the result on c_bus.
-- 7. Based on the c_source control signals, "bus_bux" multiplexes
-- c_bus onto reg_dest.
-- 8. Based on the rd_index control signal, "reg_bank" saves
-- reg_dest into the correct register.
--
-- All signals are active high. Writing to high memory where a(31)='1'
-- takes five cycles to meet RAM address hold times.
-- Addresses with a(31)='0' are assumed to be clocked and take three cycles.
-- Here are the signals for writing a character to address 0xffff:
--
-- intr_in mem_pause
-- reset_in mem_write
-- clk mem_byte_sel
-- ns mem_address m_data_r m_data_w
-- =============================================
-- 3000 1 0 0 0000002C A2820000 ZZZZZZZZ 0 0 0 (0 fetch write opcode)
-- 3050 0 0 0 0000002C A2820000 ZZZZZZZZ 0 0 0
-- 3100 1 0 0 00000030 340A0041 ZZZZZZZZ 0 0 0 (1 execute write opcode)
-- 3150 0 0 0 00000030 340A0041 ZZZZZZZZ 0 0 0
-- 3200 1 0 0 00000030 340A0041 ZZZZZZZZ 0 0 0 (2 calculating address)
-- 3250 0 0 0 00000030 340A0041 ZZZZZZZZ 0 0 0
-- 3300 1 0 0 0000FFFF ZZZZZZZZ 6A6A6A6A 1 1 0 (3 writing value)
-- 3350 0 0 0 0000FFFF ZZZZZZZZ 6A6A6A6A 1 1 0
-- 3400 1 0 0 00000034 340B0042 ZZZZZZZZ 0 0 0
-- 3450 0 0 0 00000034 340B0042 ZZZZZZZZ 0 0 0
--
-- Program:
-- addr value opcode args
-- ===================================
-- 002c a2820000 sb $v0,0($s4)
-- 0030 340a0041 li $t2,0x41
-- 0034 340b0042 li $t3,0x42
---------------------------------------------------------------------
library ieee;
use work.mlite_pack.all;
--library ieee, mlite_lib;
--use mlite_lib.mlite_pack.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
 
entity mlite_cpu is
generic(memory_type : string := "GENERIC"; --DUAL_PORT_XILINX_XC4000XLA
adder_type : string := "GENERIC"; --AREA_OPTIMIZED
mult_type : string := "GENERIC"; --AREA_OPTIMIZED
shifter_type : string := "GENERIC"; --AREA_OPTIMIZED
alu_type : string := "GENERIC"; --AREA_OPTIMIZED
pipeline_stages : natural := 3;
accurate_timing : boolean := true);
port(clk : in std_logic;
reset_in : in std_logic;
intr_in : in std_logic;
 
mem_address : out std_logic_vector(31 downto 0);
mem_data_w : out std_logic_vector(31 downto 0);
mem_data_r : in std_logic_vector(31 downto 0);
mem_byte_sel: out std_logic_vector(3 downto 0);
mem_write : out std_logic;
mem_pause : in std_logic);
end; --entity mlite_cpu
 
architecture logic of mlite_cpu is
--When using a two stage pipeline "sigD <= sig".
--When using a three stage pipeline "sigD <= sig when rising_edge(clk)",
-- so sigD is delayed by one clock cycle.
signal opcode : std_logic_vector(31 downto 0);
signal rs_index : std_logic_vector(5 downto 0);
signal rt_index : std_logic_vector(5 downto 0);
signal rd_index : std_logic_vector(5 downto 0);
signal rd_indexD : std_logic_vector(5 downto 0);
signal reg_source : std_logic_vector(31 downto 0);
signal reg_target : std_logic_vector(31 downto 0);
signal reg_dest : std_logic_vector(31 downto 0);
signal reg_destD : std_logic_vector(31 downto 0);
signal a_bus : std_logic_vector(31 downto 0);
signal a_busD : std_logic_vector(31 downto 0);
signal b_bus : std_logic_vector(31 downto 0);
signal b_busD : std_logic_vector(31 downto 0);
signal c_bus : std_logic_vector(31 downto 0);
signal c_alu : std_logic_vector(31 downto 0);
signal c_shift : std_logic_vector(31 downto 0);
signal c_mult : std_logic_vector(31 downto 0);
signal c_memory : std_logic_vector(31 downto 0);
signal imm : std_logic_vector(15 downto 0);
signal pc : std_logic_vector(31 downto 0);
signal pc_plus4 : std_logic_vector(31 downto 0);
signal alu_func : alu_function_type;
signal alu_funcD : alu_function_type;
signal shift_func : shift_function_type;
signal shift_funcD : shift_function_type;
signal mult_func : mult_function_type;
signal mult_funcD : mult_function_type;
signal branch_func : branch_function_type;
signal take_branch : std_logic;
signal a_source : a_source_type;
signal b_source : b_source_type;
signal c_source : c_source_type;
signal pc_source : pc_source_type;
signal mem_source : mem_source_type;
signal pause_mult : std_logic;
signal pause_ctrl : std_logic;
signal pause_pipeline : std_logic;
signal pause_any : std_logic;
signal pause_non_ctrl : std_logic;
signal pause_bank : std_logic;
signal nullify_op : std_logic;
signal intr_enable : std_logic;
signal intr_signal : std_logic;
signal reset_reg : std_logic_vector(3 downto 0);
signal reset : std_logic;
begin --architecture
 
pause_any <= (mem_pause or pause_ctrl) or (pause_mult or pause_pipeline);
pause_non_ctrl <= (mem_pause or pause_mult) or pause_pipeline;
pause_bank <= (mem_pause or pause_ctrl or pause_mult) and not pause_pipeline;
nullify_op <= '1' when (pc_source = from_lbranch and take_branch = '0')
or intr_signal = '1'
else '0';
c_bus <= c_alu or c_shift or c_mult;
reset <= '1' when reset_in = '1' or reset_reg /= "1111" else '0';
 
--synchronize reset and interrupt pins
intr_proc: process(clk, reset_in, reset_reg, intr_in, intr_enable,
pc_source, pc, pause_any)
begin
if reset_in = '1' then
reset_reg <= "0000";
intr_signal <= '0';
elsif rising_edge(clk) then
if reset_reg /= "1111" then
reset_reg <= reset_reg + 1;
end if;
 
--don't try to interrupt a multi-cycle instruction
if pause_any = '0' then
if intr_in = '1' and intr_enable = '1' and
pc_source = from_inc4 and pc(2) = '0' then
--the epc will be backed up one opcode (pc-4)
intr_signal <= '1';
else
intr_signal <= '0';
end if;
end if;
 
end if;
end process;
 
u1_pc_next: pc_next PORT MAP (
clk => clk,
reset_in => reset,
take_branch => take_branch,
pause_in => pause_any,
pc_new => c_bus(31 downto 2),
opcode25_0 => opcode(25 downto 0),
pc_source => pc_source,
pc_out => pc,
pc_out_plus4 => pc_plus4);
 
u2_mem_ctrl: mem_ctrl
generic map (ACCURATE_TIMING => accurate_timing)
PORT MAP (
clk => clk,
reset_in => reset,
pause_in => pause_non_ctrl,
nullify_op => nullify_op,
address_pc => pc,
opcode_out => opcode,
 
address_data => c_bus,
mem_source => mem_source,
data_write => reg_target,
data_read => c_memory,
pause_out => pause_ctrl,
mem_address => mem_address,
mem_data_w => mem_data_w,
mem_data_r => mem_data_r,
mem_byte_sel => mem_byte_sel,
mem_write => mem_write);
 
u3_control: control PORT MAP (
opcode => opcode,
intr_signal => intr_signal,
rs_index => rs_index,
rt_index => rt_index,
rd_index => rd_index,
imm_out => imm,
alu_func => alu_func,
shift_func => shift_func,
mult_func => mult_func,
branch_func => branch_func,
a_source_out => a_source,
b_source_out => b_source,
c_source_out => c_source,
pc_source_out=> pc_source,
mem_source_out=> mem_source);
 
u4_reg_bank: reg_bank
generic map(memory_type => memory_type)
port map (
clk => clk,
reset_in => reset,
pause => pause_bank,
rs_index => rs_index,
rt_index => rt_index,
rd_index => rd_indexD,
reg_source_out => reg_source,
reg_target_out => reg_target,
reg_dest_new => reg_destD,
intr_enable => intr_enable);
 
u5_bus_mux: bus_mux port map (
imm_in => imm,
reg_source => reg_source,
a_mux => a_source,
a_out => a_bus,
 
reg_target => reg_target,
b_mux => b_source,
b_out => b_bus,
 
c_bus => c_bus,
c_memory => c_memory,
c_pc => pc,
c_pc_plus4 => pc_plus4,
c_mux => c_source,
reg_dest_out => reg_dest,
 
branch_func => branch_func,
take_branch => take_branch);
 
u6_alu: alu
generic map (adder_type => adder_type,
alu_type => alu_type)
port map (
a_in => a_busD,
b_in => b_busD,
alu_function => alu_funcD,
c_alu => c_alu);
 
u7_shifter: shifter
generic map (shifter_type => shifter_type)
port map (
value => b_busD,
shift_amount => a_busD(4 downto 0),
shift_func => shift_funcD,
c_shift => c_shift);
 
u8_mult: mult
generic map (adder_type => adder_type,
mult_type => mult_type)
port map (
clk => clk,
a => a_busD,
b => b_busD,
mult_func => mult_funcD,
c_mult => c_mult,
pause_out => pause_mult);
 
pipeline2: if pipeline_stages <= 2 generate
a_busD <= a_bus;
b_busD <= b_bus;
alu_funcD <= alu_func;
shift_funcD <= shift_func;
mult_funcD <= mult_func;
rd_indexD <= rd_index;
 
reg_destD <= reg_dest;
pause_pipeline <= '0';
end generate; --pipeline2
 
pipeline3: if pipeline_stages >= 3 generate
--When operating in three stage pipeline mode, the following signals
--are delayed by one clock cycle: a_bus, b_bus, alu/shift/mult_func,
--c_source, and rd_index.
u9_pipeline: pipeline port map (
clk => clk,
reset => reset,
a_bus => a_bus,
a_busD => a_busD,
b_bus => b_bus,
b_busD => b_busD,
alu_func => alu_func,
alu_funcD => alu_funcD,
shift_func => shift_func,
shift_funcD => shift_funcD,
mult_func => mult_func,
mult_funcD => mult_funcD,
reg_dest => reg_dest,
reg_destD => reg_destD,
rd_index => rd_index,
rd_indexD => rd_indexD,
 
rs_index => rs_index,
rt_index => rt_index,
pc_source => pc_source,
mem_source => mem_source,
a_source => a_source,
b_source => b_source,
c_source => c_source,
c_bus => c_bus,
pause_any => pause_any,
pause_pipeline => pause_pipeline);
end generate; --pipeline3
 
end; --architecture logic
 
/vhdl/reg_bank.vhd
0,0 → 1,368
---------------------------------------------------------------------
-- TITLE: Register Bank
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 2/2/01
-- FILENAME: reg_bank.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Implements a register bank with 32 registers that are 32-bits wide.
-- There are two read-ports and one write port.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use work.mlite_pack.all;
 
entity reg_bank is
generic(memory_type : string := "GENERIC");
port(clk : in std_logic;
reset_in : in std_logic;
pause : in std_logic;
rs_index : in std_logic_vector(5 downto 0);
rt_index : in std_logic_vector(5 downto 0);
rd_index : in std_logic_vector(5 downto 0);
reg_source_out : out std_logic_vector(31 downto 0);
reg_target_out : out std_logic_vector(31 downto 0);
reg_dest_new : in std_logic_vector(31 downto 0);
intr_enable : out std_logic);
end; --entity reg_bank
 
 
--------------------------------------------------------------------
-- The ram_block architecture attempts to use TWO dual-port memories.
-- Different FPGAs and ASICs need different implementations.
-- Choose one of the RAM implementations below.
-- I need feedback on this section!
--------------------------------------------------------------------
architecture ram_block of reg_bank is
signal intr_enable_reg : std_logic;
type ram_type is array(31 downto 0) of std_logic_vector(31 downto 0);
--controls access to dual-port memories
signal addr_a1, addr_a2, addr_b : std_logic_vector(4 downto 0);
signal data_out1, data_out2 : std_logic_vector(31 downto 0);
signal write_enable : std_logic;
-- signal sig_false : std_logic := '0';
-- signal sig_true : std_logic := '1';
-- signal zero_sig : std_logic_vector(15 downto 0) := ZERO(15 downto 0);
 
begin
reg_proc: process(clk, rs_index, rt_index, rd_index, reg_dest_new,
intr_enable_reg, data_out1, data_out2, reset_in, pause)
begin
--setup for first dual-port memory
if rs_index = "101110" then --reg_epc CP0 14
addr_a1 <= "00000";
else
addr_a1 <= rs_index(4 downto 0);
end if;
case rs_index is
when "000000" => reg_source_out <= ZERO;
when "101100" => reg_source_out <= ZERO(31 downto 1) & intr_enable_reg;
when "111111" => --interrupt vector address = 0x3c
reg_source_out <= ZERO(31 downto 8) & "00111100";
when others => reg_source_out <= data_out1;
end case;
 
--setup for second dual-port memory
addr_a2 <= rt_index(4 downto 0);
case rt_index is
when "000000" => reg_target_out <= ZERO;
when others => reg_target_out <= data_out2;
end case;
 
--setup second port (write port) for both dual-port memories
if rd_index /= "000000" and rd_index /= "101100" and pause = '0' then
write_enable <= '1';
else
write_enable <= '0';
end if;
if rd_index = "101110" then --reg_epc CP0 14
addr_b <= "00000";
else
addr_b <= rd_index(4 downto 0);
end if;
 
if reset_in = '1' then
intr_enable_reg <= '0';
elsif rising_edge(clk) then
if rd_index = "101110" then --reg_epc CP0 14
intr_enable_reg <= '0'; --disable interrupts
elsif rd_index = "101100" then
intr_enable_reg <= reg_dest_new(0);
end if;
end if;
 
intr_enable <= intr_enable_reg;
end process;
 
 
--------------------------------------------------------------
---- Pick only ONE of the dual-port RAM implementations below!
--------------------------------------------------------------
 
-- synopsys synthesis_off
 
-- Option #1
-- One tri-port RAM, two read-ports, one write-port
-- 32 registers 32-bits wide
tri_port_mem:
if memory_type = "GENERIC" generate
ram_proc: process(clk, addr_a1, addr_a2, addr_b, reg_dest_new,
write_enable)
variable tri_port_ram : ram_type;
begin
data_out1 <= tri_port_ram(conv_integer(addr_a1));
data_out2 <= tri_port_ram(conv_integer(addr_a2));
if rising_edge(clk) then
if write_enable = '1' then
tri_port_ram(conv_integer(addr_b)) := reg_dest_new;
end if;
end if;
end process;
end generate; --tri_port_mem
 
 
-- Option #2
-- Two dual-port RAMs, each with one read-port and one write-port
-- According to the Xilinx answers database record #4075 this
-- architecture may cause Synplify to infer synchronous dual-port
-- RAM using RAM16x1D.
dual_port_mem:
if memory_type = "DUAL_PORT" generate
ram_proc2: process(clk, addr_a1, addr_a2, addr_b, reg_dest_new,
write_enable)
variable dual_port_ram1 : ram_type;
variable dual_port_ram2 : ram_type;
begin
data_out1 <= dual_port_ram1(conv_integer(addr_a1));
data_out2 <= dual_port_ram2(conv_integer(addr_a2));
if rising_edge(clk) then
if write_enable = '1' then
dual_port_ram1(conv_integer(addr_b)) := reg_dest_new;
dual_port_ram2(conv_integer(addr_b)) := reg_dest_new;
end if;
end if;
end process;
end generate; --dual_port_mem
 
-- synopsys synthesis_on
 
dual_port_mem_coregen:
if memory_type = "DUAL_PORT_XILINX" generate
reg_file_dp_ram_1: reg_file_dp_ram
port map (
addra => addr_a1,
addrb => addr_b,
clka => clk,
clkb => clk,
dinb => reg_dest_new,
douta => data_out1,
web => write_enable);
 
reg_file_dp_ram_2: reg_file_dp_ram
port map (
addra => addr_a2,
addrb => addr_b,
clka => clk,
clkb => clk,
dinb => reg_dest_new,
douta => data_out2,
web => write_enable);
 
end generate; --dual_port_mem
 
dual_port_mem_xc4000xla: if memory_type = "DUAL_PORT_XILINX_XC4000XLA" generate
reg_file_dp_ram_1: reg_file_dp_ram_xc4000xla
port map (
A => addr_b,
DI => reg_dest_new,
WR_EN => write_enable,
WR_CLK => clk,
DPRA => addr_a1,
SPO => open,
DPO => data_out1);
reg_file_dp_ram_2: reg_file_dp_ram_xc4000xla
port map (
A => addr_b,
DI => reg_dest_new,
WR_EN => write_enable,
WR_CLK => clk,
DPRA => addr_a2,
SPO => open,
DPO => data_out2);
 
end generate; --dual_port_mem
 
-- Option #3
-- Generic Two-Port Synchronous RAM
-- generic_tpram can be obtained from:
-- http://www.opencores.org/cvsweb.shtml/generic_memories/
-- Supports ASICs (Artisan, Avant, and Virage) and Xilinx FPGA
-- generic_mem:
-- if memory_type = "OPENCORES_MEM" generate
-- bank1 : generic_tpram port map (
-- clk_a => clk,
-- rst_a => '0',
-- ce_a => '1',
-- we_a => '0',
-- oe_a => '1',
-- addr_a => addr_a1,
-- di_a => ZERO,
-- do_a => data_out1,
--
-- clk_b => clk,
-- rst_b => '0',
-- ce_b => '1',
-- we_b => write_enable,
-- oe_b => '0',
-- addr_b => addr_b,
-- di_a => reg_dest_new);
--
-- bank2 : generic_tpram port map (
-- clk_a => clk,
-- rst_a => '0',
-- ce_a => '1',
-- we_a => '0',
-- oe_a => '1',
-- addr_a => addr_a2,
-- di_a => ZERO,
-- do_a => data_out2,
--
-- clk_b => clk,
-- rst_b => '0',
-- ce_b => '1',
-- we_b => write_enable,
-- oe_b => '0',
-- addr_b => addr_b,
-- di_a => reg_dest_new);
-- end generate; --generic_mem
 
 
-- Option #4
-- Xilinx mode using four 16x16 banks
-- xilinx_mem:
-- if memory_type = "XILINX" generate
-- bank1_high: ramb4_s16_s16 port map (
-- clka => clk,
-- rsta => sig_false,
-- addra => addr_a1,
-- dia => zero_sig,
-- ena => sig_true,
-- wea => sig_false,
-- doa => data_out1(31 downto 16),
--
-- clkb => clk,
-- rstb => sig_false,
-- addrb => addr_b,
-- dib => reg_dest_new(31 downto 16),
-- enb => sig_true,
-- web => write_enable);
--
-- bank1_low: ramb4_s16_s16 port map (
-- clka => clk,
-- rsta => sig_false,
-- addra => addr_a1,
-- dia => zero_sig,
-- ena => sig_true,
-- wea => sig_false,
-- doa => data_out1(15 downto 0),
--
-- clkb => clk,
-- rstb => sig_false,
-- addrb => addr_b,
-- dib => reg_dest_new(15 downto 0),
-- enb => sig_true,
-- web => write_enable);
--
-- bank2_high: ramb4_s16_s16 port map (
-- clka => clk,
-- rsta => sig_false,
-- addra => addr_a2,
-- dia => zero_sig,
-- ena => sig_true,
-- wea => sig_false,
-- doa => data_out2(31 downto 16),
--
-- clkb => clk,
-- rstb => sig_false,
-- addrb => addr_b,
-- dib => reg_dest_new(31 downto 16),
-- enb => sig_true,
-- web => write_enable);
--
-- bank2_low: ramb4_s16_s16 port map (
-- clka => clk,
-- rsta => sig_false,
-- addra => addr_a2,
-- dia => zero_sig,
-- ena => sig_true,
-- wea => sig_false,
-- doa => data_out2(15 downto 0),
--
-- clkb => clk,
-- rstb => sig_false,
-- addrb => addr_b,
-- dib => reg_dest_new(15 downto 0),
-- enb => sig_true,
-- web => write_enable);
-- end generate; --xilinx_mem
 
 
-- Option #5
-- Altera LPM_RAM_DP
-- Xilinx users may need to comment out this section!!!
altera_mem:
if memory_type = "ALTERA" generate
lpm_ram_dp_component1 : lpm_ram_dp
GENERIC MAP (
lpm_width => 32,
lpm_widthad => 5,
rden_used => "FALSE",
intended_device_family => "UNUSED",
lpm_indata => "REGISTERED",
lpm_wraddress_control => "REGISTERED",
lpm_rdaddress_control => "UNREGISTERED",
lpm_outdata => "UNREGISTERED",
use_eab => "ON",
lpm_type => "LPM_RAM_DP"
)
PORT MAP (
wren => write_enable,
wrclock => clk,
data => reg_dest_new,
rdaddress => addr_a1,
wraddress => addr_b,
q => data_out1
);
lpm_ram_dp_component2 : lpm_ram_dp
GENERIC MAP (
lpm_width => 32,
lpm_widthad => 5,
rden_used => "FALSE",
intended_device_family => "UNUSED",
lpm_indata => "REGISTERED",
lpm_wraddress_control => "REGISTERED",
lpm_rdaddress_control => "UNREGISTERED",
lpm_outdata => "UNREGISTERED",
use_eab => "ON",
lpm_type => "LPM_RAM_DP"
)
PORT MAP (
wren => write_enable,
wrclock => clk,
data => reg_dest_new,
rdaddress => addr_a2,
wraddress => addr_b,
q => data_out2
);
end generate; --altera_mem
 
end; --architecture ram_block
 
/vhdl/pipeline.vhd
0,0 → 1,123
---------------------------------------------------------------------
-- TITLE: Pipeline
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 6/24/02
-- FILENAME: pipeline.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Controls the three stage pipeline by delaying the signals:
-- a_bus, b_bus, alu/shift/mult_func, c_source, and rs_index.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
--Note: sigD <= sig after rising_edge(clk)
entity pipeline is
port(clk : in std_logic;
reset : in std_logic;
a_bus : in std_logic_vector(31 downto 0);
a_busD : out std_logic_vector(31 downto 0);
b_bus : in std_logic_vector(31 downto 0);
b_busD : out std_logic_vector(31 downto 0);
alu_func : in alu_function_type;
alu_funcD : out alu_function_type;
shift_func : in shift_function_type;
shift_funcD : out shift_function_type;
mult_func : in mult_function_type;
mult_funcD : out mult_function_type;
reg_dest : in std_logic_vector(31 downto 0);
reg_destD : out std_logic_vector(31 downto 0);
rd_index : in std_logic_vector(5 downto 0);
rd_indexD : out std_logic_vector(5 downto 0);
 
rs_index : in std_logic_vector(5 downto 0);
rt_index : in std_logic_vector(5 downto 0);
pc_source : in pc_source_type;
mem_source : in mem_source_type;
a_source : in a_source_type;
b_source : in b_source_type;
c_source : in c_source_type;
c_bus : in std_logic_vector(31 downto 0);
pause_any : in std_logic;
pause_pipeline : out std_logic);
end; --entity pipeline
 
architecture logic of pipeline is
signal rd_index_reg : std_logic_vector(5 downto 0);
signal reg_dest_reg : std_logic_vector(31 downto 0);
signal reg_dest_delay : std_logic_vector(31 downto 0);
signal c_source_reg : c_source_type;
signal pause_enable_reg : std_logic;
begin
 
--When operating in three stage pipeline mode, the following signals
--are delayed by one clock cycle: a_bus, b_bus, alu/shift/mult_func,
--c_source, and rd_index.
pipeline3: process(clk, reset, a_bus, b_bus, alu_func, shift_func, mult_func,
rd_index, rd_index_reg, pause_any, pause_enable_reg,
rs_index, rt_index,
pc_source, mem_source, a_source, b_source, c_source, c_source_reg,
reg_dest, reg_dest_reg, reg_dest_delay, c_bus)
variable pause_mult_clock : std_logic;
variable freeze_pipeline : std_logic;
begin
if (pc_source /= from_inc4 and pc_source /= from_opcode25_0) or
mem_source /= mem_fetch or
(mult_func = mult_read_lo or mult_func = mult_read_hi) then
pause_mult_clock := '1';
else
pause_mult_clock := '0';
end if;
 
freeze_pipeline := not (pause_mult_clock and pause_enable_reg) and pause_any;
pause_pipeline <= pause_mult_clock and pause_enable_reg;
rd_indexD <= rd_index_reg;
 
if c_source_reg = c_from_alu then
reg_dest_delay <= c_bus; --delayed by 1 clock cycle via a_busD & b_busD
else
reg_dest_delay <= reg_dest_reg; --need to delay 1 clock cycle from reg_dest
end if;
reg_destD <= reg_dest_delay;
 
if reset = '1' then
pause_enable_reg <= '1';
rd_index_reg <= "000000";
elsif rising_edge(clk) then
if freeze_pipeline = '0' then
if (rs_index = "000000" or rs_index /= rd_index_reg) or
(a_source /= a_from_reg_source or pause_enable_reg = '0') then
a_busD <= a_bus;
else
a_busD <= reg_dest_delay; --rs from previous operation (bypass stage)
end if;
 
if (rt_index = "000000" or rt_index /= rd_index_reg) or
(b_source /= b_from_reg_target or pause_enable_reg = '0') then
b_busD <= b_bus;
else
b_busD <= reg_dest_delay; --rt from previous operation
end if;
 
alu_funcD <= alu_func;
shift_funcD <= shift_func;
mult_funcD <= mult_func;
reg_dest_reg <= reg_dest;
c_source_reg <= c_source;
rd_index_reg <= rd_index;
end if;
 
if pause_enable_reg = '0' and pause_any = '0' then
pause_enable_reg <= '1'; --enable pause_pipeline
elsif pause_mult_clock = '1' then
pause_enable_reg <= '0'; --disable pause_pipeline
end if;
end if;
 
end process; --pipeline3
 
end; --logic
 
/vhdl/mult.vhd
0,0 → 1,538
---------------------------------------------------------------------
-- TITLE: Multiplication and Division Unit
-- AUTHORS: Steve Rhoads (rhoadss@yahoo.com)
-- Matthias Gruenewald
-- DATE CREATED: 1/31/01
-- FILENAME: mult.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Implements the multiplication and division unit.
-- Division takes 32 clock cycles.
-- Multiplication normally takes 16 clock cycles.
-- if b <= 0xffff then mult in 8 cycles.
-- if b <= 0xff then mult in 4 cycles.
--
-- For multiplication set reg_b = 0x00000000 & b. The 64-bit result
-- will be in reg_b. The lower bits of reg_b contain the upper
-- bits of b that have not yet been multiplied. For 16 clock cycles
-- shift reg_b two bits to the right. Use the lowest two bits of reg_b
-- to multiply by two bits at a time and add the result to the upper
-- 32-bits of reg_b (using C syntax):
-- reg_b = (reg_b >> 2) + (((reg_b & 3) * reg_a) << 32);
--
-- For division set reg_b = '0' & b & 30_ZEROS. The answer will be
-- in answer_reg and the remainder in reg_a. For 32 clock cycles
-- (using C syntax):
-- answer_reg = (answer_reg << 1);
-- if (reg_a >= reg_b) {
-- answer_reg += 1;
-- reg_a -= reg_b;
-- }
-- reg_b = reg_b >> 1;
---------------------------------------------------------------------
--library ieee, MLITE_LIB;
--use MLITE_LIB.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
use work.mlite_pack.all;
 
entity mult is
generic(adder_type : string := "GENERIC";
mult_type : string := "GENERIC");
port(clk : in std_logic;
a, b : in std_logic_vector(31 downto 0);
mult_func : in mult_function_type;
c_mult : out std_logic_vector(31 downto 0);
pause_out : out std_logic);
end; --entity mult
 
architecture logic of mult is
 
-- type mult_function_type is (
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo,
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide);
signal do_mult_reg : std_logic;
signal do_signed_reg : std_logic;
signal count_reg : std_logic_vector(5 downto 0);
signal reg_a : std_logic_vector(31 downto 0);
signal reg_b : std_logic_vector(63 downto 0);
signal answer_reg : std_logic_vector(31 downto 0);
signal aa, bb : std_logic_vector(33 downto 0);
signal sum : std_logic_vector(33 downto 0);
signal sum2 : std_logic_vector(67 downto 0);
signal reg_a_times3 : std_logic_vector(33 downto 0);
signal sign_extend_sig : std_logic;
 
--Used in Xilinx tri-state area optimizated version
signal SUB_Y, A_PROCESSED, B_PROCESSED, A_REG, B_REG : std_logic_vector(31 downto 0);
signal DIV_Y, DIV_Y_IN, DIV_Y_IN_CALC, DIV_Y_IN_INIT, Y_IN, Y_IN2, MULT_Y, Y : std_logic_vector(63 downto 0) := (others => '0');
signal SAVE_Y, SAVE_DIV_Y, MULT_ND, MULT_RDY, DO_SIGNED, DIV_ND : std_logic;
signal DIV_COUNT, INVERT_A, INVERT_B, INVERT_Y, DIV_RDY : std_logic;
signal DIV_COUNTER : std_logic_vector(4 downto 0);
signal PAUSE_IN, SAVE_PAUSE, PAUSE : std_logic := '0';
signal MULT_RFD : std_logic;
signal a_temp_sig, a_neg_sig, b_neg_sig : std_logic_vector(31 downto 0);
signal b_temp_sig : std_logic_vector(63 downto 0);
signal a_msb, b_msb : std_logic;
signal answer_temp_sig : std_logic_vector(31 downto 0);
signal aa_select : std_logic_vector(3 downto 0);
signal bb_select : std_logic_vector(1 downto 0);
signal a_select : std_logic_vector(4 downto 0);
signal b_select : std_logic_vector(11 downto 0);
signal answer_select : std_logic_vector(2 downto 0);
begin
--sum = aa + bb
generic_adder: if adder_type = "GENERIC" generate
sum <= (aa + bb) when do_mult_reg = '1' else
(aa - bb);
end generate; --generic_adder
 
--For Altera: sum = aa + bb
lpm_adder: if adder_type = "ALTERA" generate
lpm_add_sub_component : lpm_add_sub
GENERIC MAP (
lpm_width => 34,
lpm_direction => "UNUSED",
lpm_type => "LPM_ADD_SUB",
lpm_hint => "ONE_INPUT_IS_CONSTANT=NO"
)
PORT MAP (
dataa => aa,
add_sub => do_mult_reg,
datab => bb,
result => sum
);
end generate; --lpm_adder
 
-- Negate signals
a_neg_sig <= bv_negate(a);
b_neg_sig <= bv_negate(b);
sign_extend_sig <= do_signed_reg and do_mult_reg;
-- Result
c_mult <= reg_b(31 downto 0) when mult_func=mult_read_lo else
reg_b(63 downto 32) when mult_func=mult_read_hi else
ZERO;
 
 
GENERIC_MULT: if MULT_TYPE="GENERIC" generate
--multiplication/division unit
mult_proc: process(clk, a, b, mult_func,
do_mult_reg, do_signed_reg, count_reg,
reg_a, reg_b, answer_reg, sum, reg_a_times3)
variable do_mult_temp : std_logic;
variable do_signed_temp : std_logic;
variable count_temp : std_logic_vector(5 downto 0);
variable a_temp : std_logic_vector(31 downto 0);
variable b_temp : std_logic_vector(63 downto 0);
variable answer_temp : std_logic_vector(31 downto 0);
variable start : std_logic;
variable do_write : std_logic;
variable do_hi : std_logic;
variable sign_extend : std_logic;
 
begin
do_mult_temp := do_mult_reg;
do_signed_temp := do_signed_reg;
count_temp := count_reg;
a_temp := reg_a;
b_temp := reg_b;
answer_temp := answer_reg;
sign_extend := do_signed_reg and do_mult_reg;
start := '0';
do_write := '0';
do_hi := '0';
 
case mult_func is
when mult_read_lo =>
when mult_read_hi =>
do_hi := '1';
when mult_write_lo =>
do_write := '1';
when mult_write_hi =>
do_write := '1';
do_hi := '1';
when mult_mult =>
start := '1';
do_mult_temp := '1';
do_signed_temp := '0';
when mult_signed_mult =>
start := '1';
do_mult_temp := '1';
do_signed_temp := '1';
when mult_divide =>
start := '1';
do_mult_temp := '0';
do_signed_temp := '0';
when mult_signed_divide =>
start := '1';
do_mult_temp := '0';
do_signed_temp := a(31) xor b(31);
when others =>
end case;
 
if start = '1' then
count_temp := "000000";
answer_temp := ZERO;
if do_mult_temp = '0' then
b_temp(63) := '0';
if mult_func /= mult_signed_divide or a(31) = '0' then
a_temp := a;
else
a_temp := a_neg_sig;
end if;
if mult_func /= mult_signed_divide or b(31) = '0' then
b_temp(62 downto 31) := b;
else
b_temp(62 downto 31) := b_neg_sig;
end if;
b_temp(30 downto 0) := ZERO(30 downto 0);
else --multiply
if do_signed_temp = '0' or b(31) = '0' then
a_temp := a;
b_temp(31 downto 0) := b;
else
a_temp := a_neg_sig;
b_temp(31 downto 0) := b_neg_sig;
end if;
b_temp(63 downto 32) := ZERO;
end if;
elsif do_write = '1' then
if do_hi = '0' then
b_temp(31 downto 0) := a;
else
b_temp(63 downto 32) := a;
end if;
end if;
 
if do_mult_reg = '0' then --division
aa <= (reg_a(31) and sign_extend) & (reg_a(31) and sign_extend) & reg_a;
bb <= reg_b(33 downto 0);
else --multiplication two-bits at a time
case reg_b(1 downto 0) is
when "00" =>
aa <= "00" & ZERO;
when "01" =>
aa <= (reg_a(31) and sign_extend) & (reg_a(31) and sign_extend) & reg_a;
when "10" =>
aa <= (reg_a(31) and sign_extend) & reg_a & '0';
when others =>
aa <= reg_a_times3;
end case;
bb <= (reg_b(63) and sign_extend) & (reg_b(63) and sign_extend) & reg_b(63 downto 32);
end if;
 
if count_reg(5) = '0' and start = '0' then
count_temp := bv_inc6(count_reg);
if do_mult_reg = '0' then --division
answer_temp(31 downto 1) := answer_reg(30 downto 0);
if reg_b(63 downto 32) = ZERO and sum(32) = '0' then
a_temp := sum(31 downto 0); --aa=aa-bb;
answer_temp(0) := '1';
else
answer_temp(0) := '0';
end if;
if count_reg /= "011111" then
b_temp(62 downto 0) := reg_b(63 downto 1);
else --done with divide
b_temp(63 downto 32) := a_temp;
if do_signed_reg = '0' then
b_temp(31 downto 0) := answer_temp;
else
b_temp(31 downto 0) := bv_negate(answer_temp);
end if;
end if;
else -- mult_mode
b_temp(63 downto 30) := sum;
b_temp(29 downto 0) := reg_b(31 downto 2);
if count_reg = "001000" and sign_extend = '0' and --early stop
reg_b(15 downto 0) = ZERO(15 downto 0) then
count_temp := "111111";
b_temp(31 downto 0) := reg_b(47 downto 16);
end if;
if count_reg = "000100" and sign_extend = '0' and --early stop
reg_b(23 downto 0) = ZERO(23 downto 0) then
count_temp := "111111";
b_temp(31 downto 0) := reg_b(55 downto 24);
end if;
count_temp(5) := count_temp(4);
end if;
end if;
 
if rising_edge(clk) then
do_mult_reg <= do_mult_temp;
do_signed_reg <= do_signed_temp;
count_reg <= count_temp;
reg_a <= a_temp;
reg_b <= b_temp;
answer_reg <= answer_temp;
if start = '1' then
reg_a_times3 <= ((a_temp(31) and do_signed_temp) & a_temp & '0') +
((a_temp(31) and do_signed_temp) & (a_temp(31) and do_signed_temp) & a_temp);
end if;
end if;
 
if count_reg(5) = '0' and mult_func /= mult_nothing and start = '0' then
pause_out <= '1';
else
pause_out <= '0';
end if;
end process;
 
end generate;
 
 
AREA_OPTIMIZED_MULT: if MULT_TYPE="AREA_OPTIMIZED" generate
--Xilinx Tristate size optimization by Matthias Gruenewald
--multiplication/division unit
mult_proc: process(a, b, clk, count_reg, do_mult_reg, do_signed_reg, mult_func, reg_b, sum)
variable do_mult_temp : std_logic;
variable do_signed_temp : std_logic;
variable count_temp : std_logic_vector(5 downto 0);
variable start : std_logic;
variable do_write : std_logic;
variable do_hi : std_logic;
variable sign_extend : std_logic;
 
begin
do_mult_temp := do_mult_reg;
do_signed_temp := do_signed_reg;
count_temp := count_reg;
sign_extend := do_signed_reg and do_mult_reg;
sign_extend_sig <= sign_extend;
start := '0';
do_write := '0';
do_hi := '0';
a_select <= (others => '0');
b_select <= (others => '0');
aa_select <= (others => '0');
bb_select <= (others => '0');
answer_select <= (others => '0');
case mult_func is
when mult_read_lo =>
when mult_read_hi =>
do_hi := '1';
when mult_write_lo =>
do_write := '1';
when mult_write_hi =>
do_write := '1';
do_hi := '1';
when mult_mult =>
start := '1';
do_mult_temp := '1';
do_signed_temp := '0';
when mult_signed_mult =>
start := '1';
do_mult_temp := '1';
do_signed_temp := '1';
when mult_divide =>
start := '1';
do_mult_temp := '0';
do_signed_temp := '0';
when mult_signed_divide =>
start := '1';
do_mult_temp := '0';
do_signed_temp := a(31) xor b(31);
when others =>
end case;
 
if start = '1' then
count_temp := "000000";
answer_select(0)<='1';
--answer_temp := ZERO;
if do_mult_temp = '0' then
--b_temp(63) := '0';
if mult_func /= mult_signed_divide or a(31) = '0' then
a_select(0) <= '1';
--a_temp := a;
else
a_select(1) <= '1';
--a_temp := a_neg;
end if;
if mult_func /= mult_signed_divide or b(31) = '0' then
b_select(0) <= '1';
--b_temp(62 downto 31) := b;
else
b_select(1) <= '1';
--b_temp(62 downto 31) := b_neg;
end if;
--b_temp(30 downto 0) := ZERO(30 downto 0);
else --multiply
if do_signed_temp = '0' or b(31) = '0' then
a_select(2) <= '1';
--a_temp := a;
b_select(2) <= '1';
--b_temp(31 downto 0) := b;
else
a_select(3) <= '1';
--a_temp := a_neg;
b_select(3) <= '1';
--b_temp(31 downto 0) := b_neg;
end if;
--b_temp(63 downto 32) := ZERO;
end if;
elsif do_write = '1' then
if do_hi = '0' then
b_select(4) <= '1';
--b_temp(31 downto 0) := a;
else
b_select(5) <= '1';
--b_temp(63 downto 32) := a;
end if;
end if;
 
if do_mult_reg = '0' then --division
aa_select(0) <= '1';
--aa <= (reg_a(31) and sign_extend) & (reg_a(31) and sign_extend) & reg_a;
bb_select(0) <= '1';
--bb <= reg_b(33 downto 0);
else --multiplication two-bits at a time
case reg_b(1 downto 0) is
when "00" =>
aa_select(1) <= '1';
--aa <= "00" & ZERO;
when "01" =>
aa_select(2) <= '1';
--aa <= (reg_a(31) and sign_extend) & (reg_a(31) and sign_extend) & reg_a;
when "10" =>
aa_select(3) <= '1';
--aa <= (reg_a(31) and sign_extend) & reg_a & '0';
when others =>
--aa_select(4) <= '1';
--aa <= reg_a_times3;
end case;
bb_select(1) <= '1';
--bb <= (reg_b(63) and sign_extend) & (reg_b(63) and sign_extend) & reg_b(63 downto 32);
end if;
 
if count_reg(5) = '0' and start = '0' then
count_temp := bv_inc6(count_reg);
if do_mult_reg = '0' then --division
--answer_temp(31 downto 1) := answer_reg(30 downto 0);
if reg_b(63 downto 32) = ZERO and sum(32) = '0' then
a_select(4) <= '1';
--a_temp := sum(31 downto 0); --aa=aa-bb;
answer_select(1) <= '1';
--answer_temp(0) := '1';
else
answer_select(2) <= '1';
--answer_temp(0) := '0';
end if;
if count_reg /= "011111" then
--b_temp(62 downto 0) := reg_b(63 downto 1);
b_select(6) <= '1';
else --done with divide
--b_temp(63 downto 32) := a_temp;
if do_signed_reg = '0' then
b_select(7) <= '1';
--b_temp(31 downto 0) := answer_temp;
else
b_select(8) <= '1';
--b_temp(31 downto 0) := bv_negate(answer_temp);
end if;
end if;
else -- mult_mode
b_select(9) <= '1';
--b_temp(63 downto 30) := sum;
--b_temp(29 downto 0) := reg_b(31 downto 2);
if count_reg = "001000" and sign_extend = '0' and --early stop
reg_b(15 downto 0) = ZERO(15 downto 0) then
count_temp := "111111";
b_select(10) <= '1';
--b_temp(31 downto 0) := reg_b(47 downto 16);
end if;
if count_reg = "000100" and sign_extend = '0' and --early stop
reg_b(23 downto 0) = ZERO(23 downto 0) then
count_temp := "111111";
b_select(11) <= '1';
--b_temp(31 downto 0) := reg_b(55 downto 24);
end if;
count_temp(5) := count_temp(4);
end if;
end if;
 
if rising_edge(clk) then
do_mult_reg <= do_mult_temp;
do_signed_reg <= do_signed_temp;
count_reg <= count_temp;
reg_a <= a_temp_sig;
reg_b <= b_temp_sig;
answer_reg <= answer_temp_sig;
if start = '1' then
reg_a_times3 <= ((a_temp_sig(31) and do_signed_temp) & a_temp_sig & '0') +
((a_temp_sig(31) and do_signed_temp) & (a_temp_sig(31) and do_signed_temp) & a_temp_sig);
end if;
end if;
 
if count_reg(5) = '0' and mult_func/= mult_nothing and start = '0' then
pause_out <= '1';
else
pause_out <= '0';
end if;
end process;
 
 
-- Arguments
a_msb <= reg_a(31) and sign_extend_sig;
aa <= a_msb & a_msb & reg_a when aa_select(0)='1' else
"00" & ZERO when aa_select(1)='1' else
a_msb & a_msb & reg_a when aa_select(2)='1' else
a_msb & reg_a & '0' when aa_select(3)='1' else
reg_a_times3;
 
b_msb <= reg_b(63) and sign_extend_sig;
bb <= reg_b(33 downto 0) when bb_select(0)='1' else (others => 'Z');
bb <= b_msb & b_msb & reg_b(63 downto 32) when bb_select(1)='1' else (others => 'Z');
 
-- Divide: Init
a_temp_sig <= a when a_select(0)='1' else (others => 'Z');
a_temp_sig <= a_neg_sig when a_select(1)='1' else (others => 'Z');
b_temp_sig <= '0' & b & ZERO(30 downto 0) when b_select(0)='1' else (others => 'Z');
b_temp_sig <= '0' & b_neg_sig & ZERO(30 downto 0) when b_select(1)='1' else (others => 'Z');
-- Multiply: Init
a_temp_sig <= a when a_select(2)='1' else (others => 'Z');
b_temp_sig <= ZERO & b when b_select(2)='1' else (others => 'Z');
a_temp_sig <= a_neg_sig when a_select(3)='1' else (others => 'Z');
b_temp_sig <= ZERO & b_neg_sig when b_select(3)='1' else (others => 'Z');
 
-- Intermediate results
b_temp_sig <= reg_b(63 downto 32) & a when b_select(4)='1' else (others => 'Z');
b_temp_sig <= a & reg_b(31 downto 0) when b_select(5)='1' else (others => 'Z');
 
-- Divide: Operation
a_temp_sig <= sum(31 downto 0) when a_select(4)='1' else (others => 'Z');
b_temp_sig <= reg_b(63) & reg_b(63 downto 1) when b_select(6)='1' else (others => 'Z');
b_temp_sig <= a_temp_sig & answer_temp_sig when b_select(7)='1' else (others => 'Z');
b_temp_sig <= a_temp_sig & bv_negate(answer_temp_sig) when b_select(8)='1' else (others => 'Z');
 
-- Multiply: Operation
b_temp_sig <= sum & reg_b(31 downto 2) when b_select(9)='1' and b_select(10)='0' and b_select(11)='0' else (others => 'Z');
b_temp_sig <= sum(33 downto 2) & reg_b(47 downto 16) when b_select(10)='1' else (others => 'Z');
b_temp_sig <= sum(33 downto 2) & reg_b(55 downto 24) when b_select(11)='1' else (others => 'Z');
 
-- Default values
a_temp_sig <= reg_a when conv_integer(unsigned(a_select))=0 else (others => 'Z');
b_temp_sig <= reg_b when conv_integer(unsigned(b_select))=0 else (others => 'Z');
 
-- Result
answer_temp_sig <= ZERO when answer_select(0)='1' else
answer_reg(30 downto 0) & '1' when answer_select(1)='1' else
answer_reg(30 downto 0) & '0' when answer_select(2)='1' else
answer_reg;
end generate;
end; --architecture logic
 
/vhdl/shifter.vhd
0,0 → 1,75
---------------------------------------------------------------------
-- TITLE: Shifter Unit
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- Matthias Gruenewald
-- DATE CREATED: 2/2/01
-- FILENAME: shifter.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Implements the 32-bit shifter unit.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity shifter is
generic(shifter_type : string := "GENERIC");
port(value : in std_logic_vector(31 downto 0);
shift_amount : in std_logic_vector(4 downto 0);
shift_func : in shift_function_type;
c_shift : out std_logic_vector(31 downto 0));
end; --entity shifter
 
architecture logic of shifter is
-- type shift_function_type is (
-- shift_nothing, shift_left_unsigned,
-- shift_right_signed, shift_right_unsigned);
 
signal shift1L, shift2L, shift4L, shift8L, shift16L : std_logic_vector(31 downto 0);
signal shift1R, shift2R, shift4R, shift8R, shift16R : std_logic_vector(31 downto 0);
signal fills : std_logic_vector(31 downto 16);
 
begin
fills <= "1111111111111111" when shift_func = shift_right_signed and value(31) = '1' else
"0000000000000000";
shift1L <= value(30 downto 0) & '0' when shift_amount(0) = '1' else value;
shift2L <= shift1L(29 downto 0) & "00" when shift_amount(1) = '1' else shift1L;
shift4L <= shift2L(27 downto 0) & "0000" when shift_amount(2) = '1' else shift2L;
shift8L <= shift4L(23 downto 0) & "00000000" when shift_amount(3) = '1' else shift4L;
shift16L <= shift8L(15 downto 0) & ZERO(15 downto 0) when shift_amount(4) = '1' else shift8L;
 
shift1R <= fills(31) & value(31 downto 1) when shift_amount(0) = '1' else value;
shift2R <= fills(31 downto 30) & shift1R(31 downto 2) when shift_amount(1) = '1' else shift1R;
shift4R <= fills(31 downto 28) & shift2R(31 downto 4) when shift_amount(2) = '1' else shift2R;
shift8R <= fills(31 downto 24) & shift4R(31 downto 8) when shift_amount(3) = '1' else shift4R;
shift16R <= fills(31 downto 16) & shift8R(31 downto 16) when shift_amount(4) = '1' else shift8R;
 
-- synthesis translate_off
GENERIC_SHIFTER: if shifter_type = "GENERIC" generate
-- synthesis translate_on
 
c_shift <= shift16L when shift_func = shift_left_unsigned else
shift16R when shift_func = shift_right_unsigned or shift_func = shift_right_signed else
ZERO;
 
-- synthesis translate_off
end generate;
-- synthesis translate_on
 
-- synopsys synthesis_off
AREA_OPTIMIZED_SHIFTER: if shifter_type = "AREA_OPTIMIZED" generate
 
c_shift <= shift16L when shift_func = shift_left_unsigned else (others => 'Z');
c_shift <= shift16R when shift_func = shift_right_unsigned or
shift_func = shift_right_signed else (others => 'Z');
c_shift <= ZERO when shift_func = shift_nothing else (others => 'Z');
 
end generate;
 
-- synopsys synthesis_on
 
end; --architecture logic
 
/vhdl/mem_ctrl.vhd
0,0 → 1,271
---------------------------------------------------------------------
-- TITLE: Memory Controller
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 1/31/01
-- FILENAME: mem_ctrl.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Memory controller for the Plasma CPU.
-- Supports Big or Little Endian mode.
-- Four cycles for a write unless a(31)='1' then two cycles.
-- This entity could implement interfaces to:
-- Data cache
-- Address cache
-- Memory management unit (MMU)
-- DRAM controller
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity mem_ctrl is
generic(ACCURATE_TIMING : boolean := false);
port(clk : in std_logic;
reset_in : in std_logic;
pause_in : in std_logic;
nullify_op : in std_logic;
address_pc : in std_logic_vector(31 downto 0);
opcode_out : out std_logic_vector(31 downto 0);
 
address_data : in std_logic_vector(31 downto 0);
mem_source : in mem_source_type;
data_write : in std_logic_vector(31 downto 0);
data_read : out std_logic_vector(31 downto 0);
pause_out : out std_logic;
mem_address : out std_logic_vector(31 downto 0);
mem_data_w : out std_logic_vector(31 downto 0);
mem_data_r : in std_logic_vector(31 downto 0);
mem_byte_sel : out std_logic_vector(3 downto 0);
mem_write : out std_logic);
end; --entity mem_ctrl
 
architecture logic of mem_ctrl is
--"00" = big_endian; "11" = little_endian
constant little_endian : std_logic_vector(1 downto 0) := "00";
signal opcode_reg : std_logic_vector(31 downto 0);
signal next_opcode_reg : std_logic_vector(31 downto 0);
 
subtype mem_state_type is std_logic_vector(1 downto 0);
signal mem_state_reg : mem_state_type;
constant STATE_FETCH : mem_state_type := "00";
constant STATE_ADDR : mem_state_type := "01";
constant STATE_WRITE : mem_state_type := "10";
constant STATE_PAUSE : mem_state_type := "11";
 
--ACCURATE_TIMING notes:
--The VHDL compiler's timing calculation isn't able to realize that
--memory reads take two clock cycles. It notices that reg_bank:reg_dest
--is dependent on mem_ctrl:mem_data_r which is dependent on
--mem_ctrl:mem_address which is dependent on alu:c_alu. However,
--this dependency is only true for memory read or write cycles
--which are multiple clock cycles. Enabling ACCURATE_TIMING
--creates an additional 32-bit register that does nothing other
--than letting the VHDL compiler accurately predict the maximum
--clock speed.
signal address_reg : std_logic_vector(31 downto 0);
signal write_reg : std_logic;
signal byte_sel_reg : std_logic_vector(3 downto 0);
signal mem_state_next_sig : mem_state_type;
signal opcode_next_sig : std_logic_vector(31 downto 0);
signal write_next_sig : std_logic;
signal byte_sel_next_sig : std_logic_vector(3 downto 0);
begin
 
GEN_REGS: process(clk, reset_in)
begin
if reset_in = '1' then
mem_state_reg <= STATE_FETCH;
opcode_reg <= ZERO;
next_opcode_reg <= ZERO;
elsif rising_edge(clk) then
mem_state_reg <= mem_state_next_sig;
opcode_reg <= opcode_next_sig;
if mem_state_reg = STATE_FETCH then
next_opcode_reg <= mem_data_r;
end if;
end if;
end process;
 
GEN_REGS2: process(clk, address_data, write_next_sig, byte_sel_next_sig)
begin
if rising_edge(clk) then
if ACCURATE_TIMING then
address_reg <= address_data;
write_reg <= write_next_sig;
byte_sel_reg <= byte_sel_next_sig;
end if;
end if;
if not ACCURATE_TIMING then
address_reg <= address_data;
write_reg <= write_next_sig;
byte_sel_reg <= byte_sel_next_sig;
end if;
end process;
mem_proc: process(clk, reset_in, pause_in, nullify_op,
address_pc, address_data, mem_source, data_write,
mem_data_r,
opcode_reg, next_opcode_reg, mem_state_reg,
address_reg, write_reg, byte_sel_reg)
variable data : std_logic_vector(31 downto 0);
variable opcode_next : std_logic_vector(31 downto 0);
variable byte_sel_next : std_logic_vector(3 downto 0);
variable byte_sel : std_logic_vector(3 downto 0);
variable write_next : std_logic;
variable write_line : std_logic;
variable mem_state_next : mem_state_type;
variable pause : std_logic;
variable address : std_logic_vector(31 downto 0);
variable bits : std_logic_vector(1 downto 0);
variable mem_data_w_v : std_logic_vector(31 downto 0);
begin
byte_sel_next := "0000";
write_next := '0';
pause := '0';
mem_state_next := mem_state_reg;
 
data := ZERO;
mem_data_w_v := ZERO;
 
case mem_source is
when mem_read32 =>
data := mem_data_r;
when mem_read16 | mem_read16s =>
if address_reg(1) = little_endian(1) then
data(15 downto 0) := mem_data_r(31 downto 16);
else
data(15 downto 0) := mem_data_r(15 downto 0);
end if;
if mem_source = mem_read16 or data(15) = '0' then
data(31 downto 16) := ZERO(31 downto 16);
else
data(31 downto 16) := ONES(31 downto 16);
end if;
when mem_read8 | mem_read8s =>
bits := address_reg(1 downto 0) xor little_endian;
case bits is
when "00" => data(7 downto 0) := mem_data_r(31 downto 24);
when "01" => data(7 downto 0) := mem_data_r(23 downto 16);
when "10" => data(7 downto 0) := mem_data_r(15 downto 8);
when others => data(7 downto 0) := mem_data_r(7 downto 0);
end case;
if mem_source = mem_read8 or data(7) = '0' then
data(31 downto 8) := ZERO(31 downto 8);
else
data(31 downto 8) := ONES(31 downto 8);
end if;
when mem_write32 =>
write_next := '1';
mem_data_w_v := data_write;
byte_sel_next := "1111";
when mem_write16 =>
write_next := '1';
mem_data_w_v := data_write(15 downto 0) & data_write(15 downto 0);
if address_data(1) = little_endian(1) then
byte_sel_next := "1100";
else
byte_sel_next := "0011";
end if;
when mem_write8 =>
write_next := '1';
mem_data_w_v := data_write(7 downto 0) & data_write(7 downto 0) &
data_write(7 downto 0) & data_write(7 downto 0);
bits := address_data(1 downto 0) xor little_endian;
case bits is
when "00" =>
byte_sel_next := "1000";
when "01" =>
byte_sel_next := "0100";
when "10" =>
byte_sel_next := "0010";
when others =>
byte_sel_next := "0001";
end case;
when others =>
end case;
byte_sel_next_sig <= byte_sel_next;
write_next_sig <= write_next;
opcode_next := opcode_reg;
case mem_state_reg is --State Machine
when STATE_FETCH =>
address := address_pc;
write_line := '0';
byte_sel := "0000";
if mem_source = mem_fetch then --opcode fetch
mem_state_next := STATE_FETCH;
if pause_in = '0' then
opcode_next := mem_data_r;
end if;
else --memory read or write
pause := '1';
if pause_in = '0' then
mem_state_next := STATE_ADDR;
end if;
end if;
when STATE_ADDR => --address lines pre-hold
address := address_reg;
write_line := write_reg;
if write_reg = '1' and address_reg(31) = '1' then
pause := '1';
byte_sel := "0000";
if pause_in = '0' then
mem_state_next := STATE_WRITE; --4 cycle access
end if;
else
byte_sel := byte_sel_reg;
if pause_in = '0' then
opcode_next := next_opcode_reg;
mem_state_next := STATE_FETCH; --2 cycle access
end if;
end if;
when STATE_WRITE =>
pause := '1';
address := address_reg;
write_line := write_reg;
byte_sel := byte_sel_reg;
if pause_in = '0' then
mem_state_next := STATE_PAUSE;
end if;
when OTHERS => --STATE_PAUSE address lines post-hold
address := address_reg;
write_line := write_reg;
byte_sel := "0000";
if pause_in = '0' then
opcode_next := next_opcode_reg;
mem_state_next := STATE_FETCH;
end if;
end case;
if nullify_op = '1' and pause_in = '0' then
opcode_next := ZERO; --NOP after beql
end if;
 
mem_state_next_sig <= mem_state_next;
opcode_next_sig <= opcode_next;
 
if reset_in = '1' then
write_line := '0';
end if;
 
opcode_out <= opcode_reg;
data_read <= data;
pause_out <= pause;
mem_byte_sel <= byte_sel;
mem_address <= address;
mem_write <= write_line;
 
if write_line = '1' then
mem_data_w <= mem_data_w_v;
else
mem_data_w <= HIGH_Z; --ZERO;
end if;
 
end process; --data_proc
 
end; --architecture logic
 
/vhdl/control.vhd
0,0 → 1,455
---------------------------------------------------------------------
-- TITLE: Controller / Opcode Decoder
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 2/8/01
-- FILENAME: control.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- NOTE: MIPS(tm) is a registered trademark of MIPS Technologies.
-- MIPS Technologies does not endorse and is not associated with
-- this project.
-- DESCRIPTION:
-- Controls the CPU by decoding the opcode and generating control
-- signals to the rest of the CPU.
-- This entity decodes the MIPS(tm) opcode into a
-- Very-Long-Word-Instruction.
-- The 32-bit opcode is converted to a
-- 6+6+6+16+5+2+3+3+2+2+3+2+4 = 60 bit VLWI opcode.
-- Based on information found in:
-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich
-- and "The Designer's Guide to VHDL" by Peter J. Ashenden
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity control is
port(opcode : in std_logic_vector(31 downto 0);
intr_signal : in std_logic;
rs_index : out std_logic_vector(5 downto 0);
rt_index : out std_logic_vector(5 downto 0);
rd_index : out std_logic_vector(5 downto 0);
imm_out : out std_logic_vector(15 downto 0);
alu_func : out alu_function_type;
shift_func : out shift_function_type;
mult_func : out mult_function_type;
branch_func : out branch_function_type;
a_source_out : out a_source_type;
b_source_out : out b_source_type;
c_source_out : out c_source_type;
pc_source_out: out pc_source_type;
mem_source_out:out mem_source_type);
end; --entity control
 
architecture logic of control is
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract,
-- alu_less_than, alu_less_than_signed,
-- alu_or, alu_and, alu_xor, alu_nor);
-- type shift_function_type is (
-- shift_nothing, shift_left_unsigned,
-- shift_right_signed, shift_right_unsigned);
-- type mult_function_type is (
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo,
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide);
-- type a_source_type is (from_reg_source, from_imm10_6);
-- type b_source_type is (from_reg_target, from_imm, from_signed_imm);
-- type c_source_type is (from_null, from_alu, from_shift,
-- from_mult, from_memory, from_pc, from_imm_shift16,
-- from_reg_source_nez, from_reg_source_eqz);
-- type pc_source_type is (from_inc4, from_inc8, from_reg_source,
-- from_opcode25_0, from_branch, from_lbranch);
begin
 
control_proc: process(opcode, intr_signal)
variable op, func : std_logic_vector(5 downto 0);
variable rs, rt, rd : std_logic_vector(5 downto 0);
variable rtx : std_logic_vector(4 downto 0);
variable imm : std_logic_vector(15 downto 0);
variable alu_function : alu_function_type;
variable shift_function : shift_function_type;
variable mult_function : mult_function_type;
variable a_source : a_source_type;
variable b_source : b_source_type;
variable c_source : c_source_type;
variable pc_source : pc_source_type;
variable branch_function: branch_function_type;
variable mem_source : mem_source_type;
begin
alu_function := alu_nothing;
shift_function := shift_nothing;
mult_function := mult_nothing;
a_source := a_from_reg_source;
b_source := b_from_reg_target;
c_source := c_from_null;
pc_source := from_inc4;
branch_function := branch_eq;
mem_source := mem_fetch;
op := opcode(31 downto 26);
rs := '0' & opcode(25 downto 21);
rt := '0' & opcode(20 downto 16);
rtx := opcode(20 downto 16);
rd := '0' & opcode(15 downto 11);
func := opcode(5 downto 0);
imm := opcode(15 downto 0);
 
case op is
when "000000" => --SPECIAL
case func is
when "000000" => --SLL r[rd]=r[rt]<<re;
a_source := a_from_imm10_6;
c_source := c_from_shift;
shift_function := shift_left_unsigned;
when "000010" => --SRL r[rd]=u[rt]>>re;
a_source := a_from_imm10_6;
c_source := c_from_shift;
shift_function := shift_right_unsigned;
when "000011" => --SRA r[rd]=r[rt]>>re;
a_source := a_from_imm10_6;
c_source := c_from_shift;
shift_function := shift_right_signed;
when "000100" => --SLLV r[rd]=r[rt]<<r[rs];
c_source := c_from_shift;
shift_function := shift_left_unsigned;
when "000110" => --SRLV r[rd]=u[rt]>>r[rs];
c_source := c_from_shift;
shift_function := shift_right_unsigned;
when "000111" => --SRAV r[rd]=r[rt]>>r[rs];
c_source := c_from_shift;
shift_function := shift_right_signed;
when "001000" => --JR s->pc_next=r[rs];
pc_source := from_branch;
alu_function := alu_add;
branch_function := branch_yes;
when "001001" => --JALR r[rd]=s->pc_next; s->pc_next=r[rs];
c_source := c_from_pc_plus4;
pc_source := from_branch;
alu_function := alu_add;
branch_function := branch_yes;
when "001010" => --MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/
-- c_source := c_from_reg_source_eqz;
when "001011" => --MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/
-- c_source := from_reg_source_nez;
when "001100" => --SYSCALL
-- if(r[4]==0) printf("0x%8.8lx ",r[5]);
when "001101" => --BREAK s->wakeup=1;
when "001111" => --SYNC s->wakeup=1;
when "010000" => --MFHI r[rd]=s->hi;
c_source := c_from_mult;
mult_function := mult_read_hi;
when "010001" => --FTHI s->hi=r[rs];
mult_function := mult_write_hi;
when "010010" => --MFLO r[rd]=s->lo;
c_source := c_from_mult;
mult_function := mult_read_lo;
when "010011" => --MTLO s->lo=r[rs];
mult_function := mult_write_lo;
when "011000" => --MULT s->lo=r[rs]*r[rt]; s->hi=0;
mult_function := mult_signed_mult;
when "011001" => --MULTU s->lo=r[rs]*r[rt]; s->hi=0;
mult_function := mult_mult;
when "011010" => --DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
mult_function := mult_signed_divide;
when "011011" => --DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt];
mult_function := mult_divide;
when "100000" => --ADD r[rd]=r[rs]+r[rt];
c_source := c_from_alu;
alu_function := alu_add;
when "100001" => --ADDU r[rd]=r[rs]+r[rt];
c_source := c_from_alu;
alu_function := alu_add;
when "100010" => --SUB r[rd]=r[rs]-r[rt];
c_source := c_from_alu;
alu_function := alu_subtract;
when "100011" => --SUBU r[rd]=r[rs]-r[rt];
c_source := c_from_alu;
alu_function := alu_subtract;
when "100100" => --AND r[rd]=r[rs]&r[rt];
c_source := c_from_alu;
alu_function := alu_and;
when "100101" => --OR r[rd]=r[rs]|r[rt];
c_source := c_from_alu;
alu_function := alu_or;
when "100110" => --XOR r[rd]=r[rs]^r[rt];
c_source := c_from_alu;
alu_function := alu_xor;
when "100111" => --NOR r[rd]=~(r[rs]|r[rt]);
c_source := c_from_alu;
alu_function := alu_nor;
when "101010" => --SLT r[rd]=r[rs]<r[rt];
c_source := c_from_alu;
alu_function := alu_less_than_signed;
when "101011" => --SLTU r[rd]=u[rs]<u[rt];
c_source := c_from_alu;
alu_function := alu_less_than;
when "101101" => --DADDU r[rd]=r[rs]+u[rt];
c_source := c_from_alu;
alu_function := alu_add;
when "110001" => --TGEU
when "110010" => --TLT
when "110011" => --TLTU
when "110100" => --TEQ
when "110110" => --TNE
when others =>
end case;
when "000001" => --REGIMM
rt := "000000";
rd := "011111";
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_branch;
branch_function := branch_gtz;
--if(test) pc=pc+imm*4
case rtx is
when "10000" => --BLTZAL r[31]=s->pc_next; branch=r[rs]<0;
c_source := c_from_pc_plus4;
branch_function := branch_ltz;
when "00000" => --BLTZ branch=r[rs]<0;
branch_function := branch_ltz;
when "10001" => --BGEZAL r[31]=s->pc_next; branch=r[rs]>=0;
c_source := c_from_pc_plus4;
branch_function := branch_gez;
when "00001" => --BGEZ branch=r[rs]>=0;
branch_function := branch_gez;
when "10010" => --BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0;
c_source := c_from_pc_plus4;
pc_source := from_lbranch;
branch_function := branch_ltz;
when "00010" => --BLTZL lbranch=r[rs]<0;
pc_source := from_lbranch;
branch_function := branch_ltz;
when "10011" => --BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0;
c_source := c_from_pc_plus4;
pc_source := from_lbranch;
branch_function := branch_gez;
when "00011" => --BGEZL lbranch=r[rs]>=0;
pc_source := from_lbranch;
branch_function := branch_gez;
when others =>
end case;
when "000011" => --JAL r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target;
c_source := c_from_pc_plus4;
rd := "011111";
pc_source := from_opcode25_0;
when "000010" => --J s->pc_next=(s->pc&0xf0000000)|target;
pc_source := from_opcode25_0;
when "000100" => --BEQ branch=r[rs]==r[rt];
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_branch;
branch_function := branch_eq;
when "000101" => --BNE branch=r[rs]!=r[rt];
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_branch;
branch_function := branch_ne;
when "000110" => --BLEZ branch=r[rs]<=0;
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_branch;
branch_function := branch_lez;
when "000111" => --BGTZ branch=r[rs]>0;
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_branch;
branch_function := branch_gtz;
when "001000" => --ADDI r[rt]=r[rs]+(short)imm;
b_source := b_from_signed_imm;
c_source := c_from_alu;
rd := rt;
alu_function := alu_add;
when "001001" => --ADDIU u[rt]=u[rs]+(short)imm;
b_source := b_from_signed_imm;
c_source := c_from_alu;
rd := rt;
alu_function := alu_add;
when "001010" => --SLTI r[rt]=r[rs]<(short)imm;
b_source := b_from_signed_imm;
c_source := c_from_alu;
rd := rt;
alu_function := alu_less_than_signed;
when "001011" => --SLTIU u[rt]=u[rs]<(unsigned long)(short)imm;
b_source := b_from_imm;
c_source := c_from_alu;
rd := rt;
alu_function := alu_less_than;
when "001100" => --ANDI r[rt]=r[rs]&imm;
b_source := b_from_imm;
c_source := c_from_alu;
rd := rt;
alu_function := alu_and;
when "001101" => --ORI r[rt]=r[rs]|imm;
b_source := b_from_imm;
c_source := c_from_alu;
rd := rt;
alu_function := alu_or;
when "001110" => --XORI r[rt]=r[rs]^imm;
b_source := b_from_imm;
c_source := c_from_alu;
rd := rt;
alu_function := alu_xor;
when "001111" => --LUI r[rt]=(imm<<16);
c_source := c_from_imm_shift16;
rd := rt;
when "010000" => --COP0
alu_function := alu_or;
c_source := c_from_alu;
if opcode(23) = '0' then --move from CP0
rs := '1' & opcode(15 downto 11);
rt := "000000";
rd := '0' & opcode(20 downto 16);
else --move to CP0
rs := "000000";
rd(5) := '1';
end if;
when "010001" => --COP1
when "010010" => --COP2
when "010011" => --COP3
when "010100" => --BEQL lbranch=r[rs]==r[rt];
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_lbranch;
branch_function := branch_eq;
when "010101" => --BNEL lbranch=r[rs]!=r[rt];
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_lbranch;
branch_function := branch_ne;
when "010110" => --BLEZL lbranch=r[rs]<=0;
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_lbranch;
branch_function := branch_lez;
when "010111" => --BGTZL lbranch=r[rs]>0;
a_source := a_from_pc;
b_source := b_from_immX4;
alu_function := alu_add;
pc_source := from_lbranch;
branch_function := branch_gtz;
when "100000" => --LB r[rt]=*(signed char*)ptr;
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
rd := rt;
c_source := c_from_memory;
mem_source := mem_read8s; --address=(short)imm+r[rs];
when "100001" => --LH r[rt]=*(signed short*)ptr;
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
rd := rt;
c_source := c_from_memory;
mem_source := mem_read16s; --address=(short)imm+r[rs];
when "100010" => --LWL //Not Implemented
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
rd := rt;
c_source := c_from_memory;
mem_source := mem_read32;
when "100011" => --LW r[rt]=*(long*)ptr;
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
rd := rt;
c_source := c_from_memory;
mem_source := mem_read32;
when "100100" => --LBU r[rt]=*(unsigned char*)ptr;
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
rd := rt;
c_source := c_from_memory;
mem_source := mem_read8; --address=(short)imm+r[rs];
when "100101" => --LHU r[rt]=*(unsigned short*)ptr;
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
rd := rt;
c_source := c_from_memory;
mem_source := mem_read16; --address=(short)imm+r[rs];
when "100110" => --LWR //Not Implemented
when "101000" => --SB *(char*)ptr=(char)r[rt];
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
mem_source := mem_write8; --address=(short)imm+r[rs];
when "101001" => --SH *(short*)ptr=(short)r[rt];
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
mem_source := mem_write16;
when "101010" => --SWL //Not Implemented
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
mem_source := mem_write32; --address=(short)imm+r[rs];
when "101011" => --SW *(long*)ptr=r[rt];
a_source := a_from_reg_source;
b_source := b_from_signed_imm;
alu_function := alu_add;
mem_source := mem_write32; --address=(short)imm+r[rs];
when "101110" => --SWR //Not Implemented
when "101111" => --CACHE
when "110000" => --LL r[rt]=*(long*)ptr;
when "110001" => --LWC1
when "110010" => --LWC2
when "110011" => --LWC3
when "110101" => --LDC1
when "110110" => --LDC2
when "110111" => --LDC3
when "111000" => --SC *(long*)ptr=r[rt]; r[rt]=1;
when "111001" => --SWC1
when "111010" => --SWC2
when "111011" => --SWC3
when "111101" => --SDC1
when "111110" => --SDC2
when "111111" => --SDC3
when others =>
end case;
 
if c_source = c_from_null then
rd := "000000";
end if;
 
if intr_signal = '1' then
rs := "111111"; --interrupt vector
rt := "000000";
rd := "101110"; --save PC in EPC
alu_function := alu_or;
shift_function := shift_nothing;
mult_function := mult_nothing;
branch_function := branch_yes;
a_source := a_from_reg_source;
b_source := b_from_reg_target;
c_source := c_from_pc;
pc_source := from_lbranch;
mem_source := mem_fetch;
end if;
 
rs_index <= rs;
rt_index <= rt;
rd_index <= rd;
imm_out <= imm;
alu_func <= alu_function;
shift_func <= shift_function;
mult_func <= mult_function;
branch_func <= branch_function;
a_source_out <= a_source;
b_source_out <= b_source;
c_source_out <= c_source;
pc_source_out <= pc_source;
mem_source_out <= mem_source;
 
end process;
 
end; --logic
 
/vhdl/alu.vhd
0,0 → 1,94
---------------------------------------------------------------------
-- TITLE: Arithmetic Logic Unit
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 2/8/01
-- FILENAME: alu.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Implements the ALU.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity alu is
generic(adder_type : string := "GENERIC";
alu_type : string := "GENERIC");
port(a_in : in std_logic_vector(31 downto 0);
b_in : in std_logic_vector(31 downto 0);
alu_function : in alu_function_type;
c_alu : out std_logic_vector(31 downto 0));
end; --alu
 
architecture logic of alu is
-- type alu_function_type is (alu_nothing, alu_add, alu_subtract,
-- alu_less_than, alu_less_than_signed,
-- alu_or, alu_and, alu_xor, alu_nor);
signal aa, bb, sum : std_logic_vector(32 downto 0);
signal do_add : std_logic;
signal sign_ext : std_logic;
begin
 
do_add <= '1' when alu_function = alu_add else '0';
sign_ext <= '0' when alu_function = alu_less_than else '1';
aa <= (a_in(31) and sign_ext) & a_in;
bb <= (b_in(31) and sign_ext) & b_in;
 
-- synthesis translate_off
GENERIC_ALU: if alu_type="GENERIC" generate
-- synthesis translate_on
 
c_alu <= sum(31 downto 0) when alu_function=alu_add or alu_function=alu_subtract else
ZERO(31 downto 1) & sum(32) when alu_function=alu_less_than or alu_function=alu_less_than_signed else
a_in or b_in when alu_function=alu_or else
a_in and b_in when alu_function=alu_and else
a_in xor b_in when alu_function=alu_xor else
a_in nor b_in when alu_function=alu_nor else
ZERO;
 
-- synthesis translate_off
end generate;
-- synthesis translate_on
 
-- synopsys synthesis_off
 
AREA_OPTIMIZED_ALU: if alu_type="AREA_OPTIMIZED" generate
c_alu <= sum(31 downto 0) when alu_function=alu_add or alu_function=alu_subtract else (others => 'Z');
c_alu <= ZERO(31 downto 1) & sum(32) when alu_function=alu_less_than or alu_function=alu_less_than_signed else (others => 'Z');
c_alu <= a_in or b_in when alu_function=alu_or else (others => 'Z');
c_alu <= a_in and b_in when alu_function=alu_and else (others => 'Z');
c_alu <= a_in xor b_in when alu_function=alu_xor else (others => 'Z');
c_alu <= a_in nor b_in when alu_function=alu_nor else (others => 'Z');
c_alu <= ZERO when alu_function=alu_nothing else (others => 'Z');
end generate;
generic_adder: if adder_type = "GENERIC" generate
sum <= bv_adder(aa, bb, do_add);
end generate; --generic_adder
--For Altera
lpm_adder: if adder_type = "ALTERA" generate
lpm_add_sub_component : lpm_add_sub
GENERIC MAP (
lpm_width => 33,
lpm_direction => "UNUSED",
lpm_type => "LPM_ADD_SUB",
lpm_hint => "ONE_INPUT_IS_CONSTANT=NO"
)
PORT MAP (
dataa => aa,
add_sub => do_add,
datab => bb,
result => sum
);
end generate; --lpm_adder
 
-- synopsys synthesis_on
 
end; --architecture logic
 
/vhdl/tbench.vhd
0,0 → 1,66
---------------------------------------------------------------------
-- TITLE: Test Bench
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 4/21/01
-- FILENAME: tbench.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- This entity provides a test bench for testing the Plasma CPU core.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity tbench is
end; --entity tbench
 
architecture logic of tbench is
constant memory_type : string :=
"GENERIC";
-- "ALTERA";
-- "XILINX";
 
constant log_file : string :=
-- "UNUSED"
"output.txt";
 
signal clk : std_logic := '1';
signal reset : std_logic := '1';
signal interrupt : std_logic := '0';
signal mem_write : std_logic;
signal mem_address : std_logic_vector(31 downto 0);
signal mem_data : std_logic_vector(31 downto 0);
signal mem_pause : std_logic := '0';
signal mem_byte_sel: std_logic_vector(3 downto 0);
signal uart_read : std_logic;
signal uart_write : std_logic;
begin --architecture
clk <= not clk after 50 ns;
reset <= '0' after 500 ns;
 
--Uncomment the line below to test interrupts
-- interrupt <= '1' after 20 us when interrupt = '0' else '0' after 400 ns;
--Uncomment the line below to test mem_pause
-- mem_pause <= '1' after 100 ns when mem_pause = '0' else '0' after 100 ns;
 
u1: plasma
generic map (memory_type => memory_type,
log_file => log_file)
PORT MAP (
clk_in => clk,
reset_in => reset,
intr_in => interrupt,
 
uart_read => uart_read,
uart_write => uart_write,
mem_address_out => mem_address,
mem_data => mem_data,
mem_byte_sel_out => mem_byte_sel,
mem_write_out => mem_write,
mem_pause_in => mem_pause);
 
end; --architecture logic
 
/vhdl/plasma.vhd
0,0 → 1,87
---------------------------------------------------------------------
-- TITLE: Plasma (CPU core with memory)
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 6/4/02
-- FILENAME: plasma.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- This entity combines the CPU core with memory and a UART.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity plasma is
generic(memory_type : string := "ALTERA";
log_file : string := "UNUSED");
port(clk_in : in std_logic;
reset_in : in std_logic;
intr_in : in std_logic;
 
uart_read : in std_logic;
uart_write : out std_logic;
 
mem_address_out : out std_logic_vector(31 downto 0);
mem_data : out std_logic_vector(31 downto 0);
mem_byte_sel_out : out std_logic_vector(3 downto 0);
mem_write_out : out std_logic;
mem_pause_in : in std_logic);
end; --entity plasma
 
architecture logic of plasma is
signal mem_address : std_logic_vector(31 downto 0);
signal mem_data_r : std_logic_vector(31 downto 0);
signal mem_data_w : std_logic_vector(31 downto 0);
signal mem_byte_sel : std_logic_vector(3 downto 0);
signal mem_write : std_logic;
signal mem_pause : std_logic;
signal mem_pause_uart : std_logic;
signal uart_sel : std_logic;
begin --architecture
uart_sel <= '1' when mem_address(12 downto 0) = ONES(12 downto 0) and
mem_byte_sel /= "0000" else '0';
mem_data <= mem_data_r;
mem_pause <= (mem_pause_in and not uart_sel) or mem_pause_uart;
 
u1_cpu: mlite_cpu
generic map (memory_type => memory_type)
PORT MAP (
clk => clk_in,
reset_in => reset_in,
intr_in => intr_in,
mem_address => mem_address,
mem_data_w => mem_data_w,
mem_data_r => mem_data_r,
mem_byte_sel => mem_byte_sel,
mem_write => mem_write,
mem_pause => mem_pause);
 
u2_ram: ram
generic map (memory_type => memory_type)
PORT MAP (
clk => clk_in,
mem_byte_sel => mem_byte_sel,
mem_write => mem_write,
mem_address => mem_address,
mem_data_w => mem_data_w,
mem_data_r => mem_data_r);
 
u3_uart: uart
generic map (log_file => log_file)
port map(
clk => clk_in,
reset => reset_in,
uart_sel => uart_sel,
data => mem_data_w(7 downto 0),
uart_write => uart_write,
uart_read => uart_read,
pause => mem_pause_uart);
 
mem_address_out <= mem_address;
mem_byte_sel_out <= mem_byte_sel;
mem_write_out <= mem_write;
 
end; --architecture logic
/vhdl/makefile
0,0 → 1,119
#Makefile for Plasma
 
#for ModelSim
#WORK_DIR = work
#DEP_FILE = _primary.dat
#COMPILE = vcom -check_synthesis
 
#for FREE VHDL simulator http://www.symphonyeda.com
#WARNING: vhdle now deletes the output.txt if terminated by a ^C
WORK_DIR = work.sym
DEP_FILE = prim.dep
COMPILE = vhdlp -s
 
all: $(WORK_DIR)/tbench/$(DEP_FILE)
 
run: all
-@del output.txt
vhdle -t 30us tbench
type output.txt|more
 
run2: all
-@del output.txt
vhdle -t 50us tbench
type output.txt|more
 
run3: all
-@del output.txt
vhdle -t 100us tbench
type output.txt|more
 
opcodes: all
make -C ..\tools opcodes
vhdle -t 200us tbench
@type output.txt|more
 
simulate: all
vhdle -s -t 10us tbench -do simili.cmd -list trace.txt
-@..\tools\tracehex.exe
-@start ed trace2.txt
 
simulate2: all
vhdle -s -t 4us tbench -do simili.cmd -list trace.txt
-@..\tools\tracehex.exe
-@ed trace2.txt
 
$(WORK_DIR)/lpm_pack/$(DEP_FILE): lpm_pack.vhd
$(COMPILE) lpm_pack.vhd
 
$(WORK_DIR)/lpm_model/$(DEP_FILE): lpm_model.vhd
$(COMPILE) -87 lpm_model.vhd
 
$(WORK_DIR)/mlite_pack/$(DEP_FILE): mlite_pack.vhd
$(COMPILE) mlite_pack.vhd
 
$(WORK_DIR)/alu/$(DEP_FILE): mlite_pack.vhd alu.vhd
$(COMPILE) alu.vhd
 
$(WORK_DIR)/bus_mux/$(DEP_FILE): mlite_pack.vhd bus_mux.vhd
$(COMPILE) bus_mux.vhd
 
$(WORK_DIR)/control/$(DEP_FILE): mlite_pack.vhd control.vhd
$(COMPILE) control.vhd
 
$(WORK_DIR)/mem_ctrl/$(DEP_FILE): mlite_pack.vhd mem_ctrl.vhd
$(COMPILE) mem_ctrl.vhd
 
$(WORK_DIR)/mult/$(DEP_FILE): mlite_pack.vhd mult.vhd
$(COMPILE) mult.vhd
 
$(WORK_DIR)/pc_next/$(DEP_FILE): mlite_pack.vhd pc_next.vhd
$(COMPILE) pc_next.vhd
 
$(WORK_DIR)/reg_bank/$(DEP_FILE): mlite_pack.vhd reg_bank.vhd
$(COMPILE) reg_bank.vhd
 
$(WORK_DIR)/shifter/$(DEP_FILE): mlite_pack.vhd shifter.vhd
$(COMPILE) shifter.vhd
 
$(WORK_DIR)/pipeline/$(DEP_FILE): mlite_pack.vhd pipeline.vhd
$(COMPILE) pipeline.vhd
 
$(WORK_DIR)/mlite_cpu/$(DEP_FILE): mlite_cpu.vhd \
$(WORK_DIR)/mlite_pack/$(DEP_FILE) \
$(WORK_DIR)/alu/$(DEP_FILE) \
$(WORK_DIR)/bus_mux/$(DEP_FILE) \
$(WORK_DIR)/control/$(DEP_FILE) \
$(WORK_DIR)/mem_ctrl/$(DEP_FILE) \
$(WORK_DIR)/mult/$(DEP_FILE) \
$(WORK_DIR)/pc_next/$(DEP_FILE) \
$(WORK_DIR)/reg_bank/$(DEP_FILE) \
$(WORK_DIR)/shifter/$(DEP_FILE) \
$(WORK_DIR)/pipeline/$(DEP_FILE)
$(COMPILE) mlite_cpu.vhd
 
$(WORK_DIR)/ram/$(DEP_FILE): mlite_pack.vhd ram.vhd
$(COMPILE) -87 ram.vhd
 
$(WORK_DIR)/uart/$(DEP_FILE): mlite_pack.vhd uart.vhd
$(COMPILE) -87 uart.vhd
 
$(WORK_DIR)/plasma/$(DEP_FILE): mlite_pack.vhd plasma.vhd \
$(WORK_DIR)/mlite_cpu/$(DEP_FILE) \
$(WORK_DIR)/ram/$(DEP_FILE) \
$(WORK_DIR)/uart/$(DEP_FILE)
$(COMPILE) plasma.vhd
 
$(WORK_DIR)/plasma_if/$(DEP_FILE): mlite_pack.vhd plasma_if.vhd \
$(WORK_DIR)/plasma/$(DEP_FILE)
$(COMPILE) plasma_if.vhd
 
$(WORK_DIR)/tbench/$(DEP_FILE): mlite_pack.vhd tbench.vhd \
$(WORK_DIR)/plasma/$(DEP_FILE) \
$(WORK_DIR)/plasma_if/$(DEP_FILE)
$(COMPILE) tbench.vhd
 
altera: $(WORK_DIR)/lpm_pack/$(DEP_FILE) \
$(WORK_DIR)/lpm_model/$(DEP_FILE)
echo UNUSED > UNUSED
 
/vhdl/ram.vhd
0,0 → 1,184
---------------------------------------------------------------------
-- TITLE: Random Access Memory
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 4/21/01
-- FILENAME: ram.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Implements the RAM, reads the executable from either "code.txt",
-- or for Altera "code[0-3].hex".
-- Modified from "The Designer's Guide to VHDL" by Peter J. Ashenden
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_textio.all;
use std.textio.all;
use work.mlite_pack.all;
 
entity ram is
generic(memory_type : string := "GENERIC");
port(clk : in std_logic;
mem_byte_sel : in std_logic_vector(3 downto 0);
mem_write : in std_logic;
mem_address : in std_logic_vector(31 downto 0);
mem_data_w : in std_logic_vector(31 downto 0);
mem_data_r : out std_logic_vector(31 downto 0));
end; --entity ram
 
architecture logic of ram is
constant ADDRESS_WIDTH : natural := 13;
signal clk_inv : std_logic;
signal mem_sel : std_logic;
signal read_enable : std_logic;
signal write_byte_enable : std_logic_vector(3 downto 0);
begin
clk_inv <= not clk;
mem_sel <= '1' when mem_address(30 downto ADDRESS_WIDTH) = ZERO(30 downto ADDRESS_WIDTH) else
'0';
read_enable <= mem_sel and not mem_write;
write_byte_enable <= mem_byte_sel when mem_sel = '1' else
"0000";
 
generic_ram:
if memory_type = "GENERIC" generate
ram_proc: process(clk, mem_byte_sel, mem_write,
mem_address, mem_data_w, mem_sel)
variable mem_size : natural := 2 ** ADDRESS_WIDTH;
variable data : std_logic_vector(31 downto 0);
subtype word is std_logic_vector(mem_data_w'length-1 downto 0);
type storage_array is
array(natural range 0 to mem_size/4 - 1) of word;
variable storage : storage_array;
variable index : natural := 0;
file load_file : text is in "code.txt";
variable hex_file_line : line;
begin
--load in the ram executable image
if index = 0 then
while not endfile(load_file) loop
--The following two lines had to be commented out for synthesis
readline(load_file, hex_file_line);
hread(hex_file_line, data);
storage(index) := data;
index := index + 1;
end loop;
end if;
 
index := conv_integer(mem_address(ADDRESS_WIDTH-1 downto 2));
data := storage(index);
 
if mem_sel = '1' then
if mem_write = '0' then
mem_data_r <= data;
end if;
if mem_byte_sel(0) = '1' then
data(7 downto 0) := mem_data_w(7 downto 0);
end if;
if mem_byte_sel(1) = '1' then
data(15 downto 8) := mem_data_w(15 downto 8);
end if;
if mem_byte_sel(2) = '1' then
data(23 downto 16) := mem_data_w(23 downto 16);
end if;
if mem_byte_sel(3) = '1' then
data(31 downto 24) := mem_data_w(31 downto 24);
end if;
end if;
if rising_edge(clk) then
if mem_write = '1' then
storage(index) := data;
end if;
end if;
end process;
end generate; --generic_ram
 
 
altera_ram:
if memory_type = "ALTERA" generate
--Quartus II does not allow asynchronous RAM to be initialized
--since the RAM may see glitches on the write enable during powerup.
--Making lpm_address_control="REGISTERED" makes the RAM synchronous
--but then the reads are delayed by a clock cycle.
--Inverting the RAM clock appears to solve the clock cycle delay problem.
lpm_ram_io_component0 : lpm_ram_dq
GENERIC MAP (
intended_device_family => "UNUSED",
lpm_width => 8,
lpm_widthad => ADDRESS_WIDTH-2,
lpm_indata => "REGISTERED",
lpm_address_control => "REGISTERED",
lpm_outdata => "UNREGISTERED",
lpm_file => "code0.hex",
use_eab => "ON",
lpm_type => "LPM_RAM_DQ")
PORT MAP (
data => mem_data_w(31 downto 24),
address => mem_address(ADDRESS_WIDTH-1 downto 2),
inclock => clk_inv,
we => write_byte_enable(3),
q => mem_data_r(31 downto 24));
 
lpm_ram_io_component1 : lpm_ram_dq
GENERIC MAP (
intended_device_family => "UNUSED",
lpm_width => 8,
lpm_widthad => ADDRESS_WIDTH-2,
lpm_indata => "REGISTERED",
lpm_address_control => "REGISTERED",
lpm_outdata => "UNREGISTERED",
lpm_file => "code1.hex",
use_eab => "ON",
lpm_type => "LPM_RAM_DQ")
PORT MAP (
data => mem_data_w(23 downto 16),
address => mem_address(ADDRESS_WIDTH-1 downto 2),
inclock => clk_inv,
we => write_byte_enable(2),
q => mem_data_r(23 downto 16));
 
lpm_ram_io_component2 : lpm_ram_dq
GENERIC MAP (
intended_device_family => "UNUSED",
lpm_width => 8,
lpm_widthad => ADDRESS_WIDTH-2,
lpm_indata => "REGISTERED",
lpm_address_control => "REGISTERED",
lpm_outdata => "UNREGISTERED",
lpm_file => "code2.hex",
use_eab => "ON",
lpm_type => "LPM_RAM_DQ")
PORT MAP (
data => mem_data_w(15 downto 8),
address => mem_address(ADDRESS_WIDTH-1 downto 2),
inclock => clk_inv,
we => write_byte_enable(1),
q => mem_data_r(15 downto 8));
 
lpm_ram_io_component3 : lpm_ram_dq
GENERIC MAP (
intended_device_family => "UNUSED",
lpm_width => 8,
lpm_widthad => ADDRESS_WIDTH-2,
lpm_indata => "REGISTERED",
lpm_address_control => "REGISTERED",
lpm_outdata => "UNREGISTERED",
lpm_file => "code3.hex",
use_eab => "ON",
lpm_type => "LPM_RAM_DQ")
PORT MAP (
data => mem_data_w(7 downto 0),
address => mem_address(ADDRESS_WIDTH-1 downto 2),
inclock => clk_inv,
we => write_byte_enable(0),
q => mem_data_r(7 downto 0));
 
end generate; --altera_ram
 
end; --architecture logic
 
/vhdl/bus_mux.vhd
0,0 → 1,138
---------------------------------------------------------------------
-- TITLE: Bus Multiplexer / Signal Router
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 2/8/01
-- FILENAME: bus_mux.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- This entity is the main signal router.
-- It multiplexes signals from multiple sources to the correct location.
-- The outputs are as follows:
-- a_bus : goes to the ALU
-- b_bus : goes to the ALU
-- reg_dest_out : goes to the register bank
-- take_branch : goes to pc_next
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity bus_mux is
port(imm_in : in std_logic_vector(15 downto 0);
reg_source : in std_logic_vector(31 downto 0);
a_mux : in a_source_type;
a_out : out std_logic_vector(31 downto 0);
 
reg_target : in std_logic_vector(31 downto 0);
b_mux : in b_source_type;
b_out : out std_logic_vector(31 downto 0);
 
c_bus : in std_logic_vector(31 downto 0);
c_memory : in std_logic_vector(31 downto 0);
c_pc : in std_logic_vector(31 downto 0);
c_pc_plus4 : in std_logic_vector(31 downto 0);
c_mux : in c_source_type;
reg_dest_out : out std_logic_vector(31 downto 0);
 
branch_func : in branch_function_type;
take_branch : out std_logic);
end; --entity bus_mux
 
architecture logic of bus_mux is
begin
-- type a_source_type is (a_from_reg_source, a_from_imm10_6);
-- type b_source_type is (b_from_reg_target, b_from_imm, b_from_signed_imm);
-- type c_source_type is (c_from_null, c_from_alu, c_from_shift,
-- c_from_mult, c_from_memory, c_from_pc, c_from_imm_shift16,
-- c_from_reg_source_nez, c_from_reg_source_eqz);
amux: process(reg_source, imm_in, a_mux, c_pc)
begin
case a_mux is
when a_from_reg_source =>
a_out <= reg_source;
when a_from_imm10_6 =>
a_out(31 downto 5) <= ZERO(31 downto 5);
a_out(4 downto 0) <= imm_in(10 downto 6);
when others => --a_from_pc
a_out <= c_pc;
end case;
end process;
 
bmux: process(reg_target, imm_in, b_mux)
begin
case b_mux is
when b_from_reg_target =>
b_out <= reg_target;
when b_from_imm =>
b_out <= ZERO(31 downto 16) & imm_in;
when b_from_signed_imm =>
if imm_in(15) = '0' then
b_out(31 downto 16) <= ZERO(31 downto 16);
else
b_out(31 downto 16) <= "1111111111111111";
end if;
b_out(15 downto 0) <= imm_in;
when others => --b_from_immX4
if imm_in(15) = '0' then
b_out(31 downto 18) <= "00000000000000";
else
b_out(31 downto 18) <= "11111111111111";
end if;
b_out(17 downto 0) <= imm_in & "00";
end case;
end process;
 
cmux: process(c_bus, c_memory, c_pc, c_pc_plus4, imm_in, c_mux)
begin
case c_mux is
when c_from_alu => -- | c_from_shift | c_from_mult =>
reg_dest_out <= c_bus;
when c_from_memory =>
reg_dest_out <= c_memory;
when c_from_pc =>
reg_dest_out <= c_pc(31 downto 3) & "000"; --backup one opcode
when c_from_pc_plus4 =>
reg_dest_out <= c_pc_plus4;
when c_from_imm_shift16 =>
reg_dest_out <= imm_in & ZERO(15 downto 0);
-- when from_reg_source_nez =>
--????
-- when from_reg_source_eqz =>
--????
when others =>
reg_dest_out <= c_bus;
end case;
end process;
 
pc_mux: process(branch_func, reg_source, reg_target)
variable is_equal : std_logic;
begin
if reg_source = reg_target then
is_equal := '1';
else
is_equal := '0';
end if;
case branch_func is
when branch_ltz =>
take_branch <= reg_source(31);
when branch_lez =>
take_branch <= reg_source(31) or is_equal;
when branch_eq =>
take_branch <= is_equal;
when branch_ne =>
take_branch <= not is_equal;
when branch_gez =>
take_branch <= not reg_source(31);
when branch_gtz =>
take_branch <= not reg_source(31) and not is_equal;
when branch_yes =>
take_branch <= '1';
when others =>
take_branch <= is_equal;
end case;
end process;
 
end; --architecture logic
 
/vhdl/pc_next.vhd
0,0 → 1,68
---------------------------------------------------------------------
-- TITLE: Program Counter Next
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 2/8/01
-- FILENAME: pc_next.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Implements the Program Counter logic.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity pc_next is
port(clk : in std_logic;
reset_in : in std_logic;
pc_new : in std_logic_vector(31 downto 2);
take_branch : in std_logic;
pause_in : in std_logic;
opcode25_0 : in std_logic_vector(25 downto 0);
pc_source : in pc_source_type;
pc_out : out std_logic_vector(31 downto 0);
pc_out_plus4 : out std_logic_vector(31 downto 0));
end; --pc_next
 
architecture logic of pc_next is
-- type pc_source_type is (from_inc4, from_opcode25_0, from_branch,
-- from_lbranch);
signal pc_reg : std_logic_vector(31 downto 2); --:= ZERO(31 downto 2);
begin
 
pc_next: process(clk, reset_in, pc_new, take_branch, pause_in,
opcode25_0, pc_source, pc_reg)
variable pc_inc, pc_next : std_logic_vector(31 downto 2);
begin
pc_inc := bv_increment(pc_reg); --pc_reg+1
 
case pc_source is
when from_inc4 =>
pc_next := pc_inc;
when from_opcode25_0 =>
pc_next := pc_reg(31 downto 28) & opcode25_0;
when others => --from_branch | from_lbranch =>
if take_branch = '1' then
pc_next := pc_new;
else
pc_next := pc_inc;
end if;
end case;
 
if pause_in = '1' then
pc_next := pc_reg;
end if;
 
if reset_in = '1' then
pc_reg <= ZERO(31 downto 2);
elsif rising_edge(clk) then
pc_reg <= pc_next;
end if;
 
pc_out <= pc_reg & "00";
pc_out_plus4 <= pc_inc & "00";
end process;
 
end; --logic
 
/vhdl/uart.vhd
0,0 → 1,113
---------------------------------------------------------------------
-- TITLE: UART
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 5/29/02
-- FILENAME: uart.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- Implements the UART.
-- Stalls the CPU until the charater has been transmitted.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_unsigned.all;
use std.textio.all;
use work.mlite_pack.all;
 
entity uart is
generic(log_file : string := "UNUSED");
port(clk : in std_logic;
reset : in std_logic;
uart_sel : in std_logic;
data : in std_logic_vector(7 downto 0);
uart_read : in std_logic;
uart_write : out std_logic;
pause : out std_logic);
end; --entity ram
 
architecture logic of uart is
signal data_reg : std_logic_vector(8 downto 0);
signal bits_reg : std_logic_vector(3 downto 0);
signal div_reg : std_logic_vector(9 downto 0);
begin
 
uart_proc: process(clk, reset, data_reg, bits_reg, div_reg, uart_sel, data)
constant DIV_VALUE : std_logic_vector(9 downto 0) :=
"0100011110"; --33MHz/2/57600Hz = 0x11e
-- "0000000010"; --for debug
variable data_next : std_logic_vector(8 downto 0);
variable bits_next : std_logic_vector(3 downto 0);
variable div_next : std_logic_vector(9 downto 0);
begin
data_next := data_reg;
bits_next := bits_reg;
div_next := div_reg;
 
if uart_sel = '1' then
data_next := data & '0';
bits_next := "1010";
div_next := ZERO(9 downto 0);
elsif div_reg = DIV_VALUE then
data_next := '1' & data_reg(8 downto 1);
if bits_reg /= "0000" then
bits_next := bits_reg - 1;
end if;
div_next := ZERO(9 downto 0);
else
div_next := div_reg + 1;
end if;
 
if reset = '1' then
data_reg <= ZERO(8 downto 0);
bits_reg <= "0000";
div_reg <= ZERO(9 downto 0);
elsif rising_edge(clk) then
data_reg <= data_next;
bits_reg <= bits_next;
div_reg <= div_next;
end if;
 
uart_write <= data_reg(0);
if uart_sel = '0' and bits_reg /= "0000"
and log_file = "UNUSED"
then
pause <= '1';
else
pause <= '0';
end if;
end process;
 
uart_logger:
if log_file /= "UNUSED" generate
uart_proc: process(clk, uart_sel, data)
file store_file : text is out log_file;
variable hex_file_line : line;
variable c : character;
variable index : natural;
variable line_length : natural := 0;
begin
if rising_edge(clk) then
if uart_sel = '1' then
index := conv_integer(data(6 downto 0));
if index /= 10 then
c := character'val(index);
write(hex_file_line, c);
line_length := line_length + 1;
end if;
if index = 10 or line_length >= 72 then
--The following line had to be commented out for synthesis
writeline(store_file, hex_file_line);
line_length := 0;
end if;
end if; --uart_sel
end if; --rising_edge(clk)
end process; --uart_proc
end generate; --uart_logger
 
end; --architecture logic
 
/vhdl/plasma_if.vhd
0,0 → 1,82
---------------------------------------------------------------------
-- TITLE: Plamsa Interface (clock divider and interface to FPGA board)
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 6/6/02
-- FILENAME: plasma_if.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- This entity divides the clock by two and interfaces to the
-- Altera EP20K200EFC484-2X FPGA board.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.mlite_pack.all;
 
entity plasma_if is
generic(memory_type : string := "ALTERA";
log_file : string := "UNUSED");
port(clk_in : in std_logic;
reset_n : in std_logic;
uart_read : in std_logic;
uart_write : out std_logic;
 
address : out std_logic_vector(31 downto 0);
data : out std_logic_vector(31 downto 0);
we_n : out std_logic;
oe_n : out std_logic;
be_n : out std_logic_vector(3 downto 0);
sram0_cs_n : out std_logic;
sram1_cs_n : out std_logic);
end; --entity plasma_if
 
architecture logic of plasma_if is
signal clk_reg : std_logic;
signal reset_in : std_logic;
signal intr_in : std_logic;
signal mem_address : std_logic_vector(31 downto 0);
signal mem_pause_in : std_logic;
signal write_enable : std_logic;
signal mem_byte_sel : std_logic_vector(3 downto 0);
begin --architecture
reset_in <= not reset_n;
intr_in <= '0';
mem_pause_in <= '0';
 
address <= mem_address;
we_n <= not write_enable;
oe_n <= write_enable;
be_n <= not mem_byte_sel;
sram0_cs_n <= not mem_address(16);
sram1_cs_n <= not mem_address(16);
 
--convert 33MHz clock to 16.5MHz clock
clk_div: process(clk_in, reset_in, clk_reg)
begin
if reset_in = '1' then
clk_reg <= '0';
elsif rising_edge(clk_in) then
clk_reg <= not clk_reg;
end if;
end process; --clk_div
 
u1_plama: plasma
generic map (memory_type => memory_type,
log_file => log_file)
PORT MAP (
clk_in => clk_reg,
reset_in => reset_in,
intr_in => intr_in,
 
uart_read => uart_read,
uart_write => uart_write,
mem_address_out => mem_address,
mem_data => data,
mem_byte_sel_out => mem_byte_sel,
mem_write_out => write_enable,
mem_pause_in => mem_pause_in);
 
end; --architecture logic
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.