URL
https://opencores.org/ocsvn/atlas_core/atlas_core/trunk
Subversion Repositories atlas_core
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/atlas_core/trunk/core/asm/atlas_asm.exe
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
atlas_core/trunk/core/asm/atlas_asm.exe
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: atlas_core/trunk/core/asm/src/atlas_asm.layout
===================================================================
--- atlas_core/trunk/core/asm/src/atlas_asm.layout (nonexistent)
+++ atlas_core/trunk/core/asm/src/atlas_asm.layout (revision 2)
@@ -0,0 +1,10 @@
+[Editor_0]
+CursorCol=6
+CursorRow=1241
+TopLine=1211
+LeftChar=1
+Open=0
+Top=0
+[Editors]
+Focused=0
+Order=
Index: atlas_core/trunk/core/asm/src/atlas_asm.dev
===================================================================
--- atlas_core/trunk/core/asm/src/atlas_asm.dev (nonexistent)
+++ atlas_core/trunk/core/asm/src/atlas_asm.dev (revision 2)
@@ -0,0 +1,62 @@
+[Project]
+FileName=atlas_asm.dev
+Name=atlas_asm
+Type=1
+Ver=2
+ObjFiles=
+Includes=
+Libs=
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=
+IsCpp=1
+Icon=
+ExeOutput=
+ObjectOutput=
+LogOutput=
+LogOutputEnabled=0
+OverrideOutput=0
+OverrideOutputName=
+HostApplication=
+Folders=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000000000000000000000
+UnitCount=1
+
+[VersionInfo]
+Major=1
+Minor=0
+Release=0
+Build=0
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+SyncProduct=1
+
+[Unit1]
+FileName=main.cpp
+CompileCpp=1
+Folder=atlas_asm
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
Index: atlas_core/trunk/core/asm/src/atlas_asm.exe
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: atlas_core/trunk/core/asm/src/atlas_asm.exe
===================================================================
--- atlas_core/trunk/core/asm/src/atlas_asm.exe (nonexistent)
+++ atlas_core/trunk/core/asm/src/atlas_asm.exe (revision 2)
atlas_core/trunk/core/asm/src/atlas_asm.exe
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: atlas_core/trunk/core/asm/src/main.cpp
===================================================================
--- atlas_core/trunk/core/asm/src/main.cpp (nonexistent)
+++ atlas_core/trunk/core/asm/src/main.cpp (revision 2)
@@ -0,0 +1,1257 @@
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+ // global definition table
+ char definition[512][16];
+ char def_alias[512][16];
+ int def_cnt = 0;
+
+ // global mem-data table
+ bool is_dw[65536];
+
+ // global branch-label table
+ char c_label_tab[2048][32];
+ int i_label_tab[2048];
+
+ // global error/warning indicator
+ int error_cnt = 0;
+ int warning_cnt = 0;
+
+ // function prototypes
+ void pre_processor(char *input_file, const char *output_file);
+ int conv_shift(char *input_string, int line);
+ int conv_cpreg(char *input_string, int line);
+ int conv_reg(char *input_string, int line);
+ int conv_indexing(char *input_string, int line);
+ int conv_flag_op(char *input_string, int line);
+ int conv_flag_op_2(char *input_string, int line);
+ int find_offset(char *input_label, int line);
+ int conv_imm(char *input, int max_val, int line);
+ void get_labels(const char *input_file);
+ void assemble(const char *input_file, const char *output_file, const char *bin_output_file);
+ int main(int argc, char *argv[]);
+
+
+
+// *****************************************************************************************************************
+// Formating pre-processor
+// Erase comments and empty lines, convert to higher case, get definitions and insert data initializations
+// *****************************************************************************************************************
+void pre_processor(char *input_file, const char *output_file){
+
+ FILE *input, *output;
+ char line_input[1024];
+ int i = 0, j = 0, k = 0;
+ char *cut_out;
+ char txt_string[256];
+ char tmp_string[256];
+ char buf_string[512];
+ bool empty_line = false;
+ int fill_data_cnt = 0;
+ int line = 1;
+ int high = 0, low = 0;
+ int word = 0;
+ bool insert_label = false;
+ bool empty_label_line = false;
+ bool found = false;
+
+ // open pre_processor input file
+ input = fopen(input_file, "r");
+ if(input == NULL){
+ printf("PRE_PROCESSOR: Input file error!\n");
+ exit(1);
+ }
+
+ // open pre_processor output file
+ output = fopen(output_file, "w");
+ if(output == NULL){
+ printf("PRE_PROCESSOR: Output file error!");
+ exit(1);
+ }
+
+ // clear dw table
+ for(i=0; i<65536; i++)
+ is_dw[i] = false;
+/*
+ // find strings
+ while(fgets(line_input, 512, input) != NULL){
+
+ // get line entry
+ cut_out = strtok(line_input, "\n");
+ if (cut_out != NULL)
+ sprintf(txt_string, "%s", cut_out);
+
+ // convert to higher case
+ for(i=0; i 96) and (txt_string[i] < 123)){
+ txt_string[i] = txt_string[i] - 32;
+ }
+ }
+
+ found = false;
+ for(i=0; i0; i--){
+ if ((txt_string[i] == 0) or (txt_string[i] == ' ') or (txt_string[i] == '\n') or (txt_string[i] == 9))
+ txt_string[i] = '\0';
+ else{
+ txt_string[i+1] = '\n';
+ txt_string[i+2] = '\0';
+ break;
+ }
+ }
+
+ // convert to higher case
+ for(i=0; i 96) and (txt_string[i] < 123)){
+ txt_string[i] = txt_string[i] - 32;
+ }
+ }
+
+ // erase comments
+ for(i=0; i0){
+ for(i=0; txt_string[i] != '\0'; i++){
+ if ((txt_string[i] == ' ') and (txt_string[i+1] == ' ')) {
+ for (j=i; txt_string[j] != '\0'; j++)
+ txt_string[j+1] = txt_string[j+2];
+ }
+ }
+ j--;
+ }
+
+ // line starting with space?
+ if (txt_string[0] == ' '){
+ for(i=0; txt_string[i+1] != '\0'; i++) // cut off
+ txt_string[i] = txt_string[i+1];
+ txt_string[i] ='\0';
+ }
+
+ // magic
+ strcpy(tmp_string, txt_string);
+ for (i=0; i<255; i++) {
+ if ((txt_string[i] == ':') and (txt_string[i+1] != ' ')) {
+ txt_string[i+1] = ' ';
+ for (j=i+2; j<254; j++)
+ txt_string[j] = tmp_string[j-1];
+ break;
+ }
+ }
+
+ // find definitions
+ if ((txt_string[0] == '.') and (txt_string[1] == 'E') and (txt_string[2] == 'Q') and (txt_string[3] == 'U')){
+ empty_line = true;
+ for(i=5; txt_string[i] != ' '; i++)
+ def_alias[def_cnt][i-5] = txt_string[i];
+ i++;
+ for(j=i; txt_string[j] != ' '; j++)
+ definition[def_cnt][j-i] = txt_string[j];
+ def_cnt++;
+ }
+
+mem_reserve_loop:
+
+ // find memory reserve definitions
+ found = false;
+ for(i=0; i>8)|low));
+ }
+ if(low != 0){
+ sprintf(txt_string, ".DW #%d\n", (high>>8));
+ }
+ }
+
+ if (empty_line == false){
+ strcat(txt_string, "\n");
+ fputs(txt_string, output);
+ line++; // inc line index
+ }
+
+ if(fill_data_cnt != 0){
+ // clear working string
+ for(i=0; i! (line %d)\n", input_string, line);
+ error_cnt++;
+ }
+
+ return sft;
+}
+
+
+// *****************************************************************************************************************
+// Convert coprocessor register to int address
+// *****************************************************************************************************************
+int conv_cpreg(char *input_string, int line){
+
+ int reg = 0;
+ int i = 0;
+
+ // any coprocessor register definition?
+ for (i=0; i! (line %d)\n", input_string, line);
+ error_cnt++;
+ }
+
+ return reg;
+}
+
+
+// *****************************************************************************************************************
+// Convert register to int address
+// *****************************************************************************************************************
+int conv_reg(char *input_string, int line){
+
+ int reg = 0;
+ int i = 0;
+
+ if ((input_string[0] == '+') or (input_string[0] == '-')) {
+ for(i=0; i<31; i++)
+ input_string[i] = input_string[i+1];
+ }
+
+ // any register definition?
+ for (i=0; i! (line %d)\n", input_string, line);
+ error_cnt++;
+ }
+
+ return reg;
+}
+
+
+// *****************************************************************************************************************
+// Convert PRE / POST indexing mode
+// *****************************************************************************************************************
+int conv_indexing(char *input_string, int line){
+
+ int mode = 0;
+
+ if (strcmp(input_string, "PRE") == 0)
+ mode = 0;
+ else if (strcmp(input_string, "POST") == 0)
+ mode = 1;
+ else {
+ printf("ERROR: Invalid register name <%s>! (line %d)\n", input_string, line);
+ error_cnt++;
+ }
+
+ return mode;
+}
+
+
+// *****************************************************************************************************************
+// Convert flag update option
+// *****************************************************************************************************************
+int conv_flag_op(char *input_string, int line){
+
+ int opt = 0;
+
+ if (strcmp(input_string, "ALU_FLAGS") == 0)
+ opt = 1;
+ else if (strcmp(input_string, "SYS_FLAGS") == 0)
+ opt = 2;
+ else if (strcmp(input_string, "USR_FLAGS") == 0)
+ opt = 3;
+ else if (strcmp(input_string, "") == 0)
+ opt = 0;
+ else {
+ printf("ERROR: Invalid flag option <%s>! (line %d)\n", input_string, line);
+ error_cnt++;
+ }
+
+ return opt;
+}
+
+
+// *****************************************************************************************************************
+// Convert restricted flag update option
+// *****************************************************************************************************************
+int conv_flag_op_2(char *input_string, int line){
+
+ int opt = 0;
+
+ if (strcmp(input_string, "SYS_FLAGS") == 0)
+ opt = 0;
+ else if (strcmp(input_string, "USR_FLAGS") == 0)
+ opt = 1;
+ else {
+ printf("ERROR: Invalid flag option <%s>! (line %d)\n", input_string, line);
+ error_cnt++;
+ }
+
+ return opt;
+}
+
+
+
+// *****************************************************************************************************************
+// Get branch offset
+// *****************************************************************************************************************
+int find_offset(char *input_label, int line){
+
+ int offset = 0;
+ bool match = false;
+ int i = 0;
+
+ for(i=0; i<2048; i++){
+ if (strcmp(input_label, c_label_tab[i]) == 0){
+ offset = i_label_tab[i] - line;
+ match = true;
+ break;
+ }
+ }
+ if (match == false){
+ printf("ERROR: Label <%s> not found! (line %d)\n", input_label, line);
+ error_cnt++;
+ }
+
+ if ((offset > 255) or (offset < -256)){
+ printf("ERROR: Label <%s> out of reach (offset: %d)! (line %d)\n", input_label, offset, line);
+ error_cnt++;
+ }
+
+ offset = offset & 511;
+
+ return offset;
+}
+
+
+// *****************************************************************************************************************
+// Convert immediate
+// *****************************************************************************************************************
+int conv_imm(char *input, int max_val, int line){
+
+ int imm = 65535;
+ int i = 0;
+ char temp[32];
+ char input_string[32];
+ bool extended = false;
+
+ strcpy(input_string, input);
+
+ if ((input_string[0] == '+') or (input_string[0] == '-')) {
+ for(i=0; i<31; i++)
+ input_string[i] = input_string[i+1];
+ }
+
+ // any normal immediate definition?
+ for (i=0; i> 16) & 255; // low immediate of 32-bit immediate
+ else
+ imm = atoi(temp) & 255; // low immediate
+ goto skip_analysis; // valid definition found
+ }
+ }
+ }
+
+ // any high immediate definition?
+ if ((input_string[0] == 'H') and (input_string[1] == 'I') and (input_string[2] == 'G') and (input_string[3] == 'H') and (input_string[4] == '[')){
+ for(i=5; i> 24) & 255; // high immediate of 32-bit immediate
+ else
+ imm = (atoi(temp) >> 8) & 255; // high immediate
+ goto skip_analysis; // valid definition found
+ }
+ }
+ }
+
+ imm = atoi(input_string); // normal immediate
+
+ // immediate label-address?
+ if ((input_string[0] == 'L') and (input_string[1] == 'O') and (input_string[2] == 'W') and (input_string[3] == '[')){
+ for(i=4; i<31; i++){
+ if (input_string[i] != ']')
+ temp[i-4] = input_string[i];
+ else{
+ temp[i-4] = '\0';
+ break;
+ }
+ }
+ if (temp[0] == '#'){ // immediate
+ for(i=0; i<31; i++)
+ temp[i] = temp[i+1];
+ if (extended == true)
+ imm = (atoi(temp) >> 16) & 255; // low immediate of 32-bit immediate
+ else
+ imm = atoi(temp) & 255; // low immediate
+ }
+ else {
+ if (extended == true)
+ imm = (((find_offset(temp, 0)-1)*2) >> 16) & 255; // low immediate of 32-bit immediate
+ else
+ imm = ((find_offset(temp, 0)-1)*2) & 255; // low immediate
+ }
+ }
+ if ((input_string[0] == 'H') and (input_string[1] == 'I') and (input_string[2] == 'G') and (input_string[3] == 'H') and (input_string[4] == '[')){
+ for(i=5; i<31; i++){
+ if (input_string[i] != ']')
+ temp[i-5] = input_string[i];
+ else{
+ temp[i-5] = '\0';
+ break;
+ }
+ }
+ if (temp[0] == '#'){ // immediate
+ for(i=0; i<31; i++)
+ temp[i] = temp[i+1];
+ if (extended == true)
+ imm = (atoi(temp) >> 24) & 255; // high immediate of 32-bit immediate
+ else
+ imm = (atoi(temp) >> 8) & 255; // high immediate
+ }
+ else{
+ if (extended == true)
+ imm = (((find_offset(temp, 0)-1)*2) >> 24) & 255; // high immediate of 32-bit immediate
+ else
+ imm = (((find_offset(temp, 0)-1)*2) >> 8) & 255; // high immediate
+ }
+ }
+
+skip_analysis:
+
+ // message
+ if (extended == true){
+ printf("WARNING: Loading extended 32-bit immediate. (line %d)\n", line);
+ warning_cnt++;
+ }
+
+ // out of range?
+ if ((imm > max_val) or (imm < 0)){
+ printf("ERROR: Invalid immediate <%s>! (line %d)\n", input_string, line);
+ error_cnt++;
+ }
+
+ return imm;
+}
+
+
+// *****************************************************************************************************************
+// Get labels and locations
+// *****************************************************************************************************************
+void get_labels(const char *input_file){
+
+ FILE *data_in;
+ char line_input[512];
+ int index = 0;
+ int j = 0;
+ int line = 0;
+ int label_cnt = 0;
+ char *cut_out;
+ char line_string[256];
+
+ // open input/output file
+ data_in = fopen(input_file, "r");
+ if(data_in == NULL){
+ printf("GET_LABEL: Input file error_cnt!\n");
+ exit(1);
+ }
+
+ // get line
+ line = 1;
+ while(fgets(line_input, 512, data_in) != NULL){
+
+ // clear working string
+ for(j=0; j (line %d)\n", line_string, line);
+ warning_cnt++;
+ }
+
+ // label present?
+ for (index=0; line_string[index] != '\0'; index++){
+ if (line_string[index] == ':'){
+ index+=2;
+ for(j=0; line_string[j+index] != '\0'; j++) // cut off
+ line_string[j] = line_string[j+index];
+ line_string[j] ='\0';
+ break;
+ }
+ }
+
+ // get command and operands (9x)
+ for (i=0; i<10; i++){
+ for (index=0; index<512; index++){
+ if (line_string[index] == ' '){
+ strncpy(arg[i], line_string, index);
+ index++;
+ arg[i][index] = '\0';
+ for(j=0; line_string[j+index] != '\0'; j++) // cut off
+ line_string[j] = line_string[j+index];
+ line_string[j] ='\0';
+ break;
+ }
+ }
+ }
+
+ // translate line by line
+ opcode = 0;
+
+ // ALU Operations (without flag update)
+ // ---------------------------------------------------------------------------------------------------------
+ if (strcmp(arg[0], "INC") == 0)
+ opcode = (0<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_imm(arg[3], 7, line);
+ else if (strcmp(arg[0], "DEC") == 0)
+ opcode = (1<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_imm(arg[3], 7, line);
+ else if (strcmp(arg[0], "ADD") == 0)
+ opcode = (2<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "ADC") == 0)
+ opcode = (3<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "SUB") == 0)
+ opcode = (4<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "SBC") == 0)
+ opcode = (5<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if ((strcmp(arg[0], "CMP") == 0) or (strcmp(arg[0], "CMPS") == 0))
+ opcode = (6<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if ((strcmp(arg[0], "CPX") == 0) or (strcmp(arg[0], "CPXS") == 0))
+ opcode = (7<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "AND") == 0){
+ if (conv_reg(arg[2], line) == conv_reg(arg[3], line)) printf("WARNING: Redundant AND will result in STUB instruction! (line &d)\n", line);
+ opcode = (8<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ }
+ else if (strcmp(arg[0], "STUB") == 0) // store register to user bank register
+ opcode = (8<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[2], line);
+ else if (strcmp(arg[0], "ORR") == 0){
+ if (conv_reg(arg[2], line) == conv_reg(arg[3], line)) printf("WARNING: Redundant ORR will result in LDUB instruction! (line &d)\n", line);
+ opcode = (9<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ }
+ else if (strcmp(arg[0], "LDUB") == 0) // load register from user bank register
+ opcode = (9<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[2], line);
+ else if (strcmp(arg[0], "EOR") == 0)
+ opcode = (10<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "NAND") == 0)
+ opcode = (11<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "BIC") == 0)
+ opcode = (12<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if ((strcmp(arg[0], "TEQ") == 0) or (strcmp(arg[0], "TEQS") == 0))
+ opcode = (13<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if ((strcmp(arg[0], "TST") == 0) or (strcmp(arg[0], "TSTS") == 0))
+ opcode = (14<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "SFT") == 0)
+ opcode = (15<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_shift(arg[3], line);
+
+ // ALU Operations (with flag update)
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], "INCS") == 0)
+ opcode = (0<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_imm(arg[3], 7, line);
+ else if (strcmp(arg[0], "DECS") == 0)
+ opcode = (1<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_imm(arg[3], 7, line);
+ else if (strcmp(arg[0], "ADDS") == 0)
+ opcode = (2<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "ADCS") == 0)
+ opcode = (3<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "SUBS") == 0)
+ opcode = (4<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "SBCS") == 0)
+ opcode = (5<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "LDSR") == 0) // load register from msr
+ opcode = (6<<10) | (conv_reg(arg[1], line)<<7) | (conv_flag_op(arg[2], line)<<5);
+ else if (strcmp(arg[0], "STSR") == 0) // store register to msr
+ opcode = (7<<10) | (conv_flag_op(arg[2], line)<<5) | (conv_reg(arg[1], line)<<0);
+ else if (strcmp(arg[0], "STAF") == 0){ // store immediate to MSR's user/system ALU flags
+ temp = conv_imm(arg[1], 63, line);
+ opcode = (7<<10) | ((temp>>3)<<7) | (1<<6) | (conv_flag_op_2(arg[2], line)<<5) | (1<<4) | (temp & 7);
+ }
+ else if (strcmp(arg[0], "ANDS") == 0){
+ if (conv_reg(arg[2], line) == conv_reg(arg[3], line)) printf("WARNING: Redundant ANDS will result in STUBS instruction! (line &d)\n", line);
+ opcode = (8<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ }
+ else if (strcmp(arg[0], "STUBS") == 0) // store register to user bank register and set flags
+ opcode = (8<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[2], line);
+ else if (strcmp(arg[0], "ORRS") == 0){
+ if (conv_reg(arg[2], line) == conv_reg(arg[3], line)) printf("WARNING: Redundant ORRS will result in LDUBS instruction! (line &d)\n", line);
+ opcode = (9<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ }
+ else if (strcmp(arg[0], "LDUBS") == 0) // load register from user bank register and set flags
+ opcode = (9<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[2], line);
+ else if (strcmp(arg[0], "EORS") == 0)
+ opcode = (10<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "NANDS") == 0)
+ opcode = (11<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+ else if (strcmp(arg[0], "BICS") == 0)
+ opcode = (12<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line);
+
+ else if ((strcmp(arg[0], "STPC") == 0) or (strcmp(arg[0], "GT") == 0) or (strcmp(arg[0], "RET") == 0)) // goto [register]
+ opcode = (13<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4);
+ else if ((strcmp(arg[0], "STPCL") == 0) or (strcmp(arg[0], "GTL") == 0) or (strcmp(arg[0], "RETL") == 0)) // goto [register] and link
+ opcode = (13<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | (1<<2);
+ else if ((strcmp(arg[0], "STPCX") == 0) or (strcmp(arg[0], "GTX") == 0) or (strcmp(arg[0], "RETX") == 0)) // goto [register] and switch to user mode
+ opcode = (13<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | (1<<0);
+ else if ((strcmp(arg[0], "STPCI") == 0) or (strcmp(arg[0], "GTI") == 0) or (strcmp(arg[0], "RETI") == 0)) // goto [register] and set global xint flag
+ opcode = (13<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | (1<<1);
+ else if ((strcmp(arg[0], "STPCXI") == 0) or (strcmp(arg[0], "GTXI") == 0) or (strcmp(arg[0], "RETXI") == 0)) // goto [register] and set global xint flag and switch to user mode
+ opcode = (13<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | (1<<1) | (1<<0);
+ else if ((strcmp(arg[0], "STPCXL") == 0) or (strcmp(arg[0], "GTXL") == 0) or (strcmp(arg[0], "RETXL") == 0)) // goto [register] and switch to user mode and link
+ opcode = (13<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | (1<<2) | (1<<0);
+ else if ((strcmp(arg[0], "STPCIL") == 0) or (strcmp(arg[0], "GTIL") == 0) or (strcmp(arg[0], "RETIL") == 0)) // goto [register] and set global xint flag and link
+ opcode = (13<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | (1<<2) | (1<<1);
+ else if ((strcmp(arg[0], "STPCXIL") == 0) or (strcmp(arg[0], "GTXIL") == 0) or (strcmp(arg[0], "RETXIL") == 0)) // goto [register] and set global xint flag and switch to user mode and link
+ opcode = (13<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | (1<<2) | (1<<1) | (1<<0);
+
+ else if (strcmp(arg[0], "LDPC") == 0) // load program counter to register
+ opcode = (14<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4);
+ else if (strcmp(arg[0], "SFTS") == 0)
+ opcode = (15<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_shift(arg[3], line);
+
+ // Branch
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], "B") == 0) // branch always
+ opcode = (1<<15) | (15<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BEQ") == 0) // branch if equal
+ opcode = (1<<15) | (0<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BNE") == 0) // branch if not equal
+ opcode = (1<<15) | (1<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BCS") == 0) // branch if unsigned higher or same
+ opcode = (1<<15) | (2<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BCC") == 0) // branch if unsigned lower
+ opcode = (1<<15) | (3<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BMI") == 0) // branch if negative
+ opcode = (1<<15) | (4<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BPL") == 0) // branch if positive or zero
+ opcode = (1<<15) | (5<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BOS") == 0) // branch if overflow
+ opcode = (1<<15) | (6<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BOC") == 0) // branch if no overflow
+ opcode = (1<<15) | (7<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BHI") == 0) // branch if unsigned higher
+ opcode = (1<<15) | (8<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLS") == 0) // branch if unsigned lower or same
+ opcode = (1<<15) | (9<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BGE") == 0) // branch if greater than or equal
+ opcode = (1<<15) | (10<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLT") == 0) // branch if less than
+ opcode = (1<<15) | (11<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BGT") == 0) // branch if greater than
+ opcode = (1<<15) | (12<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLE") == 0) // branch if less than or equal
+ opcode = (1<<15) | (13<<10) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BTS") == 0) // branch if transfer flag set
+ opcode = (1<<15) | (14<<10) | find_offset(arg[1], line);
+
+ // Branch and link
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], "BL") == 0) // branch and link always
+ opcode = (1<<15) | (15<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLEQ") == 0) // branch and link if equal
+ opcode = (1<<15) | (0<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLNE") == 0) // branch and link if not equal
+ opcode = (1<<15) | (1<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLCS") == 0) // branch and link if unsigned higher or same
+ opcode = (1<<15) | (2<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLCC") == 0) // branch and link if unsigned lower
+ opcode = (1<<15) | (3<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLMI") == 0) // branch and link if negative
+ opcode = (1<<15) | (4<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLPL") == 0) // branch and link if positive or zero
+ opcode = (1<<15) | (5<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLOS") == 0) // branch and link if overflow
+ opcode = (1<<15) | (6<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLOC") == 0) // branch and link if no overflow
+ opcode = (1<<15) | (7<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLHI") == 0) // branch and link if unsigned higher
+ opcode = (1<<15) | (8<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLLS") == 0) // branch and link if unsigned lower or same
+ opcode = (1<<15) | (9<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLGE") == 0) // branch and link if greater than or equal
+ opcode = (1<<15) | (10<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLLT") == 0) // branch and link if less than
+ opcode = (1<<15) | (11<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLGT") == 0) // branch and link if greater than
+ opcode = (1<<15) | (12<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLLE") == 0) // branch and link if less than or equal
+ opcode = (1<<15) | (13<<10) | (1<<9) | find_offset(arg[1], line);
+ else if (strcmp(arg[0], "BLTS") == 0) // branch and link if transfer flag set
+ opcode = (1<<15) | (14<<10) | (1<<9) | find_offset(arg[1], line);
+
+ // Load immediate
+ // ---------------------------------------------------------------------------------------------------------
+ else if ((strcmp(arg[0], "LDIL") == 0) or (strcmp(arg[0], "LDIH") == 0)){
+ temp = conv_imm(arg[2], 255, line);
+ if (strcmp(arg[0], "LDIL") == 0) // load whole register with sign extended immediate
+ opcode = (3<<14) | (0<<11) | ((temp & 128)<<3) | (conv_reg(arg[1], line)<<7) | (temp & 127);
+ else if (strcmp(arg[0], "LDIH") == 0) // only load high byte of register with immediate
+ opcode = (3<<14) | (1<<11) | ((temp & 128)<<3) | (conv_reg(arg[1], line)<<7) | (temp & 127);
+ }
+
+ // Bit operations
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], "SBR") == 0) // set bit
+ opcode = (13<<12) | (0<<11) | (1<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_imm(arg[3], 15, line);
+ else if (strcmp(arg[0], "CBR") == 0) // clear bit
+ opcode = (13<<12) | (0<<11) | (0<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_imm(arg[3], 15, line);
+ else if (strcmp(arg[0], "STB") == 0) // store bit to t-flag
+ opcode = (13<<12) | (1<<11) | (1<<10) | (0<<7) | (conv_reg(arg[1], line)<<4) | conv_imm(arg[2], 15, line);
+ else if (strcmp(arg[0], "STBI") == 0) // store inverted bit to t-flag
+ opcode = (13<<12) | (1<<11) | (1<<10) | (1<<7) | (conv_reg(arg[1], line)<<4) | conv_imm(arg[2], 15, line);
+ else if (strcmp(arg[0], "LDB") == 0) // laod bit form t-flag
+ opcode = (13<<12) | (1<<11) | (0<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_imm(arg[3], 15, line);
+
+ // System call
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], "SYSCALL") == 0){ // trigger software interrupt trap
+ if (strcmp(arg[1], "") == 0)
+ temp = 0;
+ else
+ temp = conv_imm(arg[1], 1023, line);
+ opcode = (63<<10) | temp; // 10-bit system call tag
+ }
+
+ // Memory Access
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], "LDR") == 0){ // load register
+ opcode = (1<<14) | (0<<10) | (conv_reg(arg[1], line)<<7); // mem_access, load, data register
+ opcode = opcode | (conv_reg(arg[2], line)<<4); // base register
+ opcode = opcode | (conv_indexing(arg[4], line)<<13); // indexing mode
+ if (arg[3][0] == '+') // add indexing
+ opcode = opcode | (1<<12);
+ if (arg[3][1] == '#') // immediate offset
+ opcode = opcode | (1<<3) | conv_imm(arg[3], 7, line);
+ else // register offset
+ opcode = opcode | conv_reg(arg[3], line);
+ if (arg[5][0] == '!') // write back base register
+ opcode = opcode | (1<<11);
+ }
+ else if (strcmp(arg[0], "STR") == 0){ // store register
+ opcode = (1<<14) | (1<<10) | (conv_reg(arg[1], line)<<7); // mem_access, store, data register
+ opcode = opcode | (conv_reg(arg[2], line)<<4); // base register
+ opcode = opcode | (conv_indexing(arg[4], line)<<13); // indexing mode
+ if (arg[3][0] == '+') // add indexing
+ opcode = opcode | (1<<12);
+ if (arg[3][1] == '#') // immediate offset
+ opcode = opcode | (1<<3) | conv_imm(arg[3], 7, line);
+ else // register offset
+ opcode = opcode | conv_reg(arg[3], line);
+ if (arg[5][0] == '!') // write back base register
+ opcode = opcode | (1<<11);
+ }
+ else if (strcmp(arg[0], "SWP") == 0){ // data swap: Rd -> MEM[Rb] -> Rd
+ opcode = (1<<14) | (conv_reg(arg[1], line)<<7); // mem_access, load_data register
+ opcode = opcode | (conv_reg(arg[2], line)<<4) | conv_reg(arg[3], line); // base register, store_data register
+ opcode = opcode | (1<<13) | (0<<11); // indexing mode = post and NO write back = redundant to mark swap operation
+ }
+
+ // Coprocessor Access
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], "CDP") == 0){ // coprocessor data processing
+ opcode = (14<<12) | (conv_imm(arg[1], 1, line)<<10) | (conv_cpreg(arg[2], line)<<7);
+ opcode = opcode | (conv_cpreg(arg[3], line)<<4) | conv_imm(arg[4], 7, line);
+ }
+ else if (strcmp(arg[0], "MRC") == 0){ // move data from coprocessor
+ opcode = (14<<12) | (1<<11) | (conv_imm(arg[1], 1, line)<<10) | (conv_reg(arg[2], line)<<7);
+ opcode = opcode | (conv_cpreg(arg[3], line)<<4) | (0<<3) | conv_imm(arg[4], 7, line);
+ }
+ else if (strcmp(arg[0], "MCR") == 0){ // move data to coprocessor
+ opcode = (14<<12) | (1<<11) | (conv_imm(arg[1], 1, line)<<10) | (conv_cpreg(arg[2], line)<<7);
+ opcode = opcode | (conv_reg(arg[3], line)<<4) | (1<<3) | conv_imm(arg[4], 7, line);
+ }
+
+ // Pseudo-Instructions
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], "NOP") == 0) // dummy operation (no actual system state change)
+ opcode = 0; // actually this is an increment with a zero immediate and no flag update
+ else if (strcmp(arg[0], "MOV") == 0) // increment with #0 = move register
+ opcode = (0<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | 0;
+ else if (strcmp(arg[0], "MOVS") == 0) // increment with #0 = move register and flag update
+ opcode = (0<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | 0;
+ else if (strcmp(arg[0], "CLR") == 0) // set register to 0
+ opcode = (10<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[1], line);
+ else if (strcmp(arg[0], "CLRS") == 0) // set register to 0 and set flags
+ opcode = (10<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[1], line);
+ else if (strcmp(arg[0], "COM") == 0) // 1's complement
+ opcode = (11<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[1], line);
+ else if (strcmp(arg[0], "COMS") == 0) // 1's complement and set flags
+ opcode = (11<<10) | (1<<3) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[1], line);
+
+ // Direct memory initialization
+ // ---------------------------------------------------------------------------------------------------------
+ else if (strcmp(arg[0], ".DW") == 0) // dummy operation (no actual system state change)
+ opcode = conv_imm(arg[1], pow(2,16)-1, line);
+
+ // Unknown Command
+ // ---------------------------------------------------------------------------------------------------------
+ else {
+ printf("ERROR: Unknown command <%s>! (line %d)\n", arg[0], line);
+ error_cnt++;
+ }
+
+
+ opcode = opcode & (int(pow(2, 16))-1); // only 16-bit, thanks
+
+ if (error_cnt == 0) {
+ // init file output
+ sprintf(tmp_string, "%06d => x\"%04x\", -- %s\n", line-1, opcode, arg[0]);
+ fputs(tmp_string, data_out);
+ // data file output
+ fputc(char(opcode>>8), bin_data_out);
+ fputc(char(opcode & 255), bin_data_out);
+ }
+
+ line++;
+ }
+
+ if (error_cnt == 0)
+ fputs("others => x\"0000\" -- NOP", data_out);
+
+ fclose(bin_data_out);
+ fclose(data_out);
+ fclose(data_in);
+}
+
+
+// *****************************************************************************************************************
+// Main function
+// *****************************************************************************************************************
+int main(int argc, char *argv[]){
+
+ printf("\nAtlas Processor - Evaluation Assembler, Version 2013.03.13\n");
+ printf("by Stephan Nolting (stnolting@gmail.com), Hanover, Germany\n\n");
+
+ // pre_processor.asm - intermediate processing file
+ // init.vhd - vhdl memory initialization data block
+ // out.bin - binary program output for bootloader downloading
+
+ pre_processor(argv[1], "pre_processor.asm"); // erase comments & empty lines & get definitions
+ get_labels("pre_processor.asm"); // find and list labels
+ assemble("pre_processor.asm", "init.vhd", "out.bin"); // do the magic conversion
+
+ if (error_cnt == 0){
+ printf("\nAssembler completed without errors (%d warnings).\n", warning_cnt);
+ if (warning_cnt != 0)
+ printf("Line numbers refer to the intermediate \"pre_processor.asm\" processing file.\n");
+ }
+ else{
+ printf("\nAssembler terminated with %d errors (%d warnings)!\n", error_cnt, warning_cnt);
+ printf("Line numbers refer to the intermediate \"pre_processor.asm\" processing file.\n");
+ }
+
+ return 0;
+}
Index: atlas_core/trunk/core/asm/src/Makefile.win
===================================================================
--- atlas_core/trunk/core/asm/src/Makefile.win (nonexistent)
+++ atlas_core/trunk/core/asm/src/Makefile.win (revision 2)
@@ -0,0 +1,29 @@
+# Project: atlas_asm
+# Makefile created by Dev-C++ 5.3.0.3
+
+CPP = g++.exe
+CC = gcc.exe
+WINDRES = windres.exe
+OBJ = main.o $(RES)
+LINKOBJ = main.o $(RES)
+LIBS = -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib" -static-libgcc
+INCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include"
+CXXINCS = -I"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/include"
+BIN = atlas_asm.exe
+CXXFLAGS = $(CXXINCS)
+CFLAGS = $(INCS)
+RM = rm -f
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before $(BIN) all-after
+
+
+clean: clean-custom
+ ${RM} $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+ $(CPP) $(LINKOBJ) -o $(BIN) $(LIBS)
+
+main.o: main.cpp
+ $(CPP) -c main.cpp -o main.o $(CXXFLAGS)
Index: atlas_core/trunk/core/asm/src/out.bin
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: atlas_core/trunk/core/asm/src/out.bin
===================================================================
--- atlas_core/trunk/core/asm/src/out.bin (nonexistent)
+++ atlas_core/trunk/core/asm/src/out.bin (revision 2)
atlas_core/trunk/core/asm/src/out.bin
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: atlas_core/trunk/core/asm/test.asm
===================================================================
--- atlas_core/trunk/core/asm/test.asm (nonexistent)
+++ atlas_core/trunk/core/asm/test.asm (revision 2)
@@ -0,0 +1,136 @@
+; -------------------------------------------------------------------------------------------------
+; ATLAS ASSEMBLER test/example program file, March 2013
+; -------------------------------------------------------------------------------------------------
+
+; -> for all further lexical explanations see the rules given between the '>' and '<' symbol
+; -> this is a comment, initiated with >;<
+; -> all constant numbers must have an '#'-prefix
+; -> assembler is not case-sensitive!
+
+
+; User defintions
+; -------------------------------------------------------------------------------------------------
+; user-defined definitions for registers (r0, .., r1), cp_registers (c0, .., c7), constants ('#...')
+; definitions: >.equ<> <>alias_name<> <>real_name/constant<
+; do not use a definition name also as label name!
+; .equ definitions must be at the beginning of a program (before actual code)
+.equ cnt r0 ; counter register
+.equ data r3 ; data transfer register
+.equ LR r7 ; r7 is always the link register
+.equ dec_val #1 ; constant/immediate alias used for decrement
+.equ msr_xint0_en #13 ; this is the MSR's external interrupt 0 enable flag
+.equ msr_xint1_en #14 ; this is the MSR's external interrupt 1 enable flag
+.equ data_area_size #4 ; space area alias
+.equ bytes #4 ; number of bytes to transfer within the demo program
+.equ some_data #1289 ; just some data for memory init
+
+
+; Exception vector table
+; -------------------------------------------------------------------------------------------------
+; This table MUST be the first logical instructions within
+; a program ( block 0) due to fixed exception vectors!
+
+; labels: >lable_name: letters, numbers and '_' symbols<>:<
+; only one label can point to one specific location (so no redundant labels!!!)
+reset_vec: b init ; destination after reset, always starting in system mode
+x_int0_vec: b x_int_handler ; external interrupt 0 interrupt handler
+x_int1_vec: b x_int_handler ; external interrupt 1 interrupt handler
+swi_vec: b swi_handler ; software interrupt exception handler
+
+
+; Exception handlers (system mode)
+; -------------------------------------------------------------------------------------------------
+swi_handler:
+; instructions
+; >cmd mnemonic<> <>OP1<>,<> <>OP2<>,<> < ...
+ dec LR, LR, #2 ; restore WORD (!!!) address of calling instruction
+ ldr r0, LR, +#0, pre ; load the instruction, which caused the exception
+ clr r1 ; load tag mask
+ ldih r1, #252
+ bic r0, r0, r1 ; isolate syscall tag in r0
+
+ ldil r4, #low[test_mem_data_table]
+ ldih r4, #high[test_mem_data_table]
+ ldr r4, r4, +#0, pre
+
+nirvana: b nirvana ; this is the end, my friend...
+
+
+x_int_handler: ; do nothing in this exception handlers but return
+ dec LR, LR, #2 ; restore WORD (!!!) address of interrupted instruction
+ b skip_dummy_mem_area ; skip dummy mem area
+
+; reserve memory (fill with zeros)
+; reserve: >.space<> <>#<>integer value = number of zero words / defintion<
+dummy_mem_area:
+ .space #4 ; insert 4 * x"0000" = "NOP"
+
+skip_dummy_mem_area:
+ reti LR ; return from interrupt handler routine, re-enable global xint_en and resume operation in user_mode at [r7]
+
+
+; Main program
+; -------------------------------------------------------------------------------------------------
+init: ldil r0, #xlow[main_usr] ; get extended (upper 16-bit of 32-bit) low address byte of label "main_usr" - just a demo, it is 0 here
+ ldih r0, #xhigh[main_usr] ; get extended (upper 16-bit of 32-bit) high address byte of label "main_usr" - just a demo, it is 0 here
+ ldil r0, #low[main_usr] ; get low address byte of label "main_usr"
+ ldih r0, #high[main_usr] ; get high address byte of label "main_usr"
+
+ ldsr r1
+ sbr r1, r1, msr_xint0_en ; enable external interrupt 0 mask, no '#'-prefix when using a constant definition!
+ stsr r1
+
+ gtxi r0 ; enable external interrupts and resume operation in user mode at [r0]
+
+.space #4 ; just some space (4*x"0000") to isolate user program...
+
+
+; Here starts the user program (of course in user mode)
+; -------------------------------------------------------------------------------------------------
+main_usr: ldil cnt, #low[bytes] ; loading a sign extended constant definition -> number of bytes to transfer
+
+ ldil r1, #low[test_mem_data_table] ; load address of constant table (see below
+ ldih r1, #high[test_mem_data_table]
+
+ ldil r2, #low[data_area] ; get address of label 'data_area' - store data there
+ ldih r2, #high[data_area]
+
+ ldil r4, #low[test_mem_data_table] ; swap with first data table entry
+ ldih r4, #high[test_mem_data_table]
+ ldil r5, #low[#2222] ; dummy data
+ ldih r5, #high[#2222]
+ swp r5, r4, r5 ; swap memory[r4] with r5
+
+ clr data ; clear data transfer register
+
+ staf #1, usr_flags
+
+loop1: bl load_subroutine ; branch to 'load_subroutine' and link (save return address to link register = r7)
+ bl store_subroutine
+ decs cnt, cnt, dec_val ; decrement 'cnt' by 'dec_val' and set alu flags corresponding to the result ('s'-appendix)
+ bne loop1
+ syscall #129 ; terminate by system call with tag '129'
+
+store_subroutine: ; just some subroutine testing
+ str data, r2, +#2, post, ! ; store 'data' at [r2] and set r2=r2+2 afterwards
+ ret LR ; 'ret' and 'stpc' are equal
+
+load_subroutine: ; and again some subroutine testing
+ ldr data, r1, +#2, post, ! ; load 'data' from [r1] and set r1=r1+2 afterwards
+ ret LR ; return to location stored in the link register LR (=r7)
+
+
+; this is a pseudo data area
+; -------------------------------------------------------------------------------------------------
+data_area: .space data_area_size ; insert 'data_area_size' * x"0000" = "NOP"
+ .space #32 ; just some room
+; direct memory initialization
+; word init: >.dw<> <>#<>integer value (max (2^16)-1)<
+test_mem_data_table:
+.dw #23432
+.dw #234
+.dw #14
+.dw some_data ; you can also use definitions here
+.dw [test_mem_data_table] ; here, the absolute address (inside a page) of branch label "test_mem_data_table" will be placed
+
+;.string "To boldly go, where no man has gone before..." ; string test... not working yet
Index: atlas_core/trunk/core/rtl/ALU.vhd
===================================================================
--- atlas_core/trunk/core/rtl/ALU.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/ALU.vhd (revision 2)
@@ -0,0 +1,413 @@
+-- ########################################################
+-- # << ATLAS Project - Arithmetical/Logical Unit >> #
+-- # **************************************************** #
+-- # The main data processing is done here. Also the CP #
+-- # interface emergea from this unit. #
+-- # **************************************************** #
+-- # Last modified: 12.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity ALU is
+ port (
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+-- ###############################################################################################
+-- ## Function Control ##
+-- ###############################################################################################
+
+ EX_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- stage control
+ FLAG_BUS_I : in std_logic_vector(flag_bus_width_c-1 downto 0); -- flag input
+
+-- ###############################################################################################
+-- ## Data Input ##
+-- ###############################################################################################
+
+ OP_A_I : in std_logic_vector(data_width_c-1 downto 0); -- operand A input
+ OP_B_I : in std_logic_vector(data_width_c-1 downto 0); -- operand B input
+ OP_C_I : in std_logic_vector(data_width_c-1 downto 0); -- operand C input
+
+ PC_1D_I : in std_logic_vector(data_width_c-1 downto 0); -- 1x delayed PC
+
+ MA_FWD_I : in std_logic_vector(fwd_width_c-1 downto 0); -- MA stage forwarding path
+ WB_FWD_I : in std_logic_vector(fwd_width_c-1 downto 0); -- WB stage forwarding path
+
+-- ###############################################################################################
+-- ## Data Output ##
+-- ###############################################################################################
+
+ FLAG_BUS_O : out std_logic_vector(flag_bus_width_c-1 downto 0); -- flag output
+ MASK_T_FLAG_O : out std_logic; -- T-Flag for mask generation
+
+ MSR_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- MSR write data
+ PC_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- PC write data
+ ALU_RES_O : out std_logic_vector(data_width_c-1 downto 0); -- ALU result
+ MAC_RES_O : out std_logic_vector(data_width_c-1 downto 0); -- MAC result
+ BP_OPA_O : out std_logic_vector(data_width_c-1 downto 0); -- operand A bypass
+ BP_OPC_O : out std_logic_vector(data_width_c-1 downto 0); -- operand C bypass
+
+ CP_CP0_EN_O : out std_logic; -- access to cp0
+ CP_CP1_EN_O : out std_logic; -- access to cp1
+ CP_OP_O : out std_logic; -- data transfer/operation
+ CP_RW_O : out std_logic; -- read/write access
+ CP_CMD_O : out std_logic_vector(cp_cmd_width_c-1 downto 0); -- register addresses / cmd
+ CP_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data
+
+ MEM_REQ_O : out std_logic -- data memory access request for next cycle
+ );
+end ALU;
+
+architecture ALU_STRUCTURE of ALU is
+
+ -- Pipeline register --
+ signal OP_A_FF : std_logic_vector(data_width_c-1 downto 0);
+ signal OP_B_FF : std_logic_vector(data_width_c-1 downto 0);
+ signal OP_C_FF : std_logic_vector(data_width_c-1 downto 0);
+
+ -- Internal data lines --
+ signal OP_A_INT : std_logic_vector(data_width_c-1 downto 0);
+ signal OP_B_INT : std_logic_vector(data_width_c-1 downto 0);
+ signal OP_C_INT : std_logic_vector(data_width_c-1 downto 0);
+ signal ALU_RES_INT : std_logic_vector(data_width_c-1 downto 0);
+ signal TRANSF_INT : std_logic;
+ signal SEL_BIT : std_logic;
+ signal INV_BIT : std_logic;
+ signal IS_ZERO : std_logic;
+ signal EXTND_ZERO : std_logic;
+
+ -- Multiplier --
+ signal MAC_BUF : std_logic_vector(data_width_c-1 downto 0);
+
+begin
+
+ -- Pipeline Register -----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ PIPE_REG: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ OP_A_FF <= (others => '0');
+ OP_B_FF <= (others => '0');
+ op_c_ff <= (others => '0');
+ elsif (CE_I = '1') then
+ OP_A_FF <= OP_A_I;
+ OP_B_FF <= OP_B_I;
+ OP_C_FF <= OP_C_I;
+ end if;
+ end if;
+ end process PIPE_REG;
+
+
+
+ -- Execution Forwarding Unit ---------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ EX_FWD: process(MA_FWD_I, WB_FWD_I, EX_CTRL_BUS_I, OP_A_FF, OP_B_FF, OP_C_FF)
+ variable op_a_ma_match_v : std_logic;
+ variable op_b_ma_match_v : std_logic;
+ variable op_a_wb_match_v : std_logic;
+ variable op_b_wb_match_v : std_logic;
+ variable op_c_wb_match_v : std_logic;
+ begin
+
+ -- Data from early stages -> higher priority than data from later stages
+ -- No forwarding when OP_A is the PC
+ -- No forwarding when OP_B is an immediate
+
+ -- Local data dependency detectors --
+ op_a_ma_match_v := '0';
+ if (MA_FWD_I(fwd_en_c) = '1') and (EX_CTRL_BUS_I(ctrl_ra_is_pc_c) = '0') and (EX_CTRL_BUS_I(ctrl_ra_3_c downto ctrl_ra_0_c) = MA_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+ op_a_ma_match_v := '1';
+ end if;
+ op_a_wb_match_v := '0';
+ if (WB_FWD_I(fwd_en_c) = '1') and (EX_CTRL_BUS_I(ctrl_ra_is_pc_c) = '0') and (EX_CTRL_BUS_I(ctrl_ra_3_c downto ctrl_ra_0_c) = WB_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+ op_a_wb_match_v := '1';
+ end if;
+
+ op_b_ma_match_v := '0';
+ if (MA_FWD_I(fwd_en_c) = '1') and (EX_CTRL_BUS_I(ctrl_rb_is_imm_c) = '0') and (EX_CTRL_BUS_I(ctrl_rb_3_c downto ctrl_rb_0_c) = MA_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+ op_b_ma_match_v := '1';
+ end if;
+ op_b_wb_match_v := '0';
+ if (WB_FWD_I(fwd_en_c) = '1') and (EX_CTRL_BUS_I(ctrl_rb_is_imm_c) = '0') and (EX_CTRL_BUS_I(ctrl_rb_3_c downto ctrl_rb_0_c) = WB_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+ op_b_wb_match_v := '1';
+ end if;
+
+ op_c_wb_match_v := '0';
+ if (WB_FWD_I(fwd_en_c) = '1') and (EX_CTRL_BUS_I(ctrl_rb_3_c downto ctrl_rb_0_c) = WB_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+ op_c_wb_match_v := '1';
+ end if;
+
+-- op_a_ma_match_v := MA_FWD_I(fwd_en_c) and EX_CTRL_BUS_I(ctrl_a_ex_ma_fw_c);
+-- op_a_wb_match_v := WB_FWD_I(fwd_en_c) and EX_CTRL_BUS_I(ctrl_a_ex_wb_fw_c);
+-- op_b_ma_match_v := MA_FWD_I(fwd_en_c) and EX_CTRL_BUS_I(ctrl_b_ex_ma_fw_c);
+-- op_b_wb_match_v := WB_FWD_I(fwd_en_c) and EX_CTRL_BUS_I(ctrl_b_ex_wb_fw_c);
+-- op_c_wb_match_v := WB_FWD_I(fwd_en_c) and EX_CTRL_BUS_I(ctrl_c_ex_wb_fw_c);
+
+ -- operand A forwarding --
+ if (op_a_ma_match_v = '1') then
+ OP_A_INT <= MA_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c); -- MA stage
+ elsif (op_a_wb_match_v = '1') then
+ OP_A_INT <= WB_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c); -- WB stage
+ else
+ OP_A_INT <= OP_A_FF;
+ end if;
+
+ -- operand B forwarding --
+ if (op_b_ma_match_v = '1') then
+ OP_B_INT <= MA_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c); -- MA stage
+ elsif (op_b_wb_match_v = '1') then
+ OP_B_INT <= WB_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c); -- WB stage
+ else
+ OP_B_INT <= OP_B_FF;
+ end if;
+
+ -- operand C forwarding --
+ if (op_c_wb_match_v = '1') then
+ OP_C_INT <= WB_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c); -- WB stage
+ else
+ OP_C_INT <= OP_C_FF;
+ end if;
+
+ end process EX_FWD;
+
+
+
+ -- ALU / Shfter Logic ----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ ALU_KERNEL: process(EX_CTRL_BUS_I, OP_A_INT, OP_B_INT, OP_B_FF, FLAG_BUS_I)
+ variable add_a_v, add_b_v : std_logic_vector(data_width_c downto 0);
+ variable add_cf_in_v : std_logic_vector(0 downto 0);
+ variable adder_carry_in_v : std_logic;
+ variable adder_tmp_v : std_logic_vector(data_width_c downto 0);
+ variable adder_res_v : std_logic_vector(data_width_c-1 downto 0);
+ variable adder_car_v : std_logic;
+ variable adder_ovf_v : std_logic;
+ variable shifter_dat_v : std_logic_vector(data_width_c-1 downto 0);
+ variable shifter_carry_v : std_logic;
+ variable shifter_ovf_v : std_logic;
+ variable mask_data_v : std_logic_vector(data_width_c-1 downto 0);
+ begin
+
+ -- ADDER / SUBTRACTOR --
+ -- ==============================================
+ add_a_v := '0' & OP_A_INT;
+ adder_carry_in_v := FLAG_BUS_I(flag_c_c) and EX_CTRL_BUS_I(ctrl_alu_usec_c);
+ case (EX_CTRL_BUS_I(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c)) is
+ when alu_sbc_c => -- (+OP_A) + (-OP_B) {+ (-CARRY)}
+ add_b_v := '0' & (not OP_B_INT);
+ add_cf_in_v(0) := not adder_carry_in_v;
+ when alu_adc_c => -- (+OP_A) + (+OP_B) {+ (+CARRY)}
+ add_b_v := '0' & OP_B_INT;
+ add_cf_in_v(0) := adder_carry_in_v;
+ when others => -- other function set, adder irrelevant
+ add_b_v := '0' & OP_B_INT;
+ add_cf_in_v(0) := adder_carry_in_v;
+ end case;
+
+ -- adder core --
+ adder_tmp_v := std_logic_vector(unsigned(add_a_v) + unsigned(add_b_v) + unsigned(add_cf_in_v(0 downto 0)));
+ adder_res_v := adder_tmp_v(data_width_c-1 downto 0); -- result, MSB of adder_tmp_v is CARRY bit
+
+ -- adder flag carry output logic --
+ case (EX_CTRL_BUS_I(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c)) is
+ when alu_adc_c => -- add
+ adder_car_v := adder_tmp_v(data_width_c);
+ when alu_sbc_c => -- sub
+ adder_car_v := not adder_tmp_v(data_width_c);
+ when others => -- other function set, adder irrelevant
+ adder_car_v := adder_tmp_v(data_width_c);
+ end case;
+
+ -- Arithmetica overflow flag --
+ adder_ovf_v := ((not add_a_v(data_width_c-1)) and (not add_b_v(data_width_c-1)) and ( adder_tmp_v(data_width_c-1))) or
+ (( add_a_v(data_width_c-1)) and ( add_b_v(data_width_c-1)) and (not adder_tmp_v(data_width_c-1)));
+
+
+ -- SHIFTER --
+ -- ==============================================
+ case (op_b_ff(2 downto 0)) is
+ when sft_asr_c => -- arithmetical right shift
+ shifter_dat_v := OP_A_INT(data_width_c-1) & OP_A_INT(data_width_c-1 downto 1);
+ shifter_carry_v := OP_A_INT(0);
+ when sft_rol_c => -- rotate left
+ shifter_dat_v := OP_A_INT(data_width_c-2 downto 0) & OP_A_INT(data_width_c-1);
+ shifter_carry_v := OP_A_INT(data_width_c-1);
+ when sft_ror_c => -- rotate right
+ shifter_dat_v := OP_A_INT(0) & OP_A_INT(data_width_c-1 downto 1);
+ shifter_carry_v := OP_A_INT(0);
+ when sft_lsl_c => -- logical shift left
+ shifter_dat_v := OP_A_INT(data_width_c-2 downto 0) & '0';
+ shifter_carry_v := OP_A_INT(data_width_c-1);
+ when sft_lsr_c => -- logical shift right
+ shifter_dat_v := '0' & OP_A_INT(data_width_c-1 downto 1);
+ shifter_carry_v := OP_A_INT(0);
+ when sft_rlc_c => -- rotate left through carry
+ shifter_dat_v := OP_A_INT(data_width_c-2 downto 0) & FLAG_BUS_I(flag_c_c);
+ shifter_carry_v := OP_A_INT(data_width_c-1);
+ when sft_rrc_c => -- rotate right through carry
+ shifter_dat_v := FLAG_BUS_I(flag_c_c) & OP_A_INT(data_width_c-1 downto 1);
+ shifter_carry_v := OP_A_INT(0);
+ when others => -- swap halfwords (sft_swp_c)
+ shifter_dat_v := OP_A_INT(data_width_c/2-1 downto 0) & OP_A_INT(data_width_c-1 downto data_width_c/2);
+ shifter_carry_v := OP_A_INT(data_width_c-1);
+ end case;
+
+ -- Overflow flag --
+ shifter_ovf_v := OP_A_INT(data_width_c-1) xor shifter_dat_v(data_width_c-1);
+
+
+ -- MASK UNIT for immediate loading --
+ -- ==============================================
+ mask_data_v := OP_A_INT;
+ if (EX_CTRL_BUS_I(ctrl_clr_ha_c) = '1') then -- clear high half word
+ mask_data_v(15 downto 08) := (others => '0');
+ end if;
+ if (EX_CTRL_BUS_I(ctrl_clr_la_c) = '1') then -- clear low half word
+ mask_data_v(07 downto 00) := (others => '0');
+ end if;
+
+
+ -- FUNCTION SELECTOR --
+ -- ==============================================
+ FLAG_BUS_O(flag_c_c) <= FLAG_BUS_I(flag_c_c); -- keep carry
+ FLAG_BUS_O(flag_o_c) <= '0'; -- clear overflow flag
+ ALU_RES_INT <= adder_res_v;
+
+ -- elementary function control --
+ case (EX_CTRL_BUS_I(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c)) is
+ when alu_and_c => -- logical and
+ ALU_RES_INT <= mask_data_v and OP_B_INT; -- mask irrelevant
+ when alu_orr_c => -- logical or
+ ALU_RES_INT <= mask_data_v or OP_B_INT; -- use mask data for immediate loading
+ when alu_eor_c => -- logical xor
+ ALU_RES_INT <= mask_data_v xor OP_B_INT; -- mask irrelevant
+ when alu_nand_c => -- logical nand
+ ALU_RES_INT <= mask_data_v nand OP_B_INT; -- mask irrelevant
+ when alu_bic_c => -- bit clear (a and (not b))
+ ALU_RES_INT <= OP_A_INT and (not OP_B_INT);
+ when alu_sft_c => -- shift (alu_sft_c)
+ FLAG_BUS_O(flag_c_c) <= shifter_carry_v;
+ FLAG_BUS_O(flag_o_c) <= shifter_ovf_v;
+ ALU_RES_INT <= shifter_dat_v;
+ when alu_adc_c => -- add
+ FLAG_BUS_O(flag_c_c) <= adder_car_v;
+ FLAG_BUS_O(flag_o_c) <= adder_ovf_v;
+ ALU_RES_INT <= adder_res_v;
+ when alu_sbc_c => -- sub/cmp/cpc
+ FLAG_BUS_O(flag_c_c) <= adder_car_v;
+ FLAG_BUS_O(flag_o_c) <= adder_ovf_v;
+ ALU_RES_INT <= adder_res_v;
+ when others => -- undefined
+ NULL;
+ end case;
+
+ end process ALU_KERNEL;
+
+ -- Zero detector - Ladies and gentleman, the critical path! --
+ IS_ZERO <= '1' when (to_integer(unsigned(ALU_RES_INT)) = 0) else '0'; -- zero detector
+ EXTND_ZERO <= FLAG_BUS_I(flag_z_c) and IS_ZERO; -- extended zero detector
+ FLAG_BUS_O(flag_z_c) <= EXTND_ZERO when (EX_CTRL_BUS_I(ctrl_alu_usez_c) = '1') else IS_ZERO; -- zero flag
+
+ -- Negative flag --
+ FLAG_BUS_O(flag_n_c) <= ALU_RES_INT(data_width_c-1); -- negative flag
+
+ -- T-Flag update --
+ SEL_BIT <= OP_A_INT(to_integer(unsigned(EX_CTRL_BUS_I(ctrl_bit_3_c downto ctrl_bit_0_c))));
+ INV_BIT <= (not SEL_BIT) when (EX_CTRL_BUS_I(ctrl_tf_inv_c) = '1') else SEL_BIT; -- invert bit?
+ TRANSF_INT <= INV_BIT when (EX_CTRL_BUS_I(ctrl_tf_store_c) = '1') else FLAG_BUS_I(flag_t_c); -- transfer flag
+ FLAG_BUS_O(flag_t_c) <= TRANSF_INT;
+
+ -- T-Flag for mask generation --
+ MASK_T_FLAG_O <= TRANSF_INT when (EX_CTRL_BUS_I(ctrl_en_c) = '1') and (EX_CTRL_BUS_I(ctrl_tf_store_c) = '1') else FLAG_BUS_I(flag_t_c);
+
+
+
+ -- Multiplier ------------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ MAC_BUFFER: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ MAC_BUF <= (others => '0');
+ elsif (CE_I = '1') then
+ if (EX_CTRL_BUS_I(ctrl_load_mac_c) = '1') and (EX_CTRL_BUS_I(ctrl_en_c) = '1') then -- load mac buffer
+ MAC_BUF <= OP_C_I;
+ else
+ MAC_BUF <= (others => '0');
+ end if;
+ end if;
+ end if;
+ end process MAC_BUFFER;
+
+
+
+ MULTIPLIER: process(EX_CTRL_BUS_I, OP_A_INT, OP_B_INT, MAC_BUF)
+ variable mul_res_v : std_logic_vector(2*data_width_c-1 downto 0);
+ variable mac_ofs_v : std_logic_vector(data_width_c-1 downto 0);
+ begin
+ -- Multiplier --
+ if (build_mul_c = true) then
+ mul_res_v := std_logic_vector(unsigned(OP_A_INT) * unsigned(OP_B_INT));
+ else
+ mul_res_v := (others => '0');
+ end if;
+
+ -- Offset --
+ if (EX_CTRL_BUS_I(ctrl_use_offs_c) = '1') and (build_mac_c = true) then
+ mac_ofs_v := MAC_BUF;
+ else
+ mac_ofs_v := (others => '0');
+ end if;
+
+ -- Accumulate --
+ if (build_mac_c = true) then
+ MAC_RES_O <= std_logic_vector(unsigned(mul_res_v(data_width_c-1 downto 0)) + unsigned(mac_ofs_v));
+ else
+ MAC_RES_O <= mul_res_v(data_width_c-1 downto 0);
+ end if;
+ end process MULTIPLIER;
+
+
+
+ -- Module Data Output ----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+
+ -- Coprocessor Interface --
+ CP_CP0_EN_O <= EX_CTRL_BUS_I(ctrl_en_c) and EX_CTRL_BUS_I(ctrl_cp_acc_c) and (not EX_CTRL_BUS_I(ctrl_cp_id_c)); -- cp 0 access
+ CP_CP1_EN_O <= EX_CTRL_BUS_I(ctrl_en_c) and EX_CTRL_BUS_I(ctrl_cp_acc_c) and EX_CTRL_BUS_I(ctrl_cp_id_c); -- cp 1 access
+ CP_OP_O <= EX_CTRL_BUS_I(ctrl_cp_trans_c); -- data transfer / cp operation
+ CP_DAT_O <= OP_A_INT; -- data output
+ CP_RW_O <= EX_CTRL_BUS_I(ctrl_cp_wr_c); -- read/write transfer
+ CP_CMD_O(cp_op_a_msb_c downto cp_op_a_lsb_c) <= EX_CTRL_BUS_I(ctrl_cp_rd_2_c downto ctrl_cp_rd_0_c); -- cp destination / op A reg
+ CP_CMD_O(cp_op_b_msb_c downto cp_op_b_lsb_c) <= EX_CTRL_BUS_I(ctrl_cp_ra_2_c downto ctrl_cp_ra_0_c); -- cp op B reg
+ CP_CMD_O(cp_cmd_msb_c downto cp_cmd_lsb_c) <= EX_CTRL_BUS_I(ctrl_cp_cmd_2_c downto ctrl_cp_cmd_0_c); -- cp command
+
+ -- Data Output --
+ MSR_DATA_O <= OP_B_INT; -- MSR write data
+ PC_DATA_O <= ALU_RES_INT; -- PC write data
+ ALU_RES_O <= ALU_RES_INT; -- ALU result
+ BP_OPA_O <= OP_A_INT; -- operand A bypass out (address base for mem access)
+
+ -- Link_address/mem_w_data port --
+ BP_OPC_O <= PC_1D_I when (EX_CTRL_BUS_I(ctrl_link_c) = '1') else OP_C_INT; -- operand C bypass out (data for mem write access) or link address
+
+ -- Memory system --
+ MEM_REQ_O <= EX_CTRL_BUS_I(ctrl_en_c) and EX_CTRL_BUS_I(ctrl_mem_acc_c); -- mem access in next cycle
+
+
+
+end ALU_STRUCTURE;
Index: atlas_core/trunk/core/rtl/ATLAS_PROCESSOR.vhd
===================================================================
--- atlas_core/trunk/core/rtl/ATLAS_PROCESSOR.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/ATLAS_PROCESSOR.vhd (revision 2)
@@ -0,0 +1,241 @@
+-- ########################################################
+-- # << ATLAS Project - Atlas Processor >> #
+-- # **************************************************** #
+-- # This is the top entity of the Atlas Processor. #
+-- # The design features the CPU itself, a Wishbone- #
+-- # compatible bus unit incorporating a cache and a #
+-- # memory management unit, implemented as system CP. #
+-- # **************************************************** #
+-- # Last modified: 09.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity ATLAS_PROCESSOR is
+-- ###############################################################################################
+-- ## Configuration ##
+-- ###############################################################################################
+ generic (
+ UC_AREA_BEGIN_G : std_logic_vector(bus_adr_width_c-1 downto 0) := x"FF000000"; -- begin of uncached area
+ UC_AREA_END_G : std_logic_vector(bus_adr_width_c-1 downto 0) := x"FFFFFFFF" -- end of uncached area
+ );
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+ port (
+ CLK_I : in std_logic; -- global clock line
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+-- ###############################################################################################
+-- ## Coprocessor Interface ##
+-- ###############################################################################################
+
+ CP_EN_O : out std_logic; -- access to cp0
+ CP_OP_O : out std_logic; -- data transfer/processing
+ CP_RW_O : out std_logic; -- read/write access
+ CP_CMD_O : out std_logic_vector(8 downto 0); -- register addresses / cmd
+ CP_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data
+ CP_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- read data cp0
+
+-- ###############################################################################################
+-- ## External Interrupt Line ##
+-- ###############################################################################################
+
+ IRQ_I : in std_logic; -- external interrupt request
+
+-- ###############################################################################################
+-- ## Wishbone Bus Interface ##
+-- ###############################################################################################
+
+ WB_ADR_O : out std_logic_vector(bus_adr_width_c-1 downto 0); -- address
+ WB_CTI_O : out std_logic_vector(02 downto 0); -- cycle type
+ WB_SEL_O : out std_logic_vector(01 downto 0); -- byte select
+ WB_TGC_O : out std_logic_vector(wb_tag_size_c-1 downto 0); -- cycle tag
+ WB_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- data out
+ WB_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- data in
+ WB_WE_O : out std_logic; -- read/write
+ WB_CYC_O : out std_logic; -- cycle
+ WB_STB_O : out std_logic; -- strobe
+ WB_ACK_I : in std_logic; -- acknowledge
+ WB_HALT_I : in std_logic -- halt bus transaction
+ );
+end ATLAS_PROCESSOR;
+
+architecture ATLAS_PROCESSOR_STRUCTURE of ATLAS_PROCESSOR is
+
+ -- Global Control --
+ signal HALT : std_logic; -- halt system
+ signal SYS_MODE : std_logic; -- current processor mode
+ signal SYS_INT : std_logic; -- processing exception
+ signal SYS_IRQ : std_logic; -- system interrupt
+
+ -- Instruction Interface --
+ signal INSTR_ADR : std_logic_vector(data_width_c-1 downto 0); -- instruction address
+ signal INSTR_DATA : std_logic_vector(data_width_c-1 downto 0); -- opcode
+ signal INSTR_EN : std_logic; -- enable pseudo-IR
+ signal XTND_I_ADR : std_logic_vector(bus_adr_width_c-1 downto 0); -- extended instruction address
+
+ -- Data Interface --
+ signal MEM_REQ : std_logic; -- memory request
+ signal MEM_RW : std_logic; -- read/write access
+ signal MEM_R_DATA : std_logic_vector(data_width_c-1 downto 0); -- read data
+ signal MEM_W_DATA : std_logic_vector(data_width_c-1 downto 0); -- write data
+ signal MEM_ADR : std_logic_vector(data_width_c-1 downto 0); -- memory address
+ signal XTND_D_ADR : std_logic_vector(bus_adr_width_c-1 downto 0); -- extended data address
+
+ -- Coprocessor Signals --
+ signal USR_CP_EN : std_logic; -- access user coprocessor
+ signal SYS_CP_EN : std_logic; -- access system coprocessor
+ signal CP_OP : std_logic; -- transfer/data processing
+ signal CP_RW : std_logic; -- read/write access
+ signal CP_CMD : std_logic_vector(8 downto 0); -- register addresses / cmd
+ signal CP_W_DATA : std_logic_vector(data_width_c-1 downto 0); -- write data
+ signal SYS_CP_DRB : std_logic_vector(data_width_c-1 downto 0); -- system coprocessor data readback
+ signal CP_DATA_RB : std_logic_vector(data_width_c-1 downto 0); -- coprocessor data readback
+
+ -- Bus Unit Control --
+ signal BUS_ERROR : std_logic; -- error during bus transaction
+ signal CACHE_SYNC : std_logic; -- cache is sync
+ signal CLR_CACHE : std_logic; -- clear cache
+ signal FLS_CACHE : std_logic; -- flush cache
+ signal DIR_ACC : std_logic; -- force direct access
+ signal D_PAGE : std_logic_vector(15 downto 0); -- data page
+ signal I_PAGE : std_logic_vector(15 downto 0); -- instruction page
+
+begin
+
+ -- Atlas CPU -------------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ processor_core: ATLAS_CORE
+ port map (
+ -- Global Control --
+ CLK_I => CLK_I, -- global clock line
+ RST_I => RST_I, -- global reset line, sync, high-active
+ HOLD_I => HALT, -- stops core when high
+
+ -- Instruction Interface --
+ INSTR_ADR_O => INSTR_ADR, -- instruction byte adr
+ INSTR_DAT_I => INSTR_DATA, -- instruction input
+ INSTR_EN_O => INSTR_EN, -- allow IR update
+
+ -- Data Interface --
+ SYS_MODE_O => SYS_MODE, -- current operating mode
+ SYS_INT_O => SYS_INT, -- interrupt processing
+ MEM_REQ_O => MEM_REQ, -- mem access in next cycle
+ MEM_RW_O => MEM_RW, -- read write
+ MEM_ADR_O => MEM_ADR, -- data byte adr
+ MEM_DAT_O => MEM_W_DATA, -- write data
+ MEM_DAT_I => MEM_R_DATA, -- read data
+
+ -- Coprocessor Interface --
+ USR_CP_EN_O => USR_CP_EN, -- access to cp0
+ SYS_CP_EN_O => SYS_CP_EN, -- access to cp1
+ CP_OP_O => CP_OP, -- data transfer/processing
+ CP_RW_O => CP_RW, -- read/write access
+ CP_CMD_O => CP_CMD, -- register addresses / cmd
+ CP_DAT_O => CP_W_DATA, -- write data
+ CP_DAT_I => CP_DATA_RB, -- read data cp0 OR cp1
+
+ -- Interrupt Lines --
+ EXT_INT_0_I => IRQ_I, -- external interrupt
+ EXT_INT_1_I => SYS_IRQ -- internal interrupt
+ );
+
+ -- Coprocessor Data Read-Back --
+ CP_DATA_RB <= SYS_CP_DRB or CP_DAT_I;
+
+
+
+ -- System Coprocessor ----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ memory_management_unit: MMU
+ port map (
+ -- Global Control --
+ CLK_I => CLK_I, -- global clock line
+ RST_I => RST_I, -- global reset line, sync, high-active
+ HALT_I => HALT, -- inverted clock enable
+
+ -- Processor Interface --
+ CP_EN_I => SYS_CP_EN, -- access coprocessor
+ CP_OP_I => CP_OP, -- data transfer/processing
+ CP_RW_I => CP_RW, -- read/write access
+ CP_CMD_I => CP_CMD, -- register addresses / cmd
+ CP_DAT_I => CP_W_DATA, -- write data
+ CP_DAT_O => SYS_CP_DRB, -- read data
+ SYS_MODE_I => SYS_MODE, -- current operating mode
+ INT_EXE_I => SYS_INT, -- interrupt beeing executed
+ MMU_IRQ_O => SYS_IRQ, -- mmu interrupt request
+
+ -- Bus Unit Interface --
+ CACHE_ERROR_I => BUS_ERROR, -- bus access error
+ CACHE_SYNC_I => CACHE_SYNC, -- cache is sync
+ CACHE_CLR_O => CLR_CACHE, -- reload cache
+ CACHE_FLUSH_O => FLS_CACHE, -- synchronize cache with mem
+ MEM_DIR_ACC_O => DIR_ACC, -- direct access (bypass cache)
+ MEM_IP_ADR_O => I_PAGE, -- instruction page
+ MEM_DP_ADR_O => D_PAGE -- data page
+ );
+
+ XTND_I_ADR <= I_PAGE & INSTR_ADR; -- address extension
+ XTND_D_ADR <= D_PAGE & MEM_ADR; -- address extension
+
+
+
+ -- Cache and Bus Unit ----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ bus_unit: BUS_INTERFACE
+ generic map (
+ -- Configuration --
+ UC_AREA_BEGIN_G => UC_AREA_BEGIN_G, -- begin of uncached area
+ UC_AREA_END_G => UC_AREA_END_G -- end of uncached area
+ )
+ port map (
+ -- Global Control --
+ CLK_I => CLK_I, -- core clock, all triggering on rising edge
+ RST_I => RST_I, -- global reset, high active, sync
+
+ -- Instruction Interface --
+ INSTR_ADR_I => XTND_I_ADR, -- instruction byte address
+ INSTR_DAT_O => INSTR_DATA, -- current opcode
+ INSTR_EN_I => INSTR_EN, -- allow pseudo-IR update
+
+ -- Data Interface --
+ MEM_REQ_I => MEM_REQ, -- access in next cycle
+ MEM_RW_I => MEM_RW, -- read/write access
+ MEM_ADR_I => XTND_D_ADR, -- data byte address
+ MEM_DAT_I => MEM_W_DATA, -- write data
+ MEM_DAT_O => MEM_R_DATA, -- read data
+
+ -- Arbitration --
+ SYS_MODE_I => SYS_MODE, -- current processor mode
+ HALT_O => HALT, -- stop processor
+ ERROR_O => BUS_ERROR, -- bus access error
+ CACHE_SYNC_O => CACHE_SYNC, -- cache is sync
+ CLR_CACHE_I => CLR_CACHE, -- reload cache
+ FLUSH_CACHE_I => FLS_CACHE, -- synchronize cache with mem
+ DIR_ACC_I => DIR_ACC, -- force direct access
+
+ -- Wishbone Bus --
+ WB_ADR_O => WB_ADR_O, -- address
+ WB_CTI_O => WB_CTI_O, -- cycle type
+ WB_SEL_O => WB_SEL_O, -- byte select
+ WB_TGC_O => WB_TGC_O, -- cycle tag
+ WB_DATA_O => WB_DATA_O, -- data out
+ WB_DATA_I => WB_DATA_I, -- data in
+ WB_WE_O => WB_WE_O, -- read/write
+ WB_CYC_O => WB_CYC_O, -- cycle
+ WB_STB_O => WB_STB_O, -- strobe
+ WB_ACK_I => WB_ACK_I, -- acknowledge
+ WB_HALT_I => WB_HALT_I -- halt bus transaction
+ );
+
+
+
+end ATLAS_PROCESSOR_STRUCTURE;
Index: atlas_core/trunk/core/rtl/MEM_ACC.vhd
===================================================================
--- atlas_core/trunk/core/rtl/MEM_ACC.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/MEM_ACC.vhd (revision 2)
@@ -0,0 +1,194 @@
+-- ########################################################
+-- # << ATLAS Project - Memory Access System >> #
+-- # **************************************************** #
+-- # This unit generates all neccessary signals for the #
+-- # data memory interface. Furthermore, internal data #
+-- # switching networks are located here. #
+-- # **************************************************** #
+-- # Last modified: 09.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity MEM_ACC is
+ port (
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+-- ###############################################################################################
+-- ## Function Control ##
+-- ###############################################################################################
+
+ MA_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- ma stage control
+
+-- ###############################################################################################
+-- ## Data Input ##
+-- ###############################################################################################
+
+ ALU_RES_I : in std_logic_vector(data_width_c-1 downto 0); -- alu result
+ MAC_RES_I : in std_logic_vector(data_width_c-1 downto 0); -- mac result
+ ADR_BASE_I : in std_logic_vector(data_width_c-1 downto 0); -- op_a bypass
+ DATA_BP_I : in std_logic_vector(data_width_c-1 downto 0); -- op_b bypass
+ CP_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- coprocessor rd data
+ RD_MSR_I : in std_logic_vector(data_width_c-1 downto 0); -- read data msr
+
+ WB_FWD_I : in std_logic_vector(fwd_width_c-1 downto 0); -- WB stage forwarding path
+
+-- ###############################################################################################
+-- ## Data Output ##
+-- ###############################################################################################
+
+ DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- data output
+ MEM_ADR_FB_O : out std_logic_vector(data_width_c-1 downto 0); -- memory address feedback
+
+ MA_FWD_O : out std_logic_vector(fwd_width_c-1 downto 0); -- MA stage forwarding path
+
+-- ###############################################################################################
+-- ## Memory (w) Interface ##
+-- ###############################################################################################
+
+ MEM_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- address output
+ MEM_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data output
+ MEM_RW_O : out std_logic -- read write
+ );
+end MEM_ACC;
+
+architecture MA_STRUCTURE of MEM_ACC is
+
+ -- Pipeline register --
+ signal ALU_RES_FF : std_logic_vector(data_width_c-1 downto 0);
+ signal MAC_RES_FF : std_logic_vector(data_width_c-1 downto 0);
+ signal ADR_BASE_FF : std_logic_vector(data_width_c-1 downto 0);
+ signal DATA_BP_FF : std_logic_vector(data_width_c-1 downto 0);
+
+ -- ALU data buffer --
+ signal ALU_RES_BUF : std_logic_vector(data_width_c-1 downto 0);
+
+ -- Internal signals --
+ signal DATA_BP_INT : std_logic_vector(data_width_c-1 downto 0);
+ signal ALU_MAC_DAT : std_logic_vector(data_width_c-1 downto 0);
+ signal SYS_CP_R_DAT : std_logic_vector(data_width_c-1 downto 0);
+ signal SYS_CP_ALU_R_DAT : std_logic_vector(data_width_c-1 downto 0);
+
+begin
+
+ -- Pipeline Register -----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ PIPE_REG: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ ALU_RES_FF <= (others => '0');
+ MAC_RES_FF <= (others => '0');
+ ADR_BASE_FF <= (others => '0');
+ DATA_BP_FF <= (others => '0');
+ ALU_RES_BUF <= (others => '0');
+ elsif (CE_I = '1') then
+ ALU_RES_FF <= ALU_RES_I;
+ MAC_RES_FF <= MAC_RES_I;
+ ADR_BASE_FF <= ADR_BASE_I;
+ DATA_BP_FF <= DATA_BP_I;
+ ALU_RES_BUF <= ALU_RES_FF;
+ end if;
+ end if;
+ end process PIPE_REG;
+
+
+
+ -- Memory Access Forwarding Unit -----------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ MA_FWD: process(WB_FWD_I, MA_CTRL_BUS_I, DATA_BP_FF)
+ begin
+ -- Memory write data (OP_B) forwarding --
+ if (WB_FWD_I(fwd_en_c) = '1') and (MA_CTRL_BUS_I(ctrl_mcyc_c) = '0') and (MA_CTRL_BUS_I(ctrl_rb_3_c downto ctrl_rb_0_c) = WB_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+-- if (WB_FWD_I(fwd_en_c) = '1') and (MA_CTRL_BUS_I(ctrl_rb_3_c downto ctrl_rb_0_c) = WB_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+ DATA_BP_INT <= WB_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c); -- WB stage
+ else
+ DATA_BP_INT <= DATA_BP_FF;
+ end if;
+ end process MA_FWD;
+
+
+
+ -- Memory Address Generator and Data Alignment ---------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ W_MEM_ACC: process(MA_CTRL_BUS_I, ALU_RES_BUF, ADR_BASE_FF, ALU_RES_FF, DATA_BP_INT)
+ variable mem_adr_v : std_logic_vector(data_width_c-1 downto 0);
+ variable dat_end_v : std_logic_vector(data_width_c-1 downto 0);
+ begin
+ -- address origin --
+ if (MA_CTRL_BUS_I(ctrl_mem_daa_c) = '1') then
+ mem_adr_v := ALU_RES_BUF; -- use delayed address
+ elsif (MA_CTRL_BUS_I(ctrl_mem_bpba_c) = '1') then
+ mem_adr_v := ADR_BASE_FF; -- use bypassed address
+ else
+ mem_adr_v := ALU_RES_FF;
+ end if;
+ MEM_ADR_FB_O <= mem_adr_v; -- data alignment address
+ MEM_ADR_O <= mem_adr_v; -- memory address output
+
+ -- Endianness converter --
+ if (big_endian_c = true) then
+ dat_end_v := DATA_BP_INT(data_width_c/2-1 downto 0) & DATA_BP_INT(data_width_c-1 downto data_width_c/2);
+ else
+ dat_end_v := DATA_BP_INT;
+ end if;
+
+ -- data alignment --
+ if (word_mode_en_c = false) then -- byte-addressed memory
+ if (mem_adr_v(0) = '1') then -- unaligned? -> swap bytes
+ MEM_DAT_O <= dat_end_v(data_width_c/2-1 downto 0) & dat_end_v(data_width_c-1 downto data_width_c/2);
+ else -- aligned
+ MEM_DAT_O <= dat_end_v;
+ end if;
+ else -- word-addressed memory
+ MEM_DAT_O <= dat_end_v;
+ end if;
+ end process W_MEM_ACC;
+
+ -- R/W Control --
+ MEM_RW_O <= MA_CTRL_BUS_I(ctrl_mem_wr_c);
+
+
+
+ -- Stage Data Multiplexer ------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+-- SYS_CP_R_DAT <= CP_DATA_I when (MA_CTRL_BUS_I(ctrl_rd_cp_acc_c) = '1') else RD_MSR_I;
+-- SYS_CP_ALU_R_DAT <= SYS_CP_R_DAT when (MA_CTRL_BUS_I(ctrl_cp_msr_rd_c) = '1') else ALU_RES_FF;
+-- DATA_O <= DATA_BP_FF when (MA_CTRL_BUS_I(ctrl_link_c) = '1') else SYS_CP_ALU_R_DAT;
+
+ SYS_CP_R_DAT <= CP_DATA_I when (MA_CTRL_BUS_I(ctrl_rd_cp_acc_c) = '1') else RD_MSR_I;
+ ALU_MAC_DAT <= MAC_RES_FF when (MA_CTRL_BUS_I(ctrl_use_mac_c) = '1') else ALU_RES_FF;
+ SYS_CP_ALU_R_DAT <= SYS_CP_R_DAT when (MA_CTRL_BUS_I(ctrl_cp_msr_rd_c) = '1') else ALU_MAC_DAT;
+ DATA_O <= DATA_BP_FF when (MA_CTRL_BUS_I(ctrl_link_c) = '1') else SYS_CP_ALU_R_DAT;
+
+
+
+ -- Forwarding Path Output ------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+
+ -- forwarding data --
+ MA_FWD_O(fwd_dat_msb_c downto fwd_dat_lsb_c) <= SYS_CP_ALU_R_DAT;
+
+ -- destination address --
+ MA_FWD_O(fwd_adr_3_c downto fwd_adr_0_c) <= MA_CTRL_BUS_I(ctrl_rd_3_c downto ctrl_rd_0_c);
+
+ -- valid forwarding --
+ MA_FWD_O(fwd_en_c) <= MA_CTRL_BUS_I(ctrl_wb_en_c);
+
+
+
+
+end MA_STRUCTURE;
Index: atlas_core/trunk/core/rtl/CTRL.vhd
===================================================================
--- atlas_core/trunk/core/rtl/CTRL.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/CTRL.vhd (revision 2)
@@ -0,0 +1,259 @@
+-- ########################################################
+-- # << ATLAS Project - CPU Control Spine >> #
+-- # **************************************************** #
+-- # Main control system, generating control signals #
+-- # for each pipeline stage. #
+-- # **************************************************** #
+-- # Last modified: 12.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity CTRL is
+ port (
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+-- ###############################################################################################
+-- ## Decoder Interface ##
+-- ###############################################################################################
+
+ OP_DEC_CTRL_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- decoder ctrl lines
+ MULTI_CYC_O : out std_logic; -- multi-cycle indicator
+ MULTI_CYC_REQ_I : in std_logic; -- multi-cycle request
+
+-- ###############################################################################################
+-- ## Control Lines ##
+-- ###############################################################################################
+
+ OF_CTRL_BUS_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- of stage control
+ EX_CTRL_BUS_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- ex stage control
+ MA_CTRL_BUS_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- ma stage control
+ WB_CTRL_BUS_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- wb stage control
+
+-- ###############################################################################################
+-- ## Function Control ##
+-- ###############################################################################################
+
+ VALID_BRANCH_I : in std_logic; -- valid branch detected
+ EXC_TAKEN_I : in std_logic; -- exception taken
+ EXC_POS_O : out std_logic; -- exception would be possible
+ STOP_PC_O : out std_logic; -- freeze program counter
+ IR_UPDATE_EN_O : out std_logic -- enable instruction reg update
+ );
+end CTRL;
+
+architecture CTRL_STRUCTURE of CTRL is
+
+ -- Pipeline register --
+ signal EX_CTRL_FF : std_logic_vector(ctrl_width_c-1 downto 0);
+ signal EX_CTRL_BUF : std_logic_vector(ctrl_width_c-1 downto 0);
+ signal MA_CTRL_FF : std_logic_vector(ctrl_width_c-1 downto 0);
+ signal WB_CTRL_FF : std_logic_vector(ctrl_width_c-1 downto 0);
+
+ -- Branch arbiter --
+ signal DIS_CYCLE_FF : std_logic;
+ signal DIS_CYCLE : std_logic;
+
+ -- Instruction Fetch Arbiter --
+ signal DIS_IF : std_logic;
+ signal MEM_DEPENDECY : std_logic;
+ signal MULTI_CYC_FF : std_logic;
+
+ -- Start-up control --
+ signal START_FF : std_logic;
+
+ -- EX LDDD --
+-- signal EX_A_MA_FWD : std_logic;
+-- signal EX_A_WB_FWD : std_logic;
+-- signal EX_B_MA_FWD : std_logic;
+-- signal EX_B_WB_FWD : std_logic;
+-- signal EX_C_WB_FWD : std_logic;
+
+begin
+
+ -- System Start-Up Sync --------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ START_UP: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ START_FF <= '0';
+ elsif (CE_I = '1') then
+ START_FF <= '1'; -- pretty amazing, huh?
+ end if;
+ end if;
+ end process START_UP;
+
+
+
+ -- Stage 0: Pipeline Flow Arbiter ----------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ FLOW_ARBITER: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ MULTI_CYC_FF <= '0';
+ DIS_CYCLE_FF <= '0';
+ elsif (CE_I = '1') then
+ MULTI_CYC_FF <= MULTI_CYC_REQ_I;
+ if (VALID_BRANCH_I = '1') then
+ DIS_CYCLE_FF <= '1'; -- one additional cycle for branches and system / ext interrupts
+ elsif (DIS_CYCLE_FF = '1') then
+ DIS_CYCLE_FF <= '0';
+ end if;
+ end if;
+ end if;
+ end process FLOW_ARBITER;
+
+ -- Multi cycle outut --
+ MULTI_CYC_O <= MULTI_CYC_FF;
+
+
+ -- Temporal Data Dependency Detector for Memory-Load Operations --
+ ---------------------------------------------------------------------
+ T_DDD: process(OP_DEC_CTRL_I, EX_CTRL_FF)
+ variable a_match_v, b_match_v : std_logic;
+ begin
+ -- Operand A dependency? --
+ a_match_v := '0';
+ if ((OP_DEC_CTRL_I(ctrl_ra_3_c downto ctrl_ra_0_c) = EX_CTRL_FF(ctrl_rd_3_c downto ctrl_rd_0_c)) and (OP_DEC_CTRL_I(ctrl_ra_is_pc_c) = '0')) then
+ a_match_v := '1';
+ end if;
+
+ -- Operand B dependency? --
+ b_match_v := '0';
+ if ((OP_DEC_CTRL_I(ctrl_rb_3_c downto ctrl_rb_0_c) = EX_CTRL_FF(ctrl_rd_3_c downto ctrl_rd_0_c)) and (OP_DEC_CTRL_I(ctrl_rb_is_imm_c) = '0')) then
+ b_match_v := '1';
+ end if;
+
+ -- Memory load dependency? --
+ MEM_DEPENDECY <= EX_CTRL_FF(ctrl_en_c) and EX_CTRL_FF(ctrl_rd_wb_c) and EX_CTRL_FF(ctrl_mem_acc_c) and (not EX_CTRL_FF(ctrl_mem_wr_c)) and (a_match_v or b_match_v);
+ end process T_DDD;
+
+
+ -- Disable Control --
+ -- Branch / Exception: Disable next 2 cycles
+ -- Mem-load dependency: Insert 1 dummy cycle
+ DIS_IF <= '1' when (MULTI_CYC_REQ_I = '1') else '0';
+ branch_slots:
+ if (branch_slots_en_c = true) generate
+ DIS_CYCLE <= '1' when (MEM_DEPENDECY = '1') or (START_FF = '0') else '0';
+ end generate branch_slots;
+ no_branch_slots:
+ if (branch_slots_en_c = false) generate
+ DIS_CYCLE <= '1' when (DIS_CYCLE_FF = '1') or (VALID_BRANCH_I = '1') or (MEM_DEPENDECY = '1') or (START_FF = '0') else '0';
+ end generate no_branch_slots;
+ STOP_PC_O <= DIS_IF or MEM_DEPENDECY;
+ IR_UPDATE_EN_O <= (not DIS_IF) and (not MEM_DEPENDECY);
+
+
+
+ -- Stage 1: Operand Fetch ------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ OF_CTRL_BUS_O <= OP_DEC_CTRL_I;
+
+
+-- -- Local Data Dependency Detector for EX Stage (pre-processed in OF-Stage) --
+-- EX_A_MA_FWD <= '1' when ((OP_DEC_CTRL_I(ctrl_ra_3_c downto ctrl_ra_0_c) = EX_CTRL_BUF(ctrl_rd_3_c downto ctrl_rd_0_c)) and (OP_DEC_CTRL_I(ctrl_ra_is_pc_c) = '0')) else '0';
+-- EX_A_WB_FWD <= '1' when ((OP_DEC_CTRL_I(ctrl_ra_3_c downto ctrl_ra_0_c) = MA_CTRL_FF(ctrl_rd_3_c downto ctrl_rd_0_c)) and (OP_DEC_CTRL_I(ctrl_ra_is_pc_c) = '0')) else '0';
+-- EX_B_MA_FWD <= '1' when ((OP_DEC_CTRL_I(ctrl_rb_3_c downto ctrl_rb_0_c) = EX_CTRL_BUF(ctrl_rd_3_c downto ctrl_rd_0_c)) and (OP_DEC_CTRL_I(ctrl_rb_is_imm_c) = '0')) else '0';
+-- EX_B_WB_FWD <= '1' when ((OP_DEC_CTRL_I(ctrl_rb_3_c downto ctrl_rb_0_c) = MA_CTRL_FF(ctrl_rd_3_c downto ctrl_rd_0_c)) and (OP_DEC_CTRL_I(ctrl_rb_is_imm_c) = '0')) else '0';
+-- EX_C_WB_FWD <= '1' when ((OP_DEC_CTRL_I(ctrl_rb_3_c downto ctrl_rb_0_c) = MA_CTRL_FF(ctrl_rd_3_c downto ctrl_rd_0_c))) else '0';
+
+
+
+ -- Stage 2: Execution ----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ EX_STAGE: process (CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ EX_CTRL_FF <= (others => '0');
+ elsif (CE_I = '1') then
+ EX_CTRL_FF <= OP_DEC_CTRL_I;
+ EX_CTRL_FF(ctrl_en_c) <= OP_DEC_CTRL_I(ctrl_en_c) and (not DIS_CYCLE);
+ EX_CTRL_FF(ctrl_mcyc_c) <= MULTI_CYC_FF; -- un-interruptable multi-cycle operation?
+-- EX_CTRL_FF(ctrl_a_ex_ma_fw_c) <= EX_A_MA_FWD;
+-- EX_CTRL_FF(ctrl_a_ex_wb_fw_c) <= EX_A_WB_FWD;
+-- EX_CTRL_FF(ctrl_b_ex_ma_fw_c) <= EX_B_MA_FWD;
+-- EX_CTRL_FF(ctrl_b_ex_wb_fw_c) <= EX_B_WB_FWD;
+-- EX_CTRL_FF(ctrl_c_ex_wb_fw_c) <= EX_C_WB_FWD;
+ end if;
+ end if;
+ end process EX_STAGE;
+
+
+ -- Exception insertion system --
+ EXC_INSERTION: process (EX_CTRL_FF, EXC_TAKEN_I)
+ begin
+ EX_CTRL_BUF <= EX_CTRL_FF;
+ if (EXC_TAKEN_I = '1') then -- is exception? - insert link and terminate current operation
+ EX_CTRL_BUF(ctrl_rd_3_c downto ctrl_rd_0_c) <= system_mode_c & link_reg_adr_c; -- save to sys link reg
+ EX_CTRL_BUF(ctrl_en_c) <= '0'; -- disable it all
+ EX_CTRL_BUF(ctrl_link_c) <= '1'; -- link return address
+ end if;
+ end process EXC_INSERTION;
+
+ -- Output --
+ EX_CTRL_BUS_O <= EX_CTRL_BUF;
+ EXC_POS_O <= EX_CTRL_FF(ctrl_en_c) and (not EX_CTRL_FF(ctrl_mcyc_c)); -- exception would be possible and no in-interuptable OP
+
+
+
+ -- Stage 3: Memory Access ------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ MA_STAGE: process (CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ MA_CTRL_FF <= (others => '0');
+ elsif (CE_I = '1') then
+ MA_CTRL_FF <= EX_CTRL_BUF;
+ -- some pre-processing to shorten critical path --
+ MA_CTRL_FF(ctrl_wb_en_c) <= (EX_CTRL_BUF(ctrl_en_c) and EX_CTRL_BUF(ctrl_rd_wb_c)) or EXC_TAKEN_I; -- valid reg data write-back
+ MA_CTRL_FF(ctrl_rd_cp_acc_c) <= EX_CTRL_BUF(ctrl_cp_acc_c) and (not EX_CTRL_BUF(ctrl_cp_wr_c)); -- cp read-back
+ MA_CTRL_FF(ctrl_cp_msr_rd_c) <= (EX_CTRL_BUF(ctrl_cp_acc_c) and (not EX_CTRL_BUF(ctrl_cp_wr_c))) or (EX_CTRL_BUF(ctrl_msr_rd_c)); -- cp or msr read access
+ end if;
+ end if;
+ end process MA_STAGE;
+
+ -- Output --
+ MA_CTRL_BUS_O <= MA_CTRL_FF;
+
+
+
+ -- Stage 4: Write Back ---------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ WB_STAGE: process (CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ WB_CTRL_FF <= (others => '0');
+ elsif (CE_I = '1') then
+ WB_CTRL_FF <= MA_CTRL_FF;
+ -- some pre-processing to shorten critical path --
+ WB_CTRL_FF(ctrl_rd_mem_acc_c) <= MA_CTRL_FF(ctrl_mem_acc_c) and (not MA_CTRL_FF(ctrl_mem_wr_c)); -- valid memory read-back
+ end if;
+ end if;
+ end process WB_STAGE;
+
+ -- Output --
+ WB_CTRL_BUS_O <= WB_CTRL_FF;
+
+
+
+
+end CTRL_STRUCTURE;
Index: atlas_core/trunk/core/rtl/ATLAS_pkg.vhd
===================================================================
--- atlas_core/trunk/core/rtl/ATLAS_pkg.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/ATLAS_pkg.vhd (revision 2)
@@ -0,0 +1,631 @@
+-- ########################################################
+-- # << ATLAS Project - System Package >> #
+-- # **************************************************** #
+-- # All architecture configurations, options, signal #
+-- # definitions and components are listed here. #
+-- # **************************************************** #
+-- # Last modified: 11.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package atlas_core_package is
+
+ -- Architecture Configuration -------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant big_endian_c : boolean := false; -- use little/big endian memory system
+ constant cp0_present_c : boolean := false; -- coprocessor 0 (usr cp) present?
+ constant cp1_present_c : boolean := true; -- coprocessor 1 (sys cp) present?
+ constant build_mul_c : boolean := true; -- build a dedicated MUL unit
+ constant build_mac_c : boolean := false; -- build a dedicated MAC unit
+ constant log2_cache_pages_c : natural := 2; -- address bits to specify number of cache pages, max 5
+ constant log2_cache_page_size_c : natural := 5; -- address bits to specify cache page size (in words)
+ constant max_bus_latency_c : natural := (2**log2_cache_page_size_c)/2; -- max bus cycle latency
+
+ ---- DO NOT CHANGE ANYTHING BELOW UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! ----
+
+ -- Architecture Constants -----------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant data_width_c : natural := 16; -- processing data width
+ constant data_bytes_c : natural := data_width_c/8; -- processing data width in bytes
+ constant align_lsb_c : natural := data_bytes_c/2; -- lsb of word boundary
+ constant cache_pages_c : natural := 2**log2_cache_pages_c; -- number of cache pages, max 32
+ constant cache_page_size_c : natural := 2**log2_cache_page_size_c; -- size of cache page in words
+ constant bus_adr_width_c : natural := 32; -- wishbone bus address width
+ constant link_reg_adr_c : std_logic_vector(2 downto 0) := "111"; -- link reg for calls
+ constant user_mode_c : std_logic := '0'; -- user mode indicator
+ constant system_mode_c : std_logic := '1'; -- system mode indicator
+ constant word_mode_en_c : boolean := false; -- use word-addressed memory system instead of byte-addressed
+ constant branch_slots_en_c : boolean := false; -- use branch delay slots (highly experimental!!!)
+
+
+ -- Wishbone Bus Constants -----------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant wb_classic_cyc_c : std_logic_vector(2 downto 0) := "000"; -- classic cycle
+ constant wb_con_bst_cyc_c : std_logic_vector(2 downto 0) := "001"; -- constant address burst
+ constant wb_inc_bst_cyc_c : std_logic_vector(2 downto 0) := "010"; -- incrementing address burst
+ constant wb_end_cyc_cyc_c : std_logic_vector(2 downto 0) := "111"; -- burst end
+ constant wb_tag_size_c : natural := 3; -- tag signal size
+
+
+ -- Machine Status Register ----------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant msr_usr_z_flag_c : natural := 0; -- user mode zero flag
+ constant msr_usr_c_flag_c : natural := 1; -- user mode carry flag
+ constant msr_usr_o_flag_c : natural := 2; -- user mode overflow flag
+ constant msr_usr_n_flag_c : natural := 3; -- user mode negative flag
+ constant msr_usr_t_flag_c : natural := 4; -- user mode transfer flag
+ constant msr_sys_z_flag_c : natural := 5; -- system mode zero flag
+ constant msr_sys_c_flag_c : natural := 6; -- system mode carry flag
+ constant msr_sys_o_flag_c : natural := 7; -- system mode overflow flag
+ constant msr_sys_n_flag_c : natural := 8; -- system mode negative flag
+ constant msr_sys_t_flag_c : natural := 9; -- system mode transfer flag
+ constant msr_usr_cp_ptc_c : natural := 10; -- user coprocessor protected
+-- constant msr_reserved_c : natural := 11; -- reserved
+ constant msr_xint_en_c : natural := 12; -- enable external interrupts (global)
+ constant msr_xint0_en_c : natural := 13; -- enable external interrupt 0
+ constant msr_xint1_en_c : natural := 14; -- enable external interrupt 1
+ constant msr_mode_flag_c : natural := 15; -- system ('1') / user ('0') mode
+
+
+ -- Forwarding Bus -------------------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant fwd_en_c : natural := 0; -- valid register signal
+ constant fwd_adr_0_c : natural := 1; -- address bit 0
+ constant fwd_adr_1_c : natural := 2; -- address bit 1
+ constant fwd_adr_2_c : natural := 3; -- address bit 2
+ constant fwd_adr_3_c : natural := 4; -- address bit 3 (bank select)
+ constant fwd_dat_lsb_c : natural := 5; -- forwarding data lsb
+ constant fwd_dat_msb_c : natural := 5+data_width_c-1; -- forwarding data msb
+ constant fwd_width_c : natural := 5+data_width_c; -- size of forwarding bus
+
+
+ -- Flag Bus -------------------------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant flag_z_c : natural := 0; -- user mode zero flag
+ constant flag_c_c : natural := 1; -- user mode carry flag
+ constant flag_o_c : natural := 2; -- user mode overflow flag
+ constant flag_n_c : natural := 3; -- user mode negative flag
+ constant flag_t_c : natural := 4; -- user mode transfer flag
+ constant flag_bus_width_c : natural := 5; -- size of flag bus
+
+ -- Freude, schöner Götterfunken,
+ -- Tochter aus Elysium,
+ -- Wir betreten feuertrunken,
+ -- Himmlische, dein Heiligthum!
+ -- Deine Zauber binden wieder
+ -- Was die Mode streng geteilt;
+ -- Alle Menschen werden Brüder,
+ -- Wo dein sanfter Flügel weilt.
+
+
+ -- Main Control Bus -----------------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ -- Global Control --
+ constant ctrl_en_c : natural := 0; -- valid cycle
+ constant ctrl_mcyc_c : natural := 1; -- un-interruptable/atomic operation
+
+ -- Operand A Register --
+ constant ctrl_ra_is_pc_c : natural := 2; -- operand register A is the PC
+ constant ctrl_clr_ha_c : natural := 3; -- set higher half word of A to 0 (@ 16 bit)
+ constant ctrl_clr_la_c : natural := 4; -- set lower half word of A to 0 (@ 16 bit)
+ constant ctrl_ra_0_c : natural := 5; -- operand register A adr bit 0
+ constant ctrl_ra_1_c : natural := 6; -- operand register A adr bit 1
+ constant ctrl_ra_2_c : natural := 7; -- operand register A adr bit 2
+ constant ctrl_ra_3_c : natural := 8; -- operand register A adr bit 3 (bank select)
+
+ -- Operand B Register --
+ constant ctrl_rb_is_imm_c : natural := 9; -- operand register B is an immediate
+ constant ctrl_rb_0_c : natural := 10; -- operand register B adr bit 0
+ constant ctrl_rb_1_c : natural := 11; -- operand register B adr bit 1
+ constant ctrl_rb_2_c : natural := 12; -- operand register B adr bit 2
+ constant ctrl_rb_3_c : natural := 13; -- operand register B adr bit 3 (bank select)
+
+ -- Destiantion Register --
+ constant ctrl_rd_wb_c : natural := 14; -- register write back request
+ constant ctrl_rd_0_c : natural := 15; -- register destination adr bit 0
+ constant ctrl_rd_1_c : natural := 16; -- register destination adr bit 1
+ constant ctrl_rd_2_c : natural := 17; -- register destination adr bit 2
+ constant ctrl_rd_3_c : natural := 18; -- register destination adr bit 3 (bank select)
+
+ -- ALU Control --
+ constant ctrl_alu_fs_0_c : natural := 19; -- alu function set bit 0
+ constant ctrl_alu_fs_1_c : natural := 20; -- alu function set bit 1
+ constant ctrl_alu_fs_2_c : natural := 21; -- alu function set bit 2
+ constant ctrl_alu_usec_c : natural := 22; -- alu use MSR(carry_flag)
+ constant ctrl_alu_usez_c : natural := 23; -- alu use MSR(zero_flag)
+ constant ctrl_fupdate_c : natural := 24; -- msr flag update enable
+
+ -- Bit Manipulation --
+ constant ctrl_tf_store_c : natural := 25; -- store bit to t-flag
+ constant ctrl_tf_inv_c : natural := 26; -- invert bit to be store in t-flag
+ constant ctrl_bit_0_c : natural := 27; -- bit index bit 0
+ constant ctrl_bit_1_c : natural := 28; -- bit index bit 1
+ constant ctrl_bit_2_c : natural := 29; -- bit index bit 2
+ constant ctrl_bit_3_c : natural := 30; -- bit index bit 3
+
+ -- System Register Access --
+ constant ctrl_msr_wr_c : natural := 31; -- write to mcr
+ constant ctrl_msr_rd_c : natural := 32; -- read from mcr
+ constant ctrl_pc_wr_c : natural := 33; -- write pc
+
+ -- Branch/Context Control --
+ constant ctrl_cond_0_c : natural := 34; -- condition code bit 0
+ constant ctrl_cond_1_c : natural := 35; -- condition code bit 1
+ constant ctrl_cond_2_c : natural := 36; -- condition code bit 2
+ constant ctrl_cond_3_c : natural := 37; -- condition code bit 3
+ constant ctrl_branch_c : natural := 38; -- is branch operation
+ constant ctrl_link_c : natural := 39; -- store old pc
+ constant ctrl_syscall_c : natural := 40; -- is a system call
+ constant ctrl_ctx_down_c : natural := 41; -- go to user mode
+
+ -- Memory Access --
+ constant ctrl_mem_acc_c : natural := 42; -- request d-mem access
+ constant ctrl_mem_wr_c : natural := 43; -- write to d-mem
+ constant ctrl_mem_bpba_c : natural := 44; -- use bypassed base address
+ constant ctrl_mem_daa_c : natural := 45; -- use delayed address
+
+ -- Coprocessor Access --
+ constant ctrl_cp_acc_c : natural := 46; -- coprocessor operation
+ constant ctrl_cp_trans_c : natural := 47; -- coprocessor data transfer
+ constant ctrl_cp_wr_c : natural := 48; -- write to coprocessor
+ constant ctrl_cp_id_c : natural := 49; -- coprocessor id bit
+
+ -- Multiply-and-Acuumulate Unit --
+ constant ctrl_use_mac_c : natural := 50; -- use MAC unit
+ constant ctrl_load_mac_c : natural := 51; -- load addition buffer for MAC
+ constant ctrl_use_offs_c : natural := 52; -- use loaded offset
+
+-- -- EX Forwarding --
+-- constant ctrl_a_ex_ma_fw_c : natural := 53;
+-- constant ctrl_a_ex_wb_fw_c : natural := 54;
+-- constant ctrl_b_ex_ma_fw_c : natural := 55;
+-- constant ctrl_b_ex_wb_fw_c : natural := 56;
+-- constant ctrl_c_ex_wb_fw_c : natural := 57;
+
+ -- Bus Size --
+ constant ctrl_width_c : natural := 53; -- control bus size
+
+ -- Progress Redefinitions --
+ constant ctrl_wb_en_c : natural := ctrl_rd_wb_c; -- valid write back
+ constant ctrl_rd_mem_acc_c : natural := ctrl_mem_acc_c; -- true mem_read
+ constant ctrl_rd_cp_acc_c : natural := ctrl_cp_acc_c; -- true cp_read
+ constant ctrl_cp_msr_rd_c : natural := ctrl_msr_rd_c; -- true cp or msr read access
+ constant ctrl_cp_cmd_0_c : natural := ctrl_rb_0_c; -- coprocessor cmd bit 0
+ constant ctrl_cp_cmd_1_c : natural := ctrl_rb_1_c; -- coprocessor cmd bit 1
+ constant ctrl_cp_cmd_2_c : natural := ctrl_rb_2_c; -- coprocessor cmd bit 2
+ constant ctrl_cp_ra_0_c : natural := ctrl_ra_0_c; -- coprocessor op A bit 0
+ constant ctrl_cp_ra_1_c : natural := ctrl_ra_1_c; -- coprocessor op A bit 1
+ constant ctrl_cp_ra_2_c : natural := ctrl_ra_2_c; -- coprocessor op A bit 2
+ constant ctrl_cp_rd_0_c : natural := ctrl_rd_0_c; -- coprocessor op B / dest bit 0
+ constant ctrl_cp_rd_1_c : natural := ctrl_rd_1_c; -- coprocessor op B / dest bit 1
+ constant ctrl_cp_rd_2_c : natural := ctrl_rd_2_c; -- coprocessor op B / dest bit 2
+ constant ctrl_re_xint_c : natural := ctrl_rb_1_c; -- re-enable ext interrupts (global)
+ constant ctrl_msr_am_0_c : natural := ctrl_ra_1_c; -- MSR access mode bit 0
+ constant ctrl_msr_am_1_c : natural := ctrl_ra_2_c; -- MSR access mode bit 1
+
+
+ -- Coprocessor Control Bus ----------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant cp_cmd_lsb_c : natural := 0; -- command word lsb
+ constant cp_cmd_msb_c : natural := 2; -- command word msb
+ constant cp_op_b_lsb_c : natural := 3; -- operand B address lsb
+ constant cp_op_b_msb_c : natural := 5; -- operand B address msb
+ constant cp_op_a_lsb_c : natural := 6; -- operand A / destination address lsb
+ constant cp_op_a_msb_c : natural := 8; -- operand A / destination address msb
+ constant cp_cmd_width_c : natural := 9; -- bus size
+
+
+ -- Condition Codes ------------------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant cond_eq_c : std_logic_vector(3 downto 0) := "0000"; -- equal
+ constant cond_ne_c : std_logic_vector(3 downto 0) := "0001"; -- not equal
+ constant cond_cs_c : std_logic_vector(3 downto 0) := "0010"; -- unsigned higher or same
+ constant cond_cc_c : std_logic_vector(3 downto 0) := "0011"; -- unsigned lower
+ constant cond_mi_c : std_logic_vector(3 downto 0) := "0100"; -- negative
+ constant cond_pl_c : std_logic_vector(3 downto 0) := "0101"; -- positive or zero
+ constant cond_os_c : std_logic_vector(3 downto 0) := "0110"; -- overflow
+ constant cond_oc_c : std_logic_vector(3 downto 0) := "0111"; -- no overflow
+ constant cond_hi_c : std_logic_vector(3 downto 0) := "1000"; -- unsigned higher
+ constant cond_ls_c : std_logic_vector(3 downto 0) := "1001"; -- unsigned lower or same
+ constant cond_ge_c : std_logic_vector(3 downto 0) := "1010"; -- greater than or equal
+ constant cond_lt_c : std_logic_vector(3 downto 0) := "1011"; -- less than
+ constant cond_gt_c : std_logic_vector(3 downto 0) := "1100"; -- greater than
+ constant cond_le_c : std_logic_vector(3 downto 0) := "1101"; -- less than or equal
+ constant cond_ts_c : std_logic_vector(3 downto 0) := "1110"; -- transfer flag set
+ constant cond_al_c : std_logic_vector(3 downto 0) := "1111"; -- always
+
+
+ -- ALU Function Select --------------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant fs_inc_c : std_logic_vector(3 downto 0) := "0000"; -- add immediate
+ constant fs_dec_c : std_logic_vector(3 downto 0) := "0001"; -- subtract immediate
+ constant fs_add_c : std_logic_vector(3 downto 0) := "0010"; -- add
+ constant fs_adc_c : std_logic_vector(3 downto 0) := "0011"; -- add with carry
+ constant fs_sub_c : std_logic_vector(3 downto 0) := "0100"; -- subtract
+ constant fs_sbc_c : std_logic_vector(3 downto 0) := "0101"; -- subtract with carry
+ constant fs_cmp_c : std_logic_vector(3 downto 0) := "0110"; -- compare (sub)
+ constant fs_cpx_c : std_logic_vector(3 downto 0) := "0111"; -- extende compare with flags (sbc)
+ constant fs_and_c : std_logic_vector(3 downto 0) := "1000"; -- logical and
+ constant fs_orr_c : std_logic_vector(3 downto 0) := "1001"; -- logical or
+ constant fs_eor_c : std_logic_vector(3 downto 0) := "1010"; -- logical xor
+ constant fs_nand_c : std_logic_vector(3 downto 0) := "1011"; -- logical nand
+ constant fs_bic_c : std_logic_vector(3 downto 0) := "1100"; -- bit clear
+ constant fs_teq_c : std_logic_vector(3 downto 0) := "1101"; -- compare by logical and
+ constant fs_tst_c : std_logic_vector(3 downto 0) := "1110"; -- compare by logical xor
+ constant fs_sft_c : std_logic_vector(3 downto 0) := "1111"; -- shift operation
+
+ -- Pseudo Intructions --
+ constant fs_ld_user_c : std_logic_vector(3 downto 0) := fs_orr_c; -- load from user bank
+ constant fs_st_user_c : std_logic_vector(3 downto 0) := fs_and_c; -- store to user bank
+ constant fs_ld_msr_c : std_logic_vector(3 downto 0) := fs_cmp_c; -- load from msr
+ constant fs_st_msr_c : std_logic_vector(3 downto 0) := fs_cpx_c; -- store to msr
+ constant fs_ld_pc_c : std_logic_vector(3 downto 0) := fs_tst_c; -- load from pc
+ constant fs_st_pc_c : std_logic_vector(3 downto 0) := fs_teq_c; -- store to pc
+
+ -- Elementary ALU Operations --
+ constant alu_adc_c : std_logic_vector(2 downto 0) := "000"; -- add with carry
+ constant alu_sbc_c : std_logic_vector(2 downto 0) := "001"; -- subtract with carry
+ constant alu_and_c : std_logic_vector(2 downto 0) := "010"; -- logical and
+ constant alu_orr_c : std_logic_vector(2 downto 0) := "011"; -- logical or
+ constant alu_eor_c : std_logic_vector(2 downto 0) := "100"; -- logical xor
+ constant alu_nand_c : std_logic_vector(2 downto 0) := "101"; -- logical nand
+ constant alu_bic_c : std_logic_vector(2 downto 0) := "110"; -- bit clear
+ constant alu_sft_c : std_logic_vector(2 downto 0) := "111"; -- shift operation
+
+
+ -- Shifter Control ------------------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ constant sft_swp_c : std_logic_vector(2 downto 0) := "000"; -- swap halfwords
+ constant sft_asr_c : std_logic_vector(2 downto 0) := "001"; -- arithemtical right shift
+ constant sft_rol_c : std_logic_vector(2 downto 0) := "010"; -- rotate left
+ constant sft_ror_c : std_logic_vector(2 downto 0) := "011"; -- rotate right
+ constant sft_lsl_c : std_logic_vector(2 downto 0) := "100"; -- logical shift left
+ constant sft_lsr_c : std_logic_vector(2 downto 0) := "101"; -- logical shift right
+ constant sft_rlc_c : std_logic_vector(2 downto 0) := "110"; -- rotate left through carry
+ constant sft_rrc_c : std_logic_vector(2 downto 0) := "111"; -- rotate right through carry
+
+
+ -- Cool Stuff -----------------------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ -- Carrie Underwood - Thank God For The Hometowns
+ -- Precious - Das Leben ist kostbar
+ -- Mean Creek
+
+
+ -- Component: Data Register File ----------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component REG_FILE
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+ -- Function Control --
+ WB_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- wb stage control
+ OF_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- of stage control
+
+ -- Data Input --
+ WB_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- write back data
+ IMMEDIATE_I : in std_logic_vector(data_width_c-1 downto 0); -- immediates
+ PC_1D_I : in std_logic_vector(data_width_c-1 downto 0); -- pc 1x delayed
+ WB_FWD_I : in std_logic_vector(fwd_width_c-1 downto 0); -- WB stage forwarding path
+
+ -- Data Output --
+ OP_A_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- operand A output
+ OP_B_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- operand B output
+ OP_C_DATA_O : out std_logic_vector(data_width_c-1 downto 0) -- operand C output
+ );
+ end component;
+
+
+ -- Component: Arithmetic/Logic Unit -------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component ALU
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+ -- Function Control --
+ EX_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- stage control
+ FLAG_BUS_I : in std_logic_vector(flag_bus_width_c-1 downto 0); -- flag input
+
+ -- Data Input --
+ OP_A_I : in std_logic_vector(data_width_c-1 downto 0); -- operand A input
+ OP_B_I : in std_logic_vector(data_width_c-1 downto 0); -- operand B input
+ OP_C_I : in std_logic_vector(data_width_c-1 downto 0); -- operand C input
+ PC_1D_I : in std_logic_vector(data_width_c-1 downto 0); -- 1x delayed PC
+ MA_FWD_I : in std_logic_vector(fwd_width_c-1 downto 0); -- MA stage forwarding path
+ WB_FWD_I : in std_logic_vector(fwd_width_c-1 downto 0); -- WB stage forwarding path
+
+ -- Data Output --
+ FLAG_BUS_O : out std_logic_vector(flag_bus_width_c-1 downto 0); -- flag output
+ MASK_T_FLAG_O : out std_logic; -- T-Flag for mask generation
+ MSR_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- MSR write data
+ PC_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- PC write data
+ ALU_RES_O : out std_logic_vector(data_width_c-1 downto 0); -- ALU result
+ MAC_RES_O : out std_logic_vector(data_width_c-1 downto 0); -- MAC result
+ BP_OPA_O : out std_logic_vector(data_width_c-1 downto 0); -- operand A bypass
+ BP_OPC_O : out std_logic_vector(data_width_c-1 downto 0); -- operand C bypass
+ CP_CP0_EN_O : out std_logic; -- access to cp0
+ CP_CP1_EN_O : out std_logic; -- access to cp1
+ CP_OP_O : out std_logic; -- data transfer/operation
+ CP_RW_O : out std_logic; -- read/write access
+ CP_CMD_O : out std_logic_vector(cp_cmd_width_c-1 downto 0); -- register addresses / cmd
+ CP_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data
+ MEM_REQ_O : out std_logic -- data memory access request for next cycle
+ );
+ end component;
+
+
+ -- Component: Machine Status System -------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component SYS_REG
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, asyc
+
+ -- Function Control --
+ EX_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- ex stage control
+ EXT_INT_REQ0_I : in std_logic; -- external interrupt request 0
+ EXT_INT_REQ1_I : in std_logic; -- external interrupt request 1
+
+ -- Data Input --
+ FLAG_BUS_I : in std_logic_vector(flag_bus_width_c-1 downto 0); -- flag input
+ EXC_POS_I : in std_logic; -- external interrupt would be possible
+ STOP_PC : in std_logic; -- freeze pc
+ PC_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- PC write data
+ MSR_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- MSR write data
+
+ -- Data Output --
+ FLAG_BUS_O : out std_logic_vector(flag_bus_width_c-1 downto 0); -- flag output
+ VALID_BRANCH_O : out std_logic; -- valid branch detected
+ EXC_EXECUTED_O : out std_logic; -- executed exception
+ RD_MSR_O : out std_logic_vector(data_width_c-1 downto 0); -- read data msr
+ PC_O : out std_logic_vector(data_width_c-1 downto 0); -- pc output
+ PC_1D_O : out std_logic_vector(data_width_c-1 downto 0); -- pc 1x delayed
+ CP_PTC_O : out std_logic; -- user coprocessor protection
+ MODE_O : out std_logic -- current operating mode
+ );
+ end component;
+
+
+ -- Component: Memory Access Control -------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component MEM_ACC
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, asyc
+
+ -- Function Control --
+ MA_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- ma stage control
+
+ -- Data Input --
+ ALU_RES_I : in std_logic_vector(data_width_c-1 downto 0); -- alu result
+ MAC_RES_I : in std_logic_vector(data_width_c-1 downto 0); -- mac result
+ ADR_BASE_I : in std_logic_vector(data_width_c-1 downto 0); -- op_a bypass
+ DATA_BP_I : in std_logic_vector(data_width_c-1 downto 0); -- op_b bypass
+ CP_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- coprocessor rd data
+ RD_MSR_I : in std_logic_vector(data_width_c-1 downto 0); -- read data msr
+ WB_FWD_I : in std_logic_vector(fwd_width_c-1 downto 0); -- WB stage forwarding path
+
+ -- Data Output --
+ DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- data output
+ MEM_ADR_FB_O : out std_logic_vector(data_width_c-1 downto 0); -- memory address feedback
+ MA_FWD_O : out std_logic_vector(fwd_width_c-1 downto 0); -- MA stage forwarding path
+
+ -- Memory (w) Interface --
+ MEM_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- address output
+ MEM_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data output
+ MEM_RW_O : out std_logic -- read write
+ );
+ end component;
+
+
+ -- Component: Data Write Back Unit --------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component WB_UNIT
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+ -- Function Control --
+ WB_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- wb stage control
+
+ -- Data Input --
+ MEM_WB_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- memory read data
+ ALU_WB_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- alu read data
+ MEM_ADR_FB_I : in std_logic_vector(data_width_c-1 downto 0); -- memory address feedback
+
+ -- Data Output --
+ WB_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- write back data
+ WB_FWD_O : out std_logic_vector(fwd_width_c-1 downto 0) -- WB stage forwarding path
+ );
+ end component;
+
+
+ -- Component: Control System --------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component CTRL
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+ -- Decoder Interface --
+ OP_DEC_CTRL_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- decoder ctrl lines
+ MULTI_CYC_O : out std_logic; -- multi-cycle indicator
+ MULTI_CYC_REQ_I : in std_logic; -- multi-cycle request
+
+ -- Control Lines --
+ OF_CTRL_BUS_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- of stage control
+ EX_CTRL_BUS_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- ex stage control
+ MA_CTRL_BUS_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- ma stage control
+ WB_CTRL_BUS_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- wb stage control
+
+ -- Function Control --
+ VALID_BRANCH_I : in std_logic; -- valid branch detected
+ EXC_TAKEN_I : in std_logic; -- exception taken
+ EXC_POS_O : out std_logic; -- exception would be possible
+ STOP_PC_O : out std_logic; -- freeze program counter
+ IR_UPDATE_EN_O : out std_logic -- enable instruction reg update
+ );
+ end component;
+
+
+ -- Component: Opcode Decoder --------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component OP_DEC
+ port (
+ -- Decoder Interface Input --
+ INSTR_I : in std_logic_vector(data_width_c-1 downto 0); -- instruction input
+ T_FLAG_I : in std_logic; -- T-Flag input
+ M_FLAG_I : in std_logic; -- Mode flag input
+ MULTI_CYC_I : in std_logic; -- multi-cycle indicator
+ CP_PTC_I : in std_logic; -- user coprocessor protection
+
+ -- Decoder Interface Output --
+ MULTI_CYC_REQ_O : out std_logic; -- multi-cycle reqest
+ CTRL_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- decoder ctrl lines
+ IMM_O : out std_logic_vector(data_width_c-1 downto 0) -- immediate
+ );
+ end component;
+
+
+ -- Component: Atlas CPU Core --------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component ATLAS_CORE
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- global clock line
+ RST_I : in std_logic; -- global reset line, sync, high-active
+ HOLD_I : in std_logic; -- stops core when high
+
+ -- Instruction Interface --
+ INSTR_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction byte adr
+ INSTR_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- instruction input
+ INSTR_EN_O : out std_logic; -- allow IR update
+
+ -- Memory Arbitration --
+ SYS_MODE_O : out std_logic; -- current operating mode
+ SYS_INT_O : out std_logic; -- interrupt processing
+
+ -- Memory System --
+ MEM_REQ_O : out std_logic; -- mem access in next cycle
+ MEM_RW_O : out std_logic; -- read write
+ MEM_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- data byte adr
+ MEM_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data
+ MEM_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- read data
+
+ -- Coprocessor Interface --
+ USR_CP_EN_O : out std_logic; -- access to cp0
+ SYS_CP_EN_O : out std_logic; -- access to cp1
+ CP_OP_O : out std_logic; -- data transfer/processing
+ CP_RW_O : out std_logic; -- read/write access
+ CP_CMD_O : out std_logic_vector(cp_cmd_width_c-1 downto 0); -- register addresses / cmd
+ CP_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data
+ CP_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- read data cp0 OR cp1
+
+ -- External Interrupt Lines --
+ EXT_INT_0_I : in std_logic; -- external interrupt request 0
+ EXT_INT_1_I : in std_logic -- external interrupt request 1
+ );
+ end component;
+
+
+ -- Component: Bus Interface ---------------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component BUS_INTERFACE
+ generic (
+ -- Configuration --
+ UC_AREA_BEGIN_G : std_logic_vector(bus_adr_width_c-1 downto 0); -- begin of uncached area
+ UC_AREA_END_G : std_logic_vector(bus_adr_width_c-1 downto 0) -- end of uncached area
+ );
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- core clock, all triggering on rising edge
+ RST_I : in std_logic; -- global reset, high active, sync
+
+ -- Instruction Interface --
+ INSTR_ADR_I : in std_logic_vector(bus_adr_width_c-1 downto 0); -- instruction byte address
+ INSTR_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- current opcode
+ INSTR_EN_I : in std_logic; -- allow pseudo-IR update
+
+ -- Data Interface --
+ MEM_REQ_I : in std_logic; -- access in next cycle
+ MEM_RW_I : in std_logic; -- read/write access
+ MEM_ADR_I : in std_logic_vector(bus_adr_width_c-1 downto 0); -- data byte address
+ MEM_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- write data
+ MEM_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- read data
+
+ -- Arbitration --
+ SYS_MODE_I : in std_logic; -- current processor mode
+ HALT_O : out std_logic; -- stop processor
+ ERROR_O : out std_logic; -- bus access error
+ CACHE_SYNC_O : out std_logic; -- cache is sync
+ CLR_CACHE_I : in std_logic; -- reload cache
+ FLUSH_CACHE_I : in std_logic; -- synchronize cache with mem
+ DIR_ACC_I : in std_logic; -- force direct access
+
+ -- Wishbone Bus --
+ WB_ADR_O : out std_logic_vector(bus_adr_width_c-1 downto 0); -- address
+ WB_CTI_O : out std_logic_vector(02 downto 0); -- cycle type
+ WB_SEL_O : out std_logic_vector(01 downto 0); -- byte select
+ WB_TGC_O : out std_logic_vector(wb_tag_size_c-1 downto 0); -- cycle tag
+ WB_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- data out
+ WB_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- data in
+ WB_WE_O : out std_logic; -- read/write
+ WB_CYC_O : out std_logic; -- cycle
+ WB_STB_O : out std_logic; -- strobe
+ WB_ACK_I : in std_logic; -- acknowledge
+ WB_HALT_I : in std_logic -- halt bus transaction
+ );
+ end component;
+
+
+ -- Component: Memory Management Unit ------------------------------------------------------
+ -- -------------------------------------------------------------------------------------------
+ component MMU
+ port (
+ -- Global Control --
+ CLK_I : in std_logic; -- global clock line
+ RST_I : in std_logic; -- global reset line, sync, high-active
+ HALT_I : in std_logic; -- inverted clock enable
+
+ -- Processor Interface --
+ CP_EN_I : in std_logic; -- access coprocessor
+ CP_OP_I : in std_logic; -- data transfer/processing
+ CP_RW_I : in std_logic; -- read/write access
+ CP_CMD_I : in std_logic_vector(cp_cmd_width_c-1 downto 0); -- register addresses / cmd
+ CP_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- write data
+ CP_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- read data
+ SYS_MODE_I : in std_logic; -- current operating mode
+ INT_EXE_I : in std_logic; -- interrupt beeing executed
+ MMU_IRQ_O : out std_logic; -- mmu interrupt request
+
+ -- Bus Unit Interface --
+ CACHE_ERROR_I : in std_logic; -- bus access error
+ CACHE_SYNC_I : in std_logic; -- cache is sync
+ CACHE_CLR_O : out std_logic; -- reload cache
+ CACHE_FLUSH_O : out std_logic; -- synchronize cache with mem
+ MEM_DIR_ACC_O : out std_logic; -- direct access (bypass cache)
+ MEM_IP_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction page
+ MEM_DP_ADR_O : out std_logic_vector(data_width_c-1 downto 0) -- data page
+ );
+ end component;
+
+end atlas_core_package;
\ No newline at end of file
Index: atlas_core/trunk/core/rtl/WB_UNIT.vhd
===================================================================
--- atlas_core/trunk/core/rtl/WB_UNIT.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/WB_UNIT.vhd (revision 2)
@@ -0,0 +1,131 @@
+-- ########################################################
+-- # << ATLAS Project - Data Write-Back >> #
+-- # **************************************************** #
+-- # Data write back selector for register file input. #
+-- # **************************************************** #
+-- # Last modified: 09.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity WB_UNIT is
+ port (
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+-- ###############################################################################################
+-- ## Function Control ##
+-- ###############################################################################################
+
+ WB_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- wb stage control
+
+-- ###############################################################################################
+-- ## Data Input ##
+-- ###############################################################################################
+
+ MEM_WB_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- memory read data
+ ALU_WB_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- alu read data
+ MEM_ADR_FB_I : in std_logic_vector(data_width_c-1 downto 0); -- memory address feedback
+
+-- ###############################################################################################
+-- ## Data Output ##
+-- ###############################################################################################
+
+ WB_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- write back data
+ WB_FWD_O : out std_logic_vector(fwd_width_c-1 downto 0) -- WB stage forwarding path
+ );
+end WB_UNIT;
+
+architecture WB_STRUCTURE of WB_UNIT is
+
+ -- Pipeline register --
+ signal ALU_FF : std_logic_vector(data_width_c-1 downto 0);
+
+ -- Write-Back Source Select --
+ signal WB_DATA_INT : std_logic_vector(data_width_c-1 downto 0);
+
+ -- Aligned Mem Data --
+ signal MEM_ADR_FB : std_logic_vector(data_width_c-1 downto 0);
+ signal MEM_WB_DAT_INT : std_logic_vector(data_width_c-1 downto 0);
+
+begin
+
+ -- Pipeline Register -----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ PIPE_REG: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ ALU_FF <= (others => '0');
+ MEM_ADR_FB <= (others => '0');
+ elsif (CE_I = '1') then
+ ALU_FF <= ALU_WB_DAT_I;
+ MEM_ADR_FB <= MEM_ADR_FB_I;
+ end if;
+ end if;
+ end process PIPE_REG;
+
+
+
+ -- Data Alignment --------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ DAT_ALIGN: process(MEM_ADR_FB, MEM_WB_DAT_I)
+ variable dat_end_v : std_logic_vector(data_width_c-1 downto 0);
+ begin
+ -- Endianness converter --
+ if (big_endian_c = true) then
+ dat_end_v := MEM_WB_DAT_I(data_width_c/2-1 downto 0) & MEM_WB_DAT_I(data_width_c-1 downto data_width_c/2);
+ else
+ dat_end_v := MEM_WB_DAT_I;
+ end if;
+
+ -- Unaligned access? --
+ if (word_mode_en_c = false) then -- byte-addressed memory
+ if (MEM_ADR_FB(0) = '1') then -- swap bytes
+ MEM_WB_DAT_INT <= dat_end_v(data_width_c/2-1 downto 0) & dat_end_v(data_width_c-1 downto data_width_c/2);
+ else
+ MEM_WB_DAT_INT <= dat_end_v;
+ end if;
+ else -- word-addressed memory
+ MEM_WB_DAT_INT <= dat_end_v;
+ end if;
+ end process DAT_ALIGN;
+
+
+
+ -- Module Data Output ----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ -- route mem data if valid mem-read-access
+ WB_DATA_INT <= MEM_WB_DAT_INT when (WB_CTRL_BUS_I(ctrl_rd_mem_acc_c) = '1') else ALU_FF;
+ WB_DATA_O <= WB_DATA_INT;
+
+
+
+ -- Forwarding Path Output ------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+
+ -- forwarding data --
+ WB_FWD_O(fwd_dat_msb_c downto fwd_dat_lsb_c) <= WB_DATA_INT;
+
+ -- destination address --
+ WB_FWD_O(fwd_adr_3_c downto fwd_adr_0_c) <= WB_CTRL_BUS_I(ctrl_rd_3_c downto ctrl_rd_0_c);
+
+ -- valid forwarding --
+ WB_FWD_O(fwd_en_c) <= WB_CTRL_BUS_I(ctrl_wb_en_c);
+
+
+
+
+end WB_STRUCTURE;
Index: atlas_core/trunk/core/rtl/BUS_INTERFACE.vhd
===================================================================
--- atlas_core/trunk/core/rtl/BUS_INTERFACE.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/BUS_INTERFACE.vhd (revision 2)
@@ -0,0 +1,659 @@
+-- ########################################################
+-- # << ATLAS Project - Bus Interface >> #
+-- # **************************************************** #
+-- # This unit features a Wishbone-compatible bus #
+-- # together with a fully-associative shared data / #
+-- # instruction cache. The system is capable of #
+-- # generating a true 32-bit wide address for the NoC. #
+-- # **************************************************** #
+-- # Last modified: 12.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity BUS_INTERFACE is
+-- ################################################################################################################
+-- ## Cached Area Configuration ##
+-- ################################################################################################################
+ generic (
+ UC_AREA_BEGIN_G : std_logic_vector(bus_adr_width_c-1 downto 0); -- begin of uncached area
+ UC_AREA_END_G : std_logic_vector(bus_adr_width_c-1 downto 0) -- end of uncached area
+ );
+-- ################################################################################################################
+-- ## Global Control ##
+-- ################################################################################################################
+ port (
+ CLK_I : in std_logic; -- core clock, all triggering on rising edge
+ RST_I : in std_logic; -- global reset, high active, sync
+
+-- ################################################################################################################
+-- ## Processor Access ##
+-- ################################################################################################################
+
+ -- Instruction Interface --
+ INSTR_ADR_I : in std_logic_vector(bus_adr_width_c-1 downto 0); -- instruction byte address
+ INSTR_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- current opcode
+ INSTR_EN_I : in std_logic; -- allow pseudo-IR update
+
+ -- Data Interface --
+ MEM_REQ_I : in std_logic; -- access in next cycle
+ MEM_RW_I : in std_logic; -- read/write access
+ MEM_ADR_I : in std_logic_vector(bus_adr_width_c-1 downto 0); -- data byte address
+ MEM_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- write data
+ MEM_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- read data
+
+ -- Arbitration --
+ SYS_MODE_I : in std_logic; -- current processor mode
+ HALT_O : out std_logic; -- stop processor
+ ERROR_O : out std_logic; -- bus access error
+ CACHE_SYNC_O : out std_logic; -- cache is sync
+ CLR_CACHE_I : in std_logic; -- reload cache
+ FLUSH_CACHE_I : in std_logic; -- synchronize cache with mem
+ DIR_ACC_I : in std_logic; -- force direct access
+
+-- ################################################################################################################
+-- ## Wishbone Bus ##
+-- ################################################################################################################
+
+ WB_ADR_O : out std_logic_vector(bus_adr_width_c-1 downto 0); -- address
+ WB_CTI_O : out std_logic_vector(02 downto 0); -- cycle type
+ WB_SEL_O : out std_logic_vector(01 downto 0); -- byte select
+ WB_TGC_O : out std_logic_vector(wb_tag_size_c-1 downto 0); -- cycle tag
+ WB_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- data out
+ WB_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- data in
+ WB_WE_O : out std_logic; -- read/write
+ WB_CYC_O : out std_logic; -- cycle
+ WB_STB_O : out std_logic; -- strobe
+ WB_ACK_I : in std_logic; -- acknowledge
+ WB_HALT_I : in std_logic -- halt bus transaction
+ );
+end BUS_INTERFACE;
+
+architecture BUS_INTERFACE_STRUCTURE of BUS_INTERFACE is
+
+ -- Arbiter --
+ type arb_state_type is (IDLE, ANALYSE, TRANSFER_PAGE, RE_SYNC_1, RE_SYNC_2, DIRECT_ACCESS, FLUSH);
+ type dir_flag_type is (UP, DOWN);
+ signal ARB_STATE, ARB_STATE_NXT : arb_state_type; -- main arbiter
+ signal RET_STATE, RET_STATE_NXT : arb_state_type; -- main arbiter return state
+ signal BUS_DIR, BUS_DIR_NXT : dir_flag_type; -- current transfer operation
+ signal PAGE_PNT, PAGE_PNT_NXT : std_logic_vector(log2_cache_pages_c-1 downto 0); -- page pointer
+ signal TYPE_FLAG, TYPE_FLAG_NXT : std_logic; -- data/instruction transfer
+ signal FREEZE_FLAG, FREEZE_FLAG_NXT : std_logic; -- disable cpu
+ signal D_ACC_BUF, D_ACC_BUF_NXT : std_logic_vector(bus_adr_width_c-1 downto 0); -- data access address buffer
+ signal I_ACC_BUF, I_ACC_BUF_NXT : std_logic_vector(bus_adr_width_c-1 downto 0); -- instruction access address buffer
+ signal DIR_DAT_REQ : std_logic; -- direct access request
+ signal RND_GEN : std_logic_vector(5 downto 0); -- random generator
+ signal TIMEOUT_CNT, TIMEOUT_CNT_NXT : std_logic_vector(log2_cache_page_size_c-1 downto 0); -- timeout counter
+ signal SYNC_CNT, SYNC_CNT_NXT : std_logic_vector(1 downto 0); -- bus synchroization counter
+ signal DATA_CNT, DATA_CNT_NXT : std_logic_vector(log2_cache_page_size_c downto 0); -- data packet counter
+ signal DA_RB_FF, DA_RB_FF_NXT : std_logic; -- direct access readback
+
+ -- Cache System --
+ type cache_mem_type is array(0 to (cache_pages_c*cache_page_size_c-1)) of std_logic_vector(data_width_c-1 downto 0);
+ signal CACHE_MEM : cache_mem_type := (others => (others => '0'));
+ signal CACHE_EN : std_logic; -- valid access to cache (up/download, d-access)
+ signal CACHE_RW : std_logic; -- read/write (up/download, d-access)
+ signal MEM_REQ_FF : std_logic; -- processor requires d-mem access
+ signal MEM_REQ_FF_FF : std_logic; -- processor requires d-mem access, signal buffer
+ signal INST_EN_FF : std_logic; -- instruction reg enable ff
+ signal I_UPDATE : std_logic; -- instruction reg enable
+ signal D_ACC_DAT_BUF : std_logic_vector(data_width_c-1 downto 0); -- data write buffer
+ signal CACHE_D_ADR : std_logic_vector(log2_cache_pages_c+log2_cache_page_size_c-1 downto 0); -- cache instr. word address
+ signal CACHE_I_ADR : std_logic_vector(log2_cache_pages_c+log2_cache_page_size_c-1 downto 0); -- cache data word address
+ signal CA_ADR_BUF, CA_ADR_BUF_NXT : std_logic_vector(log2_cache_pages_c+log2_cache_page_size_c-1 downto 0); -- word address cache adr buffer
+ signal CACHE_DR_DATA : std_logic_vector(data_width_c-1 downto 0); -- cache read data (processor/bus unit)
+ signal CACHE_DW_DATA : std_logic_vector(data_width_c-1 downto 0); -- cache write data (processor/bus unit)
+ signal CACHE_I_MISS, CACHE_D_MISS : std_logic; -- miss during instruction/data access -- I/D miss access
+ signal VALID_FLAG, VALID_FLAG_NXT : std_logic_vector(cache_pages_c-1 downto 0); -- page valid flag
+ signal DIRTY_FLAG, DIRTY_FLAG_NXT : std_logic_vector(cache_pages_c-1 downto 0); -- page dirty flag
+
+ -- Page Selector --
+ type page_base_type is array(0 to cache_pages_c-1) of std_logic_vector(bus_adr_width_c-1 downto log2_cache_page_size_c+align_lsb_c);
+ signal PAGE_BASE_ADR : page_base_type := (others => (others => '0')); -- page base address
+ signal PAGE_BASE_ADR_NXT : page_base_type := (others => (others => '0')); -- page base address
+ signal I_PAGE_SELECT, D_PAGE_SELECT : std_logic_vector(log2_cache_pages_c-1 downto 0); -- page translator output
+ signal I_PAGE_BUF, I_PAGE_BUF_NXT : std_logic_vector(log2_cache_pages_c-1 downto 0); -- last accessed i-page
+ signal D_PAGE_BUF, D_PAGE_BUF_NXT : std_logic_vector(log2_cache_pages_c-1 downto 0); -- last accessed d-page
+ signal NEW_ENTRY_PAGE : std_logic_vector(log2_cache_pages_c-1 downto 0); -- new cache enty address
+ signal CACHE_SYNC : std_logic; -- cache is sync
+
+ -- Wishbone Bus --
+ signal WB_ADR_BUF, WB_ADR_BUF_NXT : std_logic_vector(bus_adr_width_c-1 downto 0); -- bus address
+ signal WB_CYC_BUF, WB_CYC_BUF_NXT : std_logic; -- valid cycle
+ signal WB_STB_BUF, WB_STB_BUF_NXT : std_logic; -- strobe
+ signal WB_ACK_BUF : std_logic; -- ack signal buffer
+ signal WB_DO_BUF, WB_DO_BUF_NXT : std_logic_vector(data_width_c-1 downto 0); -- data out
+ signal WB_DI_BUF : std_logic_vector(data_width_c-1 downto 0); -- data in
+ signal WB_ACK_CNT, WB_ACK_CNT_NXT : std_logic_vector(log2_cache_page_size_c downto 0); -- ack counter
+
+begin
+
+ -- Control Arbiter (Sync) ------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ ARBITER_SYNC: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ -- Arbiter --
+ ARB_STATE <= IDLE;
+ RET_STATE <= IDLE;
+ BUS_DIR <= DOWN;
+ PAGE_PNT <= (others => '0');
+ TYPE_FLAG <= '0';
+ FREEZE_FLAG <= '0';
+ WB_ACK_CNT <= (others => '0');
+ D_ACC_BUF <= (others => '0');
+ I_ACC_BUF <= (others => '0');
+ TIMEOUT_CNT <= (others => '0');
+ SYNC_CNT <= (others => '0');
+ DATA_CNT <= (others => '0');
+ DA_RB_FF <= '0';
+
+ -- Processor --
+ MEM_REQ_FF <= '0';
+ MEM_REQ_FF_FF <= '0';
+ D_ACC_DAT_BUF <= (others => '0');
+ INST_EN_FF <= '0';
+
+ -- Cache --
+ CA_ADR_BUF <= (others => '0');
+ VALID_FLAG <= (others => '0');
+ DIRTY_FLAG <= (others => '0');
+ PAGE_BASE_ADR <= (others => (others => '0'));
+ D_PAGE_BUF <= (others => '0');
+ I_PAGE_BUF <= (others => '0');
+
+ -- Wishbone Bus --
+ WB_ADR_BUF <= (others => '0');
+ WB_DI_BUF <= (others => '0');
+ WB_DO_BUF <= (others => '0');
+ WB_CYC_BUF <= '0';
+ WB_STB_BUF <= '0';
+ WB_ACK_BUF <= '0';
+
+ else
+ if (WB_HALT_I = '0') then -- this is where we freeze it all
+ -- Arbiter --
+ ARB_STATE <= ARB_STATE_NXT;
+ RET_STATE <= RET_STATE_NXT;
+ BUS_DIR <= BUS_DIR_NXT;
+ PAGE_PNT <= PAGE_PNT_NXT;
+ TYPE_FLAG <= TYPE_FLAG_NXT;
+ FREEZE_FLAG <= FREEZE_FLAG_NXT;
+ WB_ACK_CNT <= WB_ACK_CNT_NXT;
+ TIMEOUT_CNT <= TIMEOUT_CNT_NXT;
+ SYNC_CNT <= SYNC_CNT_NXT;
+ DATA_CNT <= DATA_CNT_NXT;
+ DA_RB_FF <= DA_RB_FF_NXT;
+
+ -- Processor --
+ if (FREEZE_FLAG = '0') then
+ I_ACC_BUF <= INSTR_ADR_I;
+ D_ACC_BUF <= MEM_ADR_I;
+ D_ACC_DAT_BUF <= MEM_DAT_I;
+ MEM_REQ_FF <= MEM_REQ_I;
+ MEM_REQ_FF_FF <= MEM_REQ_FF;
+ INST_EN_FF <= INSTR_EN_I;
+ end if;
+
+ -- Cache --
+ CA_ADR_BUF <= CA_ADR_BUF_NXT;
+ VALID_FLAG <= VALID_FLAG_NXT;
+ DIRTY_FLAG <= DIRTY_FLAG_NXT;
+ PAGE_BASE_ADR <= PAGE_BASE_ADR_NXT;
+ D_PAGE_BUF <= D_PAGE_BUF_NXT;
+ I_PAGE_BUF <= I_PAGE_BUF_NXT;
+
+ -- Wishbone Bus --
+ WB_ADR_BUF <= WB_ADR_BUF_NXT;
+ WB_DI_BUF <= WB_DATA_I;
+ WB_DO_BUF <= WB_DO_BUF_NXT;
+ WB_CYC_BUF <= WB_CYC_BUF_NXT;
+ WB_STB_BUF <= WB_STB_BUF_NXT;
+ WB_ACK_BUF <= WB_ACK_I;
+ end if;
+ end if;
+ end if;
+ end process ARBITER_SYNC;
+
+ -- Processor Output --
+ HALT_O <= FREEZE_FLAG;
+
+ -- Sync Bus Output --
+ WB_ADR_O <= WB_ADR_BUF;
+ WB_DATA_O <= WB_DO_BUF;
+ WB_CYC_O <= WB_CYC_BUF;
+ WB_STB_O <= WB_STB_BUF;
+
+
+
+ -- Control Arbiter (Async) -----------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ ARBITER_ASYNC: process(ARB_STATE, RET_STATE, DATA_CNT, PAGE_PNT, WB_ACK_CNT, D_PAGE_SELECT, DA_RB_FF, I_PAGE_SELECT, TYPE_FLAG, NEW_ENTRY_PAGE, PAGE_BASE_ADR, BUS_DIR, TIMEOUT_CNT, SYNC_CNT, -- arbiter signals
+ SYS_MODE_I, MEM_REQ_FF, MEM_REQ_FF_FF, MEM_ADR_I, MEM_DAT_I, MEM_RW_I, INST_EN_FF, INSTR_ADR_I, D_ACC_DAT_BUF, FREEZE_FLAG, I_ACC_BUF, D_ACC_BUF, DIR_DAT_REQ, INSTR_EN_I, CLR_CACHE_I, FLUSH_CACHE_I, -- processor signals
+ CACHE_I_MISS, CACHE_D_MISS, CACHE_DR_DATA, CA_ADR_BUF, VALID_FLAG, DIRTY_FLAG, PAGE_BASE_ADR, D_PAGE_BUF, I_PAGE_BUF, CACHE_SYNC, -- cache signals
+ WB_ADR_BUF, WB_CYC_BUF, WB_STB_BUF, WB_ACK_I, WB_ACK_BUF, WB_DI_BUF, WB_DO_BUF) -- bus signals
+ variable modified_page_v : std_logic; -- assigned page is valid and dirty
+ begin
+ -- Arbiter Defaults --
+ ARB_STATE_NXT <= ARB_STATE; -- arbiter state
+ RET_STATE_NXT <= RET_STATE; -- return state
+ PAGE_PNT_NXT <= PAGE_PNT; -- page pointer
+ BUS_DIR_NXT <= BUS_DIR; -- transfer direction
+ DATA_CNT_NXT <= DATA_CNT; -- transferred data counter
+ WB_ACK_CNT_NXT <= (others => '0'); -- bus acknowledge counte
+ TYPE_FLAG_NXT <= TYPE_FLAG; -- transfer type
+ FREEZE_FLAG_NXT <= FREEZE_FLAG; -- disable cpu flag
+ DA_RB_FF_NXT <= '0'; -- direct access readback flag
+ SYNC_CNT_NXT <= "00"; -- sync counter
+
+ -- Cache Defaults --
+ PAGE_BASE_ADR_NXT <= PAGE_BASE_ADR; -- cache pages base address
+ CA_ADR_BUF_NXT <= CA_ADR_BUF; -- cache address
+ D_PAGE_BUF_NXT <= D_PAGE_BUF; -- last accessed D page
+ I_PAGE_BUF_NXT <= I_PAGE_BUF; -- last accessed I page
+ modified_page_v := DIRTY_FLAG_NXT(to_integer(unsigned(PAGE_PNT))) and VALID_FLAG_NXT(to_integer(unsigned(PAGE_PNT))); -- current page is dirty and valid
+
+ -- Status Flags --
+ VALID_FLAG_NXT <= VALID_FLAG; -- valid cache page
+ DIRTY_FLAG_NXT <= DIRTY_FLAG; -- modified cache page
+
+ -- Bus monitoring --
+ TIMEOUT_CNT_NXT <= (others => '0'); -- bus timeout
+ ERROR_O <= '0';
+
+ -- Wishbone Bus Defaults --
+ WB_ADR_BUF_NXT <= WB_ADR_BUF; -- address
+ WB_DO_BUF_NXT <= WB_DO_BUF; -- data out
+ WB_STB_BUF_NXT <= '0'; -- strobe data
+ WB_CYC_BUF_NXT <= WB_CYC_BUF; -- valid cycle
+ WB_SEL_O <= (others => '1'); -- full word transfer quantity
+
+ -- Wishbone Bus Static Defaults --
+ WB_CTI_O <= wb_classic_cyc_c;
+ WB_TGC_O <= "00" & SYS_MODE_I; -- cycle tag
+ if (BUS_DIR = UP) and (ARB_STATE /= IDLE) then -- download/upload
+ WB_WE_O <= '1'; -- bus write
+ else
+ WB_WE_O <= '0'; -- bus read
+ end if;
+
+ -- Static D-Cache Access --
+ CACHE_D_ADR <= D_PAGE_SELECT & MEM_ADR_I(log2_cache_page_size_c downto align_lsb_c); -- word address
+ CACHE_EN <= '0';
+ CACHE_DW_DATA <= MEM_DAT_I;
+ CACHE_RW <= MEM_RW_I;
+ MEM_DAT_O <= CACHE_DR_DATA;
+
+ -- Static I-Cache Access --
+ CACHE_I_ADR <= I_PAGE_SELECT & INSTR_ADR_I(log2_cache_page_size_c downto align_lsb_c); -- word address
+ I_UPDATE <= '0';
+
+ -- State Machine --
+ case (ARB_STATE) is
+
+ when IDLE => -- waiting for requests
+ -------------------------------------------------------------------------------
+ -- Static D-Cache Access --
+ CACHE_EN <= MEM_REQ_FF and (not DIR_DAT_REQ) and (not CACHE_D_MISS); -- no cache access for direct requests
+ D_PAGE_BUF_NXT <= D_PAGE_SELECT; -- last accessed page
+ if (DA_RB_FF = '1') then -- load data from direct access
+ MEM_DAT_O <= WB_DI_BUF;
+ end if;
+
+ -- Static I-Cache Access --
+ I_UPDATE <= INSTR_EN_I;
+ I_PAGE_BUF_NXT <= I_PAGE_SELECT; -- last accessed page
+
+ -- Modified Cache Page --
+ if ((MEM_RW_I and MEM_REQ_FF) = '1') and (CACHE_D_MISS = '0') and (DIR_DAT_REQ = '0') then
+ DIRTY_FLAG_NXT(to_integer(unsigned(D_PAGE_SELECT))) <= '1'; -- page is dirty now
+ end if;
+
+ -- Resync cache with memory --
+ if (CLR_CACHE_I = '1') then
+ VALID_FLAG_NXT <= (others => '0'); -- invalidate all pages
+ DIRTY_FLAG_NXT <= (others => '0'); -- invalidate all pages
+ end if;
+
+ -- Page pointer --
+ PAGE_PNT_NXT <= NEW_ENTRY_PAGE;
+
+ -- Transfer direction --
+ if (MEM_RW_I = '1') then
+ BUS_DIR_NXT <= UP;
+ else
+ BUS_DIR_NXT <= DOWN;
+ end if;
+
+ -- Conflict Detector --
+ if ((MEM_REQ_FF and DIR_DAT_REQ) = '1') then -- direct access
+ ARB_STATE_NXT <= DIRECT_ACCESS;
+ FREEZE_FLAG_NXT <= '1';
+ WB_CYC_BUF_NXT <= '1';
+ WB_STB_BUF_NXT <= '1';
+ WB_ADR_BUF_NXT <= MEM_ADR_I; -- direct address output
+ WB_DO_BUF_NXT <= MEM_DAT_I; -- direct data output
+ elsif (CACHE_I_MISS = '1') then -- instruction miss access
+ ARB_STATE_NXT <= ANALYSE;
+ FREEZE_FLAG_NXT <= '1';
+ TYPE_FLAG_NXT <= '1';
+ elsif (CACHE_D_MISS = '1') then -- data miss access
+ ARB_STATE_NXT <= ANALYSE;
+ FREEZE_FLAG_NXT <= '1';
+ TYPE_FLAG_NXT <= '0';
+ elsif (FLUSH_CACHE_I = '1') then -- resync memory with cache
+ ARB_STATE_NXT <= FLUSH;
+ PAGE_PNT_NXT <= (others => '0');
+ FREEZE_FLAG_NXT <= '1';
+ TYPE_FLAG_NXT <= '0';
+ end if;
+
+
+ when ANALYSE => -- is the to be replaced page dirty?
+ -------------------------------------------------------------------------------
+ -- Clear data counter --
+ DATA_CNT_NXT <= (others => '0');
+
+ -- Update cache base address (word!) --
+ CA_ADR_BUF_NXT <= (others => '0');
+ CA_ADR_BUF_NXT(log2_cache_pages_c+log2_cache_page_size_c-1 downto log2_cache_page_size_c) <= PAGE_PNT;
+
+ -- Prepare transfer operation --
+ ARB_STATE_NXT <= TRANSFER_PAGE;
+ RET_STATE_NXT <= ANALYSE;
+ WB_CYC_BUF_NXT <= '1';
+
+ -- Upload modified page? --
+ if (modified_page_v = '1') then
+ BUS_DIR_NXT <= UP; -- upload modified page
+ WB_STB_BUF_NXT <= '0';
+ WB_ADR_BUF_NXT <= (others => '0');
+ WB_ADR_BUF_NXT(bus_adr_width_c-1 downto log2_cache_page_size_c+1) <= PAGE_BASE_ADR(to_integer(unsigned(PAGE_PNT)));
+ else -- download new page
+ BUS_DIR_NXT <= DOWN; -- download new page
+ WB_STB_BUF_NXT <= '1';
+ if (TYPE_FLAG = '1') then -- new instruction page
+ WB_ADR_BUF_NXT <= I_ACC_BUF;
+ WB_ADR_BUF_NXT(log2_cache_page_size_c downto 0) <= (others => '0');
+ else -- new data page
+ WB_ADR_BUF_NXT <= D_ACC_BUF;
+ WB_ADR_BUF_NXT(log2_cache_page_size_c downto 0) <= (others => '0');
+ end if;
+ end if;
+
+
+ when FLUSH => -- synchronize cache -> mem (dirty pages writeback)
+ -------------------------------------------------------------------------------
+ -- Clear data counter --
+ DATA_CNT_NXT <= (others => '0');
+
+ -- Cache base address (word!) --
+ CA_ADR_BUF_NXT <= (others => '0');
+ CA_ADR_BUF_NXT(log2_cache_pages_c+log2_cache_page_size_c-1 downto log2_cache_page_size_c) <= PAGE_PNT;
+
+ -- Prepare transfer operation --
+ BUS_DIR_NXT <= UP; -- upload modified page
+ RET_STATE_NXT <= FLUSH;
+ WB_CYC_BUF_NXT <= '1';
+ WB_ADR_BUF_NXT <= (others => '0');
+ WB_ADR_BUF_NXT(bus_adr_width_c-1 downto log2_cache_page_size_c+1) <= PAGE_BASE_ADR(to_integer(unsigned(PAGE_PNT))); -- base address
+
+ -- Page dirty? --
+ if (CACHE_SYNC = '1') then -- cache is sync -> nothing to do
+ ARB_STATE_NXT <= RE_SYNC_1;
+ elsif (modified_page_v = '1') then -- need upload?
+ ARB_STATE_NXT <= TRANSFER_PAGE;
+ WB_STB_BUF_NXT <= '0';
+ else
+ PAGE_PNT_NXT <= std_logic_vector(unsigned(PAGE_PNT) + 1);
+ end if;
+
+
+ when TRANSFER_PAGE => -- upload/download page
+ -------------------------------------------------------------------------------
+ -- Static D-Cache Access --
+ CACHE_D_ADR <= CA_ADR_BUF;
+ CACHE_DW_DATA <= WB_DI_BUF;
+ WB_DO_BUF_NXT <= CACHE_DR_DATA;
+ if (BUS_DIR = DOWN) then
+ CACHE_RW <= '1';
+ else
+ CACHE_RW <= '0';
+ end if;
+
+ -- Sync control --
+ SYNC_CNT_NXT <= SYNC_CNT(0) & '1';
+
+ -- Bus control --
+ WB_CTI_O <= wb_inc_bst_cyc_c;
+
+ -- Update Base Address --
+ PAGE_BASE_ADR_NXT(to_integer(unsigned(PAGE_PNT))) <= WB_ADR_BUF(bus_adr_width_c-1 downto log2_cache_page_size_c+1); -- new/old base address
+
+ -- ACK Counter --
+ if (WB_ACK_I = '1') then
+ WB_ACK_CNT_NXT <= std_logic_vector(unsigned(WB_ACK_CNT) + 1);
+ end if;
+
+ -- Transfer --
+ if (BUS_DIR = DOWN) then -- download page
+ -- ------------------------------------------
+ CACHE_RW <= '1'; -- write to cache
+ -- Update Bus Address --
+ if (to_integer(unsigned(DATA_CNT)) < cache_page_size_c-1) then
+ WB_ADR_BUF_NXT <= std_logic_vector(unsigned(WB_ADR_BUF) + data_bytes_c); -- inc bus address pointer
+ DATA_CNT_NXT <= std_logic_vector(unsigned(DATA_CNT) + 1); -- inc data counter
+ WB_STB_BUF_NXT <= '1'; -- strobe data
+ else
+ WB_CTI_O <= wb_end_cyc_cyc_c;
+ WB_STB_BUF_NXT <= '0'; -- no more new strobes
+ end if;
+ -- Accept Data --
+ if (WB_ACK_BUF = '1') then
+ CACHE_EN <= '1'; -- enable data write to cache
+ CA_ADR_BUF_NXT <= std_logic_vector(unsigned(CA_ADR_BUF) + 1); -- inc cache address pointer
+ end if;
+ else -- upload page
+ -- ------------------------------------------
+ CACHE_RW <= '0'; -- read from cache
+ -- Update Bus & Cache Address --
+ if (to_integer(unsigned(DATA_CNT)) /= cache_page_size_c-1) then
+ if (SYNC_CNT(1) = '1') then -- cycle delay
+ WB_ADR_BUF_NXT <= std_logic_vector(unsigned(WB_ADR_BUF) + data_bytes_c); -- inc bus address pointer
+ DATA_CNT_NXT <= std_logic_vector(unsigned(DATA_CNT) + 1); -- inc data counter
+ end if;
+ WB_STB_BUF_NXT <= SYNC_CNT(0);
+ CACHE_EN <= '1'; -- enable data read from cache
+ CA_ADR_BUF_NXT <= std_logic_vector(unsigned(CA_ADR_BUF) + 1); -- inc cache address pointer
+ else
+ WB_CTI_O <= wb_end_cyc_cyc_c;
+ WB_STB_BUF_NXT <= '0'; -- no more new strobes
+ end if;
+ end if;
+
+ -- Wait for all ACKs --
+ if (to_integer(unsigned(WB_ACK_CNT)) = cache_page_size_c) then
+ WB_CYC_BUF_NXT <= '0'; -- terminate cycle
+ if (BUS_DIR = DOWN) then
+ ARB_STATE_NXT <= RE_SYNC_1; -- yeay, transfer completed!
+ VALID_FLAG_NXT(to_integer(unsigned(PAGE_PNT))) <= '1'; -- page is valid now
+ if (TYPE_FLAG = '1') then
+ I_PAGE_BUF_NXT <= PAGE_PNT;
+ else
+ D_PAGE_BUF_NXT <= PAGE_PNT;
+ end if;
+ else
+ ARB_STATE_NXT <= RET_STATE; -- upload complete, redo download
+ DIRTY_FLAG_NXT(to_integer(unsigned(PAGE_PNT))) <= '0'; -- page is sync now
+ end if;
+ end if;
+
+ -- Timeout --
+ if (WB_ACK_I = '1') then
+ TIMEOUT_CNT_NXT <= (others => '0');
+ else
+ TIMEOUT_CNT_NXT <= std_logic_vector(unsigned(TIMEOUT_CNT)+1); -- timeout counter
+ end if;
+ if (to_integer(unsigned(TIMEOUT_CNT)) > max_bus_latency_c) then
+ ARB_STATE_NXT <= RE_SYNC_1;
+ ERROR_O <= '1'; -- error!
+ end if;
+
+
+ when DIRECT_ACCESS => -- direct memory access
+ -------------------------------------------------------------------------------
+ -- Data flow --
+ WB_CTI_O <= wb_classic_cyc_c;
+ if (WB_ACK_I = '1') then
+ ARB_STATE_NXT <= IDLE;
+ FREEZE_FLAG_NXT <= '0';
+ WB_CYC_BUF_NXT <= '0';
+ WB_STB_BUF_NXT <= '0';
+ end if;
+ if (BUS_DIR = DOWN) then
+ DA_RB_FF_NXT <= '1'; -- load data in next cycle
+ end if;
+
+ -- I- Cache Resync --
+ I_UPDATE <= INST_EN_FF;
+ CACHE_I_ADR <= I_PAGE_BUF & I_ACC_BUF(log2_cache_page_size_c downto align_lsb_c);
+
+ -- Timeout --
+ if (WB_ACK_I = '1') then
+ TIMEOUT_CNT_NXT <= (others => '0');
+ else
+ TIMEOUT_CNT_NXT <= std_logic_vector(unsigned(TIMEOUT_CNT)+1); -- timeout counter
+ end if;
+ if (to_integer(unsigned(TIMEOUT_CNT)) > max_bus_latency_c) then
+ ARB_STATE_NXT <= IDLE;
+ ERROR_O <= '1'; -- error!
+ end if;
+
+
+ when RE_SYNC_1 => -- re-synchronize instruction/data fetch
+ -------------------------------------------------------------------------------
+ -- D-Read Access --
+ CACHE_RW <= '0';
+ CACHE_EN <= '1';
+ CACHE_D_ADR <= D_PAGE_BUF & D_ACC_BUF(log2_cache_page_size_c downto align_lsb_c);
+
+ -- Arbiter --
+ ARB_STATE_NXT <= RE_SYNC_2;
+
+
+ when RE_SYNC_2 => -- re-synchronize instruction/data fetch
+ -------------------------------------------------------------------------------
+ -- I-Access --
+ I_UPDATE <= INST_EN_FF;
+ CACHE_I_ADR <= I_PAGE_BUF & I_ACC_BUF(log2_cache_page_size_c downto align_lsb_c);
+
+ -- D-Write Access --
+ CACHE_RW <= '1';
+ CACHE_EN <= MEM_REQ_FF_FF;
+ CACHE_D_ADR <= D_PAGE_BUF & D_ACC_BUF(log2_cache_page_size_c downto align_lsb_c);
+ CACHE_DW_DATA <= D_ACC_DAT_BUF;
+
+ -- Arbiter --
+ ARB_STATE_NXT <= IDLE;
+ FREEZE_FLAG_NXT <= '0';
+
+ end case;
+ end process ARBITER_ASYNC;
+
+
+
+ -- New Entry Address Generator -------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ PAGE_RANDOM_GEN: process(CLK_I)
+ begin
+ -- Sync Update --
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ RND_GEN <= (others => '0');
+ else--if (FREEZE_FLAG = '0') and (ARB_STATE = IDLE) then
+ RND_GEN <= RND_GEN(4 downto 0) & (RND_GEN(5) xnor RND_GEN(4));
+ end if;
+ end if;
+ end process PAGE_RANDOM_GEN;
+
+ -- Output --
+ NEW_ENTRY_PAGE <= RND_GEN(log2_cache_pages_c-1 downto 0);
+
+
+ -- HIT / MISS Detector and Page Translator -------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ CONTENT_DETECTOR: process(INSTR_ADR_I, MEM_ADR_I, PAGE_BASE_ADR, VALID_FLAG, INSTR_EN_I, MEM_REQ_FF, DIRTY_FLAG)
+ variable i_hit_v, d_hit_v, sync_v : std_logic;
+ begin
+ -- Instruction access --
+ i_hit_v := '0';
+ I_PAGE_SELECT <= (others => '0');
+ for i in 0 to cache_pages_c-1 loop
+ if (PAGE_BASE_ADR(i) = INSTR_ADR_I(bus_adr_width_c-1 downto log2_cache_page_size_c+align_lsb_c)) and (VALID_FLAG(i) = '1') then
+ I_PAGE_SELECT <= std_logic_vector(to_unsigned(i, log2_cache_pages_c));
+ i_hit_v := '1';
+ exit;
+ end if;
+ end loop;
+ CACHE_I_MISS <= (not i_hit_v) and INSTR_EN_I; -- valid insruction fetch
+
+ -- Data access --
+ d_hit_v := '0';
+ D_PAGE_SELECT <= (others => '0');
+ for j in 0 to cache_pages_c-1 loop
+ if (PAGE_BASE_ADR(j) = MEM_ADR_I(bus_adr_width_c-1 downto log2_cache_page_size_c+align_lsb_c)) and (VALID_FLAG(j) = '1') then
+ D_PAGE_SELECT <= std_logic_vector(to_unsigned(j, log2_cache_pages_c));
+ d_hit_v := '1';
+ exit;
+ end if;
+ end loop;
+ CACHE_D_MISS <= (not d_hit_v) and MEM_REQ_FF; -- valid access
+
+ -- Sync detector --
+ sync_v := '1';
+ for k in 0 to cache_pages_c-1 loop
+ if (VALID_FLAG(k) = '1') then
+ sync_v := sync_v and (not DIRTY_FLAG(k));
+ else
+ sync_v := sync_v;
+ end if;
+ end loop;
+ CACHE_SYNC <= sync_v;
+ CACHE_SYNC_O <= sync_v;
+ end process CONTENT_DETECTOR;
+
+ -- Direct Data Request --
+ DIR_DAT_REQ <= '1' when ((unsigned(MEM_ADR_I) >= unsigned(UC_AREA_BEGIN_G)) and (unsigned(MEM_ADR_I) <= unsigned(UC_AREA_END_G))) or (DIR_ACC_I = '1') else '0';
+
+
+
+ -- Cache Memory Access ---------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ CACHE_MEM_ACCESS: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (CACHE_EN = '1') then -- valid data access
+ if (CACHE_RW = '1') then -- cache data write access
+ CACHE_MEM(to_integer(unsigned(CACHE_D_ADR(log2_cache_pages_c+log2_cache_page_size_c-1 downto 0)))) <= CACHE_DW_DATA; -- word address!
+ else -- cache data read access
+ CACHE_DR_DATA <= CACHE_MEM(to_integer(unsigned(CACHE_D_ADR(log2_cache_pages_c+log2_cache_page_size_c-1 downto 0)))); -- word address!
+ end if;
+ end if;
+ if (I_UPDATE = '1') then -- cache instruction read access
+ INSTR_DAT_O <= CACHE_MEM(to_integer(unsigned(CACHE_I_ADR(log2_cache_pages_c+log2_cache_page_size_c-1 downto 0)))); -- word address!
+ end if;
+ end if;
+ end process CACHE_MEM_ACCESS;
+
+
+
+end BUS_INTERFACE_STRUCTURE;
\ No newline at end of file
Index: atlas_core/trunk/core/rtl/OP_DEC.vhd
===================================================================
--- atlas_core/trunk/core/rtl/OP_DEC.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/OP_DEC.vhd (revision 2)
@@ -0,0 +1,452 @@
+-- ########################################################
+-- # << ATLAS Project - OpCode Decoder >> #
+-- # **************************************************** #
+-- # OpCode decoding unit. #
+-- # **************************************************** #
+-- # Last modified: 12.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity OP_DEC is
+ port (
+-- ###############################################################################################
+-- ## Decoder Interface Input ##
+-- ###############################################################################################
+
+ INSTR_I : in std_logic_vector(data_width_c-1 downto 0); -- instruction input
+ T_FLAG_I : in std_logic; -- T-Flag input
+ M_FLAG_I : in std_logic; -- Mode flag input
+ MULTI_CYC_I : in std_logic; -- multi-cycle indicator
+ CP_PTC_I : in std_logic; -- user coprocessor protection
+
+-- ###############################################################################################
+-- ## Decoder Interface Output ##
+-- ###############################################################################################
+
+ MULTI_CYC_REQ_O : out std_logic; -- multi-cycle reqest
+ CTRL_O : out std_logic_vector(ctrl_width_c-1 downto 0); -- decoder ctrl lines
+ IMM_O : out std_logic_vector(data_width_c-1 downto 0) -- immediate
+ );
+end OP_DEC;
+
+architecture OP_DEC_STRUCTURE of OP_DEC is
+
+ -- aligned instruction --
+ signal INSTR_INT : std_logic_vector(15 downto 0);
+
+begin
+
+ -- Endianness Converter --------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ END_CONV: process(INSTR_I)
+ begin
+ if (big_endian_c = true) then
+ INSTR_INT <= INSTR_I(data_width_c/2-1 downto 0) & INSTR_I(data_width_c-1 downto data_width_c/2);
+ else
+ INSTR_INT <= INSTR_I;
+ end if;
+ end process END_CONV;
+
+
+
+ -- Opcode Decoder --------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ OPCODE_DECODER: process(INSTR_INT, MULTI_CYC_I, T_FLAG_I, M_FLAG_I, CP_PTC_I)
+ variable mem_acc_temp_v : std_logic_vector(3 downto 0);
+ begin
+
+ -- defaults --
+ IMM_O <= (others => '0'); -- zero immediate
+ MULTI_CYC_REQ_O <= '0'; -- no multi-cycle operation
+ CTRL_O <= (others => '0'); -- all signals disabled
+ CTRL_O(ctrl_en_c) <= '1'; -- but we're enabled ^^
+ CTRL_O(ctrl_cp_id_c) <= INSTR_INT(10); -- coprocessor ID
+ CTRL_O(ctrl_ra_3_c downto ctrl_ra_0_c) <= M_FLAG_I & INSTR_INT(06 downto 04); -- operand A register
+ CTRL_O(ctrl_rb_3_c downto ctrl_rb_0_c) <= M_FLAG_I & INSTR_INT(02 downto 00); -- operand B register
+ CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & INSTR_INT(09 downto 07); -- destination register
+ CTRL_O(ctrl_bit_3_c downto ctrl_bit_0_c) <= INSTR_INT(03 downto 00); -- bit address
+ CTRL_O(ctrl_cond_3_c downto ctrl_cond_0_c) <= INSTR_INT(13 downto 10); -- branch condition
+
+ -- decoder --
+ case (INSTR_INT(15 downto 14)) is
+
+ when "00" => -- Class 0: ALU data processing // Bank / PC / MSR transfer
+ -- ==============================================================================
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow write back
+ CTRL_O(ctrl_fupdate_c) <= INSTR_INT(3); -- flag update
+ IMM_O(2 downto 0) <= INSTR_INT(2 downto 0); -- 3-bit immediate
+ if (INSTR_INT(13 downto 10) = fs_inc_c) or (INSTR_INT(13 downto 10) = fs_dec_c) or (INSTR_INT(13 downto 10) = fs_sft_c) then
+ CTRL_O(ctrl_rb_is_imm_c) <= '1'; -- yes, this is an immediate
+ end if;
+ -- mapping to alu elementary operation --
+ case (INSTR_INT(13 downto 10)) is
+
+ when fs_orr_c => -- logical or // load from user bank register if redundant
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_orr_c; -- logical or
+ if (INSTR_INT(06 downto 04) = INSTR_INT(02 downto 00)) then -- user bank load
+ CTRL_O(ctrl_ra_3_c) <= user_mode_c; -- load from user bank
+ CTRL_O(ctrl_rb_3_c) <= user_mode_c; -- load from user bank
+ if (M_FLAG_I = user_mode_c) then -- unauthorized access
+ CTRL_O(ctrl_syscall_c) <= '1'; -- access violation
+ end if;
+ end if;
+
+ when fs_and_c => -- logical and // store to user bank register if redundant
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_and_c; -- logical and
+ if (INSTR_INT(06 downto 04) = INSTR_INT(02 downto 00)) then -- user bank store
+ CTRL_O(ctrl_rd_3_c) <= user_mode_c; -- store to user bank
+ if (M_FLAG_I = user_mode_c) then -- unauthorized access
+ CTRL_O(ctrl_syscall_c) <= '1'; -- access violation
+ end if;
+ end if;
+
+ when fs_cmp_c => -- compare by sbtraction // load from msr if s = 0
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_sbc_c; -- compare by subtraction
+ CTRL_O(ctrl_rd_wb_c) <= '0'; -- disable write back
+ --CTRL_O(ctrl_msr_am_1_c) <= INSTR_INT(6); -- not needed, redundant assignment!
+ --CTRL_O(ctrl_msr_am_0_c) <= INSTR_INT(5); -- not needed, redundant assignment!
+ if (INSTR_INT(3) = '0') then -- load from MSR
+ if (INSTR_INT(6 downto 5) /= "11") and (M_FLAG_I = user_mode_c) then
+ CTRL_O(ctrl_syscall_c) <= '1'; -- is system call
+ end if;
+ CTRL_O(ctrl_msr_rd_c) <= '1'; -- read msr
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- re-enable write back
+ end if;
+
+ when fs_cpx_c => -- extended compare with flags // store to msr if s = 0
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_sbc_c; -- compare by subtraction with flags
+ CTRL_O(ctrl_alu_usec_c) <= '1'; -- use carry input
+ CTRL_O(ctrl_alu_usez_c) <= '1'; -- use zero input
+ CTRL_O(ctrl_rd_wb_c) <= '0'; -- disable write back
+ --CTRL_O(ctrl_msr_am_1_c) <= INSTR_INT(6); -- not needed, redundant assignment!
+ --CTRL_O(ctrl_msr_am_0_c) <= INSTR_INT(5); -- not needed, redundant assignment!
+ if (INSTR_INT(5) = '1') then -- write system ALU flags
+ IMM_O(msr_sys_z_flag_c) <= INSTR_INT(0);
+ IMM_O(msr_sys_c_flag_c) <= INSTR_INT(1);
+ IMM_O(msr_sys_o_flag_c) <= INSTR_INT(2);
+ IMM_O(msr_sys_n_flag_c) <= INSTR_INT(7);
+ IMM_O(msr_sys_t_flag_c) <= INSTR_INT(8);
+ else -- write user ALU flags
+ IMM_O(msr_usr_z_flag_c) <= INSTR_INT(0);
+ IMM_O(msr_usr_c_flag_c) <= INSTR_INT(1);
+ IMM_O(msr_usr_o_flag_c) <= INSTR_INT(2);
+ IMM_O(msr_usr_n_flag_c) <= INSTR_INT(7);
+ IMM_O(msr_usr_t_flag_c) <= INSTR_INT(8);
+ end if;
+ if (INSTR_INT(3) = '0') then -- store to MSR
+ if ((M_FLAG_I = user_mode_c) and (INSTR_INT(6 downto 5) /= "11")) or
+ ((M_FLAG_I = system_mode_c) and (INSTR_INT(6) = '1') and (INSTR_INT(4) = '1')) then
+ CTRL_O(ctrl_syscall_c) <= '1'; -- access violation
+ end if;
+ if(MULTI_CYC_I = '0') then
+ CTRL_O(ctrl_msr_wr_c) <= '1'; -- write msr
+ MULTI_CYC_REQ_O <= '1'; -- we need a dummy cycle afterwards
+ if (INSTR_INT(4) = '1') then -- store immediate
+ CTRL_O(ctrl_rb_is_imm_c) <= '1'; -- yes, this is an immediate
+ end if;
+ else
+ CTRL_O(ctrl_en_c) <= '0'; -- insert empty cycle
+ end if;
+ end if;
+
+ when fs_tst_c => -- compare by logical xor // load from pc if s = 0
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_eor_c; -- compare by logical xor
+ CTRL_O(ctrl_rd_wb_c) <= '0'; -- disable write back
+ if (INSTR_INT(3) = '0') then -- load from PC
+ CTRL_O(ctrl_ra_is_pc_c) <= '1'; -- read pc
+ CTRL_O(ctrl_rb_is_imm_c) <= INSTR_INT(3); -- this is an immediate
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- re-enable write back
+ end if;
+
+ when fs_teq_c => -- compare by logical and // store to pc if s = 0
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_and_c; -- compare by logical and
+ CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & link_reg_adr_c; -- link register
+ CTRL_O(ctrl_rd_wb_c) <= '0'; -- disable write back
+ if (INSTR_INT(3) = '0') then -- store to PC
+ if ((M_FLAG_I = user_mode_c) and (INSTR_INT(1 downto 0) /= "00")) then
+ CTRL_O(ctrl_syscall_c) <= '1'; -- access violation
+ end if;
+ CTRL_O(ctrl_pc_wr_c) <= '1'; -- write pc
+ CTRL_O(ctrl_rb_is_imm_c) <= '1'; -- this is an immediate
+ IMM_O <= (others => '1'); -- 1's mask
+ CTRL_O(ctrl_ctx_down_c) <= INSTR_INT(0); -- goto user mode when bit 0 = '1'
+ CTRL_O(ctrl_re_xint_c) <= INSTR_INT(1); -- re-enable global xint flag (redundant assignment here)
+ CTRL_O(ctrl_link_c) <= INSTR_INT(2); -- link
+ CTRL_O(ctrl_rd_wb_c) <= INSTR_INT(2); -- allow write back for linking
+ end if;
+
+ when fs_inc_c | fs_add_c => -- immediate addition // addition
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_adc_c;
+
+ when fs_dec_c | fs_sub_c => -- immediate subtraction // addition
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_sbc_c;
+
+ when fs_adc_c => -- addition with carry
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_adc_c;
+ CTRL_O(ctrl_alu_usec_c) <= '1'; -- use carry input
+
+ when fs_sbc_c => -- subtraction with carry
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_sbc_c;
+ CTRL_O(ctrl_alu_usec_c) <= '1'; -- use carry input
+
+ when fs_eor_c => -- logical xor
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_eor_c;
+
+ when fs_nand_c => -- logical not-and
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_nand_c;
+
+ when fs_bic_c => -- bit clear
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_bic_c;
+
+ when fs_sft_c => -- shift operation
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_sft_c;
+
+ when others => -- undefined
+ NULL; -- use defaults
+
+ end case;
+
+
+ when "01" => -- Class 1: Memory Access
+ -- ==============================================================================
+ IMM_O(2 downto 0) <= INSTR_INT(2 downto 0); -- immediate offset
+ if (INSTR_INT(12) = '1') then
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_adc_c; -- add index
+ else
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_sbc_c; -- sub index
+ end if;
+ mem_acc_temp_v := INSTR_INT(10) & INSTR_INT(3) & INSTR_INT(13) & INSTR_INT(11); -- L,I,P,W
+ case (mem_acc_temp_v) is
+
+ when "0000" | "0100" => -- load, imm/reg offset, pre, no wb
+ CTRL_O(ctrl_mem_acc_c) <= '1'; -- this is a memory access
+ CTRL_O(ctrl_rb_is_imm_c) <= INSTR_INT(3); -- this is an immediate
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow data write back
+
+ when "0001" | "0101" => -- load, imm/reg offset, pre, do wb
+ CTRL_O(ctrl_rb_is_imm_c) <= INSTR_INT(3); -- this is an immediate
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow data write back
+ if (MULTI_CYC_I = '0') then -- fist cycle: ADD/SUB R_base, R_base, Offset
+ CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & INSTR_INT(6 downto 4); -- base adr
+ MULTI_CYC_REQ_O <= '1'; -- prepare second cycle
+ else -- second cycle: LD R_data, [R_base]
+ CTRL_O(ctrl_mem_acc_c) <= '1'; -- this is a memory access
+ CTRL_O(ctrl_mem_bpba_c) <= '1'; -- use bypassed adr from prev cycle
+ end if;
+
+ when "0011" | "0111" => -- load, imm/reg offset, post, do wb
+ CTRL_O(ctrl_rb_is_imm_c) <= INSTR_INT(3); -- this is an immediate
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow data write back
+ if (MULTI_CYC_I = '0') then -- fist cycle: LD R_data, [R_base]
+ CTRL_O(ctrl_mem_acc_c) <= '1'; -- this is a memory access
+ CTRL_O(ctrl_mem_bpba_c) <= '1'; -- use bypassed adr from prev cycle
+ MULTI_CYC_REQ_O <= '1'; -- prepare second cycle
+ else -- second cycle: ADD/SUB R_base, R_base, Offset
+ CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & INSTR_INT(6 downto 4); -- base adr
+ end if;
+
+ when "1000" | "1001" => -- store, reg offset, pre, (no) wb
+ if (MULTI_CYC_I = '0') then -- fist cycle: ADD/SUB R_base, R_base, R_offset
+ CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & INSTR_INT(6 downto 4); -- base adr
+ CTRL_O(ctrl_rd_wb_c) <= INSTR_INT(11); -- write back base?
+ MULTI_CYC_REQ_O <= '1'; -- prepare second cycle
+ else -- second cycle: ST R_data, [R_base]
+ CTRL_O(ctrl_rb_3_c downto ctrl_rb_0_c) <= M_FLAG_I & INSTR_INT(9 downto 7); -- store data
+ CTRL_O(ctrl_mem_daa_c) <= '1'; -- use delayed adr from prev cycle
+ CTRL_O(ctrl_mem_acc_c) <= '1'; -- this is a memory access
+ CTRL_O(ctrl_mem_wr_c) <= '1'; -- write access
+ end if;
+
+ when "1011" => -- store, reg offset, post, do wb
+ if (MULTI_CYC_I = '0') then -- fist cycle: ST R_data, [R_base]
+ CTRL_O(ctrl_rb_3_c downto ctrl_rb_0_c) <= M_FLAG_I & INSTR_INT(9 downto 7); -- store data
+ CTRL_O(ctrl_mem_bpba_c) <= '1'; -- use bypassed adr from prev cycle
+ CTRL_O(ctrl_mem_acc_c) <= '1'; -- this is a memory access
+ CTRL_O(ctrl_mem_wr_c) <= '1'; -- write access
+ MULTI_CYC_REQ_O <= '1'; -- prepare second cycle
+ else -- second cycle: ADD/SUB R_base, R_base, R_offset
+ CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & INSTR_INT(6 downto 4); -- base adr
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- write back base
+ end if;
+
+ when "1100" | "1101" | "1111" => -- store, imm offset, pre/post, (no) wb
+ CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & INSTR_INT(6 downto 4); -- base adr
+ CTRL_O(ctrl_rb_3_c downto ctrl_rb_0_c) <= M_FLAG_I & INSTR_INT(9 downto 7); -- store data
+ CTRL_O(ctrl_rb_is_imm_c) <= '1'; -- this is an immediate
+ CTRL_O(ctrl_mem_acc_c) <= '1'; -- this is a memory access
+ CTRL_O(ctrl_mem_wr_c) <= '1'; -- write access
+ CTRL_O(ctrl_mem_bpba_c) <= INSTR_INT(13); -- use bypassed adr base
+ CTRL_O(ctrl_rd_wb_c) <= INSTR_INT(11); -- write back base
+
+ -- Data Swap Operations R_b => M[R_a] => R_d --------------------------------
+ when "0010" | "0110" | "1010" | "1110" => -- load/store, imm/reg offset, post, no wb [REDUNDANT!]
+ CTRL_O(ctrl_mem_acc_c) <= '1'; -- this is a memory access
+ CTRL_O(ctrl_mem_bpba_c) <= '1'; -- use bypassed adr from prev cycle
+ CTRL_O(ctrl_rb_is_imm_c) <= '1'; -- this is an immediate (pseudo)
+ if (MULTI_CYC_I = '0') then -- first cycle: LD R_d, [R_a]
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- write back base
+ MULTI_CYC_REQ_O <= '1'; -- prepare second cycle
+ else -- second cycle: ST R_b, [R_a]
+ CTRL_O(ctrl_mem_wr_c) <= '1'; -- write access
+ end if;
+
+ when others => -- undefined
+ NULL; -- wayne ^^
+
+ end case;
+
+
+ when "10" => -- Class 2: Branch and Link
+ -- ==============================================================================
+ CTRL_O(ctrl_branch_c) <= '1'; -- this is a branch
+ CTRL_O(ctrl_link_c) <= INSTR_INT(9); -- link?
+ CTRL_O(ctrl_ra_is_pc_c) <= '1'; -- operand A is the pc
+ CTRL_O(ctrl_rb_is_imm_c) <= '1'; -- operand B is an immediate
+ CTRL_O(ctrl_rd_wb_c) <= INSTR_INT(9); -- allow write back for linking
+ CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & link_reg_adr_c; -- link register
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_adc_c; -- add offset (withut carry)
+ if (word_mode_en_c = false) then -- byte addressing mode
+ IMM_O(9 downto 0) <= INSTR_INT(8 downto 0) & '0'; -- offset = offset * 2 (byte offset)
+ for i in 10 to data_width_c-1 loop
+ IMM_O(i) <= INSTR_INT(8); -- sign extension
+ end loop;
+ else -- word addressing mode
+ IMM_O(8 downto 0) <= INSTR_INT(8 downto 0); -- offset = offset (word offset)
+ for i in 9 to data_width_c-1 loop
+ IMM_O(i) <= INSTR_INT(8); -- sign extension
+ end loop;
+ end if;
+
+
+ when "11" => -- Class 3: Sub Classes
+ -- ==============================================================================
+ case (INSTR_INT(13 downto 12)) is
+
+ when "00" => -- Class 3a: Load Immediate
+ -- --------------------------------------------------------------------------------
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow write back
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_orr_c; -- logical OR
+ CTRL_O(ctrl_ra_3_c downto ctrl_ra_0_c) <= M_FLAG_I & INSTR_INT(9 downto 7); -- op A = source & destination
+ CTRL_O(ctrl_rb_is_imm_c) <= '1'; -- B is an immediate
+ if (INSTR_INT(11) = '0') then -- load and expand low part
+ IMM_O(7 downto 0) <= INSTR_INT(10) & INSTR_INT(6 downto 0);
+ for i in 8 to data_width_c-1 loop -- sign extension
+ IMM_O(i) <= INSTR_INT(10);
+ end loop;
+ CTRL_O(ctrl_clr_la_c) <= '1'; -- set low byte of A to 0
+ CTRL_O(ctrl_clr_ha_c) <= '1'; -- set high byte of A to 0
+ else -- load high part
+ IMM_O(15 downto 8) <= INSTR_INT(10) & INSTR_INT(6 downto 0);
+ CTRL_O(ctrl_clr_ha_c) <= '1'; -- set high byte of A to 0
+ end if;
+
+
+ when "01" => -- Class 3b: Bit Transfer
+ -- --------------------------------------------------------------------------------
+ CTRL_O(ctrl_rb_is_imm_c) <= '1'; -- B is an immediate
+ case (INSTR_INT(11 downto 10)) is
+ when "00" => -- modifiy bit -> clear bit
+ IMM_O(to_integer(unsigned(INSTR_INT(3 downto 0)))) <= '1';
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_bic_c; -- bit clear
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow write back
+ when "01" => -- modify bit -> set bit
+ IMM_O(to_integer(unsigned(INSTR_INT(3 downto 0)))) <= '1';
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_orr_c; -- logical or
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow write back
+ when "10" => -- T-flag transfer, load from T
+ IMM_O(to_integer(unsigned(INSTR_INT(3 downto 0)))) <= '1';
+ CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow write back
+ if (T_FLAG_I = '0') then
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_bic_c; -- bit clear
+ else
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_orr_c; -- logical or
+ end if;
+ when others => -- T-flag transfer, store to T
+ CTRL_O(ctrl_tf_inv_c) <= INSTR_INT(7); -- invert bit to be transfered to T-flag
+ IMM_O <= (others => '0');
+ CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_orr_c; -- logical or
+ CTRL_O(ctrl_tf_store_c) <= '1'; -- store to t-flag
+ end case;
+
+
+ when "10" => -- Class 3c: Coprocessor Access
+ -- --------------------------------------------------------------------------------
+ CTRL_O(ctrl_cp_acc_c) <= '1'; -- this is a cp access
+ if (INSTR_INT(11) = '1') then -- data transfer
+ CTRL_O(ctrl_cp_trans_c) <= '1'; -- this is a cp data transfer
+ CTRL_O(ctrl_cp_wr_c) <= INSTR_INT(3); -- read / write
+ CTRL_O(ctrl_rd_wb_c) <= not INSTR_INT(3); -- allow write back
+ end if;
+ if (M_FLAG_I = user_mode_c) then -- access violation?
+ if (((CP_PTC_I = '1') or (cp0_present_c = false)) and (INSTR_INT(10) = '0')) or -- usr cp access
+ ((cp1_present_c = false) and (INSTR_INT(10) = '1')) then -- sys cp access
+ CTRL_O(ctrl_syscall_c) <= '1'; -- is system call (unauthorized/impossible cp_access)
+ end if;
+ end if;
+
+
+ when others => -- Class 3d: Sub Sub Classes
+ -- ==============================================================================
+ case (INSTR_INT(11 downto 10)) is
+
+ when "00" => -- Class 3c0: Multiply-and-Accumulate
+ -- --------------------------------------------------------------------------------
+ if (INSTR_INT(3) = '1') then -- MAC
+ if (build_mac_c = true) then -- unit present?
+ if (MULTI_CYC_I = '0') then -- fist cycle: load MAC buffer
+ CTRL_O(ctrl_rb_3_c downto ctrl_rb_0_c) <= M_FLAG_I & INSTR_INT(9 downto 7); -- mac offset
+ CTRL_O(ctrl_load_mac_c) <= '1'; -- load mac buffer
+ MULTI_CYC_REQ_O <= '1'; -- prepare second cycle
+ else -- second cycle: MUL operation with offset = MAC
+ CTRL_O(ctrl_use_offs_c) <= '1'; -- use loaded offset
+ CTRL_O(ctrl_use_mac_c) <= '1'; -- use mac unit
+ end if;
+ else -- not present
+ CTRL_O(ctrl_syscall_c) <= '1'; -- is system call
+ end if;
+ else -- MUL
+ if (build_mul_c = true) then -- unit present?
+ CTRL_O(ctrl_use_mac_c) <= '1'; -- use mac unit
+ else -- not present
+ CTRL_O(ctrl_syscall_c) <= '1'; -- is system call
+ end if;
+ end if;
+
+ when "01" => -- Class 3c1: Undefined Insruction
+ -- --------------------------------------------------------------------------------
+ CTRL_O(ctrl_syscall_c) <= '1'; -- is system call
+
+ when "10" => -- Class 3c2: Undefined Insruction
+ -- --------------------------------------------------------------------------------
+ CTRL_O(ctrl_syscall_c) <= '1'; -- is system call
+
+ when others => -- Class 3c3: System Call with 10-bit tag
+ -- --------------------------------------------------------------------------------
+ CTRL_O(ctrl_syscall_c) <= '1'; -- is system call
+
+ end case;
+
+ end case;
+
+
+ when others => -- undefined
+ -- ==============================================================================
+ NULL; -- wayne...
+
+
+ end case;
+
+ end process OPCODE_DECODER;
+
+
+
+
+end OP_DEC_STRUCTURE;
Index: atlas_core/trunk/core/rtl/SYS_REG.vhd
===================================================================
--- atlas_core/trunk/core/rtl/SYS_REG.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/SYS_REG.vhd (revision 2)
@@ -0,0 +1,384 @@
+-- ########################################################
+-- # << ATLAS Project - System Registers >> #
+-- # **************************************************** #
+-- # The main system register (MSR & PC) are located #
+-- # here. Also the context control and interrupt #
+-- # processing circuits are implemented within this #
+-- # unit. #
+-- # **************************************************** #
+-- # Last modified: 12.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity SYS_REG is
+ port (
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+-- ###############################################################################################
+-- ## Function Control ##
+-- ###############################################################################################
+
+ EX_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- ex stage control
+ EXT_INT_REQ0_I : in std_logic; -- external interrupt request 0
+ EXT_INT_REQ1_I : in std_logic; -- external interrupt request 1
+
+-- ###############################################################################################
+-- ## Data Input ##
+-- ###############################################################################################
+
+ FLAG_BUS_I : in std_logic_vector(flag_bus_width_c-1 downto 0); -- flag input
+ EXC_POS_I : in std_logic; -- exception would be possible
+ STOP_PC : in std_logic; -- freeze pc
+ PC_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- PC write data
+ MSR_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- MSR write data
+
+-- ###############################################################################################
+-- ## Data Output ##
+-- ###############################################################################################
+
+ FLAG_BUS_O : out std_logic_vector(flag_bus_width_c-1 downto 0); -- flag output
+ VALID_BRANCH_O : out std_logic; -- valid branch detected
+ EXC_EXECUTED_O : out std_logic; -- executed executed
+ RD_MSR_O : out std_logic_vector(data_width_c-1 downto 0); -- read data msr
+ PC_O : out std_logic_vector(data_width_c-1 downto 0); -- pc output
+ PC_1D_O : out std_logic_vector(data_width_c-1 downto 0); -- pc 1x delayed
+ CP_PTC_O : out std_logic; -- user coprocessor protection
+ MODE_O : out std_logic -- current operating mode
+ );
+end SYS_REG;
+
+architecture SR_STRUCTURE of SYS_REG is
+
+ -- System Register --
+ signal SYS_REG_PC : std_logic_vector(data_width_c-1 downto 0);
+ signal SYS_REG_MSR : std_logic_vector(data_width_c-1 downto 0);
+ signal PC_1D : std_logic_vector(data_width_c-1 downto 0);
+
+ -- Branch system --
+ signal VALID_BRANCH : std_logic;
+
+ -- Interrupt System --
+ signal INT_REQ : std_logic;
+ signal INT_VECTOR : std_logic_vector(1 downto 0);
+ signal XINT_SYNC : std_logic_vector(1 downto 0);
+ signal XINT_0_TAKEN : std_logic;
+ signal XINT_1_TAKEN : std_logic;
+
+begin
+ -- External Interrupt Sychronizer ----------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ XI_SYNCHRONIZER: process(CLK_I)
+ variable valid_int_req_v : std_logic;
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ XINT_SYNC <= (others => '0');
+ elsif (CE_I = '1') then
+ XINT_SYNC(0) <= EXT_INT_REQ0_I;
+ XINT_SYNC(1) <= EXT_INT_REQ1_I;
+ end if;
+ end if;
+ end process XI_SYNCHRONIZER;
+
+
+
+ -- Exception Priority System ---------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ EXC_SYS: process(EX_CTRL_BUS_I, XINT_SYNC, EXC_POS_I, SYS_REG_MSR)
+ variable xint0_valid_v : std_logic;
+ variable xint1_valid_v : std_logic;
+ begin
+ -- external interrupt enable --
+ -- => external int is possible AND int source is masked AND global ints are enabled
+ xint0_valid_v := EXC_POS_I and SYS_REG_MSR(msr_xint0_en_c) and SYS_REG_MSR(msr_xint_en_c);
+ xint1_valid_v := EXC_POS_I and SYS_REG_MSR(msr_xint1_en_c) and SYS_REG_MSR(msr_xint_en_c);
+
+ -- exception priority list and encoding --
+ if ((xint0_valid_v = '1') and (XINT_SYNC(0) = '1')) then -- external interrupt 0
+ INT_REQ <= '1';
+ INT_VECTOR <= "01"; -- ext int 1 vector
+ elsif ((xint1_valid_v = '1') and (XINT_SYNC(1) = '1')) then -- external interrupt 1
+ INT_REQ <= '1';
+ INT_VECTOR <= "10"; -- ext int 0 vector
+ elsif ((EXC_POS_I = '1') and (EX_CTRL_BUS_I(ctrl_syscall_c) = '1')) then
+ -- software interrupt: system call // msr/coprocessor access violation // undefined instruction
+ INT_REQ <= '1';
+ INT_VECTOR <= "11"; -- sw int vector
+ else -- no exception
+ INT_REQ <= '0';
+ INT_VECTOR <= "00"; -- irrelevant [hw reset vector]
+ end if;
+ end process EXC_SYS;
+
+ -- output to cycle manager --
+ EXC_EXECUTED_O <= INT_REQ;
+
+
+
+ -- System Register Update ------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ SR_UPDATE: process(CLK_I, SYS_REG_MSR, EX_CTRL_BUS_I)
+ variable msr_acc_v : std_logic_vector(2 downto 0);
+ begin
+ -- manual msr access mode --
+ msr_acc_v := SYS_REG_MSR(msr_mode_flag_c) & EX_CTRL_BUS_I(ctrl_msr_am_1_c downto ctrl_msr_am_0_c);
+
+ -- sync update --
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ SYS_REG_PC <= (others => '0'); -- fixed reset vector!
+ SYS_REG_MSR <= (others => '0');
+ SYS_REG_MSR(msr_mode_flag_c) <= system_mode_c; -- we're the king after reset
+ SYS_REG_MSR(msr_usr_cp_ptc_c) <= '1'; -- user coprocessor -> only access in system mode
+ elsif (CE_I = '1') then -- clock enable
+
+ -- Exception MSR Access -------------------------------------------------
+ if (INT_REQ = '1') then -- switch to system mode
+ SYS_REG_MSR(msr_mode_flag_c) <= system_mode_c; -- goto sytem mode
+ SYS_REG_MSR(msr_xint_en_c) <= '0'; -- clear global xint enable flag
+
+ -- Manual MSR Access ----------------------------------------------------
+ elsif (EX_CTRL_BUS_I(ctrl_en_c) = '1') then -- valid operation
+ if (EX_CTRL_BUS_I(ctrl_msr_wr_c) = '1') then -- write operation
+ case (msr_acc_v) is
+ when "100" => -- system mode: full access
+ SYS_REG_MSR <= MSR_DATA_I;
+ when "101" => -- system mode: only access all ALU flags
+ SYS_REG_MSR(msr_usr_z_flag_c) <= MSR_DATA_I(msr_usr_z_flag_c);
+ SYS_REG_MSR(msr_usr_c_flag_c) <= MSR_DATA_I(msr_usr_c_flag_c);
+ SYS_REG_MSR(msr_usr_o_flag_c) <= MSR_DATA_I(msr_usr_o_flag_c);
+ SYS_REG_MSR(msr_usr_n_flag_c) <= MSR_DATA_I(msr_usr_n_flag_c);
+ SYS_REG_MSR(msr_usr_t_flag_c) <= MSR_DATA_I(msr_usr_t_flag_c);
+ SYS_REG_MSR(msr_sys_z_flag_c) <= MSR_DATA_I(msr_sys_z_flag_c);
+ SYS_REG_MSR(msr_sys_c_flag_c) <= MSR_DATA_I(msr_sys_c_flag_c);
+ SYS_REG_MSR(msr_sys_o_flag_c) <= MSR_DATA_I(msr_sys_o_flag_c);
+ SYS_REG_MSR(msr_sys_n_flag_c) <= MSR_DATA_I(msr_sys_n_flag_c);
+ SYS_REG_MSR(msr_sys_t_flag_c) <= MSR_DATA_I(msr_sys_t_flag_c);
+ when "110" => -- system mode: only access system ALU flags
+ SYS_REG_MSR(msr_sys_z_flag_c) <= MSR_DATA_I(msr_sys_z_flag_c);
+ SYS_REG_MSR(msr_sys_c_flag_c) <= MSR_DATA_I(msr_sys_c_flag_c);
+ SYS_REG_MSR(msr_sys_o_flag_c) <= MSR_DATA_I(msr_sys_o_flag_c);
+ SYS_REG_MSR(msr_sys_n_flag_c) <= MSR_DATA_I(msr_sys_n_flag_c);
+ SYS_REG_MSR(msr_sys_t_flag_c) <= MSR_DATA_I(msr_sys_t_flag_c);
+ when others => -- system/user mode: only access user ALU flags
+ SYS_REG_MSR(msr_usr_z_flag_c) <= MSR_DATA_I(msr_usr_z_flag_c);
+ SYS_REG_MSR(msr_usr_c_flag_c) <= MSR_DATA_I(msr_usr_c_flag_c);
+ SYS_REG_MSR(msr_usr_o_flag_c) <= MSR_DATA_I(msr_usr_o_flag_c);
+ SYS_REG_MSR(msr_usr_n_flag_c) <= MSR_DATA_I(msr_usr_n_flag_c);
+ SYS_REG_MSR(msr_usr_t_flag_c) <= MSR_DATA_I(msr_usr_t_flag_c);
+ end case;
+
+ -- Automatic MSR Access -------------------------------------------------
+ elsif (EX_CTRL_BUS_I(ctrl_ctx_down_c) = '1') then -- context down switch?
+ SYS_REG_MSR(msr_mode_flag_c) <= user_mode_c; -- go down to user mode
+ if (SYS_REG_MSR(msr_mode_flag_c) = system_mode_c) then -- only in system mode!
+ SYS_REG_MSR(msr_xint_en_c) <= EX_CTRL_BUS_I(ctrl_re_xint_c); -- auto re-enable global x_ints
+ end if;
+ elsif (EX_CTRL_BUS_I(ctrl_fupdate_c) = '1') then -- allow auto update of ALU flags
+ if (SYS_REG_MSR(msr_mode_flag_c) = user_mode_c) then -- user mode auto alu flag update
+ SYS_REG_MSR(msr_usr_z_flag_c) <= FLAG_BUS_I(flag_z_c);
+ SYS_REG_MSR(msr_usr_c_flag_c) <= FLAG_BUS_I(flag_c_c);
+ SYS_REG_MSR(msr_usr_o_flag_c) <= FLAG_BUS_I(flag_o_c);
+ SYS_REG_MSR(msr_usr_n_flag_c) <= FLAG_BUS_I(flag_n_c);
+ else -- system mode auto alu flag update
+ SYS_REG_MSR(msr_sys_z_flag_c) <= FLAG_BUS_I(flag_z_c);
+ SYS_REG_MSR(msr_sys_c_flag_c) <= FLAG_BUS_I(flag_c_c);
+ SYS_REG_MSR(msr_sys_o_flag_c) <= FLAG_BUS_I(flag_o_c);
+ SYS_REG_MSR(msr_sys_n_flag_c) <= FLAG_BUS_I(flag_n_c);
+ end if;
+ elsif (EX_CTRL_BUS_I(ctrl_tf_store_c) = '1') then -- allow auto update of T-flag
+ if (SYS_REG_MSR(msr_mode_flag_c) = user_mode_c) then -- user mode
+ SYS_REG_MSR(msr_usr_t_flag_c) <= FLAG_BUS_I(flag_t_c);
+ else -- system mode
+ SYS_REG_MSR(msr_sys_t_flag_c) <= FLAG_BUS_I(flag_t_c);
+ end if;
+ end if;
+ end if;
+
+ -- Exception PC Access --------------------------------------------------
+ if (INT_REQ = '1') then
+ SYS_REG_PC <= (others => '0');
+ SYS_REG_PC(2 downto 1) <= INT_VECTOR;
+
+ -- Manual/Branch PC Access ----------------------------------------------
+ elsif (VALID_BRANCH = '1') or ((EX_CTRL_BUS_I(ctrl_en_c) = '1') and (EX_CTRL_BUS_I(ctrl_ctx_down_c) = '1')) then -- valid automatic/manual update / goto user mode
+ SYS_REG_PC <= PC_DATA_I;
+
+ -- Automatic PC Update --------------------------------------------------
+ elsif (STOP_PC = '0') then -- update BYTE address
+ if (word_mode_en_c = false) then -- byte-addressed memory
+ SYS_REG_PC <= Std_Logic_Vector(unsigned(SYS_REG_PC) + 2); -- byte increment
+ else
+ SYS_REG_PC <= Std_Logic_Vector(unsigned(SYS_REG_PC) + 1); -- word increment
+ end if;
+ end if;
+
+ end if;
+ end if;
+ end process SR_UPDATE;
+
+
+ -- Mode-Corresponding Flag Output --
+ FLAG_BUS_O(flag_z_c) <= SYS_REG_MSR(msr_usr_z_flag_c) when (SYS_REG_MSR(msr_mode_flag_c) = user_mode_c) else SYS_REG_MSR(msr_sys_z_flag_c);
+ FLAG_BUS_O(flag_c_c) <= SYS_REG_MSR(msr_usr_c_flag_c) when (SYS_REG_MSR(msr_mode_flag_c) = user_mode_c) else SYS_REG_MSR(msr_sys_c_flag_c);
+ FLAG_BUS_O(flag_o_c) <= SYS_REG_MSR(msr_usr_o_flag_c) when (SYS_REG_MSR(msr_mode_flag_c) = user_mode_c) else SYS_REG_MSR(msr_sys_o_flag_c);
+ FLAG_BUS_O(flag_n_c) <= SYS_REG_MSR(msr_usr_n_flag_c) when (SYS_REG_MSR(msr_mode_flag_c) = user_mode_c) else SYS_REG_MSR(msr_sys_n_flag_c);
+ FLAG_BUS_O(flag_t_c) <= SYS_REG_MSR(msr_usr_t_flag_c) when (SYS_REG_MSR(msr_mode_flag_c) = user_mode_c) else SYS_REG_MSR(msr_sys_t_flag_c);
+
+
+ -- MSR Data Read-Back Access --
+ MSR_RD_ACC: process(EX_CTRL_BUS_I, SYS_REG_MSR)
+ begin
+ RD_MSR_O <= (others => '0');
+ case (EX_CTRL_BUS_I(ctrl_msr_am_1_c downto ctrl_msr_am_0_c)) is
+ when "00" => -- full read access
+ RD_MSR_O <= SYS_REG_MSR;
+ when "01" => -- only read all ALU flags
+ RD_MSR_O(msr_sys_z_flag_c) <= SYS_REG_MSR(msr_sys_z_flag_c);
+ RD_MSR_O(msr_sys_c_flag_c) <= SYS_REG_MSR(msr_sys_c_flag_c);
+ RD_MSR_O(msr_sys_o_flag_c) <= SYS_REG_MSR(msr_sys_o_flag_c);
+ RD_MSR_O(msr_sys_n_flag_c) <= SYS_REG_MSR(msr_sys_n_flag_c);
+ RD_MSR_O(msr_sys_t_flag_c) <= SYS_REG_MSR(msr_sys_t_flag_c);
+ RD_MSR_O(msr_usr_z_flag_c) <= SYS_REG_MSR(msr_usr_z_flag_c);
+ RD_MSR_O(msr_usr_c_flag_c) <= SYS_REG_MSR(msr_usr_c_flag_c);
+ RD_MSR_O(msr_usr_o_flag_c) <= SYS_REG_MSR(msr_usr_o_flag_c);
+ RD_MSR_O(msr_usr_n_flag_c) <= SYS_REG_MSR(msr_usr_n_flag_c);
+ RD_MSR_O(msr_usr_t_flag_c) <= SYS_REG_MSR(msr_usr_t_flag_c);
+ when "10" => -- only read system ALU flags
+ RD_MSR_O(msr_sys_z_flag_c) <= SYS_REG_MSR(msr_sys_z_flag_c);
+ RD_MSR_O(msr_sys_c_flag_c) <= SYS_REG_MSR(msr_sys_c_flag_c);
+ RD_MSR_O(msr_sys_o_flag_c) <= SYS_REG_MSR(msr_sys_o_flag_c);
+ RD_MSR_O(msr_sys_n_flag_c) <= SYS_REG_MSR(msr_sys_n_flag_c);
+ RD_MSR_O(msr_sys_t_flag_c) <= SYS_REG_MSR(msr_sys_t_flag_c);
+ when others => -- only read user ALU flags
+ RD_MSR_O(msr_usr_z_flag_c) <= SYS_REG_MSR(msr_usr_z_flag_c);
+ RD_MSR_O(msr_usr_c_flag_c) <= SYS_REG_MSR(msr_usr_c_flag_c);
+ RD_MSR_O(msr_usr_o_flag_c) <= SYS_REG_MSR(msr_usr_o_flag_c);
+ RD_MSR_O(msr_usr_n_flag_c) <= SYS_REG_MSR(msr_usr_n_flag_c);
+ RD_MSR_O(msr_usr_t_flag_c) <= SYS_REG_MSR(msr_usr_t_flag_c);
+ end case;
+ if (SYS_REG_MSR(msr_mode_flag_c) = system_mode_c) then -- full read access
+ RD_MSR_O <= SYS_REG_MSR;
+ else -- only user ALU flags are visible
+ RD_MSR_O(msr_usr_z_flag_c) <= SYS_REG_MSR(msr_usr_z_flag_c);
+ RD_MSR_O(msr_usr_c_flag_c) <= SYS_REG_MSR(msr_usr_c_flag_c);
+ RD_MSR_O(msr_usr_o_flag_c) <= SYS_REG_MSR(msr_usr_o_flag_c);
+ RD_MSR_O(msr_usr_n_flag_c) <= SYS_REG_MSR(msr_usr_n_flag_c);
+ RD_MSR_O(msr_usr_t_flag_c) <= SYS_REG_MSR(msr_usr_t_flag_c);
+ end if;
+ end process MSR_RD_ACC;
+
+ -- Special Flag output --
+ CP_PTC_O <= SYS_REG_MSR(msr_usr_cp_ptc_c); -- user coprocessor protection
+ MODE_O <= SYS_REG_MSR(msr_mode_flag_c);
+
+ -- PC output and delay --
+ PD_DELAY: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ PC_1D <= (others => '0');
+ elsif (STOP_PC = '0') and (CE_I = '1') then
+ PC_1D <= SYS_REG_PC;
+ end if;
+ end if;
+ end process PD_DELAY;
+
+ -- PC outputs --
+ PC_O <= SYS_REG_PC; -- direct output
+ PC_1D_O <= PC_1D; -- 1x delayed
+
+
+
+ -- Branch Detector -------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ BRANCH_DETECTOR: process(EX_CTRL_BUS_I, SYS_REG_MSR, INT_REQ)
+ variable z_v, c_v, o_v, n_v, t_v : std_logic;
+ variable valid_v : std_logic;
+ variable valid_branch_v : std_logic;
+ variable manual_branch_v : std_logic;
+ begin
+
+ -- flag isolation --
+ if (SYS_REG_MSR(msr_mode_flag_c) = user_mode_c) then -- user mode
+ z_v := SYS_REG_MSR(msr_usr_z_flag_c);
+ c_v := SYS_REG_MSR(msr_usr_c_flag_c);
+ o_v := SYS_REG_MSR(msr_usr_o_flag_c);
+ n_v := SYS_REG_MSR(msr_usr_n_flag_c);
+ t_v := SYS_REG_MSR(msr_usr_t_flag_c);
+ else -- system mode
+ z_v := SYS_REG_MSR(msr_sys_z_flag_c);
+ c_v := SYS_REG_MSR(msr_sys_c_flag_c);
+ o_v := SYS_REG_MSR(msr_sys_o_flag_c);
+ n_v := SYS_REG_MSR(msr_sys_n_flag_c);
+ t_v := SYS_REG_MSR(msr_sys_t_flag_c);
+ end if;
+
+ -- condition check --
+ case (EX_CTRL_BUS_I(ctrl_cond_3_c downto ctrl_cond_0_c)) is
+ when cond_eq_c => -- equal
+ valid_v := z_v;
+ when cond_ne_c => -- not equal
+ valid_v := not z_v;
+ when cond_cs_c => -- unsigned higher or same
+ valid_v := c_v;
+ when cond_cc_c => -- unsigned lower
+ valid_v := not c_v;
+ when cond_mi_c => -- negative
+ valid_v := n_v;
+ when cond_pl_c => -- positive or zero
+ valid_v := not n_v;
+ when cond_os_c => -- overflow
+ valid_v := o_v;
+ when cond_oc_c => -- no overflow
+ valid_v := not o_v;
+ when cond_hi_c => -- unisgned higher
+ valid_v := c_v and (not z_v);
+ when cond_ls_c => -- unsigned lower or same
+ valid_v := (not c_v) and z_v;
+ when cond_ge_c => -- greater than or equal
+ valid_v := n_v xnor o_v;
+ when cond_lt_c => -- less than
+ valid_v := n_v xor o_v;
+ when cond_gt_c => -- greater than
+ valid_v := (not z_v) and (n_v xnor o_v);
+ when cond_le_c => -- less than or equal
+ valid_v := z_v or (n_v xor o_v);
+ when cond_ts_c => -- transfer set
+ valid_v := t_v;
+ when cond_al_c => -- always
+ valid_v := '1';
+ when others => -- undefined
+ valid_v := '0';
+ end case;
+
+ -- Manual branch? --
+ manual_branch_v := EX_CTRL_BUS_I(ctrl_pc_wr_c);
+
+ -- Valid branch command? --
+ valid_branch_v := EX_CTRL_BUS_I(ctrl_en_c) and ((EX_CTRL_BUS_I(ctrl_branch_c) and valid_v) or manual_branch_v);
+
+ -- Output to cycle arbiter --
+ VALID_BRANCH <= valid_branch_v;-- or INT_REQ; -- internal signal, no INT_REQ since it is redundant
+ VALID_BRANCH_O <= valid_branch_v or INT_REQ; -- external signal
+
+ end process BRANCH_DETECTOR;
+
+
+
+
+end SR_STRUCTURE;
Index: atlas_core/trunk/core/rtl/ATLAS_CORE.vhd
===================================================================
--- atlas_core/trunk/core/rtl/ATLAS_CORE.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/ATLAS_CORE.vhd (revision 2)
@@ -0,0 +1,357 @@
+-- ########################################################
+-- # << ATLAS Project - Atlas CPU Core >> #
+-- # **************************************************** #
+-- # This is the top entity of the CPU core. #
+-- # All submodules are instantiated here. #
+-- # **************************************************** #
+-- # Last modified: 09.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity ATLAS_CORE is
+ port (
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+
+ CLK_I : in std_logic; -- global clock line
+ RST_I : in std_logic; -- global reset line, sync, high-active
+ HOLD_I : in std_logic; -- stops core when high
+
+-- ###############################################################################################
+-- ## Instruction Interface ##
+-- ###############################################################################################
+
+ INSTR_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction byte adr
+ INSTR_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- instruction input
+ INSTR_EN_O : out std_logic; -- allow IR update
+
+-- ###############################################################################################
+-- ## Data Interface ##
+-- ###############################################################################################
+
+ -- Memory Arbitration --
+ SYS_MODE_O : out std_logic; -- current operating mode
+ SYS_INT_O : out std_logic; -- interrupt processing
+
+ -- Memory System --
+ MEM_REQ_O : out std_logic; -- mem access in next cycle
+ MEM_RW_O : out std_logic; -- read write
+ MEM_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- data byte adr
+ MEM_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data
+ MEM_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- read data
+
+-- ###############################################################################################
+-- ## Coprocessor Interface ##
+-- ###############################################################################################
+
+ USR_CP_EN_O : out std_logic; -- access to cp0
+ SYS_CP_EN_O : out std_logic; -- access to cp1
+ CP_OP_O : out std_logic; -- data transfer/processing
+ CP_RW_O : out std_logic; -- read/write access
+ CP_CMD_O : out std_logic_vector(cp_cmd_width_c-1 downto 0); -- register addresses / cmd
+ CP_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- write data
+ CP_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- read data cp0 OR cp1
+
+-- ###############################################################################################
+-- ## External Interrupt Lines ##
+-- ###############################################################################################
+
+ EXT_INT_0_I : in std_logic; -- external interrupt request 0
+ EXT_INT_1_I : in std_logic -- external interrupt request 1
+ );
+end ATLAS_CORE;
+
+architecture ATLAS_CORE_STRUCTURE of ATLAS_CORE is
+
+ -- Global Nets --
+ signal G_CLK : std_logic; -- global clock line
+ signal G_RST : std_logic; -- global reset line
+ signal G_CE : std_logic; -- global clock enable
+
+ -- Control Lines --
+ signal OF_CTRL : std_logic_vector(ctrl_width_c-1 downto 0);
+ signal EX_CTRL : std_logic_vector(ctrl_width_c-1 downto 0);
+ signal MA_CTRL : std_logic_vector(ctrl_width_c-1 downto 0);
+ signal WB_CTRL : std_logic_vector(ctrl_width_c-1 downto 0);
+
+ -- Forwarding Paths --
+ signal MA_FWD : std_logic_vector(fwd_width_c-1 downto 0);
+ signal WB_FWD : std_logic_vector(fwd_width_c-1 downto 0);
+
+ -- Data Lines --
+ signal WB_DATA : std_logic_vector(data_width_c-1 downto 0); -- write back data
+ signal OP_A_DATA : std_logic_vector(data_width_c-1 downto 0); -- operand A data
+ signal OP_B_DATA : std_logic_vector(data_width_c-1 downto 0); -- operand B data
+ signal OP_C_DATA : std_logic_vector(data_width_c-1 downto 0); -- operand C data
+ signal BP_A_DATA : std_logic_vector(data_width_c-1 downto 0); -- operand A bypass
+ signal BP_C_DATA : std_logic_vector(data_width_c-1 downto 0); -- operand C bypass
+ signal ALU_RES : std_logic_vector(data_width_c-1 downto 0); -- alu result
+ signal MAC_RES : std_logic_vector(data_width_c-1 downto 0); -- mac result
+ signal IMMEDIATE : std_logic_vector(data_width_c-1 downto 0); -- immediate value
+ signal T_FLAG : std_logic; -- transfer flag
+ signal MA_DATA : std_logic_vector(data_width_c-1 downto 0); -- ma stage result
+ signal MEM_ADR_FB : std_logic_vector(data_width_c-1 downto 0); -- mem adr feedback
+
+ -- Program Counter --
+ signal PC_1D : std_logic_vector(data_width_c-1 downto 0); -- 1x delayed pc
+ signal PC_W_DATA : std_logic_vector(data_width_c-1 downto 0); -- PC write data
+ signal STOP_PC : std_logic; -- freeze PC
+
+ -- Flag Stuff --
+ signal ALU_FLAG_I : std_logic_vector(flag_bus_width_c-1 downto 0); -- alu flag input
+ signal ALU_FLAG_O : std_logic_vector(flag_bus_width_c-1 downto 0); -- alu flag input
+ signal MSR_W_DATA : std_logic_vector(data_width_c-1 downto 0); -- msr write data
+ signal MSR_R_DATA : std_logic_vector(data_width_c-1 downto 0); -- msr read data
+
+ -- Control Signals --
+ signal VALID_BRANCH : std_logic; -- taken branch
+ signal EXC_POS : std_logic; -- exception would be possible
+ signal EXC_TAKEN : std_logic; -- async interrupt taken
+ signal MODE : std_logic; -- current operating mode
+
+ -- Opcode Decoder --
+ signal OP_CTRL : std_logic_vector(ctrl_width_c-1 downto 0); -- decoder contorl output
+ signal MULTI_CYC : std_logic; -- multi-cycle indicator
+ signal MULTI_CYC_REQ : std_logic; -- multi-cycle reqest
+
+ -- Coprocessor --
+ signal CP_PTC : std_logic; -- user coprocessor protection
+
+begin
+
+ -- Global Signals --------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ G_CLK <= CLK_I;
+ G_CE <= not HOLD_I;
+ G_RST <= RST_I;
+
+
+
+ -- Opcode Decoder --------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ Opcode_Decoder: OP_DEC
+ port map (
+ -- Decoder Interface Input --
+ INSTR_I => INSTR_DAT_I, -- instruction input
+ T_FLAG_I => T_FLAG, -- T-Flag input
+ M_FLAG_I => MODE, -- Mode flag input
+ MULTI_CYC_I => MULTI_CYC, -- multi-cycle indicator
+ CP_PTC_I => CP_PTC, -- coprocessor protection
+
+ -- Decoder Interface Output --
+ MULTI_CYC_REQ_O => MULTI_CYC_REQ, -- multi-cycle reqest
+ CTRL_O => OP_CTRL, -- decoder ctrl lines
+ IMM_O => IMMEDIATE -- immediate
+ );
+
+
+
+ -- Control System --------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ Control_Spine: CTRL
+ port map (
+ -- Global Control --
+ CLK_I => G_CLK, -- global clock line
+ CE_I => G_CE, -- clock enable
+ RST_I => G_RST, -- global reset line, sync, high-active
+
+ -- Decoder Interface --
+ OP_DEC_CTRL_I => OP_CTRL, -- decoder ctrl lines
+ MULTI_CYC_O => MULTI_CYC, -- multi-cycle indicator
+ MULTI_CYC_REQ_I => MULTI_CYC_REQ, -- multi-cycle request
+
+ -- Control Lines --
+ OF_CTRL_BUS_O => OF_CTRL, -- of stage control
+ EX_CTRL_BUS_O => EX_CTRL, -- ex stage control
+ MA_CTRL_BUS_O => MA_CTRL, -- ma stage control
+ WB_CTRL_BUS_O => WB_CTRL, -- wb stage control
+
+ -- Function Control --
+ VALID_BRANCH_I => VALID_BRANCH, -- valid branch detected
+ EXC_TAKEN_I => EXC_TAKEN, -- excation execute
+ EXC_POS_O => EXC_POS, -- exception would be possible
+ STOP_PC_O => STOP_PC, -- freeze program counter
+ IR_UPDATE_EN_O => INSTR_EN_O -- enable instruction reg update
+ );
+
+
+
+ -- Machine Status System -------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ System_Reg: SYS_REG
+ port map (
+ -- Global Control --
+ CLK_I => G_CLK, -- global clock line
+ CE_I => G_CE, -- clock enable
+ RST_I => G_RST, -- global reset line, asyc
+
+ -- Function Control --
+ EX_CTRL_BUS_I => EX_CTRL, -- ex stage control
+ EXT_INT_REQ0_I => EXT_INT_0_I, -- external interrupt request 0
+ EXT_INT_REQ1_I => EXT_INT_1_I, -- external interrupt request 1
+
+ -- Data Input --
+ FLAG_BUS_I => ALU_FLAG_O, -- flag input
+ EXC_POS_I => EXC_POS, -- exception would be possible
+ STOP_PC => STOP_PC, -- freeze pc
+ PC_DATA_I => PC_W_DATA, -- PC write data
+ MSR_DATA_I => MSR_W_DATA, -- MSR write data
+
+ -- Data Output --
+ FLAG_BUS_O => ALU_FLAG_I, -- flag output
+ VALID_BRANCH_O => VALID_BRANCH, -- valid branch detected
+ EXC_EXECUTED_O => EXC_TAKEN, -- executed exception
+ RD_MSR_O => MSR_R_DATA, -- read data msr
+ PC_O => INSTR_ADR_O, -- pc output
+ PC_1D_O => PC_1D, -- pc 1x delayed
+ CP_PTC_O => CP_PTC, -- coprocessor protection
+ MODE_O => MODE -- current mode
+ );
+
+ -- Control Lines --
+ SYS_MODE_O <= MODE; -- current operating mode
+ SYS_INT_O <= EXC_TAKEN; -- exception taken
+
+
+
+ -- OF Stage --------------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ Operand_Fetch: REG_FILE
+ port map (
+ -- Global Control --
+ CLK_I => G_CLK, -- global clock line
+ CE_I => G_CE, -- clock enable
+ RST_I => G_RST, -- global reset line, sync, high-active
+
+ -- Function Control --
+ WB_CTRL_BUS_I => WB_CTRL, -- wb stage control
+ OF_CTRL_BUS_I => OF_CTRL, -- of stage control
+
+ -- Data Input --
+ WB_DATA_I => WB_DATA, -- write back data
+ IMMEDIATE_I => IMMEDIATE, -- immediates
+ PC_1D_I => PC_1D, -- pc 1x delayed
+ WB_FWD_I => WB_FWD, -- WB stage forwarding path
+
+ -- Data Output --
+ OP_A_DATA_O => OP_A_DATA, -- operand A output
+ OP_B_DATA_O => OP_B_DATA, -- operand B output
+ OP_C_DATA_O => OP_C_DATA -- operand C output
+ );
+
+
+
+ -- EX Stage --------------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ Executor: ALU
+ port map (
+ -- Global Control --
+ CLK_I => G_CLK, -- global clock line
+ CE_I => G_CE, -- clock enable
+ RST_I => G_RST, -- global reset line, sync, high-active
+
+ -- Function Control --
+ EX_CTRL_BUS_I => EX_CTRL, -- stage control
+ FLAG_BUS_I => ALU_FLAG_I, -- flag input
+
+ -- Data Input --
+ OP_A_I => OP_A_DATA, -- operand A input
+ OP_B_I => OP_B_DATA, -- operand B input
+ OP_C_I => OP_C_DATA, -- operand C input
+ PC_1D_I => PC_1D, -- 1x delayed PC
+ MA_FWD_I => MA_FWD, -- MA stage forwarding path
+ WB_FWD_I => WB_FWD, -- WB stage forwarding path
+
+ -- Data Output --
+ FLAG_BUS_O => ALU_FLAG_O, -- flag output
+ MASK_T_FLAG_O => T_FLAG, -- T-Flag for mask generation
+ MSR_DATA_O => MSR_W_DATA, -- MSR write data
+ PC_DATA_O => PC_W_DATA, -- PC write data
+ ALU_RES_O => ALU_RES, -- ALU result
+ MAC_RES_O => MAC_RES, -- MAC result
+ BP_OPA_O => BP_A_DATA, -- operand A bypass
+ BP_OPC_O => BP_C_DATA, -- operand C bypass
+
+ -- Coprocessor Interface --
+ CP_CP0_EN_O => USR_CP_EN_O, -- access to cp0
+ CP_CP1_EN_O => SYS_CP_EN_O, -- access to cp1
+ CP_OP_O => CP_OP_O, -- data transfer/operation
+ CP_RW_O => CP_RW_O, -- read/write access
+ CP_CMD_O => CP_CMD_O, -- register addresses / cmd
+ CP_DAT_O => CP_DAT_O, -- write data
+
+ -- Memory access --
+ MEM_REQ_O => MEM_REQ_O -- data memory access request for next cycle
+ );
+
+
+
+ -- MA Stage --------------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ Memory_Access: MEM_ACC
+ port map (
+ -- Global Control --
+ CLK_I => G_CLK, -- global clock line
+ CE_I => G_CE, -- clock enable
+ RST_I => G_RST, -- global reset line, asyc
+
+ -- Function Control --
+ MA_CTRL_BUS_I => MA_CTRL, -- ma stage control
+
+ -- Data Input --
+ ALU_RES_I => ALU_RES, -- alu result
+ MAC_RES_I => MAC_RES, -- mac result
+ ADR_BASE_I => BP_A_DATA, -- op_a bypass
+ DATA_BP_I => BP_C_DATA, -- op_b bypass
+ CP_DATA_I => CP_DAT_I, -- coprocessor rd data
+ RD_MSR_I => MSR_R_DATA, -- read data msr
+ WB_FWD_I => WB_FWD, -- WB stage forwarding path
+
+ -- Data Output --
+ DATA_O => MA_DATA, -- data output
+ MEM_ADR_FB_O => MEM_ADR_FB, -- memory address feedback
+ MA_FWD_O => MA_FWD, -- MA stage forwarding path
+
+ -- Memory (w) Interface --
+ MEM_ADR_O => MEM_ADR_O, -- address output
+ MEM_DAT_O => MEM_DAT_O, -- write data output
+ MEM_RW_O => MEM_RW_O -- read write
+ );
+
+
+
+ -- WB Stage --------------------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ Write_Back: WB_UNIT
+ port map (
+ -- Global Control --
+ CLK_I => G_CLK, -- global clock line
+ CE_I => G_CE, -- clock enable
+ RST_I => G_RST, -- global reset line, sync, high-active
+
+ -- Function Control --
+ WB_CTRL_BUS_I => WB_CTRL, -- wb stage control
+
+ -- Data Input --
+ MEM_WB_DAT_I => MEM_DAT_I, -- memory read data
+ ALU_WB_DAT_I => MA_DATA, -- alu read data
+ MEM_ADR_FB_I => MEM_ADR_FB, -- memory address feedback
+
+ -- Data Output --
+ WB_DATA_O => WB_DATA, -- write back data
+ WB_FWD_O => WB_FWD -- WB stage forwarding path
+ );
+
+
+
+
+end ATLAS_CORE_STRUCTURE;
Index: atlas_core/trunk/core/rtl/REG_FILE.vhd
===================================================================
--- atlas_core/trunk/core/rtl/REG_FILE.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/REG_FILE.vhd (revision 2)
@@ -0,0 +1,111 @@
+-- ########################################################
+-- # << ATLAS Project - Data Register File >> #
+-- # **************************************************** #
+-- # Main data register file, organized in two bank, #
+-- # separated for each operating mode. Each bank holds #
+-- # 8 16-bit data registers. #
+-- # **************************************************** #
+-- # Last modified: 09.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity REG_FILE is
+ port (
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+
+ CLK_I : in std_logic; -- global clock line
+ CE_I : in std_logic; -- clock enable
+ RST_I : in std_logic; -- global reset line, sync, high-active
+
+-- ###############################################################################################
+-- ## Function Control ##
+-- ###############################################################################################
+
+ WB_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- wb stage control
+ OF_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- of stage control
+
+-- ###############################################################################################
+-- ## Data Input ##
+-- ###############################################################################################
+
+ WB_DATA_I : in std_logic_vector(data_width_c-1 downto 0); -- write back data
+ IMMEDIATE_I : in std_logic_vector(data_width_c-1 downto 0); -- immediates
+ PC_1D_I : in std_logic_vector(data_width_c-1 downto 0); -- pc 1x delayed
+ WB_FWD_I : in std_logic_vector(fwd_width_c-1 downto 0); -- WB stage forwarding path
+
+-- ###############################################################################################
+-- ## Data Output ##
+-- ###############################################################################################
+
+ OP_A_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- operand A output
+ OP_B_DATA_O : out std_logic_vector(data_width_c-1 downto 0); -- operand B output
+ OP_C_DATA_O : out std_logic_vector(data_width_c-1 downto 0) -- operand C output
+ );
+end REG_FILE;
+
+architecture RF_STRUCTURE of REG_FILE is
+
+ -- Register File --
+ type reg_file_mem_type is array (2*8-1 downto 0) of std_logic_vector(data_width_c-1 downto 0);
+ signal REG_FILE_MEM : reg_file_mem_type := (others => (others => '0'));
+
+ -- Operand Multiplexer --
+ signal OP_A_INT : std_logic_vector(data_width_c-1 downto 0);
+ signal OP_B_INT : std_logic_vector(data_width_c-1 downto 0);
+
+begin
+
+ -- Data Register File ----------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ DATA_REGISTER_FILE: process(CLK_I)
+ begin
+ -- sync write access --
+ if rising_edge(CLK_I) then
+ if (WB_CTRL_BUS_I(ctrl_wb_en_c) = '1') and (CE_I = '1') then -- valid write back
+ REG_FILE_MEM(to_integer(unsigned(WB_CTRL_BUS_I(ctrl_rd_3_c downto ctrl_rd_0_c)))) <= WB_DATA_I;
+ end if;
+ end if;
+ end process DATA_REGISTER_FILE;
+
+
+
+ -- Operand Fetch Forwarding Unit -----------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ OF_FWD: process(WB_FWD_I, OF_CTRL_BUS_I, REG_FILE_MEM)
+ begin
+ -- operand A forwarding --
+ if (WB_FWD_I(fwd_en_c) = '1') and (OF_CTRL_BUS_I(ctrl_ra_3_c downto ctrl_ra_0_c) = WB_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+ OP_A_INT <= WB_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c);
+ else
+ OP_A_INT <= REG_FILE_MEM(to_integer(unsigned(OF_CTRL_BUS_I(ctrl_ra_3_c downto ctrl_ra_0_c))));
+ end if;
+
+ -- operand B forwarding --
+ if (WB_FWD_I(fwd_en_c) = '1') and (OF_CTRL_BUS_I(ctrl_rb_3_c downto ctrl_rb_0_c) = WB_FWD_I(fwd_adr_3_c downto fwd_adr_0_c)) then
+ OP_B_INT <= WB_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c);
+ else
+ OP_B_INT <= REG_FILE_MEM(to_integer(unsigned(OF_CTRL_BUS_I(ctrl_rb_3_c downto ctrl_rb_0_c))));
+ end if;
+ end process OF_FWD;
+
+
+
+ -- Operand Multiplexer ---------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ OP_A_DATA_O <= PC_1D_I when (OF_CTRL_BUS_I(ctrl_ra_is_pc_c) = '1') else OP_A_INT;
+ OP_B_DATA_O <= IMMEDIATE_I when (OF_CTRL_BUS_I(ctrl_rb_is_imm_c) = '1') else OP_B_INT;
+ OP_C_DATA_O <= OP_B_INT;
+
+
+
+end RF_STRUCTURE;
Index: atlas_core/trunk/core/rtl/MMU.vhd
===================================================================
--- atlas_core/trunk/core/rtl/MMU.vhd (nonexistent)
+++ atlas_core/trunk/core/rtl/MMU.vhd (revision 2)
@@ -0,0 +1,204 @@
+-- ########################################################
+-- # << ATLAS Project - MMU >> #
+-- # **************************************************** #
+-- # The memory management unit allows to extend the #
+-- # accessible memory/IO space to up to 4GB. #
+-- # Base registers generate the most significant 16-bit #
+-- # of a true 32-bit addressable system. #
+-- # **************************************************** #
+-- # Last modified: 11.03.2013 #
+-- # **************************************************** #
+-- # by Stephan Nolting 4788, Hanover, Germany #
+-- ########################################################
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.atlas_core_package.all;
+
+entity MMU is
+ port (
+-- ###############################################################################################
+-- ## Global Control ##
+-- ###############################################################################################
+
+ CLK_I : in std_logic; -- global clock line
+ RST_I : in std_logic; -- global reset line, sync, high-active
+ HALT_I : in std_logic; -- inverted clock enable
+
+-- ###############################################################################################
+-- ## Processor Interface ##
+-- ###############################################################################################
+
+ CP_EN_I : in std_logic; -- access coprocessor
+ CP_OP_I : in std_logic; -- data transfer/processing
+ CP_RW_I : in std_logic; -- read/write access
+ CP_CMD_I : in std_logic_vector(cp_cmd_width_c-1 downto 0); -- register addresses / cmd
+ CP_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- write data
+ CP_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- read data
+ SYS_MODE_I : in std_logic; -- current operating mode
+ INT_EXE_I : in std_logic; -- interrupt beeing executed
+ MMU_IRQ_O : out std_logic; -- mmu interrupt request
+
+-- ###############################################################################################
+-- ## Bus Unit Interface ##
+-- ###############################################################################################
+
+ CACHE_ERROR_I : in std_logic; -- bus access error
+ CACHE_SYNC_I : in std_logic; -- cache is sync
+ CACHE_CLR_O : out std_logic; -- reload cache
+ CACHE_FLUSH_O : out std_logic; -- synchronize cache with mem
+ MEM_DIR_ACC_O : out std_logic; -- direct access (bypass cache)
+ MEM_IP_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction page
+ MEM_DP_ADR_O : out std_logic_vector(data_width_c-1 downto 0) -- data page
+ );
+end MMU;
+
+architecture MMU_STRUCTURE of MMU is
+
+ -- Registers --
+ signal MMU_CTRL : std_logic_vector(15 downto 0); -- r0: control register
+ signal MMU_SCRATCH : std_logic_vector(15 downto 0); -- r1: scratch register
+ signal MMU_SYS_I_PAGE : std_logic_vector(15 downto 0); -- r2: system mode instruction page
+ signal MMU_SYS_D_PAGE : std_logic_vector(15 downto 0); -- r3: system mode data page
+ signal MMU_USR_I_PAGE : std_logic_vector(15 downto 0); -- r4: user mode instruction page
+ signal MMU_USR_D_PAGE : std_logic_vector(15 downto 0); -- r5: user mode data page
+ signal MMU_I_PAGE_LINK : std_logic_vector(15 downto 0); -- r6: instruction link page
+ signal MMU_D_PAGE_LINK : std_logic_vector(15 downto 0); -- r7: data link page
+
+ -- Control register bits --
+ constant mmu_ctrl_cflush_c : natural := 0; -- w: flush cache
+ constant mmu_ctrl_cclr_c : natural := 1; -- w: clear cache
+ constant mmu_ctrl_da_c : natural := 2; -- r/w: direct access
+ constant mmu_ctrl_csync_c : natural := 3; -- r: cache is sync
+ constant mmu_ctrl_bus_err_c : natural := 4; -- r/w bus error interrupt/ack
+
+ -- Commands --
+ -- applied on any register
+ constant cmd_flush_cache_c : std_logic_vector(2 downto 0) := "000"; -- 0: flush cache
+ constant cmd_clear_cache_c : std_logic_vector(2 downto 0) := "001"; -- 1: reload cache
+ constant cmd_en_dir_acc_c : std_logic_vector(2 downto 0) := "010"; -- 2: enable direct access
+ constant cmd_dis_dir_acc_c : std_logic_vector(2 downto 0) := "011"; -- 3: disable diect access
+ constant cmd_ack_bus_err_c : std_logic_vector(2 downto 0) := "100"; -- 4: acknowledge bus error interupt
+ constant cmd_link_copy_c : std_logic_vector(2 downto 0) := "101"; -- 5: reload last accessed system pages
+
+begin
+
+ -- MMU Register Update ---------------------------------------------------------------------------------
+ -- --------------------------------------------------------------------------------------------------------
+ MMU_REG_UP: process(CLK_I)
+ begin
+ if rising_edge(CLK_I) then
+ if (RST_I = '1') then
+ MMU_CTRL <= (others => '0');
+ MMU_SCRATCH <= (others => '0');
+ MMU_SYS_I_PAGE <= (others => '0');
+ MMU_SYS_D_PAGE <= (others => '0');
+ MMU_USR_I_PAGE <= (others => '0');
+ MMU_USR_D_PAGE <= (others => '0');
+ MMU_I_PAGE_LINK <= (others => '0');
+ MMU_D_PAGE_LINK <= (others => '0');
+ MEM_IP_ADR_O <= (others => '0');
+ MEM_DP_ADR_O <= (others => '0');
+ CP_DAT_O <= (others => '0');
+ elsif (HALT_I = '0') then
+
+ -- Defaults --
+ CP_DAT_O <= (others => '0');
+ MMU_CTRL(mmu_ctrl_csync_c) <= CACHE_SYNC_I;
+ MMU_CTRL(mmu_ctrl_bus_err_c) <= MMU_CTRL(mmu_ctrl_bus_err_c) or CACHE_ERROR_I;
+
+ -- Exception Processing ----------------------------------------------------------
+ -- ----------------------------------------------------------------------------------
+ if (INT_EXE_I = '1') then
+-- MMU_CTRL(mmu_ctrl_cflush_c) <= not CACHE_SYNC_I; -- sync cache
+-- MMU_CTRL(mmu_ctrl_cclr_c) <= CACHE_SYNC_I; -- force reload when sync again
+ MMU_SYS_I_PAGE <= (others => '0'); -- i-page zero
+ MMU_SYS_D_PAGE <= (others => '0'); -- d-page zero
+ MEM_IP_ADR_O <= (others => '0'); -- i-page zero
+ MEM_DP_ADR_O <= (others => '0'); -- d-page zero
+ MMU_I_PAGE_LINK <= MMU_SYS_I_PAGE; -- save current sys i-page
+ MMU_D_PAGE_LINK <= MMU_SYS_D_PAGE; -- save current sys d-page
+
+ -- Data Transfer / CMD Procesing -------------------------------------------------
+ -- ----------------------------------------------------------------------------------
+ elsif (CP_EN_I = '1') then
+ if (CP_OP_I = '1') then -- Data Transfer
+ -- --------------------------------------------------------
+ if (CP_RW_I = '1') then -- valid write
+ case (CP_CMD_I(cp_op_a_msb_c downto cp_op_a_lsb_c)) is
+ when "000" => MMU_CTRL <= CP_DAT_I; -- control register
+ MMU_CTRL(mmu_ctrl_csync_c) <= CACHE_SYNC_I;
+ MMU_CTRL(mmu_ctrl_bus_err_c) <= MMU_CTRL(mmu_ctrl_bus_err_c) or CACHE_ERROR_I;
+ when "001" => MMU_SCRATCH <= CP_DAT_I; -- scratch register
+ when "010" => MMU_SYS_I_PAGE <= CP_DAT_I; -- system instruction page
+ when "011" => MMU_SYS_D_PAGE <= CP_DAT_I; -- system data page
+ when "100" => MMU_USR_I_PAGE <= CP_DAT_I; -- user instruction page
+ when "101" => MMU_USR_D_PAGE <= CP_DAT_I; -- user data page
+ when "110" => MMU_I_PAGE_LINK <= CP_DAT_I; -- instruction page link
+ when "111" => MMU_D_PAGE_LINK <= CP_DAT_I; -- data page link
+ when others => NULL; -- do nothing
+ end case;
+ else -- valid read
+ case (CP_CMD_I(cp_op_b_msb_c downto cp_op_b_lsb_c)) is
+ when "000" => CP_DAT_O <= MMU_CTRL; -- control register
+ when "001" => CP_DAT_O <= MMU_SCRATCH; -- scratch register
+ when "010" => CP_DAT_O <= MMU_SYS_I_PAGE; -- system instruction page
+ when "011" => CP_DAT_O <= MMU_SYS_D_PAGE; -- system data page
+ when "100" => CP_DAT_O <= MMU_USR_I_PAGE; -- user instruction page
+ when "101" => CP_DAT_O <= MMU_USR_D_PAGE; -- user data page
+ when "110" => CP_DAT_O <= MMU_I_PAGE_LINK; -- instruction page link
+ when "111" => CP_DAT_O <= MMU_D_PAGE_LINK; -- data page link
+ when others => CP_DAT_O <= (others => '0'); -- dummy output
+ end case;
+ end if;
+ else -- Command Processing
+ -- --------------------------------------------------------
+ case CP_CMD_I(cp_cmd_msb_c downto cp_cmd_lsb_c) is
+ when cmd_flush_cache_c => MMU_CTRL(mmu_ctrl_cflush_c) <= '1'; -- flush cache
+ when cmd_clear_cache_c => MMU_CTRL(mmu_ctrl_cclr_c) <= '1'; -- clear cache
+ when cmd_en_dir_acc_c => MMU_CTRL(mmu_ctrl_da_c) <= '1'; -- enable direct access
+ when cmd_dis_dir_acc_c => MMU_CTRL(mmu_ctrl_da_c) <= '0'; -- disable direct access
+ when cmd_ack_bus_err_c => MMU_CTRL(mmu_ctrl_bus_err_c) <= '0'; -- ack bus error
+ when cmd_link_copy_c => MMU_SYS_I_PAGE <= MMU_I_PAGE_LINK; -- reload old i-page
+ MMU_SYS_D_PAGE <= MMU_D_PAGE_LINK; -- reload old d-page
+ when others => NULL; -- undefined operation
+ end case;
+ end if;
+
+ -- Auto Update -------------------------------------------------------------------
+ -- ----------------------------------------------------------------------------------
+ else
+ -- Control Register --
+ MMU_CTRL(mmu_ctrl_csync_c) <= CACHE_SYNC_I;
+ MMU_CTRL(mmu_ctrl_cflush_c) <= '0'; -- auto clear cache flush bit
+ MMU_CTRL(mmu_ctrl_cclr_c) <= '0'; -- auto clear cache clear bit
+ MMU_CTRL(mmu_ctrl_bus_err_c) <= MMU_CTRL(mmu_ctrl_bus_err_c) or CACHE_ERROR_I;
+
+ -- Page update --
+ if (SYS_MODE_I = user_mode_c) then
+ MEM_IP_ADR_O <= MMU_USR_I_PAGE;
+ MEM_DP_ADR_O <= MMU_USR_D_PAGE;
+ else
+ MEM_IP_ADR_O <= MMU_SYS_I_PAGE;
+ MEM_DP_ADR_O <= MMU_SYS_D_PAGE;
+ end if;
+ end if;
+
+ end if;
+ end if;
+ end process MMU_REG_UP;
+
+ -- Interrupt Request --
+ MMU_IRQ_O <= MMU_CTRL(mmu_ctrl_bus_err_c);
+
+ -- Cache control --
+ CACHE_CLR_O <= MMU_CTRL(mmu_ctrl_cclr_c);
+ CACHE_FLUSH_O <= MMU_CTRL(mmu_ctrl_cflush_c);
+ MEM_DIR_ACC_O <= MMU_CTRL(mmu_ctrl_da_c);
+
+
+
+end MMU_STRUCTURE;
Index: atlas_core/trunk/core/doc/Atlas Processor Datasheet.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: atlas_core/trunk/core/doc/Atlas Processor Datasheet.pdf
===================================================================
--- atlas_core/trunk/core/doc/Atlas Processor Datasheet.pdf (nonexistent)
+++ atlas_core/trunk/core/doc/Atlas Processor Datasheet.pdf (revision 2)
atlas_core/trunk/core/doc/Atlas Processor Datasheet.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: atlas_core/trunk/core/doc/wbspec_b4.pdf
===================================================================
--- atlas_core/trunk/core/doc/wbspec_b4.pdf (nonexistent)
+++ atlas_core/trunk/core/doc/wbspec_b4.pdf (revision 2)
@@ -0,0 +1,14797 @@
+%PDF-1.4
+%äüöß
+2 0 obj
+<>
+stream
+xœŒ½ËŽt=’¸§ˆu
+ÞI ð]ªî´ëA³´š‘Ô‹
+ £Í¼þdÐÝÜÍÉÌ’Ð@uò7;<¼8ýÆó½¾Òóÿ{ü¿Ï×óõ•Ÿmµ¯öœ5}Íçÿü/Ïÿëžÿýñ¯Ïϯ%Mý½?kß(ü¾‘eåôýÿûóÿü?Žÿð?ÿÛ£õ¯ñ¬e|·ÞVæ7¹´þöD«}~·DPÿöøó?èÃëšþÆÏúó_m}Xê|þõÿyþ»IÏÒŸý¯ÿéO¯ôʯòª¤?½Ú«ÿñùO¯ñiÌ×zýÓëÏüç¿þÇÇ?ÿõñ¯BûýF÷ýÊ©})a~¦©„üã7<8Êþ³þñÍÙ>m¥ÿpï¿ä÷úüôçÏÿüûý_ÿòúçýßÿ%½¾‘)}ÿ‘?ÿ!•o™T?2©ýñåOß,åO©ÿ&‘ÿ–íJãó_?øÆ+mšñå’ß=Ÿßÿ’>D"¦üúûß{ùò=ôõxùôOMò>£TýMøçϘû?ü%ý{y²4÷ ¥¿üþNïå?þã¿|ÿO~}3~¿ðyá¿|^KÁYßvØ#þSZZú^Px«*SÚÒL¯ïŽ~3æ´yË/´öTH·^»9z»K;Ö¾gY^é—‡§U¿—ÒOïûÚ÷è¤Ï£Ò~ÉWšñ]>{¢ŒñUž#ÏïIýõMØ>;Ó7Æç?ŽýÔöÙ7.?žÿ÷ûñïþû>ÿò?žÿú¿Ø`Ÿ_÷¦y}/4Ö÷ÖÜ„ô¤ýõIÕÅ›>¨ýï=(íÿû¢2Ú7CÍÏÛüîö,ßÿá[ò¿þÃãóæ¿ý¼‰Fº¦ôý[¯ãû‰ïOëÙÛgþöÔ_¾[u·ê÷À}äæn{ýðþíñigïù›ão[äïVú–Ö7®½¾%¤Uvkêæ–L–×gìúžïß^Ÿ¡éu‰äw+S«í罶¬¯òõéõg±~Xæ§UûÖ›üvUY_ùÃÚ_Ÿw}õÝÏ—H~ã¾9[–w}ô-·ä·¬OVâߤ—ß%ySýï’v«ù»4¼söѱP2VQúT0veIüäÝÊARçÆZÕûŽñO„Ï[ÝïUlö¥%+£í¿“ÿs+Üc³íUÐ|Mô÷yÿ–3–¢}B½{É“?«ïÓÚJ{¦—JʼËúü¼SoUK{E6}úgVúVÒú^ƒÖÎ÷FmʱÑgK«é³Ñ*ÄXm½çž©½Sª²Øjü¬Íïm+»òÛ6PÆú1 ö®ü’})=~íµ‰}™ô½Œp&°tuÈRTή{*»þ"R¨¿·R˜[EdUm·êA¤Pþ@÷\v]¥¢kúM£Pþ@Û^ÂS—RÝ~Ð(¢¶çLWô”×$ ª° +iûV&Ý{ÅWIw-éD6-?T5ô—)ǽŒtN™JÀ$þ†žýÖ¥Ðc·ÆEe`ˆÛ“ œv«_Tüd÷ÍU‡Ïµo"…Bø½ÕöÚÂC~Ùv)ÔÅ?à¹w\S—±"…Bø6á¹Ñ"‘=ul¶©§KÚ/ š¶‡ ËÚJô¶&¾»¼©püðÁÄDè² ÿ}¨ÿýwé˜~ž$¿ §ñв¿
+(¢K¶ø;ûT7º×é8TÇEe`ˆ3¸p»¨°Ì邞ЃÝr§Á®–Ð.ùF/ÁZpÛng0Þµþ`\¬Ü¸ðMÅZ‚Àҵƕ
+’CÅ@œÁƒì¨~Ð l‚Íƒæ ’Zû;6Ý/=u ,¦À SLLÀ›ÆLt²õ¨6]9ˆ
+a†¦ ÍÑN
+–¡X,~ÂÅY.&ê<ˆè€ rؽ§¥Ë&/ýÙäæÛ E3OÝ0‡¡‰Ï=l˜ž\ømÛ§û¹…ßv·‚7@g¶a\Ôßk¨]k+1¢65jn¯Ô=O#á‰é0*ó•ÑÛÐÁÒ`3+!þ†‡[§y™|a¦2sâÒa±#`ûf²*˜Ê:
+q1B>+:ú.ð-˜ÊìDˆ;øtuÒEÀ͇ñ<=£fF¦Sâþ°šéo§1 ˆšÉÕÜ{OOõÀMðsÜZÛ?ÛÛµçé®õ¯ †øQòçzh9•!ÎàÀå¢:À™Àî-ö«Õ¢oq·m…bqˆõ:~Ÿ_ˆ»],&žø_ý¢ VqQ[fîiÊ2 sÙ»H·|~ñÌyG”–[nÚÚ'ÜßÿöÝóíZôÝïßúþM$»zE9óÞx2@]þuÞ–×C&¿<Ž_Ûß˲ærQçÒ÷¶ €Y|#}´x?õ¢Q „?Àí´ÀqÊM]¬y)ÔÅß¡óg#•ÎúÒèÜRpÝ`¼ß!]oâý±ê%qéöÚìM‡¾Ð2•uâ>XÓÞ2íÖM†kêJ÷—8;©\^ª7¸¼öù\ejŠ¨*à’ôPZÚ’3dÇ°JRkbÏRÉj3 UC‹%‹J
+KQÉ©¿uz^Ñ~&mI?÷Ä–Š>?ð÷ ÿ¾Ñ^Q)ª«¶ïîSvÝ^H÷•¬:gjKä0:ÆʳÈYym9U¾å¥jZ–Ém/‘¹¼\¿ï(½éþ‹¶boôñ
+¨1hìáe;z†Ö¢Vƾx@G,½ZZÈÔÒ„KçJP]W†´°Nöägö÷ßEW‚ìO¬ ù-é
+Z{/_Øñûkfë•<=9$¦¿4×Oe¸[Fдƒ³
+ÖªÊÇÚ|‘Û£ÏÊö›øŠú˜õݤÿXG]½;
+waL$,ƒÝ¸žÅy`”±^Š†«uk:Ó,b½È9ø¢3€V’ýýRv…ü†õ=¼¡¨é:Á¢<ÕÇt&¤p&è˜è© ½*§Bq]Š³9pú»°íÌ<8ø§Ï‡>;ÛYÕðìݲˆ¤žiº«E7ßÉÃßÍÆš¢aÌ~Ñ`Ú(ØçÉGÏNhoušáÂ@µ 9*gu%Ó°½Þ;IVt1…Õt_é8”®£Rµ%ã'o$ñ D{Ú]V:ïú[‹ZÍv[&CmY½b}à|0Ë¡ôý–Ãú×v«ëžª¤ö©Ò&Ÿ8°t<¦‡hÕb*‰1®°,Ô6[f©±æ‚K%ãIÛAë¢5I/&Nƒ¨«Yp]Mд/ÕЋÎݧ²&qNˆu&gÈÞ™li%õpbuÏ祑ÄE'V¶U/> ŸKX1zŽÚûe´vöÚo,™U–
+Ù[zîg=©f8çÙ ÎùžÕ”oên;%ã42+¥²/%sß¡gê>›«Î0l$h^²ádφS;@ì”,ü–”eÑHz«»pÁ&³9†)¿@Ûv·ÏDÿuX§‹<ð¡þ8,ðJ®ÙPëL5¶Ï’Z¾°‰ž®k)«õ܃݃
+>h]wÞ¹ë~–ᶀž Ó΃BžœÈ8_D[DϬ©~FJ4 lr‘Ä>‘*ì½ùT¯fïÒBšJvp7-/ÖÖ{-a©¦/ºýZæk™õÕÙj
++Ò´)Õ6è9ÑlS¨Kõ~‘ª¶-Ì“=î;¼áõd¿¹Ã2µ‰$sÔ¹dú;)GÖ=RŸ–kPÏ¿°¶±g¿”ŸOãŠÕ£¿a½{6ãˆ+)K•@Y1îÀúºRd‰Äßâ–5 3:sÐ(PD7HÇlºNø0~ÓPõ0Œë 2(„:è