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/arelease
    from Rev 350 to Rev 352
    Reverse comparison

Rev 350 → Rev 352

/tools/test.c
0,0 → 1,231
/*-------------------------------------------------------------------
-- TITLE: MIPS CPU test code
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 4/21/01
-- FILENAME: test.c
-- PROJECT: MIPS 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.
--
-- After being compiled with the Microsoft MIPS compiler, the program
-- convert will pull out the MIPS opcodes, and switch the executable
-- to Big Endian, and convert absolute jumps into relative jumps,
-- and save the opcodes in "code.txt".
--------------------------------------------------------------------*/
#ifdef SIMULATE
#undef putchar
// The MIPS 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)
#endif
 
//The main entry point must be the first function
//The program convert will change the first opcode to setting
//the stack pointer.
int main()
{
int main2();
main2();
}
 
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)
{
volatile unsigned char *uart_base = (unsigned char *)0xffff;
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);
}
}
 
int prime()
{
int i,j,k;
//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,k;
unsigned long m;
char char_buf[16];
short short_buf[16];
long long_buf[16];
//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');
//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');
 
//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');
//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');
//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');
prime();
putchar('d'); putchar('o'); putchar('n'); putchar('e'); putchar('\n');
}
 
/tools/convert.c
0,0 → 1,44
//convert.c by Steve Rhoads 4/26/01
//This program takes a little-endian MIPS executable and
//converts it to a big-endian executable and changes
//absolute jumps to branches.
#include <stdio.h>
#include <stdlib.h>
 
#define BUF_SIZE (1024*1024)
#define CODE_OFFSET 0x200
 
int main(int argc,char *argv[])
{
FILE *infile,*outfile;
unsigned char *buf;
long size,i,j;
unsigned long d;
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);
outfile=fopen("code.txt","w");
infile=fopen("test2.exe","wb");
for(i=CODE_OFFSET;i<size;i+=4) {
d=(buf[i+3]<<24)|(buf[i+2]<<16)|(buf[i+1]<<8)|buf[i];
if((d>>24)==0x0c) { //JAL
j=(d&0xfffff)-0x400-((i-CODE_OFFSET)>>2)-1; //BGEZAL
d=0x04110000+(j&0xffff);
}
if(i==CODE_OFFSET) {
d=0x341d8000; //ori $29,0,0x8000
}
fprintf(outfile,"%8.8x\n",d);
fwrite(&d,4,1,infile);
}
fclose(outfile);
fclose(infile);
free(buf);
return 0;
}
 
/tools/mips.c
0,0 → 1,413
/*-------------------------------------------------------------------
-- TITLE: MIPS CPU simulator
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 1/31/01
-- FILENAME: mips.c
-- PROJECT: MIPS CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- Software 'as is' without warranty. Author liable for nothing.
-- DESCRIPTION:
-- MIPS CPU simulator in C code.
-- This file served as the starting point for the VHDL code.
--------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.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);
 
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)
{
long value=0;
address%=MEM_SIZE;
address+=(long)s->mem;
switch(size) {
case 4: value=*(long*)address;
if(big_endian) value=ntohl(value);
break;
case 2: if(big_endian) address^=2;
value=*(unsigned short*)address;
if(big_endian) value=ntohs((unsigned short)value);
break;
case 1: if(big_endian) address^=3;
value=*(unsigned char*)address;
break;
default: printf("ERROR");
}
return(value);
}
 
static void mem_write(State *s,long size,long unsigned address,long value)
{
static char_count=0;
if(address==0xffff) { //UART write register at 0xffff
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;
address+=(long)s->mem;
switch(size) {
case 4: if(big_endian) value=htonl(value);
*(long*)address=value;
break;
case 2:
if(big_endian) {
address^=2;
value=htons((unsigned short)value);
}
*(short*)address=(short)value;
break;
case 1: if(big_endian) address^=3;
*(char*)address=(char)value;
break;
default: printf("ERROR");
}
}
 
//execute one cycle of a MIPS CPU
void cycle(State *s,int show_mode)
{
volatile unsigned long opcode;
volatile unsigned long op,rs,rt,rd,re,func,imm,target;
volatile long imm_shift,branch=0,lbranch=2;
volatile long *r=s->r;
volatile unsigned long *u=(unsigned long*)s->r;
volatile 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*/ s->lo=r[rs]*r[rt]; s->hi=0; break;
case 0x19:/*MULTU*/ s->lo=r[rs]*r[rt]; s->hi=0; break;
case 0x1a:/*DIV*/ s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
case 0x1b:/*DIVU*/ s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[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*)ptr; break;
case 0x20:/*LB*/ r[rt]=(signed char)mem_read(s,1,ptr); break;
// case 0x21:/*LH*/ r[rt]=*(signed short*)ptr; break;
case 0x21:/*LH*/ r[rt]=(signed short)mem_read(s,2,ptr); break;
case 0x22:/*LWL*/ break; //fixme
// case 0x23:/*LW*/ r[rt]=*(long*)ptr; break;
case 0x23:/*LW*/ r[rt]=mem_read(s,4,ptr); break;
// case 0x24:/*LBU*/ r[rt]=*(unsigned char*)ptr; break;
case 0x24:/*LBU*/ r[rt]=(unsigned char)mem_read(s,2,ptr); break;
// case 0x25:/*LHU*/ r[rt]=*(unsigned short*)ptr; break;
case 0x25:/*LHU*/ r[rt]=(unsigned short)mem_read(s,2,ptr); break;
case 0x26:/*LWR*/ break; //fixme
// case 0x28:/*SB*/ *(char*)ptr=(char)r[rt]; break;
case 0x28:/*SB*/ mem_write(s,1,ptr,r[rt]); break;
// case 0x29:/*SH*/ *(short*)ptr=(short)r[rt]; break;
case 0x29:/*SH*/ mem_write(s,2,ptr,r[rt]); break;
case 0x2a:/*SWL*/ break; //fixme
// case 0x2b:/*SW*/ *(long*)ptr=r[rt]; break;
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]=*(long*)ptr; 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\n"); s->wakeup=1;
}
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 i,k;
printf("MIPS emulator\n");
memset(s,0,sizeof(State));
s->big_endian=0;
s->mem=malloc(MEM_SIZE);
if(argc<=1) {
printf(" Usage: mips file.exe\n");
printf(" mips file.exe B {for big_endian}\n");
printf(" mips file.exe DD {disassemble}\n");
printf(" mips 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); }
i=fread(s->mem,1,MEM_SIZE,in);
fclose(in);
printf("Read %ld bytes.\n",i);
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(k=0;k<i+3;k+=4) {
*(long*)&s->mem[k]=htonl(*(long*)&s->mem[k]);
}
in=fopen("big.exe","wb");
fwrite(s->mem,i,1,in);
fclose(in);
return(0);
}
if(argc==3&&argv[2][1]=='D') { /*dump image*/
for(k=0;k<i;k+=4) {
s->pc=k;
cycle(s,10);
}
free(s->mem);
return(0);
}
s->pc=0x0;
do_debug(s);
free(s->mem);
return(0);
}
 
/tools/cpu.gif Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
tools/cpu.gif Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tools/index.shtml =================================================================== --- tools/index.shtml (nonexistent) +++ tools/index.shtml (revision 352) @@ -0,0 +1,330 @@ +Project Name: MIPS-lite core +

+Description +

+MIPS-lite is a "clean room" VHDL implementation of a MIPS CPU. +It supports a simplified MIPS III+ instruction set with a two-stage pipeline. +Only User Mode instructions are supported. + +

+Block Diagram +

+

+ +
+
+Example Instruction +

+As an example, an ADD instruction would take the following steps: +

    +
  1. The "pc_next" entity would pass the program + counter (PC) to the "mem_ctrl" entity. [First Stage of Pipeline]
  2. +
  3. "Mem_ctrl" passes the opcode to the "control" entity.
  4. +
  5. "Control" converts the 32-bit opcode to a 60-bit VLWI opcode + and sends control signals to the other entities.
  6. +
  7. Based on the rs_index and rt_index control signals, "reg_bank" + sends the 32-bit reg_source and reg_target to "bus_mux".
  8. +
  9. Based on the a_source and b_source control signals, "bus_mux" + multiplexes reg_source onto a_bus and reg_target onto b_bus.
  10. +
  11. Based on the alu_func control signals, "alu" adds the values + from a_bus and b_bus and places the result on c_bus.
  12. +
  13. Based on the c_source control signals, "bus_bux" multiplexes + c_bus onto reg_dest.
  14. +
  15. Based on the rd_index control signal, "reg_bank" saves + reg_dest into the correct register.
  16. +
+Features +

+The CPU is implemented as a two-stage pipeline with step #1 in the +first stage and steps #2-8 occurring the second stage. +Each instruction takes one clock cycle, except memory accesses, +which take two clock cycles, and multiplication and division, which +can be accessed in 32 clock cycles. +
+
+There are several control lines not shown in the diagram. +A pause (wait-state) line will cause the pipeline to pause +if the multiplication results are accessed before the +multiplication is complete. + +

+Supporting Documentation +

+The implementation is 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
  • +
+ +Tools +

+The tools used include VHDL Synopsys, ModelTech, and the Microsoft +MIPS C compiler. + +

+Registers +

+All of the registers are clocked by the single master clock. +The registers used in the design are grouped by entity and listed below: +









    +     mem_ctrl








    +     ===========================================








    +     |    Register Name    |   Type    | Width |








    +     ===========================================








    +     | next_opcode_reg_reg | Flip-flop |  32   |








    +     |   opcode_reg_reg    | Flip-flop |  32   |








    +     |   setup_done_reg    | Flip-flop |   1   |








    +     ===========================================








    +








    +     mult








    +     ===========================================








    +     |    Register Name    |   Type    | Width |








    +     ===========================================








    +     |   answer_reg_reg    | Flip-flop |  32   |








    +     |    count_reg_reg    | Flip-flop |   6   |








    +     |   do_div_reg_reg    | Flip-flop |   1   |








    +     |  do_signed_reg_reg  | Flip-flop |   1   |








    +     |      reg_a_reg      | Flip-flop |  32   |








    +     |      reg_b_reg      | Flip-flop |  64   |








    +     ===========================================








    +








    +     pc_next








    +     ===========================================








    +     |    Register Name    |   Type    | Width |








    +     ===========================================








    +     |     pc_reg_reg      | Flip-flop |  30   |








    +     ===========================================








    +








    +     reg_bank








    +     ===========================================








    +     |    Register Name    |   Type    | Width |








    +     ===========================================








    +     |      reg01_reg      | Flip-flop |  32   |








    +     |      reg02_reg      | Flip-flop |  32   |








    +     |      reg03_reg      | Flip-flop |  32   |








    +     |      reg04_reg      | Flip-flop |  32   |








    +     |      reg05_reg      | Flip-flop |  32   |








    +     |      reg06_reg      | Flip-flop |  32   |








    +     |      reg07_reg      | Flip-flop |  32   |








    +     |      reg08_reg      | Flip-flop |  32   |








    +     |      reg09_reg      | Flip-flop |  32   |








    +     |      reg10_reg      | Flip-flop |  32   |








    +     |      reg11_reg      | Flip-flop |  32   |








    +     |      reg12_reg      | Flip-flop |  32   |








    +     |      reg13_reg      | Flip-flop |  32   |








    +     |      reg14_reg      | Flip-flop |  32   |








    +     |      reg15_reg      | Flip-flop |  32   |








    +     |      reg16_reg      | Flip-flop |  32   |








    +     |      reg17_reg      | Flip-flop |  32   |








    +     |      reg18_reg      | Flip-flop |  32   |








    +     |      reg19_reg      | Flip-flop |  32   |








    +     |      reg20_reg      | Flip-flop |  32   |








    +     |      reg21_reg      | Flip-flop |  32   |








    +     |      reg22_reg      | Flip-flop |  32   |








    +     |      reg23_reg      | Flip-flop |  32   |








    +     |      reg24_reg      | Flip-flop |  32   |








    +     |      reg25_reg      | Flip-flop |  32   |








    +     |      reg26_reg      | Flip-flop |  32   |








    +     |      reg27_reg      | Flip-flop |  32   |








    +     |      reg28_reg      | Flip-flop |  32   |








    +     |      reg29_reg      | Flip-flop |  32   |








    +     |      reg30_reg      | Flip-flop |  32   |








    +     |      reg31_reg      | Flip-flop |  32   |








    +     |     reg_epc_reg     | Flip-flop |  32   |








    +     |   reg_status_reg    | Flip-flop |   1   |








    +     ===========================================








    +
+ +Preliminary Synthesis +

+The CPU core was synthesized for 0.13 um line widths with a predicted +area less than 0.2 millimeters squared. The predicted maximum +latency was less than 6 ns for a maximum clock speed of 150 MHz. +
+
+A preliminary synthesis yields the following cells and die area. +I think that optimization caused the mips_cpu entity +to be smaller than the sum of its +components. +If one assumes that a standard cell is composed of three gates, +then this is approximately a 20K gate design. [Is this correct??] +It is interesting to note that the register bank requires over 60% of the area. +









    +     Block    ports   nets  cells cell_area   ~%   delay(ns)








    +     ------   -----   ----  ----- ---------  ---   ---------








    +     alu        101    919    850      7503   12        1.11








    +     bus_mux    283    672    486      4906    8        0.35








    +     control     93    296    263      2250    4        0.29








    +     mem_ctrl   271    455    318      3299    5        0.95








    +     mult       101   1111   1043      9342   15        0.72 ??








    +     pc_next     94    277    215      1756    3        0.15








    +     reg_bank   116   2650   2599     39477   62        1.02








    +     shifter     71    423    384      3026    5        1.51








    +     mips_cpu   201    555     45     63888  100        5.61








    +








    +     total     1331   7358   6203








    +
+ +List of Files +

+

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FILEPURPOSE
    makefileMakefile for the HP workstation for Synopsys
    code.txtInput opcodes for the test bench -- test.exe "converted"
    alu.vhdArithmetic Logic Unit
    bus_mux.vhdBUS Multiplex Unit
    control.vhdOpcode Decoder
    mem_ctrl.vhdMemory Controller
    mips_cpu.vhdTop Level VHDL for MIPS CPU
    mips_pack.vhdConstants and Functions Package
    mult.vhdMultiplication and Division Unit
    pc_next.vhdProgram Counter Unit
    ram.vhdRAM for the Test Bench
    reg_bank.vhdRegister Bank for 32, 32-bit Registers
    shifter.vhdShifter Unit
    tbench.vhdTest Bench that uses mips_vpu.vhd and ram.vhd
    makefileMakefile for the PC for creating "code.txt"
    convert.cConverts test.exe to code.txt
    mips.cSimulates a MIPS CPU in software
    test.cTest program (opcodes) for the MIPS CPU
    output.txtOutput from the test bench
    index.shtmlThis help file
    cpu.gifBlock Diagram
    +
+ +

+ZIP File +

+CVS is the only way to download the latest files. However +for a quick look at an old version you can download +MIPSlite.zip. + +

+Convert +

+The program "convert" changes the file "test.exe" into the HEX file "code.txt". +The opcodes in "test.exe" are changed to Big Endian. +All absolute jumps are changed to relative jumps. +The first opcode is also changed to set up the stack pointer. + +

+Big/Little Endian +

+The MIPS CPU operates in Big Endian mode by default. To operate in +Little Endian mode, change "little_endian" from "00" to "11" in +the file mem_ctrl.vhd. + +

+Legal Notice +

+ +MIPS is a registered trademark of MIPS Technologies, Inc. +If you use this core you are responsible for all legal issues. +This "clean room" implementation of a MIPS CPU does not negate +MIPS Technologies, Inc. of their trademark, copyrights, or patents.... +

+Free for commercial and non-commercial use as long as the author and +warning notices are maintained. +
+
+This software is provided by Steve Rhoads "as is" and +any express or implied warranties, including, but not limited to, the +implied warranties of merchantability and fitness for a particular purpose +are disclaimed. In no event shall the author or contributors be liable +for any direct, indirect, incidental, special, exemplary, or consequential +damages (including, but not limited to, procurement of substitute goods +or services; loss of use, data, or profits; or business interruption) +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence or otherwise) arising in any way +out of the use of this software, even if advised of the possibility of +such damage. +
+

+

Bus Interface

+

+









    +   port(clk         : in std_logic;








    +        reset_in    : in std_logic;








    +        intr_in     : in std_logic;  --interrupt line








    +








    +        --memory access buses








    +        mem_address : out std_logic_vector(31 downto 0);








    +        mem_data_w  : out std_logic_vector(31 downto 0); --avoided tri-state








    +        mem_data_r  : in std_logic_vector(31 downto 0);








    +        mem_sel     : out std_logic_vector(3 downto 0);	 --byte lines








    +        mem_write   : out std_logic;








    +        mem_pause   : in std_logic








    +        );








    +
+ +

+Current Status +

    +
  • The test bench needs to be strengthened.
  • +
  • Need feedback on the design.
  • +
  • Need feedback on the tools.
  • +
  • Need to add simulation of a cache.
  • +
+ +

+Maintainer +

+

+

    *** I am not an experienced VHDL designer *** +Please let me know of any incorrect statements in this document.
+

+Mailing-list +

+

+ Index: tools/makefile =================================================================== --- tools/makefile (nonexistent) +++ tools/makefile (revision 352) @@ -0,0 +1,25 @@ +MIPS_DRIVE=e: + +INCPATH="$(MIPS_DRIVE)\Program Files\DevStudio\WCE\include\WCE200" +LIBPATH="$(MIPS_DRIVE)\Program Files\DevStudio\wce\lib\wce200\wcemips" +CC=clmips -c /I$(INCPATH) /Ox /GF /nologo /Fatest.s +LINK=link /nologo /machine:MIPS /SUBSYSTEM:WINDOWSCE /entry:main \ + /libpath:$(LIBPATH) /nodefaultlib /base:0x00000000 + +all: convert.exe mips.exe test.exe + +convert.exe: convert.c + cl convert.c + +mips.exe: mips.c + cl mips.c + +test.exe: test.c + $(CC) test.c -D SIMULATE + $(LINK) /out:test.exe /map:test.map test.obj + convert + mips test.exe DD > test.txt + mips test2.exe DD > test2.txt + mips test2.exe + + Index: tools/output.txt =================================================================== --- tools/output.txt (nonexistent) +++ tools/output.txt (revision 352) @@ -0,0 +1,43 @@ +12345678 091a2b3c 048d159e 02468acf 01234567 0091a2b3 0048d159 002468ac +00123456 00091a2b 00048d15 0002468a 00012345 000091a2 000048d1 00002468 +00001234 0000091a 0000048d 00000246 00000123 00000091 00000048 00000024 +00000012 00000009 00000004 00000002 00000001 00000000 00000000 00000000 + +92345678 c91a2b3c e48d159e f2468acf f9234567 fc91a2b3 fe48d159 ff2468ac +ff923456 ffc91a2b ffe48d15 fff2468a fff92345 fffc91a2 fffe48d1 ffff2468 +ffff9234 ffffc91a ffffe48d fffff246 fffff923 fffffc91 fffffe48 ffffff24 +ffffff92 ffffffc9 ffffffe4 fffffff2 fffffff9 fffffffc fffffffe ffffffff + +12345678 2468acf0 48d159e0 91a2b3c0 23456780 468acf00 8d159e00 1a2b3c00 +34567800 68acf000 d159e000 a2b3c000 45678000 8acf0000 159e0000 2b3c0000 +56780000 acf00000 59e00000 b3c00000 67800000 cf000000 9e000000 3c000000 +78000000 f0000000 e0000000 c0000000 80000000 00000000 00000000 00000000 + + +0 7 14 21 28 35 42 49 56 63 70 +038f5ae5 038f5e06 038f6127 038f6448 038f6769 038f6a8a +05fb4e83 060091a4 0605d4c5 060b17e6 06105b07 06159e28 +00012345 000091a2 00006117 000048d1 00003a41 0000308b 0000299c 00002468 +0000205d +00000000 00000001 00000000 00000001 00000000 00000003 00000001 00000005 +00000000 + +00001234 00001235 00001236 00001237 00001238 00001239 0000123a 0000123b +0000123c 0000123d +00001234 00001233 00001232 00001231 00001230 0000122f 0000122e 0000122d +0000122c 0000122b + +00000220 00005335 00005115 ffffedcb 00001246 00001222 + +0 0 0 +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 6 +7 7 7 +8 8 8 +9 9 9 + +3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 Index: vhdl/mips_cpu.vhd =================================================================== --- vhdl/mips_cpu.vhd (nonexistent) +++ vhdl/mips_cpu.vhd (revision 352) @@ -0,0 +1,302 @@ +--------------------------------------------------------------------- +-- TITLE: MIPS CPU core +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 2/15/01 +-- FILENAME: mips_cpu.vhd +-- PROJECT: MIPS CPU core +-- COPYRIGHT: Software placed into the public domain by the author. +-- Software 'as is' without warranty. Author liable for nothing. +-- DESCRIPTION: +-- Top level VHDL document that ties the eight other entities together. +-- Implements a MIPS CPU. 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 +-- An add instruction would take the following steps (see cpu.gif): +-- 1. The "pc_next" entity would have previously passed the program +-- counter (PC) to the "mem_ctrl" entity. +-- 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. +-- 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. +-- The CPU is implemented as a two stage pipeline with step #1 in the +-- first stage and steps #2-8 occuring the second stage. +-- +-- The CPU core was synthesized for 0.13 um line widths with an area +-- of 0.2 millimeters squared. The maximum latency was less than 6 ns +-- for a maximum clock speed of 150 MHz. +--------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use work.mips_pack.all; + +entity mips_cpu is + 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_sel : out std_logic_vector(3 downto 0); + mem_write : out std_logic; + mem_pause : in std_logic; + + t_pc : out std_logic_vector(31 downto 0); + t_opcode : out std_logic_vector(31 downto 0); + t_r_dest : out std_logic_vector(31 downto 0) + ); +end; --entity mips_cpu + +architecture logic of mips_cpu is + +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)); +end component; + +component mem_ctrl + 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; + mem_pause : in 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 + port(clk : 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_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 + 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 + 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 + 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; + + signal opcode : std_logic_vector(31 downto 0); + signal rs_index, rt_index, rd_index : std_logic_vector(5 downto 0); + signal reg_source, reg_target, reg_dest : std_logic_vector(31 downto 0); + signal a_bus, b_bus, c_bus : std_logic_vector(31 downto 0); + signal c_alu, c_shift, c_mult, 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 alu_function : alu_function_type; + signal shift_function : shift_function_type; + signal mult_function : mult_function_type; + signal branch_function: 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_memory : std_logic; + signal pause : std_logic; + signal nullify_op : std_logic; + signal intr_enable : std_logic; + signal intr_signal : std_logic; +-- signal mem_byte_sel : std_logic_vector(3 downto 0); +-- signal mem_write : std_logic; +begin --architecture + + pause <= pause_mult or pause_memory; + --nulify_op = pc_source==from_lbranch && take_branch=='0' + nullify_op <= pc_source(1) and pc_source(0) and not take_branch; + c_bus <= c_alu or c_shift or c_mult; + intr_signal <= (intr_in and intr_enable) and + (not pc_source(0) and not pc_source(1)); --from_inc4 + + u1: pc_next PORT MAP ( + clk => clk, + reset_in => reset_in, + take_branch => take_branch, + pause_in => pause, + pc_new => c_alu(31 downto 2), + opcode25_0 => opcode(25 downto 0), + pc_source => pc_source, + pc_out => pc); + + u2: mem_ctrl PORT MAP ( + clk => clk, + reset_in => reset_in, + pause_in => pause, + nullify_op => nullify_op, + address_pc => pc, + opcode_out => opcode, + + address_data => c_alu, + mem_source => mem_source, + data_write => reg_target, + data_read => c_memory, + pause_out => pause_memory, + + mem_address => mem_address, + mem_data_w => mem_data_w, + mem_data_r => mem_data_r, + mem_byte_sel => mem_sel, + mem_write => mem_write, + mem_pause => mem_pause); + + u3: 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_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); + + u4: reg_bank port map ( + clk => clk, + rs_index => rs_index, + rt_index => rt_index, + rd_index => rd_index, + reg_source_out => reg_source, + reg_target_out => reg_target, + reg_dest_new => reg_dest, + intr_enable => intr_enable); + + u5: 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_mux => c_source, + reg_dest_out => reg_dest, + + branch_func => branch_function, + take_branch => take_branch); + + u6: alu port map ( + a_in => a_bus, + b_in => b_bus, + alu_function => alu_function, + c_alu => c_alu); + + u7: shifter port map ( + value => b_bus, + shift_amount => a_bus(4 downto 0), + shift_func => shift_function, + c_shift => c_shift); + + u8: mult port map ( + clk => clk, + a => a_bus, + b => b_bus, + mult_func => mult_function, + c_mult => c_mult, + pause_out => pause_mult); + + t_pc <= pc; + t_opcode <= opcode; + t_r_dest <= reg_dest; + +end; --architecture logic + Index: vhdl/ram.vhd =================================================================== --- vhdl/ram.vhd (nonexistent) +++ vhdl/ram.vhd (revision 352) @@ -0,0 +1,113 @@ +--------------------------------------------------------------------- +-- TITLE: Random Access Memory +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 4/21/01 +-- FILENAME: ram.vhd +-- PROJECT: MIPS 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 "code.txt", +-- and saves a character to "output.txt" upon a write to 0xffff. +-- 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_textio.all; +use std.textio.all; + +use ieee.std_logic_unsigned.all; +use work.mips_pack.all; + +entity ram is + generic(load_file_name : string); + 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; + 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 +begin + +ram_proc: process + variable data : std_logic_vector(31 downto 0); + variable d : std_logic_vector(31 downto 0); + variable datab : std_logic_vector(31 downto 0); + variable value : natural; + subtype word is std_logic_vector(mem_data_w'length-1 downto 0); + type storage_array is + array(natural range 0 to 2**mem_address'length-1) of word; + variable storage : storage_array; + variable index : natural; + file load_file : text is in load_file_name; + file store_file : text is out "output.txt"; + variable hex_file_line : line; + variable c : character; + variable line_length : natural := 0; +begin + --load in the ram executable image + index := 0; + while not endfile(load_file) loop + readline(load_file, hex_file_line); + hread(hex_file_line, data); + storage(index) := data; + index := index + 1; + end loop; + assert false report "done reading code" severity note; + + wait on clk; --wait for line noise to go away + + loop + wait on clk, mem_address, mem_write; + + --support putchar() when writing to address 0xffff + if rising_edge(clk) then + if mem_write = '1' and mem_address = ONES(15 downto 0) then + index := conv_integer(mem_data_w(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 + writeline(store_file, hex_file_line); + line_length := 0; + end if; + end if; + end if; + + index := conv_integer(mem_address(mem_address'length-1 downto 2)); + data := storage(index); + + 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; + + if rising_edge(clk) then + if mem_write = '1' then + storage(index) := data; + end if; + end if; + end loop; +end process; + +end; --architecture logic + + Index: vhdl/control.vhd =================================================================== --- vhdl/control.vhd (nonexistent) +++ vhdl/control.vhd (revision 352) @@ -0,0 +1,440 @@ +--------------------------------------------------------------------- +-- TITLE: Controller / Opcode Decoder +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 2/8/01 +-- FILENAME: control.vhd +-- PROJECT: MIPS CPU core +-- COPYRIGHT: Software placed into the public domain by the author. +-- Software 'as is' without warranty. Author liable for nothing. +-- DESCRIPTION: +-- Controls the CPU by decoding the opcode and generating control +-- signals to the rest of the CPU. +-- This entity decodes the MIPS 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.mips_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_equal, alu_not_equal, +-- alu_ltz, alu_lez, alu_eqz, alu_nez, alu_gez, alu_gtz, +-- 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 re, 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_none; + 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); + re := opcode(10 downto 6); + func := opcode(5 downto 0); + imm := opcode(15 downto 0); + + case op is + when "000000" => --00 SPECIAL + case func is + when "000000" => --00 SLL r[rd]=r[rt]< --02 SRL r[rd]=u[rt]>>re; + a_source := a_from_imm10_6; + c_source := c_from_shift; + shift_function := shift_right_unsigned; + when "000011" => --03 SRA r[rd]=r[rt]>>re; + a_source := a_from_imm10_6; + c_source := c_from_shift; + shift_function := shift_right_signed; + when "000100" => --04 SLLV r[rd]=r[rt]< --06 SRLV r[rd]=u[rt]>>r[rs]; + c_source := c_from_shift; + shift_function := shift_right_unsigned; + when "000111" => --07 SRAV r[rd]=r[rt]>>r[rs]; + c_source := c_from_shift; + shift_function := shift_right_signed; + when "001000" => --08 JR s->pc_next=r[rs]; + pc_source := from_branch; + alu_function := alu_add; + branch_function := branch_yes; + when "001001" => --09 JALR r[rd]=s->pc_next; s->pc_next=r[rs]; + c_source := c_from_pc; + pc_source := from_branch; + alu_function := alu_add; + branch_function := branch_yes; + when "001010" => --0a MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/ +-- c_source := c_from_reg_source_eqz; + when "001011" => --0b MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/ +-- c_source := from_reg_source_nez; + when "001100" => --0c SYSCALL +-- if(r[4]==0) printf("0x%8.8lx ",r[5]); + when "001101" => --0d BREAK s->wakeup=1; + when "001111" => --0f SYNC s->wakeup=1; + when "010000" => --10 MFHI r[rd]=s->hi; + c_source := c_from_mult; + mult_function := mult_read_hi; + when "010001" => --11 FTHI s->hi=r[rs]; + mult_function := mult_write_hi; + when "010010" => --12 MFLO r[rd]=s->lo; + c_source := c_from_mult; + mult_function := mult_read_lo; + when "010011" => --13 MTLO s->lo=r[rs]; + mult_function := mult_write_lo; + when "011000" => --18 MULT s->lo=r[rs]*r[rt]; s->hi=0; + mult_function := mult_mult; + when "011001" => --19 MULTU s->lo=r[rs]*r[rt]; s->hi=0; + mult_function := mult_mult; + when "011010" => --1a DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; + mult_function := mult_signed_divide; + when "011011" => --1b DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; + mult_function := mult_divide; + when "100000" => --20 ADD r[rd]=r[rs]+r[rt]; + c_source := c_from_alu; + alu_function := alu_add; + when "100001" => --21 ADDU r[rd]=r[rs]+r[rt]; + c_source := c_from_alu; + alu_function := alu_add; + when "100010" => --22 SUB r[rd]=r[rs]-r[rt]; + c_source := c_from_alu; + alu_function := alu_subtract; + when "100011" => --23 SUBU r[rd]=r[rs]-r[rt]; + c_source := c_from_alu; + alu_function := alu_subtract; + when "100100" => --24 AND r[rd]=r[rs]&r[rt]; + c_source := c_from_alu; + alu_function := alu_and; + when "100101" => --25 OR r[rd]=r[rs]|r[rt]; + c_source := c_from_alu; + alu_function := alu_or; + when "100110" => --26 XOR r[rd]=r[rs]^r[rt]; + c_source := c_from_alu; + alu_function := alu_xor; + when "100111" => --27 NOR r[rd]=~(r[rs]|r[rt]); + c_source := c_from_alu; + alu_function := alu_nor; + when "101010" => --2a SLT r[rd]=r[rs] --2b SLTU r[rd]=u[rs] --2d DADDU r[rd]=r[rs]+u[rt]; + c_source := c_from_alu; + alu_function := alu_add; + when "110001" => --31 TGEU + when "110010" => --32 TLT + when "110011" => --33 TLTU + when "110100" => --34 TEQ + when "110110" => --36 TNE + when others => + end case; + when "000001" => --00 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" => --10 BLTZAL r[31]=s->pc_next; branch=r[rs]<0; + c_source := c_from_pc; + branch_function := branch_ltz; + when "00000" => --00 BLTZ branch=r[rs]<0; + branch_function := branch_ltz; + when "10001" => --11 BGEZAL r[31]=s->pc_next; branch=r[rs]>=0; + c_source := c_from_pc; + branch_function := branch_gez; + when "00001" => --01 BGEZ branch=r[rs]>=0; + branch_function := branch_gez; + when "10010" => --12 BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0; + c_source := c_from_pc; + pc_source := from_lbranch; + branch_function := branch_ltz; + when "00010" => --02 BLTZL lbranch=r[rs]<0; + pc_source := from_lbranch; + branch_function := branch_ltz; + when "10011" => --13 BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0; + c_source := c_from_pc; + pc_source := from_lbranch; + branch_function := branch_gez; + when "00011" => --03 BGEZL lbranch=r[rs]>=0; + pc_source := from_lbranch; + branch_function := branch_gez; + when others => + end case; + when "000011" => --03 JAL r[31]=s->pc_next; s->pc_next=(s->pc&0xf0000000)|target; + c_source := c_from_pc; + rd := "011111"; + pc_source := from_opcode25_0; + when "000010" => --02 J s->pc_next=(s->pc&0xf0000000)|target; + pc_source := from_opcode25_0; + when "000100" => --04 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" => --05 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" => --06 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_ltz; + when "000111" => --07 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" => --08 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" => --09 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" => --0a 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; + when "001011" => --0b 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" => --0c ANDI r[rt]=r[rs]&imm; + b_source := b_from_imm; + c_source := c_from_alu; + rd := rt; + alu_function := alu_and; + when "001101" => --0d ORI r[rt]=r[rs]|imm; + b_source := b_from_imm; + c_source := c_from_alu; + rd := rt; + alu_function := alu_or; + when "001110" => --0e XORI r[rt]=r[rs]^imm; + b_source := b_from_imm; + c_source := c_from_alu; + rd := rt; + alu_function := alu_xor; + when "001111" => --0f LUI r[rt]=(imm<<16); + c_source := c_from_imm_shift16; + rd := rt; + when "010000" => --10 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" => --11 COP1 + when "010010" => --12 COP2 + when "010011" => --13 COP3 + when "010100" => --14 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" => --15 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" => --16 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" => --17 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" => --20 LB r[rt]=*(signed char*)ptr; + a_source := a_from_reg_source; + b_source := b_from_imm; + alu_function := alu_add; + rd := rt; + c_source := c_from_memory; + mem_source := mem_read8s; --address=(short)imm+r[rs]; + when "100001" => --21 LH r[rt]=*(signed short*)ptr; + a_source := a_from_reg_source; + b_source := b_from_imm; + alu_function := alu_add; + rd := rt; + c_source := c_from_memory; + mem_source := mem_read16s; --address=(short)imm+r[rs]; + when "100010" => --22 LWL //fixme + when "100011" => --23 LW r[rt]=*(long*)ptr; + a_source := a_from_reg_source; + b_source := b_from_imm; + alu_function := alu_add; + rd := rt; + c_source := c_from_memory; + mem_source := mem_read32; + when "100100" => --24 LBU r[rt]=*(unsigned char*)ptr; + a_source := a_from_reg_source; + b_source := b_from_imm; + alu_function := alu_add; + rd := rt; + c_source := c_from_memory; + mem_source := mem_read8; --address=(short)imm+r[rs]; + when "100101" => --25 LHU r[rt]=*(unsigned short*)ptr; + a_source := a_from_reg_source; + b_source := b_from_imm; + alu_function := alu_add; + rd := rt; + c_source := c_from_memory; + mem_source := mem_read16; --address=(short)imm+r[rs]; + when "100110" => --26 LWR //fixme + when "101000" => --28 SB *(char*)ptr=(char)r[rt]; + a_source := a_from_reg_source; + b_source := b_from_imm; + alu_function := alu_add; + mem_source := mem_write8; --address=(short)imm+r[rs]; + when "101001" => --29 SH *(short*)ptr=(short)r[rt]; + a_source := a_from_reg_source; + b_source := b_from_imm; + alu_function := alu_add; + mem_source := mem_write16; + when "101010" => --2a SWL //fixme + when "101011" => --2b SW *(long*)ptr=r[rt]; + a_source := a_from_reg_source; + b_source := b_from_imm; + alu_function := alu_add; + mem_source := mem_write32; --address=(short)imm+r[rs]; + when "101110" => --2e SWR //fixme + when "101111" => --2f CACHE + when "110000" => --30 LL r[rt]=*(long*)ptr; + when "110001" => --31 LWC1 + when "110010" => --32 LWC2 + when "110011" => --33 LWC3 + when "110101" => --35 LDC1 + when "110110" => --36 LDC2 + when "110111" => --37 LDC3 + when "111000" => --38 SC *(long*)ptr=r[rt]; r[rt]=1; + when "111001" => --39 SWC1 + when "111010" => --3a SWC2 + when "111011" => --3b SWC3 + when "111101" => --3d SDC1 + when "111110" => --3e SDC2 + when "111111" => --3f SDC3 + when others => + end case; + + if c_source = c_from_null then + rd := "000000"; + end if; + + if intr_signal = '1' then + rd := "101110"; --EPC + c_source := c_from_pc; + rs := "111111"; --interrupt vector + rt := "000000"; + a_source := a_from_reg_source; + b_source := b_from_reg_target; + alu_function := alu_or; + pc_source := from_branch; + branch_function := branch_yes; + 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 + Index: vhdl/pc_next.vhd =================================================================== --- vhdl/pc_next.vhd (nonexistent) +++ vhdl/pc_next.vhd (revision 352) @@ -0,0 +1,67 @@ +--------------------------------------------------------------------- +-- TITLE: Program Counter Next +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 2/8/01 +-- FILENAME: pc_next.vhd +-- PROJECT: MIPS 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.mips_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)); +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 + pc_next := pc_reg; + case pc_source is + when from_inc4 => + if pause_in = '0' then + pc_next := pc_inc; + end if; + when from_opcode25_0 => + pc_next := pc_reg(31 downto 28) & opcode25_0; + when from_branch | from_lbranch => + if take_branch = '1' then + pc_next := pc_new; + else + pc_next := pc_inc; + end if; + when others => + end case; + if reset_in = '1' then + pc_next := ZERO(31 downto 2); + end if; + + if rising_edge(clk) then + pc_reg <= pc_next; + end if; + + pc_out <= pc_reg & "00"; +end process; + +end; --logic + Index: vhdl/alu.vhd =================================================================== --- vhdl/alu.vhd (nonexistent) +++ vhdl/alu.vhd (revision 352) @@ -0,0 +1,106 @@ +--------------------------------------------------------------------- +-- TITLE: Arithmetic Logic Unit +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 2/8/01 +-- FILENAME: alu.vhd +-- PROJECT: MIPS 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.mips_pack.all; + +entity alu is + 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_equal, alu_not_equal, +-- alu_ltz, alu_lez, alu_eqz, alu_nez, alu_gez, alu_gtz, +-- alu_or, alu_and, alu_xor, alu_nor); +begin + +alu_proc: process(a_in, b_in, alu_function) + variable c : std_logic_vector(31 downto 0); + variable aa, bb, sum : std_logic_vector(32 downto 0); + variable do_sub : std_logic; + variable a_eq_b : std_logic; + variable a_zero : std_logic; + variable sign_ext : std_logic; +begin + c := ZERO; + if alu_function = alu_add then + do_sub := '0'; + else + do_sub := '1'; + end if; + if alu_function = alu_less_than then + sign_ext := '0'; + else + sign_ext := '1'; + end if; + aa := (a_in(31) and sign_ext) & a_in; + bb := (b_in(31) and sign_ext) & b_in; + sum := bv_adder(aa, bb, do_sub); +-- sum := bv_adder_lookahead(aa, bb, do_sub); + if a_in = b_in then + a_eq_b := '1'; + else + a_eq_b := '0'; + end if; + if a_in = ZERO then + a_zero := '1'; + else + a_zero := '0'; + end if; + case alu_function is + when alu_add | alu_subtract => --c=a+b + c := sum(31 downto 0); + when alu_less_than => --c=a --c=a --c=a==b + c(0) := a_eq_b; + when alu_not_equal => --c=a!=b + c(0) := not a_eq_b; + when alu_ltz => --c=a<0 + c(0) := a_in(31); + when alu_lez => --c=a<=0 + c(0) := a_in(31) or a_zero; + when alu_eqz => --c=a==0 + c(0) := a_zero; + when alu_nez => --c=a!=0 + c(0) := not a_zero; + when alu_gez => --c=a>=0 + c(0) := not a_in(31); + when alu_gtz => --c=a>0 + c(0) := not a_zero and not a_in(31); + when alu_or => --c=a|b + c := a_in or b_in; + when alu_and => --c=a&b + c := a_in and b_in; + when alu_xor => --c=a^b + c := a_in xor b_in; + when alu_nor => --c=~(a|b) + c := a_in nor b_in; + when others => --alu_function = alu_nothing + c := ZERO; + end case; + +-- if alu_function = alu_nothing then +-- c_alu <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; +-- else + c_alu <= c; +-- end if; +end process; + +end; --architecture logic + Index: vhdl/mult.vhd =================================================================== --- vhdl/mult.vhd (nonexistent) +++ vhdl/mult.vhd (revision 352) @@ -0,0 +1,185 @@ +--------------------------------------------------------------------- +-- TITLE: Multiplication and Division Unit +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 1/31/01 +-- FILENAME: mult.vhd +-- PROJECT: MIPS 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. +-- Normally takes 32 clock cycles. +--------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use work.mips_pack.all; + +entity mult is + 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_div_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); +begin + +--multiplication/division unit +mult_proc: process(clk, a, b, mult_func, + do_div_reg, do_signed_reg, count_reg, + reg_a, reg_b, answer_reg) + variable do_div_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 sign_extension : std_logic; + variable aa, bb : std_logic_vector(32 downto 0); + variable sum : std_logic_vector(32 downto 0); + variable start : std_logic; + variable do_write : std_logic; + variable do_hi : std_logic; + +begin + do_div_temp := do_div_reg; + do_signed_temp := do_signed_reg; + count_temp := count_reg; + a_temp := reg_a; + b_temp := reg_b; + answer_temp := answer_reg; + + sign_extension := '0'; + aa := '0' & ZERO; + bb := '0' & ZERO; + sum := '0' & ZERO; + 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_div_temp := '0'; + when mult_divide => + start := '1'; + do_div_temp := '1'; + do_signed_temp := '0'; + when mult_signed_divide => + start := '1'; + do_div_temp := '1'; + do_signed_temp := '1'; + when others => + end case; + + if start = '1' then + count_temp := "000000"; + a_temp := a; + answer_temp := ZERO; + if do_div_temp = '1' then + if do_signed_temp = '0' or b(31) = '0' then + b_temp(62 downto 31) := b; + else + b_temp(62 downto 31) := bv_negate(b); + a_temp := bv_negate(a); + end if; + b_temp(30 downto 0) := ZERO(30 downto 0); + else --multiply + b_temp := zero & b; + 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_div_reg = '1' then + bb := reg_b(32 downto 0); + else + bb := '0' & reg_b(63 downto 32); + end if; + sign_extension := reg_a(31) and do_signed_reg; + aa := sign_extension & reg_a; + sum := bv_adder(aa, bb, do_div_reg); +-- sum := bv_adder_lookahead(aa, bb, do_div_reg); + + if count_reg(5) = '0' and start = '0' then + count_temp := bv_inc6(count_reg); + if do_div_reg = '1' then + 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 + b_temp(63 downto 32) := a_temp; + b_temp(31 downto 0) := answer_temp; + end if; + else -- mult_mode + if reg_b(0) = '1' then + b_temp(63 downto 31) := sum; + else + b_temp(63 downto 31) := '0' & reg_b(63 downto 32); + end if; + b_temp(30 downto 0) := reg_b(31 downto 1); + if count_reg = "010000" 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; + end if; + end if; + + if rising_edge(clk) then + do_div_reg <= do_div_temp; + do_signed_reg <= do_signed_temp; + count_reg <= count_temp; + reg_a <= a_temp; + reg_b <= b_temp; + answer_reg <= answer_temp; + 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; + if mult_func = mult_read_lo then + c_mult <= reg_b(31 downto 0); + elsif mult_func = mult_read_hi then + c_mult <= reg_b(63 downto 32); + else +-- c_mult <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; + c_mult <= ZERO; + end if; + +end process; + +end; --architecture logic + + Index: vhdl/bus_mux.vhd =================================================================== --- vhdl/bus_mux.vhd (nonexistent) +++ vhdl/bus_mux.vhd (revision 352) @@ -0,0 +1,135 @@ +--------------------------------------------------------------------- +-- TITLE: Bus Multiplexer / Signal Router +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 2/8/01 +-- FILENAME: bus_mux.vhd +-- PROJECT: MIPS 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 : a signal to pc_next +--------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use work.mips_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_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 + a_out(31 downto 5) <= reg_source(31 downto 5); + case a_mux is + when a_from_reg_source => + a_out(4 downto 0) <= reg_source(4 downto 0); + when a_from_imm10_6 => + 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, 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; + 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 + Index: vhdl/mem_ctrl.vhd =================================================================== --- vhdl/mem_ctrl.vhd (nonexistent) +++ vhdl/mem_ctrl.vhd (revision 352) @@ -0,0 +1,178 @@ +--------------------------------------------------------------------- +-- TITLE: Memory Controller +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 1/31/01 +-- FILENAME: mem_ctrl.vhd +-- PROJECT: MIPS 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 MIPS CPU. +-- Supports Big or Little Endian mode. +-- 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.mips_pack.all; + +entity mem_ctrl is + 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; + mem_pause : in 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); + signal setup_done : std_logic; +begin + +mem_proc: process(clk, reset_in, pause_in, nullify_op, address_pc, + address_data, mem_source, data_write, mem_data_r, + mem_pause, + opcode_reg, next_opcode_reg, setup_done) + variable data, datab : std_logic_vector(31 downto 0); + variable opcode_temp : std_logic_vector(31 downto 0); + variable byte_sel_temp : std_logic_vector(3 downto 0); + variable write_temp : std_logic; + variable setup_done_var : std_logic; + variable pause : std_logic; + variable address_temp : 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_temp := "0000"; + write_temp := '0'; + pause := '0'; + setup_done_var := setup_done; + + address_temp := address_pc; + data := mem_data_r; + datab := ZERO; + mem_data_w_v := ZERO; --"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; + + case mem_source is + when mem_read32 => + datab := data; + when mem_read16 | mem_read16s => + if address_data(1) = little_endian(1) then + datab(15 downto 0) := data(31 downto 16); + else + datab(15 downto 0) := data(15 downto 0); + end if; + if mem_source = mem_read16 or datab(15) = '0' then + datab(31 downto 16) := ZERO(31 downto 16); + else + datab(31 downto 16) := ONES(31 downto 16); + end if; + when mem_read8 | mem_read8s => + bits := address_data(1 downto 0) xor little_endian; + case bits is + when "00" => datab(7 downto 0) := data(31 downto 24); + when "01" => datab(7 downto 0) := data(23 downto 16); + when "10" => datab(7 downto 0) := data(15 downto 8); + when others => datab(7 downto 0) := data(7 downto 0); + end case; + if mem_source = mem_read8 or datab(7) = '0' then + datab(31 downto 8) := ZERO(31 downto 8); + else + datab(31 downto 8) := ONES(31 downto 8); + end if; + when mem_write32 => + write_temp := '1'; + mem_data_w_v := data_write; + byte_sel_temp := "1111"; + when mem_write16 => + write_temp := '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_temp := "1100"; + else + byte_sel_temp := "0011"; + end if; + when mem_write8 => + write_temp := '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_temp := "1000"; + when "01" => + byte_sel_temp := "0100"; + when "10" => + byte_sel_temp := "0010"; + when others => + byte_sel_temp := "0001"; + end case; + when others => + end case; + + opcode_temp := opcode_reg; + if mem_source = mem_none then + setup_done_var := '0'; + if pause_in = '0' and mem_pause = '0' then + if nullify_op = '0' then + opcode_temp := data; + else + opcode_temp := ZERO; --NOP + end if; + end if; + else + pause := not setup_done; + setup_done_var := '1'; + if setup_done = '1' then + address_temp := address_data; + if mem_pause = '0' then + opcode_temp := next_opcode_reg; + setup_done_var := '0'; + end if; + end if; + end if; + if reset_in = '1' then + setup_done_var := '0'; + opcode_temp := ZERO; + end if; + + if rising_edge(clk) then + opcode_reg <= opcode_temp; + if setup_done = '0' then + next_opcode_reg <= data; + end if; + setup_done <= setup_done_var; + end if; + + opcode_out <= opcode_reg; + data_read <= datab; + pause_out <= mem_pause or pause; + mem_byte_sel <= byte_sel_temp; + mem_address <= address_temp; + mem_write <= write_temp and setup_done; + mem_data_w <= mem_data_w_v; + +end process; --data_proc + +end; --architecture logic + Index: vhdl/tbench.vhd =================================================================== --- vhdl/tbench.vhd (nonexistent) +++ vhdl/tbench.vhd (revision 352) @@ -0,0 +1,99 @@ +--------------------------------------------------------------------- +-- TITLE: Test Bench +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 4/21/01 +-- FILENAME: tbench.vhd +-- PROJECT: MIPS 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 MIPS CPU core. +--------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use work.mips_pack.all; + +entity tbench is + port(clk_out : out std_logic; + pc : out std_logic_vector(31 downto 0) + ); +end; --entity tbench + +architecture logic of tbench is + +component mips_cpu + 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_sel : out std_logic_vector(3 downto 0); + mem_write : out std_logic; + mem_pause : in std_logic; + + t_pc : out std_logic_vector(31 downto 0); + t_opcode : out std_logic_vector(31 downto 0); + t_r_dest : out std_logic_vector(31 downto 0) + ); +end component; + +component ram + generic(load_file_name : string); + 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; + mem_data_w : in std_logic_vector(31 downto 0); + mem_data_r : out std_logic_vector(31 downto 0)); +end component; + + signal clk : std_logic := '0'; + signal reset : std_logic := '1'; --, '0' after 100 ns; + signal interrupt : std_logic := '0'; + signal mem_sel : std_logic_vector(3 downto 0); + signal mem_write : std_logic; + signal mem_address : std_logic_vector(31 downto 0); + signal mem_data_w : std_logic_vector(31 downto 0); + signal mem_data_r : std_logic_vector(31 downto 0); + signal mem_pause : std_logic; + signal t_pc : std_logic_vector(31 downto 0); + signal t_opcode : std_logic_vector(31 downto 0); + signal t_r_dest : std_logic_vector(31 downto 0); + signal mem_byte_sel: std_logic_vector(3 downto 0); +begin --architecture + clk <= not clk after 50 ns; + reset <= '0' after 100 ns; + mem_pause <= '0'; + + u1: mips_cpu PORT MAP ( + clk => clk, + reset_in => reset, + intr_in => interrupt, + + mem_address => mem_address, + mem_data_w => mem_data_w, + mem_data_r => mem_data_r, + mem_sel => mem_byte_sel, + mem_write => mem_write, + mem_pause => mem_pause, + + t_pc => t_pc, + t_opcode => t_opcode, + t_r_dest => t_r_dest); + + u2: ram generic map ("code.txt") + PORT MAP ( + clk => clk, + mem_byte_sel => mem_byte_sel, + mem_write => mem_write, + mem_address => mem_address(15 downto 0), + mem_data_w => mem_data_w, + mem_data_r => mem_data_r); + + clk_out <= clk; + pc <= t_pc; + +end; --architecture logic + Index: vhdl/shifter.vhd =================================================================== --- vhdl/shifter.vhd (nonexistent) +++ vhdl/shifter.vhd (revision 352) @@ -0,0 +1,107 @@ +--------------------------------------------------------------------- +-- TITLE: Shifter Unit +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 2/2/01 +-- FILENAME: shifter.vhd +-- PROJECT: MIPS 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.mips_pack.all; + +entity shifter is + 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_left_signed, shift_right_unsigned); +begin + +shift_proc: process(value, shift_amount, shift_func) --barrel shifter unit + variable shift1, shift2, shift4, + shift8, shift16 : std_logic_vector(31 downto 0); + variable fills : std_logic_vector(31 downto 16); +variable go_right : std_logic; +begin + if shift_func = shift_right_unsigned or shift_func = shift_right_signed then + go_right := '1'; + else + go_right := '0'; + end if; + if shift_func = shift_right_signed and value(31) = '1' then + fills := "1111111111111111"; + else + fills := "0000000000000000"; + end if; + if go_right = '0' then --shift left + if shift_amount(0) = '1' then + shift1 := value(30 downto 0) & '0'; + else + shift1 := value; + end if; + if shift_amount(1) = '1' then + shift2 := shift1(29 downto 0) & "00"; + else + shift2 := shift1; + end if; + if shift_amount(2) = '1' then + shift4 := shift2(27 downto 0) & "0000"; + else + shift4 := shift2; + end if; + if shift_amount(3) = '1' then + shift8 := shift4(23 downto 0) & "00000000"; + else + shift8 := shift4; + end if; + if shift_amount(4) = '1' then + shift16 := shift8(15 downto 0) & ZERO(15 downto 0); + else + shift16 := shift8; + end if; + else --shift right + if shift_amount(0) = '1' then + shift1 := fills(31) & value(31 downto 1); + else + shift1 := value; + end if; + if shift_amount(1) = '1' then + shift2 := fills(31 downto 30) & shift1(31 downto 2); + else + shift2 := shift1; + end if; + if shift_amount(2) = '1' then + shift4 := fills(31 downto 28) & shift2(31 downto 4); + else + shift4 := shift2; + end if; + if shift_amount(3) = '1' then + shift8 := fills(31 downto 24) & shift4(31 downto 8); + else + shift8 := shift4; + end if; + if shift_amount(4) = '1' then + shift16 := fills(31 downto 16) & shift8(31 downto 16); + else + shift16 := shift8; + end if; + end if; --shift_dir + if shift_func = shift_nothing then +-- c_shift <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; + c_shift <= ZERO; + else + c_shift <= shift16; + end if; +end process; + +end; --architecture logic + Index: vhdl/mips_pack.vhd =================================================================== --- vhdl/mips_pack.vhd (nonexistent) +++ vhdl/mips_pack.vhd (revision 352) @@ -0,0 +1,274 @@ +--------------------------------------------------------------------- +-- TITLE: MIPS Misc. Package +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 2/15/01 +-- FILENAME: mips_pack.vhd +-- PROJECT: MIPS 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 MIPS CPU. +--------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; + +package mips_pack is + constant ZERO : std_logic_vector(31 downto 0) := + "00000000000000000000000000000000"; + constant ONES : std_logic_vector(31 downto 0) := + "11111111111111111111111111111111"; + +-- type alu_function_type is (alu_nothing, alu_add, alu_subtract, +-- alu_less_than, alu_less_than_signed, alu_equal, alu_not_equal, +-- alu_ltz, alu_lez, alu_eqz, alu_nez, alu_gez, alu_gtz, +-- alu_or, alu_and, alu_xor, alu_nor); + subtype alu_function_type is std_logic_vector(4 downto 0); + constant alu_nothing : alu_function_type := "00000"; + constant alu_add : alu_function_type := "00010"; + constant alu_subtract : alu_function_type := "00011"; + constant alu_less_than : alu_function_type := "00100"; + constant alu_less_than_signed : alu_function_type := "00101"; + constant alu_equal : alu_function_type := "00110"; + constant alu_not_equal : alu_function_type := "00111"; + constant alu_ltz : alu_function_type := "01000"; + constant alu_lez : alu_function_type := "01001"; + constant alu_eqz : alu_function_type := "01010"; + constant alu_nez : alu_function_type := "01011"; + constant alu_gez : alu_function_type := "01100"; + constant alu_gtz : alu_function_type := "01101"; + constant alu_or : alu_function_type := "01110"; + constant alu_and : alu_function_type := "01111"; + constant alu_xor : alu_function_type := "10001"; + constant alu_nor : alu_function_type := "10010"; + +-- 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(2 downto 0); + constant mult_nothing : mult_function_type := "000"; + constant mult_read_lo : mult_function_type := "001"; + constant mult_read_hi : mult_function_type := "010"; + constant mult_write_lo : mult_function_type := "011"; + constant mult_write_hi : mult_function_type := "100"; + constant mult_mult : mult_function_type := "101"; + constant mult_divide : mult_function_type := "110"; + constant mult_signed_divide : mult_function_type := "111"; + +-- 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_alu : c_source_type := "000"; + constant c_from_shift : c_source_type := "001"; + constant c_from_mult : c_source_type := "010"; + constant c_from_memory : c_source_type := "011"; + constant c_from_pc : c_source_type := "100"; + constant c_from_imm_shift16: c_source_type := "101"; + constant c_from_reg_sourcen: c_source_type := "110"; + constant c_from_null : c_source_type := "111"; + +-- type pc_source_type is (from_inc4, from_inc8, from_reg_source, +-- 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_none : 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_sub: 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_sub: 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; +end; --package mips_pack + +package body mips_pack is + +function add_1(a:integer) return integer is +begin + return a+1; +end; --function + +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_sub: 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 := "000000000000000000000000000000000"; + if do_sub = '0' 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_sub: 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 := "000000000000000000000000000000000"; + if do_sub = '0' 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 := "000000000000000000000000000000"; + 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 + + Index: vhdl/code.txt =================================================================== --- vhdl/code.txt (nonexistent) +++ vhdl/code.txt (revision 352) @@ -0,0 +1,640 @@ +341d8000 +afbf0014 +041100cb +00000000 +8fbf0014 +03e00008 +27bd0018 +80ae0000 +00801825 +24840001 +a08effff +8082ffff +24a50001 +10400008 +00000000 +80af0000 +24840001 +24a50001 +a08fffff +8082ffff +5440fffb +80af0000 +03e00008 +00601025 +27bdffa8 +afb10018 +afb00014 +00c08025 +00e08825 +afbf001c +afa40058 +afa5005c +240e0020 +240f0020 +24180020 +a3b80042 +a3af0041 +a3ae0040 +27a30043 +27a4004f +24020020 +24630004 +a062fffc +a062fffd +a062fffe +1464fffb +a062ffff +8fb90058 +a3a0004f +8fa90058 +07230005 +24080001 +2401000a +12010002 +2408ffff +24080001 +01280019 +2405000e +27a6004e +2407000f +00002012 +00000000 +00000000 +0090001b +16000002 +00000000 +0007000d +00001010 +00002012 +2841000a +54200002 +24430030 +24430057 +14800006 +a0c30000 +8e2b0000 +00e55023 +014b082a +50200005 +2401ffff +24a5ffff +04a1ffed +24c6ffff +2401ffff +15010004 +240c002d +a0ccffff +24a5ffff +24c6ffff +8e220000 +240d000f +01a58023 +10400003 +0050082a +10200006 +8fa4005c +8fa4005c +0411ffa5 +00c02825 +10000005 +ae300000 +00027023 +27af004f +0411ff9f +01cf2821 +8fb00014 +8fb10018 +8fbf001c +03e00008 +27bd0058 +27bdff58 +afa600b0 +00a03025 +afbf0014 +afa500ac +27a50020 +0411ffa3 +27a700b0 +83af0020 +27ae0020 +01c01025 +51e00010 +8fbf0014 +81c30000 +2406000d +2405000a +3404ffff +a0830000 +80580000 +24420001 +54b80004 +80430000 +2442ffff +a0460000 +80430000 +5460fff8 +a0830000 +8fbf0014 +03e00008 +27bd00a8 +2402001c +3405ffff +00441806 +3063000f +2c61000a +10200004 +2442fffc +246e0030 +10000003 +a0ae0000 +246f0057 +a0af0000 +0443fff6 +00441806 +03e00008 +00000000 +27bdffd8 +afbf0024 +afb30020 +afb2001c +afb10018 +afb00014 +24100003 +241303e9 +24120020 +3411ffff +2a010004 +14200012 +24020003 +0202001a +14400002 +00000000 +0007000d +2401ffff +14410004 +3c018000 +16010002 +00000000 +0006000d +00007010 +51c00005 +00001025 +24420002 +0050082a +1420fff0 +00000000 +50400007 +26100002 +02002025 +2405000a +0411ffaf +00003025 +a2320000 +26100002 +5613ffe4 +2a010004 +240f000a +a22f0000 +8fbf0024 +8fb30020 +8fb2001c +8fb10018 +8fb00014 +00001025 +03e00008 +27bd0028 +27bdff40 +afbf0034 +afb70030 +afb6002c +afb50028 +afb40024 +afb30020 +afb2001c +afb10018 +afb00014 +3c121234 +36525678 +00008025 +24150020 +3414ffff +24110020 +0411ffad +02122007 +26100001 +1611fffc +a2950000 +2417000a +3c139234 +a2970000 +36735678 +00008025 +0411ffa3 +02132007 +26100001 +1611fffc +a2950000 +a2970000 +00008025 +0411ff9c +02122004 +26100001 +1611fffc +a2950000 +a2970000 +a2970000 +00008825 +2410004d +02202025 +2405000a +0411ff73 +00003025 +26310007 +1630fffa +a2950000 +3c11038f +3c10038f +a2970000 +36106dab +36315ae5 +0411ff87 +02202025 +26310321 +1630fffc +a2950000 +3c1105fb +3c10061a +a2970000 +3610e149 +36314e83 +0411ff7d +02202025 +3c010005 +34214321 +02218821 +1630fffa +a2950000 +3c110001 +a2970000 +36312345 +24100001 +2416000a +0230001a +16000002 +00000000 +0007000d +2401ffff +16010004 +3c018000 +16210002 +00000000 +0006000d +00002012 +0411ff66 +00000000 +26100001 +1616fff1 +a2950000 +a2970000 +24100001 +0230001a +16000002 +00000000 +0007000d +2401ffff +16010004 +3c018000 +16210002 +00000000 +0006000d +00002010 +0411ff54 +00000000 +26100001 +1616fff1 +a2950000 +a2970000 +a2970000 +00008025 +0411ff4c +26041234 +26100001 +1616fffc +a2950000 +a2970000 +00008025 +24111234 +0411ff44 +02302023 +26100001 +1616fffc +a2950000 +a2970000 +a2970000 +0411ff3d +24040220 +a2950000 +0411ff3a +24045335 +a2950000 +0411ff37 +24045115 +a2950000 +0411ff34 +2404edcb +a2950000 +0411ff31 +24041246 +a2950000 +0411ff2e +24041222 +a2970000 +a2970000 +240e0001 +240f0001 +24180001 +afb8004c +a7af008a +a3ae00a9 +afa00048 +a7a00088 +a3a000a8 +24100002 +27b200aa +27b3008c +27b10050 +26020001 +26030002 +26040003 +a2500000 +a6700000 +ae300000 +26100004 +a2440003 +a6640006 +ae24000c +a2430002 +a6630004 +ae230008 +a2420001 +a6620002 +ae220004 +26520004 +26730008 +1616ffed +26310010 +27b200a8 +27b30088 +27b10048 +27b60070 +82440000 +2405000a +0411fee5 +00003025 +a2950000 +86640000 +2405000a +0411fee0 +00003025 +a2950000 +8e240000 +2405000a +0411fedb +00003025 +26310004 +a2970000 +26520001 +1636ffee +26730002 +0411ff02 +a2970000 +24190064 +a2990000 +2408006f +a2880000 +2409006e +a2890000 +240a0065 +a28a0000 +a2970000 +8fbf0034 +8fb70030 +8fb6002c +8fb50028 +8fb40024 +8fb30020 +8fb2001c +8fb10018 +8fb00014 +03e00008 +27bd00c0 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00001000 +0000101c +00000000 +00000000 +00001008 +00001060 +000011b8 +00000000 +00000000 +00001080 +000011b8 +00001230 +00000000 +00000000 +000011cc +00001270 +00001338 +00000000 +00000000 +00001288 +00001338 +000016bc +00000000 +00000000 +00001360 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 Index: vhdl/reg_bank.vhd =================================================================== --- vhdl/reg_bank.vhd (nonexistent) +++ vhdl/reg_bank.vhd (revision 352) @@ -0,0 +1,169 @@ +--------------------------------------------------------------------- +-- TITLE: Register Bank +-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com) +-- DATE CREATED: 2/2/01 +-- FILENAME: reg_bank.vhd +-- PROJECT: MIPS 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 work.mips_pack.all; + +entity reg_bank is + port(clk : 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 + +architecture logic of reg_bank is + signal reg31, reg01, reg02, reg03 : std_logic_vector(31 downto 0); + --For Altera simulations, comment out reg04 through reg30 + signal reg04, reg05, reg06, reg07 : std_logic_vector(31 downto 0); + signal reg08, reg09, reg10, reg11 : std_logic_vector(31 downto 0); + signal reg12, reg13, reg14, reg15 : std_logic_vector(31 downto 0); + signal reg16, reg17, reg18, reg19 : std_logic_vector(31 downto 0); + signal reg20, reg21, reg22, reg23 : std_logic_vector(31 downto 0); + signal reg24, reg25, reg26, reg27 : std_logic_vector(31 downto 0); + signal reg28, reg29, reg30 : std_logic_vector(31 downto 0); + signal reg_epc : std_logic_vector(31 downto 0); + signal reg_status : std_logic; +begin + +reg_proc: process(clk, rs_index, rt_index, rd_index, reg_dest_new, + reg31, reg01, reg02, reg03, reg04, reg05, reg06, reg07, + reg08, reg09, reg10, reg11, reg12, reg13, reg14, reg15, + reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23, + reg24, reg25, reg26, reg27, reg28, reg29, reg30, + reg_epc, reg_status) +begin + case rs_index is + when "000000" => reg_source_out <= ZERO; + when "000001" => reg_source_out <= reg01; + when "000010" => reg_source_out <= reg02; + when "000011" => reg_source_out <= reg03; + when "000100" => reg_source_out <= reg04; + when "000101" => reg_source_out <= reg05; + when "000110" => reg_source_out <= reg06; + when "000111" => reg_source_out <= reg07; + when "001000" => reg_source_out <= reg08; + when "001001" => reg_source_out <= reg09; + when "001010" => reg_source_out <= reg10; + when "001011" => reg_source_out <= reg11; + when "001100" => reg_source_out <= reg12; + when "001101" => reg_source_out <= reg13; + when "001110" => reg_source_out <= reg14; + when "001111" => reg_source_out <= reg15; + when "010000" => reg_source_out <= reg16; + when "010001" => reg_source_out <= reg17; + when "010010" => reg_source_out <= reg18; + when "010011" => reg_source_out <= reg19; + when "010100" => reg_source_out <= reg20; + when "010101" => reg_source_out <= reg21; + when "010110" => reg_source_out <= reg22; + when "010111" => reg_source_out <= reg23; + when "011000" => reg_source_out <= reg24; + when "011001" => reg_source_out <= reg25; + when "011010" => reg_source_out <= reg26; + when "011011" => reg_source_out <= reg27; + when "011100" => reg_source_out <= reg28; + when "011101" => reg_source_out <= reg29; + when "011110" => reg_source_out <= reg30; + when "011111" => reg_source_out <= reg31; + when "101100" => reg_source_out <= ZERO(31 downto 1) & reg_status; + when "101110" => reg_source_out <= reg_epc; --CP0 14 + when "111111" => reg_source_out <= '1' & ZERO(30 downto 0); --intr vector + when others => reg_source_out <= ZERO; + end case; + + case rt_index is + when "000000" => reg_target_out <= ZERO; + when "000001" => reg_target_out <= reg01; + when "000010" => reg_target_out <= reg02; + when "000011" => reg_target_out <= reg03; + when "000100" => reg_target_out <= reg04; + when "000101" => reg_target_out <= reg05; + when "000110" => reg_target_out <= reg06; + when "000111" => reg_target_out <= reg07; + when "001000" => reg_target_out <= reg08; + when "001001" => reg_target_out <= reg09; + when "001010" => reg_target_out <= reg10; + when "001011" => reg_target_out <= reg11; + when "001100" => reg_target_out <= reg12; + when "001101" => reg_target_out <= reg13; + when "001110" => reg_target_out <= reg14; + when "001111" => reg_target_out <= reg15; + when "010000" => reg_target_out <= reg16; + when "010001" => reg_target_out <= reg17; + when "010010" => reg_target_out <= reg18; + when "010011" => reg_target_out <= reg19; + when "010100" => reg_target_out <= reg20; + when "010101" => reg_target_out <= reg21; + when "010110" => reg_target_out <= reg22; + when "010111" => reg_target_out <= reg23; + when "011000" => reg_target_out <= reg24; + when "011001" => reg_target_out <= reg25; + when "011010" => reg_target_out <= reg26; + when "011011" => reg_target_out <= reg27; + when "011100" => reg_target_out <= reg28; + when "011101" => reg_target_out <= reg29; + when "011110" => reg_target_out <= reg30; + when "011111" => reg_target_out <= reg31; + when others => reg_target_out <= ZERO; + end case; + + if rising_edge(clk) then +-- assert reg_dest_new'last_event >= 10 ns +-- report "Reg_dest timing error"; + case rd_index is + when "000001" => reg01 <= reg_dest_new; + when "000010" => reg02 <= reg_dest_new; + when "000011" => reg03 <= reg_dest_new; + when "000100" => reg04 <= reg_dest_new; + when "000101" => reg05 <= reg_dest_new; + when "000110" => reg06 <= reg_dest_new; + when "000111" => reg07 <= reg_dest_new; + when "001000" => reg08 <= reg_dest_new; + when "001001" => reg09 <= reg_dest_new; + when "001010" => reg10 <= reg_dest_new; + when "001011" => reg11 <= reg_dest_new; + when "001100" => reg12 <= reg_dest_new; + when "001101" => reg13 <= reg_dest_new; + when "001110" => reg14 <= reg_dest_new; + when "001111" => reg15 <= reg_dest_new; + when "010000" => reg16 <= reg_dest_new; + when "010001" => reg17 <= reg_dest_new; + when "010010" => reg18 <= reg_dest_new; + when "010011" => reg19 <= reg_dest_new; + when "010100" => reg20 <= reg_dest_new; + when "010101" => reg21 <= reg_dest_new; + when "010110" => reg22 <= reg_dest_new; + when "010111" => reg23 <= reg_dest_new; + when "011000" => reg24 <= reg_dest_new; + when "011001" => reg25 <= reg_dest_new; + when "011010" => reg26 <= reg_dest_new; + when "011011" => reg27 <= reg_dest_new; + when "011100" => reg28 <= reg_dest_new; + when "011101" => reg29 <= reg_dest_new; + when "011110" => reg30 <= reg_dest_new; + when "011111" => reg31 <= reg_dest_new; + when "101100" => reg_status <= reg_dest_new(0); + when "101110" => reg_epc <= reg_dest_new; --CP0 14 + reg_status <= '0'; --disable interrupts + when others => + end case; + end if; + intr_enable <= reg_status; +end process; + +end; --architecture logic + Index: vhdl/makefile =================================================================== --- vhdl/makefile (nonexistent) +++ vhdl/makefile (revision 352) @@ -0,0 +1,52 @@ +VHD = mips_pack alu bus_mux control mem_ctrl mult pc_next reg_bank shifter \ + mips_cpu + +all: work/tbench/_primary.dat + +work/mips_pack/_primary.dat: mips_pack.vhd + vcom -check_synthesis mips_pack.vhd + +work/alu/_primary.dat: mips_pack.vhd alu.vhd + vcom -check_synthesis alu.vhd + +work/bus_mux/_primary.dat: mips_pack.vhd bus_mux.vhd + vcom -check_synthesis bus_mux.vhd + +work/control/_primary.dat: mips_pack.vhd control.vhd + vcom -check_synthesis control.vhd + +work/mem_ctrl/_primary.dat: mips_pack.vhd mem_ctrl.vhd + vcom -check_synthesis mem_ctrl.vhd + +work/mult/_primary.dat: mips_pack.vhd mult.vhd + vcom -check_synthesis mult.vhd + +work/pc_next/_primary.dat: mips_pack.vhd pc_next.vhd + vcom -check_synthesis pc_next.vhd + +work/reg_bank/_primary.dat: mips_pack.vhd reg_bank.vhd + vcom -check_synthesis reg_bank.vhd + +work/shifter/_primary.dat: mips_pack.vhd shifter.vhd + vcom -check_synthesis shifter.vhd + +work/mips_cpu/_primary.dat: mips_cpu.vhd \ + work/mips_pack/_primary.dat \ + work/alu/_primary.dat \ + work/bus_mux/_primary.dat \ + work/control/_primary.dat \ + work/mem_ctrl/_primary.dat \ + work/mult/_primary.dat \ + work/pc_next/_primary.dat \ + work/reg_bank/_primary.dat \ + work/shifter/_primary.dat + vcom -check_synthesis mips_cpu.vhd + +work/ram/_primary.dat: ram.vhd + vcom -explicit ram.vhd + +work/tbench/_primary.dat: tbench.vhd \ + work/mips_cpu/_primary.dat \ + work/ram/_primary.dat + vcom tbench.vhd +

powered by: WebSVN 2.1.0

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