OpenCores
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
    /atlas_core
    from Rev 20 to Rev 21
    Reverse comparison

Rev 20 → Rev 21

/trunk/asm/atlas_asm.exe Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
trunk/asm/atlas_asm.exe Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/asm/src/atlas_asm.layout =================================================================== --- trunk/asm/src/atlas_asm.layout (nonexistent) +++ trunk/asm/src/atlas_asm.layout (revision 21) @@ -0,0 +1,10 @@ +[Editors] +Focused=0 +Order=0 +[Editor_0] +Open=1 +Top=1 +CursorCol=36 +CursorRow=1638 +TopLine=1611 +LeftChar=1 Index: trunk/asm/src/atlas_asm.dev =================================================================== --- trunk/asm/src/atlas_asm.dev (nonexistent) +++ trunk/asm/src/atlas_asm.dev (revision 21) @@ -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=atlas_asm.exe +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=1.0.0.0 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +AutoIncBuildNr=0 +SyncProduct=1 + +[Unit1] +FileName=main.cpp +CompileCpp=1 +Folder=atlas_asm +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + Index: trunk/asm/src/job.xasm =================================================================== --- trunk/asm/src/job.xasm (nonexistent) +++ trunk/asm/src/job.xasm (revision 21) @@ -0,0 +1,397 @@ + + + + + + + + + + + + +.EQU SYS0_CORE C0 +.EQU COM0_CORE C2 +.EQU LR R7 + + + + + + +RESET_VEC: + B RESET + +X_INT0_VEC: + B ERR_HANDLER + +X_INT1_VEC: + B ERR_HANDLER + +CMD_ERR_VEC: + B ERR_HANDLER + +SWI_VEC: + B ERR_HANDLER + + + + + + + +ERR_HANDLER: + BL UART_LINEBREAK + + LDIL R2, LOW[ERR_STRING] + LDIH R2, HIGH[ERR_STRING] + BL UART_PRINT + BL UART_LINEBREAK + B #+0 + + + + + + +RESET: + + + LDIL R2, LOW[STRING_INTRO] + LDIH R2, HIGH[STRING_INTRO] + BL UART_PRINT_BR + +RESTART: + + + LDIL R2, LOW[STRING_SEED] + LDIH R2, HIGH[STRING_SEED] + BL UART_PRINT + BL RECEIVE_HEX_WORD + MCR #1, SYS0_CORE, R4, #5 + BL UART_LINEBREAK + + + LDIL R2, LOW[STRING_TAPS] + LDIH R2, HIGH[STRING_TAPS] + BL UART_PRINT + BL RECEIVE_HEX_WORD + CBR R4, R4, #15 + MCR #1, SYS0_CORE, R4, #6 + BL UART_LINEBREAK + + +FOREVER: + LDIL R1, #'0' + + BL UART_SENDBYTE + LDIL R1, #'x' + BL UART_SENDBYTE + + + MRC #1, R4, SYS0_CORE, #5 + BL PRINT_HEX_STRING + BL UART_LINEBREAK + + + MRC #1, R0, COM0_CORE, #0 + STB R0, #15 + BTS RESTART + + + B FOREVER + + + + + + + + + + + + +UART_PRINT_BR: + + + + LDIL R3, #0XFF + MOV R4, LR + B UART_PRINT_LOOP + + + + + + + +UART_PRINT: + + + + CLR R3 + MOV R4, LR + +UART_PRINT_LOOP: + + + LDR R0, R2, +#1, POST, ! + LDIL R1, #0X00 + LDIH R1, #0XFF + AND R1, R0, R1 + SFTS R1, R1, #SWP + BEQ UART_PRINT_LOOP_END + BL UART_SENDBYTE + B UART_PRINT_LOOP + +UART_PRINT_LOOP_END: + + + MOV LR, R4 + TEQ R3, R3 + RBAEQ LR + + + + + + + + +UART_LINEBREAK: + + + + MOV R2, LR + LDIL R1, #0X0D + BL UART_SENDBYTE + LDIL R1, #0X0A + MOV LR, R2 + + + + + + + + +UART_SENDBYTE: + + + + MRC #1, R0, COM0_CORE, #2 + STB R0, #5 + BTS UART_SENDBYTE + MCR #1, COM0_CORE, R1, #0 + RET LR + + + + + + + +UART_RECEIVEBYTE: + + + + MRC #1, R0, COM0_CORE, #0 + STBI R0, #15 + BTS UART_RECEIVEBYTE + LDIH R0, #0X00 + RET LR + + + + + + + + +RECEIVE_HEX_WORD: + + + + MOV R2, LR + LDIL R4, #0 + LDIL R3, #4 + +RECEIVE_HEX_WORD_LOOP: + + + BL UART_RECEIVEBYTE + + + LDIL R1, #'F' + CMP R0, R1 + BMI #+3 + LDIL R1, #32 + SUB R0, R0, R1 + + + LDIL R1, #'0' + CMP R0, R1 + BMI RECEIVE_HEX_WORD_LOOP + + LDIL R1, #'F' + CMP R1, R0 + BMI RECEIVE_HEX_WORD_LOOP + + LDIL R1, #'9' + CMP R1, R0 + BLS RECEIVE_HEX_WORD_ECHO + + LDIL R1, #'A' + CMP R0, R1 + BHI RECEIVE_HEX_WORD_LOOP + + +RECEIVE_HEX_WORD_ECHO: + + + MOV R1, R0 + BL UART_SENDBYTE + + + LDIL R0, #'0' + SUB R1, R1, R0 + LDIL R0, #9 + CMP R0, R1 + BLS #+2 + DEC R1, R1, #7 + + + SFT R4, R4, #ROL + SFT R4, R4, #ROL + SFT R4, R4, #ROL + SFT R4, R4, #ROL + ORR R4, R4, R1 + + + DECS R3, R3, #1 + BNE RECEIVE_HEX_WORD_LOOP + + RET R2 + + + + + + + + +PRINT_HEX_STRING: + + + + MOV R6, LR + + + SFT R2, R4, #ROL + SFT R2, R2, #ROL + SFT R2, R2, #ROL + SFT R2, R2, #ROL + BL CONV_HEX_COMP + BL UART_SENDBYTE + + + SFT R2, R4, #SWP + BL CONV_HEX_COMP + BL UART_SENDBYTE + + + SFT R2, R4, #LSR + SFT R2, R2, #LSR + SFT R2, R2, #LSR + SFT R2, R2, #LSR + BL CONV_HEX_COMP + BL UART_SENDBYTE + + + MOV R2, R4 + BL CONV_HEX_COMP + BL UART_SENDBYTE + + RET R6 + + +CONV_HEX_COMP: + LDIL R1, #0X0F + + AND R2, R2, R1 + + LDIL R1, #9 + CMP R1, R2 + BCS #+3 + + LDIL R1, #48 + B #+2 + LDIL R1, #55 + ADD R1, R1, R2 + RET LR + + + + + + + +ERR_STRING: +.dw #17784 +.dw #25445 +.dw #28788 +.dw #26991 +.dw #28207 +.dw #26990 +.dw #29797 +.dw #29298 +.dw #30064 +.dw #29728 +.dw #25970 +.dw #29295 +.dw #29217 +.dw #0 +STRING_INTRO: +.dw #21089 +.dw #28260 +.dw #28525 +.dw #8270 +.dw #30061 +.dw #25189 +.dw #29216 +.dw #18277 +.dw #28261 +.dw #29281 +.dw #29807 +.dw #29184 +STRING_SEED: +.dw #17774 +.dw #29797 +.dw #29216 +.dw #19526 +.dw #21330 +.dw #8307 +.dw #25957 +.dw #25632 +.dw #10292 +.dw #26725 +.dw #30761 +.dw #14880 +.dw #12408 +.dw #0 +STRING_TAPS: +.dw #17774 +.dw #29797 +.dw #29216 +.dw #19526 +.dw #21330 +.dw #8308 +.dw #24944 +.dw #29472 +.dw #10292 +.dw #26725 +.dw #30761 +.dw #14880 +.dw #12408 +.dw #0 Index: trunk/asm/src/main.cpp =================================================================== --- trunk/asm/src/main.cpp (nonexistent) +++ trunk/asm/src/main.cpp (revision 21) @@ -0,0 +1,1771 @@ +#include +#include +#include +#include + +using namespace std; + + // global definition table + char definition[4*2048][16]; + char def_alias[4*2048][16]; + int def_cnt = 0; + + // global mem-data table + bool is_dw[65536]; + + // program's xor checksum + int xor_checksum = 0; + + // global branch-label table + char c_label_tab[6*2048][32]; + int i_label_tab[6*2048]; + + // global error/warning indicator + int error_cnt = 0; + int warning_cnt = 0; + + // image name + char image_name[10] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}; + + // function prototypes + void includer(char *main_file, const char *output); + void convert_strings(const char *input_file, const char *output_file); + void pre_processor(const char *input_file, const char *output_file); + int conv_shift(char *input_string, int line); + int hexc_to_int(char input_char); + 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 conv_cpx_op(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); + int assemble(const char *input_file, const char *output_file, const char *bin_output_file); + int main(int argc, char *argv[]); + + +// ***************************************************************************************************************** +// Copy included files to main file +// ***************************************************************************************************************** +void includer(char *main_file, const char *output_file){ + + FILE *input, *inc_file, *output; + char line_input[1024]; + int i = 0, j = 0; + char *cut_out; + char txt_string[256]; + char buf_string[256]; + char in_file_name[256]; + bool found = false; + char ch; + + // open input file + input = fopen(main_file, "r"); + if(input == NULL){ + printf("INCLUDER: Input file error!"); + exit(1); + } + + // open output file (main working file) + output = fopen(output_file, "w+"); + if(output == NULL){ + printf("INCLUDER: Main file error!"); + exit(1); + } + + // get line + while(fgets(line_input, 512, input) != NULL){ + + // clear working string + for(i=0; i 96) and (txt_string[i] < 123)) + txt_string[i] = txt_string[i] - 32; + } + strcpy(tmp_string, txt_string); // make a copy + strcpy(buf_string, txt_string); // make a copy + + // find ".string" definiton + 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; + } + + // insert label? + if (insert_label == true){ + strncat(buf_string, tmp_string, strlen(tmp_string)); + strncat(buf_string, txt_string, strlen(txt_string)); + strcpy(txt_string, buf_string); + } + + // find empty lines + empty_line = true; + 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++; + } + + + // find memory reserve definitions +mem_reserve_loop: + found = false; + for(i=0; i! (line %d)\n", input_string, line); + error_cnt++; + } + + return sft; +} + + +// ***************************************************************************************************************** +// Convert Hex char to int +// ***************************************************************************************************************** +int hexc_to_int(char input_char){ + + int ret = -1; + + switch(input_char){ + case '0': ret = 0; break; + case '1': ret = 1; break; + case '2': ret = 2; break; + case '3': ret = 3; break; + case '4': ret = 4; break; + case '5': ret = 5; break; + case '6': ret = 6; break; + case '7': ret = 7; break; + case '8': ret = 8; break; + case '9': ret = 9; break; + case 'A': ret = 10; break; + case 'B': ret = 11; break; + case 'C': ret = 12; break; + case 'D': ret = 13; break; + case 'E': ret = 14; break; + case 'F': ret = 15; break; + } + + return ret; +} + + +// ***************************************************************************************************************** +// 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; +} + + +// ***************************************************************************************************************** +// Convert CPX flag option +// ***************************************************************************************************************** +int conv_cpx_op(char *input_string, int line){ + + int opt = 0; + + if (strcmp(input_string, "C_ANDZ") == 0) + opt = 0; + else if (strcmp(input_string, "C_ORZ") == 0) + opt = 2; + else if (strcmp(input_string, "NOTC_ANDZ") == 0) + opt = 4; + else if (strcmp(input_string, "NOTC_ORZ") == 0) + opt = 6; + else if (strcmp(input_string, "") == 0) + opt = 0; + else { + printf("ERROR: Invalid CPX 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; + bool pos = false; + int i = 0; + + if(input_label[0] == '#'){ + for(i=0; i not found! (line %d)\n", input_label, line); + error_cnt++; + } + + // out of reach? + if (line != -1){ // marker: full 16-bit range + if ((offset > 255) or (offset < -256)){ + printf("ERROR: Label <%s> out of reach (offset: %d bytes)! (line %d)\n", input_label, offset*2, line); + error_cnt++; + } + offset = offset & 511; // make it nine bit wide + } + + 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 ' + temp[0] = input_string[1]; + temp[1] = '\0'; + imm = (int)temp[0]; + goto skip_analysis; + } + + // any label reference definition? + if ((input_string[0] == '[')){ + for(i=1; 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, -1)-2)*2) >> 16) & 255; // low immediate of 32-bit immediate + else + imm = ((find_offset(temp, -1)-2)*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, -1)-2)*2) >> 24) & 255; // high immediate of 32-bit immediate + else + imm = (((find_offset(temp, -1)-2)*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){ + if (conv_reg(arg[2], line) == conv_reg(arg[3], line)) { printf("WARNING: Redundant SUB will result in NEG instruction! (line %d)\n", line); warning_cnt++;} + 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], "NEG") == 0) + opcode = (4<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[2], line); + else if (strcmp(arg[0], "SBC") == 0){ + if (conv_reg(arg[2], line) == conv_reg(arg[3], line)) { printf("WARNING: Redundant SBC will result in NEC instruction! (line %d)\n", line); warning_cnt++;} + 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], "NEC") == 0) + opcode = (5<<10) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | conv_reg(arg[2], line); + else if ((strcmp(arg[0], "CMP") == 0) or (strcmp(arg[0], "CMPS") == 0)) + opcode = (6<<10) | (1<<3) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[2], line); + else if ((strcmp(arg[0], "CPX") == 0) or (strcmp(arg[0], "CPXS") == 0)) + opcode = (7<<10) | (1<<3) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[2], line) | (conv_cpx_op(arg[3], line)<<7); + 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); warning_cnt++;} + 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); warning_cnt++;} + 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)<<4) | conv_reg(arg[2], line); + else if ((strcmp(arg[0], "TST") == 0) or (strcmp(arg[0], "TSTS") == 0)) + opcode = (14<<10) | (1<<3) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[2], 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){ + if (conv_reg(arg[2], line) == conv_reg(arg[3], line)) { printf("WARNING: Redundant SUBS will result in NEGS instruction! (line %d)\n", line); warning_cnt++;} + 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], "NEGS") == 0) + opcode = (4<<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], "SBCS") == 0){ + if (conv_reg(arg[2], line) == conv_reg(arg[3], line)) { printf("WARNING: Redundant SBCS will result in NECS instruction! (line %d)\n", line); warning_cnt++;} + 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], "NECS") == 0) + opcode = (5<<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], "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); warning_cnt++;} + 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); warning_cnt++;} + 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)<<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)<<4) | (1<<2); + else if ((strcmp(arg[0], "STPCU") == 0) or (strcmp(arg[0], "GTU") == 0) or (strcmp(arg[0], "RETU") == 0)) // goto [register] and switch to user mode + opcode = (13<<10) | (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)<<4) | (1<<1); + else if ((strcmp(arg[0], "STPCUI") == 0) or (strcmp(arg[0], "GTUI") == 0) or (strcmp(arg[0], "RETUI") == 0)) // goto [register] and set global xint flag and switch to user mode + opcode = (13<<10) | (conv_reg(arg[1], line)<<4) | (1<<1) | (1<<0); + else if ((strcmp(arg[0], "STPCUL") == 0) or (strcmp(arg[0], "GTUL") == 0) or (strcmp(arg[0], "RETUL") == 0)) // goto [register] and switch to user mode and link + opcode = (13<<10) | (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)<<4) | (1<<2) | (1<<1); + else if ((strcmp(arg[0], "STPCUIL") == 0) or (strcmp(arg[0], "GTUIL") == 0) or (strcmp(arg[0], "RETUIL") == 0)) // goto [register] and set global xint flag and switch to user mode and link + opcode = (13<<10) | (conv_reg(arg[1], line)<<4) | (1<<2) | (1<<1) | (1<<0); + else if ((strcmp(arg[0], "STPCX") == 0) or (strcmp(arg[0], "GTX") == 0) or (strcmp(arg[0], "RETX") == 0)) // goto [register] and switch to previous mode + opcode = (13<<10) | (1<<7) | (conv_reg(arg[1], line)<<4); + 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 previous mode + opcode = (13<<10) | (1<<7) | (conv_reg(arg[1], line)<<4) | (1<<1); + else if ((strcmp(arg[0], "STPCXL") == 0) or (strcmp(arg[0], "GTXL") == 0) or (strcmp(arg[0], "RETXL") == 0)) // goto [register] and switch to previous mode and link + opcode = (13<<10) | (1<<7) | (conv_reg(arg[1], line)<<4) | (1<<2); + 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 previous mode and link + opcode = (13<<10) | (1<<7) | (conv_reg(arg[1], line)<<4) | (1<<2) | (1<<1); + + 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) or (strcmp(arg[0], "BAL") == 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) or (strcmp(arg[0], "BALL") == 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 select-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 select-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 select-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 select-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], "SPR") == 0) // store parity-bit to t-flag + opcode = (13<<12) | (1<<11) | (1<<10) | (1<<8) | (0<<7) | (conv_reg(arg[1], line)<<4) | conv_imm(arg[2], 15, line); + else if (strcmp(arg[0], "STBR") == 0) // store select-bit to t-flag (index by register) + opcode = (13<<12) | (1<<11) | (1<<10) | (1<<9) | (0<<7) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[2], line); + else if (strcmp(arg[0], "STBRI") == 0) // store inverted select-bit to t-flag (index by register) + opcode = (13<<12) | (1<<11) | (1<<10) | (1<<9) | (1<<7) | (conv_reg(arg[1], line)<<4) | conv_reg(arg[2], line); + else if (strcmp(arg[0], "LDB") == 0) // load select-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 ((conv_indexing(arg[4], line)==1) and (arg[5][0] != '!')){ + printf("WARNING: Redundant LDR indexing instruction. (line %d)\n", line); + warning_cnt++; + } + } + } + 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 ((conv_indexing(arg[4], line)==1) and (arg[5][0] != '!')){ + printf("WARNING: Redundant STR indexing instruction. (line %d)\n", line); + warning_cnt++; + } + } + } + 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); + } + + // Special Commands + // --------------------------------------------------------------------------------------------------------- + else if (strcmp(arg[0], "SLEEP") == 0){ // go to sleep + if (strcmp(arg[1], "") == 0) + temp = 0; + else + temp = conv_imm(arg[1], 511, line); + opcode = (61<<10) | (0<<9) | temp; // +9-bit tag + } + else if (strcmp(arg[0], "RBAEQ") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 0<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBANE") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 1<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBACS") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 2<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBACC") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 3<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBAMI") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 4<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBAPL") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 5<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBAVS") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 6<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBAVC") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 7<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBAHI") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 8<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALS") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | ( 9<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBAGE") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | (10<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALT") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | (11<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBAGT") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | (12<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALE") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | (13<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBATS") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | (14<<3) | (conv_reg(arg[1], line)<<0); + else if ((strcmp(arg[0], "RBA") == 0) or (strcmp(arg[0], "RBAAL") == 0)) // register-base branch absolute - always + opcode = (61<<10) | (1<<9) | (1<<8) | (0<<7) | (15<<3) | (conv_reg(arg[1], line)<<0); + + else if (strcmp(arg[0], "RBREQ") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 0<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRNE") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 1<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRCS") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 2<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRCC") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 3<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRMI") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 4<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRPL") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 5<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRVS") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 6<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRVC") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 7<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRHI") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 8<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLS") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | ( 9<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRGE") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | (10<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLT") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | (11<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRGT") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | (12<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLE") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | (13<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRTS") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | (14<<3) | (conv_reg(arg[1], line)<<0); + else if ((strcmp(arg[0], "RBR") == 0) or (strcmp(arg[0], "RBRAL") == 0)) // register-base branch relative - always + opcode = (61<<10) | (1<<9) | (0<<8) | (0<<7) | (15<<3) | (conv_reg(arg[1], line)<<0); + + else if (strcmp(arg[0], "RBALEQ") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 0<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALNE") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 1<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALCS") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 2<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALCC") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 3<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALMI") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 4<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALPL") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 5<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALVS") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 6<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALVC") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 7<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALHI") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 8<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALLS") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | ( 9<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALGE") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | (10<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALLT") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | (11<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALGT") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | (12<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALLE") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | (13<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBALTS") == 0) + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | (14<<3) | (conv_reg(arg[1], line)<<0); + else if ((strcmp(arg[0], "RBAL") == 0) or (strcmp(arg[0], "RBALAL") == 0)) // register-base branch absolute & link - always + opcode = (61<<10) | (1<<9) | (1<<8) | (1<<7) | (15<<3) | (conv_reg(arg[1], line)<<0); + + else if (strcmp(arg[0], "RBRLEQ") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 0<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLNE") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 1<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLCS") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 2<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLCC") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 3<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLMI") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 4<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLPL") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 5<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLVS") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 6<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLVC") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 7<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLHI") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 8<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLLS") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | ( 9<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLGE") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | (10<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLLT") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | (11<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLGT") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | (12<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLLE") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | (13<<3) | (conv_reg(arg[1], line)<<0); + else if (strcmp(arg[0], "RBRLTS") == 0) + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | (14<<3) | (conv_reg(arg[1], line)<<0); + else if ((strcmp(arg[0], "RBRL") == 0) or (strcmp(arg[0], "RBRLAL") == 0)) // register-base branch relative & link - always + opcode = (61<<10) | (1<<9) | (0<<8) | (1<<7) | (15<<3) | (conv_reg(arg[1], line)<<0); + + // MUL-Instruction + // --------------------------------------------------------------------------------------------------------- + else if (strcmp(arg[0], "MUL") == 0) // increment with #0 = move register + opcode = (15<<12) | (conv_reg(arg[1], line)<<7) | (conv_reg(arg[2], line)<<4) | (0<<3) | (conv_reg(arg[3], line)<<0); + + // 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); + + // Build-in Assembler Macros + // --------------------------------------------------------------------------------------------------------- + else if (strcmp(arg[0], "PUSH+") == 0) // push on positive growing stack + opcode = (1<<14) | (1<<13) | (1<<12) | (1<<11) | (1<<10) | (conv_reg(arg[1], line)<<7) | (6<<4) | (1<<3) | (2<<0); + else if (strcmp(arg[0], "POP+") == 0) // pop from positive growing stack + opcode = (1<<14) | (0<<13) | (0<<12) | (1<<11) | (0<<10) | (conv_reg(arg[1], line)<<7) | (6<<4) | (1<<3) | (2<<0); + else if (strcmp(arg[0], "PUSHPOP") == 0) // pushpop from/on stack + opcode = (1<<14) | (0<<13) | (1<<12) | (0<<11) | (0<<10) | (conv_reg(arg[1], line)<<7) | (6<<4) | (1<<3) | (0<<0); + else if (strcmp(arg[0], "PUSH-") == 0) // push on negative growing stack + opcode = (1<<14) | (1<<13) | (0<<12) | (1<<11) | (1<<10) | (conv_reg(arg[1], line)<<7) | (6<<4) | (1<<3) | (2<<0); + else if (strcmp(arg[0], "POP-") == 0) // pop from negative growing stack + opcode = (1<<14) | (0<<13) | (1<<12) | (1<<11) | (0<<10) | (conv_reg(arg[1], line)<<7) | (6<<4) | (1<<3) | (2<<0); + + // Direct memory initialization - WORD + // --------------------------------------------------------------------------------------------------------- + else if (strcmp(arg[0], ".DW") == 0) // memory init + opcode = conv_imm(arg[1], (int)(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); + // binary data file output + fputc(char((opcode>>8)&255), bin_data_out); + fputc(char(opcode&255), bin_data_out); + // compute xor-checksum + xor_checksum = xor_checksum xor opcode; + xor_checksum = xor_checksum & (int)(pow(2, 16)-1); + } + + line++; + } + + if (error_cnt == 0) + fputs("others => x\"0000\" -- NOP", data_out); + + // build header + rewind(bin_data_out); + + // bootfile signature + fputc(char(((51966)>>8)&255), bin_data_out); + fputc(char((51966)&255), bin_data_out); + + // program size (words) + fputc(char(((line-1)>>8)&255), bin_data_out); + fputc(char((line-1)&255), bin_data_out); + + // xor-checksum + fputc(char(((xor_checksum)>>8)&255), bin_data_out); + fputc(char((xor_checksum)&255), bin_data_out); + + // image name + for(i=0; i<10; i++) + fputc(char((image_name[i])&255), bin_data_out); + + fclose(bin_data_out); + fclose(data_out); + fclose(data_in); + + return line; +} + + +// ***************************************************************************************************************** +// Main function +// ***************************************************************************************************************** +int main(int argc, char *argv[]){ + + int p_size = 0; + int i = 0; + + printf("ATLAS 2k Assembler, Version 2014.03.06\n"); + printf("by Stephan Nolting (stnolting@gmail.com), Hanover, Germany\n"); + printf("www.opencores.org/project,atlas_core\n\n"); + + // save image name + if (argv[2] != '\0'){ + for(i=0; i<10; i++) + image_name[i] = char(argv[2][i]); + } + else{ + for(i=0; i<10; i++) + image_name[i] = '\0'; + } + + // pre_processor.asm - intermediate processing file + // init.vhd - vhdl memory initialization data block + // out.bin - binary program output for bootloader downloading + + includer(argv[1], "included.xasm"); // include other files - copy them to work file + convert_strings("included.xasm", "job.xasm"); // convert strings into direct memory inits + pre_processor("job.xasm", "pre_processor.asm"); // erase comments & empty lines & get definitions + get_labels("pre_processor.asm"); // find and list labels + p_size = 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); + printf("Final image size: 0x%04X (%d) bytes\n", (p_size-1)*2, (p_size-1)*2); + printf("Image XOR checksum: 0x%04X\n", xor_checksum); + printf("Binary image name: "); + if (image_name[0] != '\0'){ + for(i=0; i<10;i++) + printf("%c", image_name[i]); + printf("\n"); + } + else + printf("-\n"); + 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: trunk/asm/src/Makefile.win =================================================================== --- trunk/asm/src/Makefile.win (nonexistent) +++ trunk/asm/src/Makefile.win (revision 21) @@ -0,0 +1,29 @@ +# Project: atlas_asm +# Makefile created by Dev-C++ 5.4.0 + +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: trunk/asm/src/included.xasm =================================================================== --- trunk/asm/src/included.xasm (nonexistent) +++ trunk/asm/src/included.xasm (revision 21) @@ -0,0 +1,301 @@ +; ************************************************************************************************************** +; Print Random Numbers - LFSR Test +; +; Print random hex numbers from the LFSR via UART +; Uses BAUD rate from bootloader config!!! +; ************************************************************************************************************** + + +; ************************************************************************************************************** +; Defintions +; ************************************************************************************************************** + +.equ sys0_core c0 +.equ com0_core c2 +.equ lr r7 ; link register + + +; ************************************************************************************************************** +; Exception Vector Table +; ************************************************************************************************************** + +reset_vec: b reset +x_int0_vec: b err_handler +x_int1_vec: b err_handler +cmd_err_vec: b err_handler +swi_vec: b err_handler + + +; ************************************************************************************************************** +; IRQ/SWI/CMD_ERR: Terminate +; ************************************************************************************************************** + +err_handler: bl uart_linebreak + ldil r2, low[err_string] + ldih r2, high[err_string] + bl uart_print + bl uart_linebreak + b #+0 ; freeze + + +; ************************************************************************************************************** +; Main Program +; ************************************************************************************************************** + +reset: ; print intro + ldil r2, low[string_intro] + ldih r2, high[string_intro] + bl uart_print_br + +restart: ; get seed + ldil r2, low[string_seed] + ldih r2, high[string_seed] + bl uart_print + bl receive_hex_word + mcr #1, sys0_core, r4, #5 ; set lfsr data register + bl uart_linebreak + + ; get taps + ldil r2, low[string_taps] + ldih r2, high[string_taps] + bl uart_print + bl receive_hex_word + cbr r4, r4, #15 ; new value after read access + mcr #1, sys0_core, r4, #6 ; set lfsr polynomial register + bl uart_linebreak + + ; read and print hex random numbers +forever: ldil r1, #'0' + bl uart_sendbyte + ldil r1, #'x' + bl uart_sendbyte + + ; get and print + mrc #1, r4, sys0_core, #5 ; get lfsr data + bl print_hex_string + bl uart_linebreak + + ; user console interrupt? + mrc #1, r0, com0_core, #0 ; get uart RTX register + stb r0, #15 ; copy uart rx_ready flag to T-flag + bts restart + + ; repeat forever + b forever + + +; ************************************************************************************************************** +; Communication Subroutines +; ************************************************************************************************************** + + +; -------------------------------------------------------------------------------------------------------- +; Print char-string (bytes) via CP0.COM_0.UART and send linebreak +; Arguments: r2 = address of string (string must be zero-terminated!) +; Results: - +; Used registers: r0, r1, r2, r3, r4, lr +uart_print_br: +; -------------------------------------------------------------------------------------------------------- + ldil r3, #0xFF + mov r4, lr + b uart_print_loop + + +; -------------------------------------------------------------------------------------------------------- +; Print char-string (bytes) via CP0.COM_0.UART +; Arguments: r2 = address of string (string must be zero-terminated!) +; Results: - +; Used registers: r0, r1, r2, r3, r4, lr +uart_print: +; -------------------------------------------------------------------------------------------------------- + clr r3 + mov r4, lr + +uart_print_loop: + ldr r0, r2, +#1, post, ! ; get one string byte + ldil r1, #0x00 ; upper byte mask + ldih r1, #0xFF + and r1, r0, r1 + sfts r1, r1, #swp ; swap bytes and test if zero + beq uart_print_loop_end + bl uart_sendbyte + b uart_print_loop + +uart_print_loop_end: + mov lr, r4 + teq r3, r3 ; do linebreak? + rbaeq lr +; b uart_linebreak + + +; -------------------------------------------------------------------------------------------------------- +; Print linebreak +; Arguments: - +; Results: - +; Used registers: r0, r1, r2, lr +uart_linebreak: +; -------------------------------------------------------------------------------------------------------- + mov r2, lr + ldil r1, #0x0D ; carriage return + bl uart_sendbyte + ldil r1, #0x0A ; line feed + mov lr, r2 +; b uart_sendbyte + + +; -------------------------------------------------------------------------------------------------------- +; Print char (byte) via CP0.COM_0.UART +; Arguments: r1 = char (low byte) +; Results: - +; Used registers: r0, r1 +uart_sendbyte: +; -------------------------------------------------------------------------------------------------------- + mrc #1, r0, com0_core, #2 ; get com control register + stb r0, #5 ; copy uart tx_busy flag to T-flag + bts uart_sendbyte ; still set, keep on waiting + mcr #1, com0_core, r1, #0 ; send data + ret lr + + +; -------------------------------------------------------------------------------------------------------- +; Receive a byte via CP0.COM_0.UART +; Arguments: - +; Results: r0 (low byte) +; Used registers: r0 +uart_receivebyte: +; -------------------------------------------------------------------------------------------------------- + mrc #1, r0, com0_core, #0 ; get uart status/data register + stbi r0, #15 ; copy inverted uart rx_ready flag to T-flag + bts uart_receivebyte ; nothing received, keep on waiting + ldih r0, #0x00 ; clear upper byte + ret lr + + +; -------------------------------------------------------------------------------------------------------- +; Reads 16 bit data as 4x hex chars via UART (+ECHO) +; Arguments: - +; Results: +; r4 = data +; Used registers: r0, r1, r2, r3, r4, lr +receive_hex_word: +; -------------------------------------------------------------------------------------------------------- + mov r2, lr ; backup link regsiter + ldil r4, #0 ; clear data register + ldil r3, #4 ; number of chars + +receive_hex_word_loop: + bl uart_receivebyte ; get one char + + ; convert to higher case + ldil r1, #'F' + cmp r0, r1 + bmi #+3 ; skip decrement + ldil r1, #32 ; -> to lower case + sub r0, r0, r1 + + ; is valid? + ldil r1, #'0' + cmp r0, r1 + bmi receive_hex_word_loop ; if less than '0' + + ldil r1, #'F' + cmp r1, r0 + bmi receive_hex_word_loop ; if higher than 'F' + + ldil r1, #'9' + cmp r1, r0 + bls receive_hex_word_echo ; if less than '9' + + ldil r1, #'A' + cmp r0, r1 + bhi receive_hex_word_loop ; if less than 'A' + + ; echo char +receive_hex_word_echo: + mov r1, r0 + bl uart_sendbyte + + ; do conversion + ldil r0, #'0' + sub r1, r1, r0 + ldil r0, #9 + cmp r0, r1 + bls #+2 ; 0..9 -> ok + dec r1, r1, #7 ; 'A' - '0' - 10 = 7 -> A..F -> ok + + ; save conversion data + sft r4, r4, #rol + sft r4, r4, #rol + sft r4, r4, #rol + sft r4, r4, #rol + orr r4, r4, r1 + + ; loop controller + decs r3, r3, #1 + bne receive_hex_word_loop + + ret r2 ; return + + +; -------------------------------------------------------------------------------------------------------- +; Prints 16bit data as 4x char hex value +; Arguments: +; r4 = data +; Results: - +; Used registers: r0, r1, r2, r3, r4, r6, lr +print_hex_string: +; -------------------------------------------------------------------------------------------------------- + mov r6, lr ; backup link regiiter + + ; char 3 + sft r2, r4, #rol + sft r2, r2, #rol + sft r2, r2, #rol + sft r2, r2, #rol + bl conv_hex_comp + bl uart_sendbyte + + ; char 2 + sft r2, r4, #swp + bl conv_hex_comp + bl uart_sendbyte + + ; char 1 + sft r2, r4, #lsr + sft r2, r2, #lsr + sft r2, r2, #lsr + sft r2, r2, #lsr + bl conv_hex_comp + bl uart_sendbyte + + ; char 0 + mov r2, r4 + bl conv_hex_comp + bl uart_sendbyte + + ret r6 + +; compute hex-char from 4-bit value of r2, result in r1 +conv_hex_comp: ldil r1, #0x0f ; mask for lowest 4 bit + and r2, r2, r1 + + ldil r1, #9 + cmp r1, r2 + bcs #+3 + + ldil r1, #48 ; this is a '0' + b #+2 + ldil r1, #55 ; this is an 'A'-10 + add r1, r1, r2 ; resulting char in lower byte + ret lr + + +; ************************************************************************************************************** +; Constants +; ************************************************************************************************************** + +; -- strings -- +err_string: .stringz "Exception/interrupt error!" +string_intro: .stringz "Random Number Generator" +string_seed: .stringz "Enter LFSR seed (4hex): 0x" +string_taps: .stringz "Enter LFSR taps (4hex): 0x" Index: trunk/rtl/BOOT_MEM.vhd =================================================================== --- trunk/rtl/BOOT_MEM.vhd (nonexistent) +++ trunk/rtl/BOOT_MEM.vhd (revision 21) @@ -0,0 +1,1086 @@ +-- ######################################################## +-- # << ATLAS Project - Bootloader ROM >> # +-- # **************************************************** # +-- # Initialized with boot loader. # +-- # **************************************************** # +-- # Last modified: 08.03.2014 # +-- # **************************************************** # +-- # 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 BOOT_MEM is + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + I_ADR_I : in std_logic_vector(15 downto 0); -- instruction adr + I_EN_I : in std_logic; -- IR update + I_DAT_O : out std_logic_vector(15 downto 0); -- instruction out + D_EN_I : in std_logic; -- access enable + D_RW_I : in std_logic; -- read/write + D_ADR_I : in std_logic_vector(15 downto 0); -- data adr + D_DAT_I : in std_logic_vector(15 downto 0); -- data in + D_DAT_O : out std_logic_vector(15 downto 0) -- data out + ); +end BOOT_MEM; + +architecture BOOT_MEM_STRUCTURE of BOOT_MEM is + + -- Internal constants(configuration -- + constant mem_size_c : natural := 2048; -- 2kB + constant log2_mem_size_c : natural := log2(mem_size_c/2); -- address width (word boundary!) + + -- Memory Type -- + type mem_file_t is array (0 to (mem_size_c/2)-1) of std_logic_vector(15 downto 0); -- word mem! + + -- MEMORY IMAGE (Bootloader Program) -- + ------------------------------------------------------ + constant BOOT_MEM_FILE_C : mem_file_t := + ( + 000000 => x"bc0e", -- B + 000001 => x"bc04", -- B + 000002 => x"bc03", -- B + 000003 => x"bc02", -- B + 000004 => x"bc01", -- B + 000005 => x"c000", -- LDIL + 000006 => x"cc00", -- LDIH + 000007 => x"ec8a", -- MCR + 000008 => x"ed0f", -- MCR + 000009 => x"be8f", -- BL + 000010 => x"c524", -- LDIL + 000011 => x"c907", -- LDIH + 000012 => x"be8a", -- BL + 000013 => x"bc00", -- B + 000014 => x"c000", -- LDIL + 000015 => x"cc78", -- LDIH + 000016 => x"1c00", -- STSR + 000017 => x"ec11", -- MRC + 000018 => x"ec88", -- MCR + 000019 => x"ec8a", -- MCR + 000020 => x"c000", -- LDIL + 000021 => x"ec08", -- MCR + 000022 => x"ec09", -- MCR + 000023 => x"ec0a", -- MCR + 000024 => x"ec0b", -- MCR + 000025 => x"ec0c", -- MCR + 000026 => x"ec0d", -- MCR + 000027 => x"ec0e", -- MCR + 000028 => x"ec00", -- MRC + 000029 => x"c801", -- LDIH + 000030 => x"ed0f", -- MCR + 000031 => x"ec17", -- MRC + 000032 => x"ec97", -- MRC + 000033 => x"c160", -- LDIL + 000034 => x"c909", -- LDIH + 000035 => x"c18f", -- LDIL + 000036 => x"0923", -- ADD + 000037 => x"29b3", -- CLR + 000038 => x"2a44", -- CLR + 000039 => x"100a", -- SUBS + 000040 => x"149b", -- SBCS + 000041 => x"9003", -- BMI + 000042 => x"0241", -- INC + 000043 => x"bdfc", -- B + 000044 => x"ed49", -- MCR + 000045 => x"ec22", -- MRC + 000046 => x"d406", -- SBR + 000047 => x"ed0a", -- MCR + 000048 => x"be68", -- BL + 000049 => x"be67", -- BL + 000050 => x"c510", -- LDIL + 000051 => x"c905", -- LDIH + 000052 => x"be62", -- BL + 000053 => x"c53a", -- LDIL + 000054 => x"c905", -- LDIH + 000055 => x"be5f", -- BL + 000056 => x"c562", -- LDIL + 000057 => x"c905", -- LDIH + 000058 => x"be5c", -- BL + 000059 => x"be5d", -- BL + 000060 => x"c108", -- LDIL + 000061 => x"c906", -- LDIH + 000062 => x"be59", -- BL + 000063 => x"ee11", -- MRC + 000064 => x"be5b", -- BL + 000065 => x"be57", -- BL + 000066 => x"c11e", -- LDIL + 000067 => x"c906", -- LDIH + 000068 => x"be53", -- BL + 000069 => x"ee97", -- MRC + 000070 => x"ee17", -- MRC + 000071 => x"be54", -- BL + 000072 => x"0250", -- MOV + 000073 => x"be52", -- BL + 000074 => x"be4e", -- BL + 000075 => x"ec27", -- MRC + 000076 => x"c083", -- LDIL + 000077 => x"2001", -- AND + 000078 => x"c330", -- LDIL + 000079 => x"0b60", -- ADD + 000080 => x"bc22", -- B + 000081 => x"be47", -- BL + 000082 => x"c568", -- LDIL + 000083 => x"c906", -- LDIH + 000084 => x"be42", -- BL + 000085 => x"c57c", -- LDIL + 000086 => x"c906", -- LDIH + 000087 => x"be3f", -- BL + 000088 => x"c116", -- LDIL + 000089 => x"c907", -- LDIH + 000090 => x"be3c", -- BL + 000091 => x"c12e", -- LDIL + 000092 => x"c907", -- LDIH + 000093 => x"be39", -- BL + 000094 => x"c148", -- LDIL + 000095 => x"c907", -- LDIH + 000096 => x"be36", -- BL + 000097 => x"c162", -- LDIL + 000098 => x"c907", -- LDIH + 000099 => x"be33", -- BL + 000100 => x"c176", -- LDIL + 000101 => x"c907", -- LDIH + 000102 => x"be30", -- BL + 000103 => x"c504", -- LDIL + 000104 => x"c907", -- LDIH + 000105 => x"be2d", -- BL + 000106 => x"c50e", -- LDIL + 000107 => x"c907", -- LDIH + 000108 => x"be2b", -- BL + 000109 => x"be2d", -- BL + 000110 => x"0300", -- MOV + 000111 => x"00e0", -- MOV + 000112 => x"be29", -- BL + 000113 => x"be27", -- BL + 000114 => x"c0b0", -- LDIL + 000115 => x"181e", -- CMP + 000116 => x"81dd", -- BEQ + 000117 => x"c0b1", -- LDIL + 000118 => x"181e", -- CMP + 000119 => x"8076", -- BEQ + 000120 => x"c0b2", -- LDIL + 000121 => x"181e", -- CMP + 000122 => x"8022", -- BEQ + 000123 => x"c0b3", -- LDIL + 000124 => x"181e", -- CMP + 000125 => x"8013", -- BEQ + 000126 => x"c2f8", -- LDIL + 000127 => x"ca83", -- LDIH + 000128 => x"c0f0", -- LDIL + 000129 => x"181e", -- CMP + 000130 => x"f705", -- RBAEQ + 000131 => x"c6f6", -- LDIL + 000132 => x"ca82", -- LDIH + 000133 => x"c0e4", -- LDIL + 000134 => x"181e", -- CMP + 000135 => x"f705", -- RBAEQ + 000136 => x"c0f2", -- LDIL + 000137 => x"181e", -- CMP + 000138 => x"85e0", -- BNE + 000139 => x"2800", -- CLR + 000140 => x"c080", -- LDIL + 000141 => x"cc80", -- LDIH + 000142 => x"ec99", -- MCR + 000143 => x"3400", -- GT + 000144 => x"c508", -- LDIL + 000145 => x"c906", -- LDIH + 000146 => x"be04", -- BL + 000147 => x"2800", -- CLR + 000148 => x"2100", -- STUB + 000149 => x"bcb1", -- B + 000150 => x"bca7", -- B + 000151 => x"bca7", -- B + 000152 => x"bca7", -- B + 000153 => x"bca7", -- B + 000154 => x"bca7", -- B + 000155 => x"bcaa", -- B + 000156 => x"c134", -- LDIL + 000157 => x"c906", -- LDIH + 000158 => x"be9f", -- BL + 000159 => x"c100", -- LDIL + 000160 => x"bea2", -- BL + 000161 => x"3eb0", -- SFT + 000162 => x"c101", -- LDIL + 000163 => x"be9f", -- BL + 000164 => x"26d3", -- ORR + 000165 => x"c47e", -- LDIL + 000166 => x"cc4a", -- LDIH + 000167 => x"180d", -- CMP + 000168 => x"849b", -- BNE + 000169 => x"c102", -- LDIL + 000170 => x"be98", -- BL + 000171 => x"3eb0", -- SFT + 000172 => x"c103", -- LDIL + 000173 => x"be95", -- BL + 000174 => x"26d3", -- ORR + 000175 => x"2055", -- STUB + 000176 => x"c104", -- LDIL + 000177 => x"be91", -- BL + 000178 => x"3eb0", -- SFT + 000179 => x"c105", -- LDIL + 000180 => x"be8e", -- BL + 000181 => x"26d3", -- ORR + 000182 => x"20d5", -- STUB + 000183 => x"c106", -- LDIL + 000184 => x"be8a", -- BL + 000185 => x"3eb0", -- SFT + 000186 => x"c107", -- LDIL + 000187 => x"be87", -- BL + 000188 => x"26d3", -- ORR + 000189 => x"2155", -- STUB + 000190 => x"c108", -- LDIL + 000191 => x"be83", -- BL + 000192 => x"3eb0", -- SFT + 000193 => x"c109", -- LDIL + 000194 => x"be80", -- BL + 000195 => x"26d3", -- ORR + 000196 => x"21d5", -- STUB + 000197 => x"c10a", -- LDIL + 000198 => x"be7c", -- BL + 000199 => x"3eb0", -- SFT + 000200 => x"c10b", -- LDIL + 000201 => x"be79", -- BL + 000202 => x"26d3", -- ORR + 000203 => x"2255", -- STUB + 000204 => x"c10c", -- LDIL + 000205 => x"be75", -- BL + 000206 => x"3eb0", -- SFT + 000207 => x"c10d", -- LDIL + 000208 => x"be72", -- BL + 000209 => x"26d3", -- ORR + 000210 => x"22d5", -- STUB + 000211 => x"c10e", -- LDIL + 000212 => x"be6e", -- BL + 000213 => x"3eb0", -- SFT + 000214 => x"c10f", -- LDIL + 000215 => x"be6b", -- BL + 000216 => x"26d3", -- ORR + 000217 => x"2355", -- STUB + 000218 => x"c300", -- LDIL + 000219 => x"ecea", -- MCR + 000220 => x"23e6", -- STUB + 000221 => x"c010", -- LDIL + 000222 => x"0960", -- ADD + 000223 => x"be63", -- BL + 000224 => x"3eb0", -- SFT + 000225 => x"c011", -- LDIL + 000226 => x"0960", -- ADD + 000227 => x"be5f", -- BL + 000228 => x"26d3", -- ORR + 000229 => x"7eea", -- STR + 000230 => x"2477", -- LDUB + 000231 => x"2805", -- EOR + 000232 => x"2380", -- STUB + 000233 => x"2400", -- LDUB + 000234 => x"1868", -- CMP + 000235 => x"85f2", -- BNE + 000236 => x"bc41", -- B + 000237 => x"c14c", -- LDIL + 000238 => x"c906", -- LDIH + 000239 => x"be4e", -- BL + 000240 => x"c16e", -- LDIL + 000241 => x"c906", -- LDIH + 000242 => x"be4b", -- BL + 000243 => x"be4e", -- BL + 000244 => x"3c80", -- SFT + 000245 => x"be4c", -- BL + 000246 => x"2490", -- ORR + 000247 => x"c47e", -- LDIL + 000248 => x"cc4a", -- LDIH + 000249 => x"1818", -- CMP + 000250 => x"8449", -- BNE + 000251 => x"be46", -- BL + 000252 => x"3c80", -- SFT + 000253 => x"be44", -- BL + 000254 => x"2490", -- ORR + 000255 => x"3c94", -- SFT + 000256 => x"2011", -- STUB + 000257 => x"be40", -- BL + 000258 => x"3c80", -- SFT + 000259 => x"be3e", -- BL + 000260 => x"2490", -- ORR + 000261 => x"2091", -- STUB + 000262 => x"be3b", -- BL + 000263 => x"3c80", -- SFT + 000264 => x"be39", -- BL + 000265 => x"2490", -- ORR + 000266 => x"2111", -- STUB + 000267 => x"be36", -- BL + 000268 => x"3c80", -- SFT + 000269 => x"be34", -- BL + 000270 => x"2490", -- ORR + 000271 => x"2191", -- STUB + 000272 => x"be31", -- BL + 000273 => x"3c80", -- SFT + 000274 => x"be2f", -- BL + 000275 => x"2490", -- ORR + 000276 => x"2211", -- STUB + 000277 => x"be2c", -- BL + 000278 => x"3c80", -- SFT + 000279 => x"be2a", -- BL + 000280 => x"2490", -- ORR + 000281 => x"2291", -- STUB + 000282 => x"be27", -- BL + 000283 => x"3c80", -- SFT + 000284 => x"be25", -- BL + 000285 => x"2490", -- ORR + 000286 => x"2311", -- STUB + 000287 => x"2ad5", -- CLR + 000288 => x"ecda", -- MCR + 000289 => x"23d5", -- STUB + 000290 => x"be1f", -- BL + 000291 => x"3c80", -- SFT + 000292 => x"be1d", -- BL + 000293 => x"2490", -- ORR + 000294 => x"7cda", -- STR + 000295 => x"2477", -- LDUB + 000296 => x"2801", -- EOR + 000297 => x"2380", -- STUB + 000298 => x"2400", -- LDUB + 000299 => x"1858", -- CMP + 000300 => x"85f6", -- BNE + 000301 => x"c000", -- LDIL + 000302 => x"cc00", -- LDIH + 000303 => x"ec8a", -- MCR + 000304 => x"2477", -- LDUB + 000305 => x"2491", -- LDUB + 000306 => x"1809", -- CMP + 000307 => x"8013", -- BEQ + 000308 => x"c530", -- LDIL + 000309 => x"c907", -- LDIH + 000310 => x"be07", -- BL + 000311 => x"c552", -- LDIL + 000312 => x"c907", -- LDIH + 000313 => x"be04", -- BL + 000314 => x"be07", -- BL + 000315 => x"2800", -- CLR + 000316 => x"3400", -- GT + 000317 => x"bcdc", -- B + 000318 => x"bcde", -- B + 000319 => x"bcea", -- B + 000320 => x"bcee", -- B + 000321 => x"bcf2", -- B + 000322 => x"bc78", -- B + 000323 => x"bccc", -- B + 000324 => x"bd26", -- B + 000325 => x"bc76", -- B + 000326 => x"c520", -- LDIL + 000327 => x"c906", -- LDIH + 000328 => x"bed4", -- BL + 000329 => x"24aa", -- LDUBS + 000330 => x"8024", -- BEQ + 000331 => x"c0a2", -- LDIL + 000332 => x"bee2", -- BL + 000333 => x"24a2", -- LDUB + 000334 => x"3c90", -- SFT + 000335 => x"bedf", -- BL + 000336 => x"3c90", -- SFT + 000337 => x"bedd", -- BL + 000338 => x"24b3", -- LDUB + 000339 => x"3c90", -- SFT + 000340 => x"beda", -- BL + 000341 => x"3c90", -- SFT + 000342 => x"bed8", -- BL + 000343 => x"24c4", -- LDUB + 000344 => x"3c90", -- SFT + 000345 => x"bed5", -- BL + 000346 => x"3c90", -- SFT + 000347 => x"bed3", -- BL + 000348 => x"24d5", -- LDUB + 000349 => x"3c90", -- SFT + 000350 => x"bed0", -- BL + 000351 => x"3c90", -- SFT + 000352 => x"bece", -- BL + 000353 => x"24e6", -- LDUB + 000354 => x"3c90", -- SFT + 000355 => x"becb", -- BL + 000356 => x"3c90", -- SFT + 000357 => x"bec9", -- BL + 000358 => x"c0a2", -- LDIL + 000359 => x"bec7", -- BL + 000360 => x"bec1", -- BL + 000361 => x"c55a", -- LDIL + 000362 => x"c906", -- LDIH + 000363 => x"beb1", -- BL + 000364 => x"2677", -- LDUB + 000365 => x"be4e", -- BL + 000366 => x"bebb", -- BL + 000367 => x"beba", -- BL + 000368 => x"2800", -- CLR + 000369 => x"d58e", -- SBR + 000370 => x"d5bf", -- SBR + 000371 => x"1c03", -- STSR + 000372 => x"ed0f", -- MCR + 000373 => x"ec88", -- MCR + 000374 => x"ec8b", -- MCR + 000375 => x"ec8c", -- MCR + 000376 => x"ec8a", -- MCR + 000377 => x"ec89", -- MCR + 000378 => x"3400", -- GT + 000379 => x"c544", -- LDIL + 000380 => x"c906", -- LDIH + 000381 => x"be9f", -- BL + 000382 => x"beba", -- BL + 000383 => x"beb4", -- BL + 000384 => x"c08d", -- LDIL + 000385 => x"1809", -- CMP + 000386 => x"8006", -- BEQ + 000387 => x"c088", -- LDIL + 000388 => x"1809", -- CMP + 000389 => x"85fa", -- BNE + 000390 => x"bea3", -- BL + 000391 => x"bdbd", -- B + 000392 => x"ecca", -- MCR + 000393 => x"bea0", -- BL + 000394 => x"c280", -- LDIL + 000395 => x"c00f", -- LDIL + 000396 => x"2058", -- ANDS + 000397 => x"840a", -- BNE + 000398 => x"be9b", -- BL + 000399 => x"c0a4", -- LDIL + 000400 => x"be9e", -- BL + 000401 => x"0250", -- MOV + 000402 => x"becb", -- BL + 000403 => x"c0ba", -- LDIL + 000404 => x"be9a", -- BL + 000405 => x"c0a0", -- LDIL + 000406 => x"be98", -- BL + 000407 => x"7a5a", -- LDR + 000408 => x"c0a0", -- LDIL + 000409 => x"be95", -- BL + 000410 => x"bec3", -- BL + 000411 => x"c00f", -- LDIL + 000412 => x"2058", -- ANDS + 000413 => x"8414", -- BNE + 000414 => x"c0a0", -- LDIL + 000415 => x"be8f", -- BL + 000416 => x"be8e", -- BL + 000417 => x"c010", -- LDIL + 000418 => x"1250", -- SUB + 000419 => x"c470", -- LDIL + 000420 => x"2240", -- AND + 000421 => x"78c9", -- LDR + 000422 => x"3c90", -- SFT + 000423 => x"c880", -- LDIH + 000424 => x"c020", -- LDIL + 000425 => x"1818", -- CMP + 000426 => x"a402", -- BLS + 000427 => x"c0ae", -- LDIL + 000428 => x"be82", -- BL + 000429 => x"c08f", -- LDIL + 000430 => x"2014", -- AND + 000431 => x"3409", -- TEQ + 000432 => x"85f5", -- BNE + 000433 => x"ec20", -- MRC + 000434 => x"dc0f", -- STB + 000435 => x"b804", -- BTS + 000436 => x"c5fe", -- LDIL + 000437 => x"343d", -- TEQ + 000438 => x"85d5", -- BNE + 000439 => x"be7c", -- BL + 000440 => x"2800", -- CLR + 000441 => x"3400", -- GT + 000442 => x"bc5e", -- B + 000443 => x"bca2", -- B + 000444 => x"c001", -- LDIL + 000445 => x"ed0c", -- MCR + 000446 => x"c050", -- LDIL + 000447 => x"c83f", -- LDIH + 000448 => x"ed0a", -- MCR + 000449 => x"c000", -- LDIL + 000450 => x"c801", -- LDIH + 000451 => x"beb8", -- BL + 000452 => x"c15e", -- LDIL + 000453 => x"c906", -- LDIH + 000454 => x"be53", -- BL + 000455 => x"c16e", -- LDIL + 000456 => x"c906", -- LDIH + 000457 => x"be50", -- BL + 000458 => x"be69", -- BL + 000459 => x"3c80", -- SFT + 000460 => x"be67", -- BL + 000461 => x"2410", -- ORR + 000462 => x"c4fe", -- LDIL + 000463 => x"ccca", -- LDIH + 000464 => x"1809", -- CMP + 000465 => x"843e", -- BNE + 000466 => x"c100", -- LDIL + 000467 => x"c5ca", -- LDIL + 000468 => x"bead", -- BL + 000469 => x"c101", -- LDIL + 000470 => x"c5fe", -- LDIL + 000471 => x"beaa", -- BL + 000472 => x"be5b", -- BL + 000473 => x"3c80", -- SFT + 000474 => x"be59", -- BL + 000475 => x"2690", -- ORR + 000476 => x"3ed4", -- SFT + 000477 => x"2055", -- STUB + 000478 => x"c102", -- LDIL + 000479 => x"3dd0", -- SFT + 000480 => x"bea1", -- BL + 000481 => x"c103", -- LDIL + 000482 => x"01d0", -- MOV + 000483 => x"be9e", -- BL + 000484 => x"be4f", -- BL + 000485 => x"3c80", -- SFT + 000486 => x"be4d", -- BL + 000487 => x"2690", -- ORR + 000488 => x"20d5", -- STUB + 000489 => x"c104", -- LDIL + 000490 => x"3dd0", -- SFT + 000491 => x"be96", -- BL + 000492 => x"c105", -- LDIL + 000493 => x"01d0", -- MOV + 000494 => x"be93", -- BL + 000495 => x"c106", -- LDIL + 000496 => x"be43", -- BL + 000497 => x"0180", -- MOV + 000498 => x"be8f", -- BL + 000499 => x"0121", -- INC + 000500 => x"c010", -- LDIL + 000501 => x"1828", -- CMP + 000502 => x"85fa", -- BNE + 000503 => x"c110", -- LDIL + 000504 => x"2ad5", -- CLR + 000505 => x"be3a", -- BL + 000506 => x"0180", -- MOV + 000507 => x"be86", -- BL + 000508 => x"0121", -- INC + 000509 => x"2400", -- LDUB + 000510 => x"02d1", -- INC + 000511 => x"1858", -- CMP + 000512 => x"85f9", -- BNE + 000513 => x"c001", -- LDIL + 000514 => x"ed0c", -- MCR + 000515 => x"c050", -- LDIL + 000516 => x"c83f", -- LDIH + 000517 => x"ed0a", -- MCR + 000518 => x"c00c", -- LDIL + 000519 => x"c801", -- LDIH + 000520 => x"be73", -- BL + 000521 => x"c530", -- LDIL + 000522 => x"c906", -- LDIH + 000523 => x"be0e", -- BL + 000524 => x"c6a2", -- LDIL + 000525 => x"ca80", -- LDIH + 000526 => x"3450", -- GT + 000527 => x"c516", -- LDIL + 000528 => x"c907", -- LDIH + 000529 => x"be08", -- BL + 000530 => x"c552", -- LDIL + 000531 => x"c907", -- LDIH + 000532 => x"be05", -- BL + 000533 => x"be1e", -- BL + 000534 => x"2800", -- CLR + 000535 => x"3400", -- GT + 000536 => x"bc9e", -- B + 000537 => x"c5ff", -- LDIL + 000538 => x"0270", -- MOV + 000539 => x"bc03", -- B + 000540 => x"29b3", -- CLR + 000541 => x"0270", -- MOV + 000542 => x"7829", -- LDR + 000543 => x"c080", -- LDIL + 000544 => x"ccff", -- LDIH + 000545 => x"2081", -- AND + 000546 => x"3c98", -- SFTS + 000547 => x"8003", -- BEQ + 000548 => x"be0a", -- BL + 000549 => x"bdf9", -- B + 000550 => x"03c0", -- MOV + 000551 => x"343b", -- TEQ + 000552 => x"f707", -- RBAEQ + 000553 => x"0170", -- MOV + 000554 => x"c08d", -- LDIL + 000555 => x"be03", -- BL + 000556 => x"c08a", -- LDIL + 000557 => x"03a0", -- MOV + 000558 => x"ec22", -- MRC + 000559 => x"dc05", -- STB + 000560 => x"b9fe", -- BTS + 000561 => x"ed18", -- MCR + 000562 => x"3470", -- RET + 000563 => x"ec20", -- MRC + 000564 => x"dc8f", -- STBI + 000565 => x"b9fe", -- BTS + 000566 => x"c800", -- LDIH + 000567 => x"3470", -- RET + 000568 => x"0170", -- MOV + 000569 => x"c200", -- LDIL + 000570 => x"c184", -- LDIL + 000571 => x"bff8", -- BL + 000572 => x"c0c6", -- LDIL + 000573 => x"1809", -- CMP + 000574 => x"9003", -- BMI + 000575 => x"c0a0", -- LDIL + 000576 => x"1001", -- SUB + 000577 => x"c0b0", -- LDIL + 000578 => x"1809", -- CMP + 000579 => x"91f8", -- BMI + 000580 => x"c0c6", -- LDIL + 000581 => x"1818", -- CMP + 000582 => x"91f5", -- BMI + 000583 => x"c0b9", -- LDIL + 000584 => x"1818", -- CMP + 000585 => x"a404", -- BLS + 000586 => x"c0c1", -- LDIL + 000587 => x"1809", -- CMP + 000588 => x"a1ef", -- BHI + 000589 => x"0080", -- MOV + 000590 => x"bfe0", -- BL + 000591 => x"c030", -- LDIL + 000592 => x"1090", -- SUB + 000593 => x"c009", -- LDIL + 000594 => x"1809", -- CMP + 000595 => x"a402", -- BLS + 000596 => x"0497", -- DEC + 000597 => x"3e42", -- SFT + 000598 => x"3e42", -- SFT + 000599 => x"3e42", -- SFT + 000600 => x"3e42", -- SFT + 000601 => x"2641", -- ORR + 000602 => x"05b9", -- DECS + 000603 => x"85e0", -- BNE + 000604 => x"3420", -- RET + 000605 => x"0370", -- MOV + 000606 => x"3d42", -- SFT + 000607 => x"3d22", -- SFT + 000608 => x"3d22", -- SFT + 000609 => x"3d22", -- SFT + 000610 => x"be0f", -- BL + 000611 => x"bfcb", -- BL + 000612 => x"3d40", -- SFT + 000613 => x"be0c", -- BL + 000614 => x"bfc8", -- BL + 000615 => x"3d45", -- SFT + 000616 => x"3d25", -- SFT + 000617 => x"3d25", -- SFT + 000618 => x"3d25", -- SFT + 000619 => x"be06", -- BL + 000620 => x"bfc2", -- BL + 000621 => x"0140", -- MOV + 000622 => x"be03", -- BL + 000623 => x"bfbf", -- BL + 000624 => x"3460", -- RET + 000625 => x"c08f", -- LDIL + 000626 => x"2121", -- AND + 000627 => x"c089", -- LDIL + 000628 => x"181a", -- CMP + 000629 => x"8803", -- BCS + 000630 => x"c0b0", -- LDIL + 000631 => x"bc02", -- B + 000632 => x"c0b7", -- LDIL + 000633 => x"0892", -- ADD + 000634 => x"3470", -- RET + 000635 => x"ed0b", -- MCR + 000636 => x"ec22", -- MRC + 000637 => x"dc03", -- STB + 000638 => x"b9fe", -- BTS + 000639 => x"ec23", -- MRC + 000640 => x"3470", -- RET + 000641 => x"00f0", -- MOV + 000642 => x"c050", -- LDIL + 000643 => x"c837", -- LDIH + 000644 => x"ed0a", -- MCR + 000645 => x"c001", -- LDIL + 000646 => x"ed0c", -- MCR + 000647 => x"c006", -- LDIL + 000648 => x"bff3", -- BL + 000649 => x"c050", -- LDIL + 000650 => x"c83f", -- LDIH + 000651 => x"ed0a", -- MCR + 000652 => x"c000", -- LDIL + 000653 => x"c805", -- LDIH + 000654 => x"bfed", -- BL + 000655 => x"dc01", -- STB + 000656 => x"b80a", -- BTS + 000657 => x"c540", -- LDIL + 000658 => x"c907", -- LDIH + 000659 => x"bf86", -- BL + 000660 => x"c552", -- LDIL + 000661 => x"c907", -- LDIH + 000662 => x"bf83", -- BL + 000663 => x"bf9c", -- BL + 000664 => x"2800", -- CLR + 000665 => x"3400", -- GT + 000666 => x"c040", -- LDIL + 000667 => x"c83f", -- LDIH + 000668 => x"ed0a", -- MCR + 000669 => x"c001", -- LDIL + 000670 => x"ed0c", -- MCR + 000671 => x"3c20", -- SFT + 000672 => x"c802", -- LDIH + 000673 => x"bfda", -- BL + 000674 => x"03a0", -- MOV + 000675 => x"cb80", -- LDIH + 000676 => x"3ff0", -- SFT + 000677 => x"0030", -- MOV + 000678 => x"c800", -- LDIH + 000679 => x"2407", -- ORR + 000680 => x"bfd3", -- BL + 000681 => x"2800", -- CLR + 000682 => x"ed0c", -- MCR + 000683 => x"c050", -- LDIL + 000684 => x"c83f", -- LDIH + 000685 => x"ed0a", -- MCR + 000686 => x"c001", -- LDIL + 000687 => x"ed0c", -- MCR + 000688 => x"c000", -- LDIL + 000689 => x"c805", -- LDIH + 000690 => x"bfc9", -- BL + 000691 => x"dc00", -- STB + 000692 => x"b9fc", -- BTS + 000693 => x"3410", -- RET + 000694 => x"00f0", -- MOV + 000695 => x"c040", -- LDIL + 000696 => x"c83f", -- LDIH + 000697 => x"ed0a", -- MCR + 000698 => x"c001", -- LDIL + 000699 => x"ed0c", -- MCR + 000700 => x"3c20", -- SFT + 000701 => x"c803", -- LDIH + 000702 => x"bfbd", -- BL + 000703 => x"0020", -- MOV + 000704 => x"c800", -- LDIH + 000705 => x"3c00", -- SFT + 000706 => x"bfb9", -- BL + 000707 => x"29b3", -- CLR + 000708 => x"ed3c", -- MCR + 000709 => x"0180", -- MOV + 000710 => x"c980", -- LDIH + 000711 => x"3410", -- RET + 000712 => x"4154", -- .DW + 000713 => x"4c41", -- .DW + 000714 => x"532d", -- .DW + 000715 => x"324b", -- .DW + 000716 => x"2042", -- .DW + 000717 => x"6f6f", -- .DW + 000718 => x"746c", -- .DW + 000719 => x"6f61", -- .DW + 000720 => x"6465", -- .DW + 000721 => x"7220", -- .DW + 000722 => x"2d20", -- .DW + 000723 => x"5665", -- .DW + 000724 => x"7273", -- .DW + 000725 => x"696f", -- .DW + 000726 => x"6e20", -- .DW + 000727 => x"3230", -- .DW + 000728 => x"3134", -- .DW + 000729 => x"2e30", -- .DW + 000730 => x"332e", -- .DW + 000731 => x"3038", -- .DW + 000732 => x"0000", -- .DW + 000733 => x"6279", -- .DW + 000734 => x"2053", -- .DW + 000735 => x"7465", -- .DW + 000736 => x"7068", -- .DW + 000737 => x"616e", -- .DW + 000738 => x"204e", -- .DW + 000739 => x"6f6c", -- .DW + 000740 => x"7469", -- .DW + 000741 => x"6e67", -- .DW + 000742 => x"2c20", -- .DW + 000743 => x"7374", -- .DW + 000744 => x"6e6f", -- .DW + 000745 => x"6c74", -- .DW + 000746 => x"696e", -- .DW + 000747 => x"6740", -- .DW + 000748 => x"676d", -- .DW + 000749 => x"6169", -- .DW + 000750 => x"6c2e", -- .DW + 000751 => x"636f", -- .DW + 000752 => x"6d00", -- .DW + 000753 => x"7777", -- .DW + 000754 => x"772e", -- .DW + 000755 => x"6f70", -- .DW + 000756 => x"656e", -- .DW + 000757 => x"636f", -- .DW + 000758 => x"7265", -- .DW + 000759 => x"732e", -- .DW + 000760 => x"6f72", -- .DW + 000761 => x"672f", -- .DW + 000762 => x"7072", -- .DW + 000763 => x"6f6a", -- .DW + 000764 => x"6563", -- .DW + 000765 => x"742c", -- .DW + 000766 => x"6174", -- .DW + 000767 => x"6c61", -- .DW + 000768 => x"735f", -- .DW + 000769 => x"636f", -- .DW + 000770 => x"7265", -- .DW + 000771 => x"0000", -- .DW + 000772 => x"426f", -- .DW + 000773 => x"6f74", -- .DW + 000774 => x"6c6f", -- .DW + 000775 => x"6164", -- .DW + 000776 => x"6572", -- .DW + 000777 => x"2073", -- .DW + 000778 => x"7461", -- .DW + 000779 => x"7274", -- .DW + 000780 => x"3a20", -- .DW + 000781 => x"3078", -- .DW + 000782 => x"0000", -- .DW + 000783 => x"436c", -- .DW + 000784 => x"6f63", -- .DW + 000785 => x"6b20", -- .DW + 000786 => x"7370", -- .DW + 000787 => x"6565", -- .DW + 000788 => x"6420", -- .DW + 000789 => x"2848", -- .DW + 000790 => x"7a29", -- .DW + 000791 => x"3a20", -- .DW + 000792 => x"3078", -- .DW + 000793 => x"0000", -- .DW + 000794 => x"426f", -- .DW + 000795 => x"6f74", -- .DW + 000796 => x"696e", -- .DW + 000797 => x"6720", -- .DW + 000798 => x"6672", -- .DW + 000799 => x"6f6d", -- .DW + 000800 => x"2053", -- .DW + 000801 => x"5049", -- .DW + 000802 => x"2045", -- .DW + 000803 => x"4550", -- .DW + 000804 => x"524f", -- .DW + 000805 => x"4d00", -- .DW + 000806 => x"426f", -- .DW + 000807 => x"6f74", -- .DW + 000808 => x"696e", -- .DW + 000809 => x"6720", -- .DW + 000810 => x"6672", -- .DW + 000811 => x"6f6d", -- .DW + 000812 => x"2055", -- .DW + 000813 => x"4152", -- .DW + 000814 => x"5400", -- .DW + 000815 => x"4275", -- .DW + 000816 => x"726e", -- .DW + 000817 => x"696e", -- .DW + 000818 => x"6720", -- .DW + 000819 => x"4545", -- .DW + 000820 => x"5052", -- .DW + 000821 => x"4f4d", -- .DW + 000822 => x"0000", -- .DW + 000823 => x"5761", -- .DW + 000824 => x"6974", -- .DW + 000825 => x"696e", -- .DW + 000826 => x"6720", -- .DW + 000827 => x"666f", -- .DW + 000828 => x"7220", -- .DW + 000829 => x"696d", -- .DW + 000830 => x"6167", -- .DW + 000831 => x"6520", -- .DW + 000832 => x"6461", -- .DW + 000833 => x"7461", -- .DW + 000834 => x"2e2e", -- .DW + 000835 => x"2e00", -- .DW + 000836 => x"426f", -- .DW + 000837 => x"6f74", -- .DW + 000838 => x"696e", -- .DW + 000839 => x"6720", -- .DW + 000840 => x"6672", -- .DW + 000841 => x"6f6d", -- .DW + 000842 => x"206d", -- .DW + 000843 => x"656d", -- .DW + 000844 => x"6f72", -- .DW + 000845 => x"792e", -- .DW + 000846 => x"2e2e", -- .DW + 000847 => x"0000", -- .DW + 000848 => x"5374", -- .DW + 000849 => x"6172", -- .DW + 000850 => x"7469", -- .DW + 000851 => x"6e67", -- .DW + 000852 => x"2069", -- .DW + 000853 => x"6d61", -- .DW + 000854 => x"6765", -- .DW + 000855 => x"2000", -- .DW + 000856 => x"446f", -- .DW + 000857 => x"776e", -- .DW + 000858 => x"6c6f", -- .DW + 000859 => x"6164", -- .DW + 000860 => x"2063", -- .DW + 000861 => x"6f6d", -- .DW + 000862 => x"706c", -- .DW + 000863 => x"6574", -- .DW + 000864 => x"6564", -- .DW + 000865 => x"2100", -- .DW + 000866 => x"456e", -- .DW + 000867 => x"7465", -- .DW + 000868 => x"7220", -- .DW + 000869 => x"7061", -- .DW + 000870 => x"6765", -- .DW + 000871 => x"2028", -- .DW + 000872 => x"3468", -- .DW + 000873 => x"6578", -- .DW + 000874 => x"293a", -- .DW + 000875 => x"2030", -- .DW + 000876 => x"7800", -- .DW + 000877 => x"4368", -- .DW + 000878 => x"6563", -- .DW + 000879 => x"6b73", -- .DW + 000880 => x"756d", -- .DW + 000881 => x"3a20", -- .DW + 000882 => x"3078", -- .DW + 000883 => x"0000", -- .DW + 000884 => x"436f", -- .DW + 000885 => x"6d6d", -- .DW + 000886 => x"616e", -- .DW + 000887 => x"642f", -- .DW + 000888 => x"626f", -- .DW + 000889 => x"6f74", -- .DW + 000890 => x"2073", -- .DW + 000891 => x"7769", -- .DW + 000892 => x"7463", -- .DW + 000893 => x"6800", -- .DW + 000894 => x"2030", -- .DW + 000895 => x"2f27", -- .DW + 000896 => x"3030", -- .DW + 000897 => x"273a", -- .DW + 000898 => x"2052", -- .DW + 000899 => x"6573", -- .DW + 000900 => x"7461", -- .DW + 000901 => x"7274", -- .DW + 000902 => x"2063", -- .DW + 000903 => x"6f6e", -- .DW + 000904 => x"736f", -- .DW + 000905 => x"6c65", -- .DW + 000906 => x"0000", -- .DW + 000907 => x"2031", -- .DW + 000908 => x"2f27", -- .DW + 000909 => x"3031", -- .DW + 000910 => x"273a", -- .DW + 000911 => x"2042", -- .DW + 000912 => x"6f6f", -- .DW + 000913 => x"7420", -- .DW + 000914 => x"6672", -- .DW + 000915 => x"6f6d", -- .DW + 000916 => x"2055", -- .DW + 000917 => x"4152", -- .DW + 000918 => x"5400", -- .DW + 000919 => x"2032", -- .DW + 000920 => x"2f27", -- .DW + 000921 => x"3130", -- .DW + 000922 => x"273a", -- .DW + 000923 => x"2042", -- .DW + 000924 => x"6f6f", -- .DW + 000925 => x"7420", -- .DW + 000926 => x"6672", -- .DW + 000927 => x"6f6d", -- .DW + 000928 => x"2045", -- .DW + 000929 => x"4550", -- .DW + 000930 => x"524f", -- .DW + 000931 => x"4d00", -- .DW + 000932 => x"2033", -- .DW + 000933 => x"2f27", -- .DW + 000934 => x"3131", -- .DW + 000935 => x"273a", -- .DW + 000936 => x"2042", -- .DW + 000937 => x"6f6f", -- .DW + 000938 => x"7420", -- .DW + 000939 => x"6672", -- .DW + 000940 => x"6f6d", -- .DW + 000941 => x"206d", -- .DW + 000942 => x"656d", -- .DW + 000943 => x"6f72", -- .DW + 000944 => x"7900", -- .DW + 000945 => x"2070", -- .DW + 000946 => x"3a20", -- .DW + 000947 => x"5072", -- .DW + 000948 => x"6f67", -- .DW + 000949 => x"7261", -- .DW + 000950 => x"6d20", -- .DW + 000951 => x"4545", -- .DW + 000952 => x"5052", -- .DW + 000953 => x"4f4d", -- .DW + 000954 => x"0000", -- .DW + 000955 => x"2064", -- .DW + 000956 => x"3a20", -- .DW + 000957 => x"5241", -- .DW + 000958 => x"4d20", -- .DW + 000959 => x"6475", -- .DW + 000960 => x"6d70", -- .DW + 000961 => x"0000", -- .DW + 000962 => x"2072", -- .DW + 000963 => x"3a20", -- .DW + 000964 => x"5265", -- .DW + 000965 => x"7365", -- .DW + 000966 => x"7400", -- .DW + 000967 => x"636d", -- .DW + 000968 => x"643a", -- .DW + 000969 => x"3e20", -- .DW + 000970 => x"0000", -- .DW + 000971 => x"494d", -- .DW + 000972 => x"4147", -- .DW + 000973 => x"4520", -- .DW + 000974 => x"4552", -- .DW + 000975 => x"524f", -- .DW + 000976 => x"5221", -- .DW + 000977 => x"0000", -- .DW + 000978 => x"4952", -- .DW + 000979 => x"5120", -- .DW + 000980 => x"4552", -- .DW + 000981 => x"524f", -- .DW + 000982 => x"5221", -- .DW + 000983 => x"0000", -- .DW + 000984 => x"4348", -- .DW + 000985 => x"4543", -- .DW + 000986 => x"4b53", -- .DW + 000987 => x"554d", -- .DW + 000988 => x"2045", -- .DW + 000989 => x"5252", -- .DW + 000990 => x"4f52", -- .DW + 000991 => x"2100", -- .DW + 000992 => x"5350", -- .DW + 000993 => x"492f", -- .DW + 000994 => x"4545", -- .DW + 000995 => x"5052", -- .DW + 000996 => x"4f4d", -- .DW + 000997 => x"2045", -- .DW + 000998 => x"5252", -- .DW + 000999 => x"4f52", -- .DW + 001000 => x"2100", -- .DW + 001001 => x"5072", -- .DW + 001002 => x"6573", -- .DW + 001003 => x"7320", -- .DW + 001004 => x"616e", -- .DW + 001005 => x"7920", -- .DW + 001006 => x"6b65", -- .DW + 001007 => x"7900", -- .DW + others => x"0000" -- NOP + ); + ------------------------------------------------------ + +begin + + -- Memory Access --------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + MEM_FILE_ACCESS: process(CLK_I) + begin + if rising_edge(CLK_I) then + -- Data Read -- + if (D_EN_I = '1') then -- valid access + if (word_mode_en_c = true) then -- read data access + D_DAT_O <= BOOT_MEM_FILE_C(to_integer(unsigned(D_ADR_I(log2_mem_size_c-1 downto 0)))); + else + D_DAT_O <= BOOT_MEM_FILE_C(to_integer(unsigned(D_ADR_I(log2_mem_size_c downto 1)))); + end if; + end if; + -- Instruction Read -- + if (I_EN_I = '1') then + if (word_mode_en_c = true) then + I_DAT_O <= BOOT_MEM_FILE_C(to_integer(unsigned(I_ADR_I(log2_mem_size_c-1 downto 0)))); + else + I_DAT_O <= BOOT_MEM_FILE_C(to_integer(unsigned(I_ADR_I(log2_mem_size_c downto 1)))); + end if; + end if; + end if; + end process MEM_FILE_ACCESS; + + + +end BOOT_MEM_STRUCTURE; Index: trunk/rtl/CTRL.vhd =================================================================== --- trunk/rtl/CTRL.vhd (nonexistent) +++ trunk/rtl/CTRL.vhd (revision 21) @@ -0,0 +1,291 @@ +-- ######################################################## +-- # << ATLAS Project - CPU Control Spine >> # +-- # **************************************************** # +-- # Main control system, generating control signals # +-- # for each pipeline stage. # +-- # **************************************************** # +-- # Last modified: 25.01.2014 # +-- # **************************************************** # +-- # 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 + INSTR_I : in std_logic_vector(data_width_c-1 downto 0); -- instruction input + INSTR_REG_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction register + +-- ############################################################################################### +-- ## 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 + WAKE_UP_I : in std_logic; -- wake up from sleep + 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; + + -- System enable/Start-up control -- + signal SYS_ENABLE : std_logic; + signal START_FF : std_logic; + signal SLEEP_FLAG : 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 Enable-FF ------------------------------------------------------------------------------------ + -- -------------------------------------------------------------------------------------------------------- + SYSTEM_ENABLE: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + START_FF <= '0'; + SLEEP_FLAG <= '0'; + elsif (CE_I = '1') then + START_FF <= '1'; -- pretty amazing, huh? ;) + if (OP_DEC_CTRL_I(ctrl_sleep_c) = '1') then + SLEEP_FLAG <= '1'; -- go to sleep + elsif (WAKE_UP_I = '1') then + SLEEP_FLAG <= '0'; -- wake up + end if; + end if; + end if; + end process SYSTEM_ENABLE; + + -- Enable control -- + SYS_ENABLE <= (not SLEEP_FLAG) and START_FF; + + + + -- 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') and (MULTI_CYC_REQ_I = '0') then -- hold when multi-cycle op required + DIS_CYCLE_FF <= '0'; + end if; + end if; + end if; + end process FLOW_ARBITER; + + -- Multi cycle outut -- + MULTI_CYC_O <= MULTI_CYC_FF; + + + -- Instruction Register -- + -------------------------- + I_REG: process(CLK_I, INSTR_I) + begin + --if rising_edge(CLK_I) then + -- if (RST_I = '1') then + -- INSTR_REG_O <= (others => '0'); + -- elsif (CE_I = '1') and (((not DIS_IF) and (not MEM_DEPENDECY)) = '1') then + INSTR_REG_O <= INSTR_I; + -- end if; + --end if; + end process I_REG; + + + -- 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 + branch_slots: -- highly experimental!!! + if (branch_slots_en_c = true) generate + DIS_CYCLE <= '1' when (MEM_DEPENDECY = '1') or (SYS_ENABLE = '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 (SYS_ENABLE = '0') else '0'; + end generate no_branch_slots; + DIS_IF <= MULTI_CYC_REQ_I or SLEEP_FLAG; + 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 register and invalidate 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 -- + if (VALID_BRANCH_I = '0') and (EX_CTRL_BUF(ctrl_branch_c) = '1') then -- unfullfilled branch + MA_CTRL_FF(ctrl_wb_en_c) <= EXC_TAKEN_I; -- IRQs may process anyway + else + 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 + end if; + 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: trunk/rtl/ATLAS_pkg.vhd =================================================================== --- trunk/rtl/ATLAS_pkg.vhd (nonexistent) +++ trunk/rtl/ATLAS_pkg.vhd (revision 21) @@ -0,0 +1,768 @@ +-- ######################################################## +-- # << ATLAS Project - Project Package >> # +-- # **************************************************** # +-- # All architecture configurations, options, signal # +-- # definitions and components are listed here. # +-- # **************************************************** # +-- # Last modified: 01.02.2014 # +-- # **************************************************** # +-- # 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 for Application --------------------------------------------- + -- ------------------------------------------------------------------------------------------- + constant big_endian_c : boolean := false; -- use little/big endian memory system + constant build_mul_c : boolean := true; -- build a dedicated MUL unit + constant build_mac_c : boolean := false; -- build a dedicated MAC unit + constant word_mode_en_c : boolean := false; -- use word-addressed memory system instead of byte-addressed + + ---- 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 adr word boundary + constant link_reg_adr_c : std_logic_vector(02 downto 0) := "111"; -- link reg for calls + constant stack_pnt_adr_c : std_logic_vector(02 downto 0) := "110"; -- stack pointer + constant boot_page_c : std_logic_vector(15 downto 0) := x"8000"; -- boot pages begin + constant boot_adr_c : std_logic_vector(15 downto 0) := x"0000"; -- boot address + constant user_mode_c : std_logic := '0'; -- user mode indicator + constant system_mode_c : std_logic := '1'; -- system mode indicator + constant branch_slots_en_c : boolean := false; -- use branch delay slots (highly experimental!!!) + constant ldil_sign_ext_c : boolean := true; -- use sign extension when loading low byte + constant reg_branches_en_c : boolean := true; -- synthesize register-based branches + + + -- Interrupt/Exception Vectors (word-address) --------------------------------------------- + -- ------------------------------------------------------------------------------------------- + constant res_int_vec_c : std_logic_vector(15 downto 0) := x"0000"; -- use boot address instead! + constant irq0_int_vec_c : std_logic_vector(15 downto 0) := x"0001"; -- external int line 0 IRQ + constant irq1_int_vec_c : std_logic_vector(15 downto 0) := x"0002"; -- external int line 1 IRQ + constant cmd_err_int_vec_c : std_logic_vector(15 downto 0) := x"0003"; -- instruction/access error + constant swi_int_vec_c : std_logic_vector(15 downto 0) := x"0004"; -- software IRQ + + + -- 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_bst_cyc_c : std_logic_vector(2 downto 0) := "111"; -- burst end + + + -- 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 protection + constant msr_xint_en_c : natural := 11; -- enable external interrupts (global) + constant msr_xint0_en_c : natural := 12; -- enable external interrupt 0 + constant msr_xint1_en_c : natural := 13; -- enable external interrupt 1 + constant msr_svd_mode_c : natural := 14; -- saved operating mode + 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 + + + -- 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_get_par_c : natural := 27; -- get parity bit + + -- Coprocessor Access -- + constant ctrl_cp_acc_c : natural := 28; -- coprocessor operation + constant ctrl_cp_trans_c : natural := 29; -- coprocessor data transfer + constant ctrl_cp_wr_c : natural := 30; -- write to coprocessor + constant ctrl_cp_id_c : natural := 31; -- coprocessor id bit + + -- System Register Access -- + constant ctrl_msr_wr_c : natural := 32; -- write to mcr + constant ctrl_msr_rd_c : natural := 33; -- read from mcr + constant ctrl_pc_wr_c : natural := 34; -- write pc + + -- Branch/Context Control -- + constant ctrl_cond_0_c : natural := 35; -- condition code bit 0 + constant ctrl_cond_1_c : natural := 36; -- condition code bit 1 + constant ctrl_cond_2_c : natural := 37; -- condition code bit 2 + constant ctrl_cond_3_c : natural := 38; -- condition code bit 3 + constant ctrl_branch_c : natural := 39; -- is branch operation + constant ctrl_link_c : natural := 40; -- store old pc to lr + constant ctrl_syscall_c : natural := 41; -- is a system call + constant ctrl_cmd_err_c : natural := 42; -- invalid/unauthorized operation + constant ctrl_ctx_down_c : natural := 43; -- go to user mode + constant ctrl_restsm_c : natural := 44; -- restore saved mode + + -- Memory Access -- + constant ctrl_mem_acc_c : natural := 45; -- request d-mem access + constant ctrl_mem_wr_c : natural := 46; -- write to d-mem + constant ctrl_mem_bpba_c : natural := 47; -- use bypassed base address + constant ctrl_mem_daa_c : natural := 48; -- use delayed address + + -- Multiply-and-Acuumulate Unit -- + constant ctrl_use_mac_c : natural := 49; -- use MAC unit + constant ctrl_load_mac_c : natural := 50; -- load addition buffer for MAC + constant ctrl_use_offs_c : natural := 51; -- use loaded offset + + -- Sleep command -- + constant ctrl_sleep_c : natural := 52; -- go to sleep + +-- -- EX Forwarding -- +-- constant ctrl_a_ex_ma_fw_c : natural := 53; -- obsolete +-- constant ctrl_a_ex_wb_fw_c : natural := 54; -- obsolete +-- constant ctrl_b_ex_ma_fw_c : natural := 55; -- obsolete +-- constant ctrl_b_ex_wb_fw_c : natural := 56; -- obsolete +-- constant ctrl_c_ex_wb_fw_c : natural := 57; -- obsolete + + -- Bus Size -- + constant ctrl_width_c : natural := 53; -- control bus size +-- constant ctrl_width_c : natural := 58; -- obsolete + + -- 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 + constant ctrl_alu_cf_opt_c : natural := ctrl_rd_2_c; -- option for carry in (normal/invert) + constant ctrl_alu_zf_opt_c : natural := ctrl_rd_1_c; -- option for zero in (AND/OR) + + + -- 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_bic_c : std_logic_vector(2 downto 0) := "010"; -- bit clear + constant alu_sft_c : std_logic_vector(2 downto 0) := "011"; -- shift operation + constant alu_and_c : std_logic_vector(2 downto 0) := "100"; -- logical and + constant alu_orr_c : std_logic_vector(2 downto 0) := "101"; -- logical or + constant alu_eor_c : std_logic_vector(2 downto 0) := "110"; -- logical xor + constant alu_nand_c : std_logic_vector(2 downto 0) := "111"; -- logical nand + + + -- 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 ----------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + -- S: Carrie Underwood - Thank God For The Hometowns + -- M: Precious - Das Leben ist kostbar + -- M: Mean Creek + -- S: Mumford & Sons - Lover of the Light + -- M: 127 Hours + -- M: Hart of Dixie + -- M: Nick und Norah - Soundtrack einer Nacht + -- M: Joyride - S**drive + -- S: David Nail - Whatever She's Got + -- M: Brantley Gilbert - Bottoms Up + + + -- Functions ------------------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + function log2(temp : natural) return natural; -- logarithm base 2 + + + -- 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 + 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 + MA_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- ma 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 + WAKE_UP_O : out std_logic; -- wake-up signal + 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 + MODE_FF_O : out std_logic -- delayed current 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 + INSTR_I : in std_logic_vector(data_width_c-1 downto 0); -- instruction input + INSTR_REG_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction register + + -- 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 + WAKE_UP_I : in std_logic; -- wake up from sleep + 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 + INSTR_ADR_I : in std_logic_vector(data_width_c-1 downto 0); -- corresponding address + 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_CPU + port ( + -- Global Control -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + CE_I : in std_logic; -- global clock enable, high-active + + -- 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: System Controller Core 0 ---------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + component SYS_0_CORE + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + + -- Interrupt Lines -- + TIMER_IRQ_O : out std_logic; -- timer irq + IRQ_I : in std_logic_vector(07 downto 0); -- irq input + IRQ_O : out std_logic -- interrupt request + ); + end component; + + -- Component: System Controller Core 1 ---------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + component SYS_1_CORE + generic ( + -- Clock Speed Configuration -- + CLK_SPEED_G : std_logic_vector(31 downto 0) := (others => '0') -- clock speed (in Hz) + ); + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + SYS_MODE_I : in std_logic; -- current operating mode + INT_EXE_I : in std_logic; -- interrupt beeing executed + + -- Memory Interface -- + MEM_IP_ADR_O : out std_logic_vector(15 downto 0); -- instruction page + MEM_DP_ADR_O : out std_logic_vector(15 downto 0) -- data page + ); + end component; + + -- Component: Communication Controller Core 0 --------------------------------------------- + -- ------------------------------------------------------------------------------------------- + component COM_0_CORE + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + + -- Memory Interface -- + UART_RX_IRQ_O : out std_logic; -- UART IRQ "data available" + UART_TX_IRQ_O : out std_logic; -- UART IRQ "sending done" + SPI_IRQ_O : out std_logic; -- SPI IRQ "transfer done" + + -- IO Interface -- + UART_TXD_O : out std_logic; -- UART serial output + UART_RXD_I : in std_logic; -- UART serial input + SPI_MOSI_O : out std_logic; -- serial data out + SPI_MISO_I : in std_logic; -- serial data in + SPI_SCK_O : out std_logic; -- serial clock out + SPI_CS_O : out std_logic_vector(15 downto 0); -- chip select (low active) + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + PIO_OUT_O : out std_logic_vector(15 downto 0) -- parallel output + ); + end component; + + -- Component: System Coprocessor ---------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + component SYSTEM_CP + generic ( + -- Configuration -- + CLOCK_SPEED_G : std_logic_vector(31 downto 0) -- clock speed in Hz + ); + port ( + -- Global Control -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + + -- 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 + CP_IRQ_O : out std_logic; -- unit interrupt request + SYS_MODE_I : in std_logic; -- current operating mode + INT_EXE_I : in std_logic; -- interrupt beeing executed + + -- Memory Interface -- + MEM_IP_ADR_O : out std_logic_vector(15 downto 0); -- instruction page + MEM_DP_ADR_O : out std_logic_vector(15 downto 0); -- data page + + -- IO Interface -- + UART_RXD_I : in std_logic; -- receiver input + UART_TXD_O : out std_logic; -- UART transmitter output + SPI_MOSI_O : out std_logic_vector(07 downto 0); -- serial data out + SPI_MISO_I : in std_logic_vector(07 downto 0); -- serial data in + SPI_SCK_O : out std_logic_vector(07 downto 0); -- serial clock out + SPI_CS_O : out std_logic_vector(07 downto 0); -- chip select (low active) + PIO_OUT_O : out std_logic_vector(15 downto 0); -- parallel output + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + SYS_OUT_O : out std_logic_vector(07 downto 0); -- system output + SYS_IN_I : in std_logic_vector(07 downto 0); -- system input + IRQ_I : in std_logic_vector(01 downto 0) -- IRQs + ); + end component; + + -- Component: Memory Gateway -------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + component MEM_GATE + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + + I_ADR_I : in std_logic_vector(15 downto 0); -- instruction adr + I_EN_I : in std_logic; -- IR update + I_DAT_O : out std_logic_vector(15 downto 0); -- instruction out + D_REQ_I : in std_logic; -- request access in next cycle + D_RW_I : in std_logic; -- read/write + D_ADR_I : in std_logic_vector(15 downto 0); -- data adr + D_DAT_I : in std_logic_vector(15 downto 0); -- data in + D_DAT_O : out std_logic_vector(15 downto 0); -- data out + MEM_IP_ADR_I : in std_logic_vector(15 downto 0); -- instruction page + MEM_DP_ADR_I : in std_logic_vector(15 downto 0); -- data page + + -- Boot ROM Interface -- + BOOT_I_ADR_O : out std_logic_vector(15 downto 0); -- instruction adr + BOOT_I_EN_O : out std_logic; -- IR update + BOOT_I_DAT_I : in std_logic_vector(15 downto 0); -- instruction out + BOOT_D_EN_O : out std_logic; -- access enable + BOOT_D_RW_O : out std_logic; -- read/write + BOOT_D_ADR_O : out std_logic_vector(15 downto 0); -- data adr + BOOT_D_DAT_O : out std_logic_vector(15 downto 0); -- data in + BOOT_D_DAT_I : in std_logic_vector(15 downto 0); -- data out + + -- Memory Interface -- + MEM_I_PAGE_O : out std_logic_vector(15 downto 0); -- instruction page + MEM_I_ADR_O : out std_logic_vector(15 downto 0); -- instruction adr + MEM_I_EN_O : out std_logic; -- IR update + MEM_I_DAT_I : in std_logic_vector(15 downto 0); -- instruction out + MEM_D_EN_O : out std_logic; -- access enable + MEM_D_RW_O : out std_logic; -- read/write + MEM_D_PAGE_O : out std_logic_vector(15 downto 0); -- data page + MEM_D_ADR_O : out std_logic_vector(15 downto 0); -- data adr + MEM_D_DAT_O : out std_logic_vector(15 downto 0); -- data in + MEM_D_DAT_I : in std_logic_vector(15 downto 0) -- data out + ); + end component; + + -- Component: Bootloader Memory ----------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + component BOOT_MEM + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + I_ADR_I : in std_logic_vector(15 downto 0); -- instruction adr + I_EN_I : in std_logic; -- IR update + I_DAT_O : out std_logic_vector(15 downto 0); -- instruction out + D_EN_I : in std_logic; -- access enable + D_RW_I : in std_logic; -- read/write + D_ADR_I : in std_logic_vector(15 downto 0); -- data adr + D_DAT_I : in std_logic_vector(15 downto 0); -- data in + D_DAT_O : out std_logic_vector(15 downto 0) -- data out + ); + end component; + +end atlas_core_package; + +package body atlas_core_package is + + -- Function: Logarithm Base 2 ------------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + function log2(temp : natural) return natural is + variable result : natural; + begin + for i in 0 to integer'high loop + if (2**i >= temp) then + return i; + end if; + end loop; + return 0; + end function log2; + + +end atlas_core_package; Index: trunk/rtl/COM_0_CORE.vhd =================================================================== --- trunk/rtl/COM_0_CORE.vhd (nonexistent) +++ trunk/rtl/COM_0_CORE.vhd (revision 21) @@ -0,0 +1,486 @@ +-- ######################################################### +-- # << ATLAS Project - Communication Controller 0 >> # +-- # ***************************************************** # +-- # -> UART (RXD, TXD) # +-- # -> SPI (8 channels) # +-- # -> Parallel IO (16 in, 16 out) # +-- # -> System IO (8 in, 8 out) # +-- # ***************************************************** # +-- # Last modified: 05.03.2014 # +-- # ***************************************************** # +-- # 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 COM_0_CORE is + port ( +-- ############################################################################################### +-- ## Host Interface ## +-- ############################################################################################### + + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + +-- ############################################################################################### +-- ## Interrupt Lines ## +-- ############################################################################################### + + UART_RX_IRQ_O : out std_logic; -- UART IRQ "data available" + UART_TX_IRQ_O : out std_logic; -- UART IRQ "sending done" + SPI_IRQ_O : out std_logic; -- SPI IRQ "transfer done" + PIO_IRQ_O : out std_logic; -- PIO input pin change irq + +-- ############################################################################################### +-- ## Communication Lines ## +-- ############################################################################################### + + UART_TXD_O : out std_logic; -- UART serial output + UART_RXD_I : in std_logic; -- UART serial input + SPI_MOSI_O : out std_logic_vector(07 downto 0); -- serial data out + SPI_MISO_I : in std_logic_vector(07 downto 0); -- serial data in + SPI_SCK_O : out std_logic_vector(07 downto 0); -- serial clock out + SPI_CS_O : out std_logic_vector(07 downto 0); -- chip select (low active) + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + PIO_OUT_O : out std_logic_vector(15 downto 0); -- parallel output + SYS_IO_I : in std_logic_vector(07 downto 0); -- system input + SYS_IO_O : out std_logic_vector(07 downto 0) -- system output + ); +end COM_0_CORE; + +architecture COM_0_CORE_BEHAV of COM_0_CORE is + + -- Module Addresses -- + constant uart_rtx_sd_reg_c : std_logic_vector(02 downto 0) := "000"; -- R/W: UART RTX data + status flags + constant uart_prsc_reg_c : std_logic_vector(02 downto 0) := "001"; -- R/W: UART prescaler register + constant com_ctrl_reg_c : std_logic_vector(02 downto 0) := "010"; -- R/W: COM control register + constant spi_data_reg_c : std_logic_vector(02 downto 0) := "011"; -- R/W: SPI RTX data register + constant spi_cs_reg_c : std_logic_vector(02 downto 0) := "100"; -- R/W: SPI chip select register + constant pio_in_reg_c : std_logic_vector(02 downto 0) := "101"; -- R: PIO input register + constant pio_out_reg_c : std_logic_vector(02 downto 0) := "110"; -- R/W: PIO output register + constant sys_io_reg_c : std_logic_vector(02 downto 0) := "111"; -- R/W: System parallel in/out + + -- CTRL Register -- + constant spi_cr_dir_flag_c : natural := 0; -- R/W: 0: MSB first, 1: LSB first + constant spi_cr_cpol_c : natural := 1; -- R/W: clock polarity, 1: idle '1' clock, 0: idle '0' clock + constant spi_cr_cpha_c : natural := 2; -- R/W: edge offset: 0: first edge, 1: second edge + constant spi_cr_bsy_c : natural := 3; -- R: transceiver is busy when '1' + constant spi_cr_auto_cs_c : natural := 4; -- R/W: Auto apply CS when '1' + constant uart_tx_busy_c : natural := 5; -- R: UART transmitter is busy + constant uart_en_c : natural := 6; -- R/W: UART enable +-- constant : natural := 7; -- reserved + constant spi_cr_ln_lsb_c : natural := 8; -- R/W: data length lsb + constant spi_cr_ln_msb_c : natural := 11; -- R/W: data length msb + constant spi_cr_prsc_lsb_c : natural := 12; -- R/W: SPI clock prescaler lsb + constant spi_cr_prsc_msb_c : natural := 15; -- R/W: SPI clock prescaler msb + + -- UART Control Flags (UART RTX REG) -- + constant uart_rx_ready_c : natural := 15; -- R: Data received + + -- UART Registers -- + signal UART_RX_REG : std_logic_vector(07 downto 0); + signal UART_PRSC_REG : std_logic_vector(15 downto 0); + + -- UART Transceiver -- + signal UART_RX_SYNC : std_logic_vector(03 downto 0); + signal UART_TX_BSY_FLAG : std_logic; + signal UART_RX_BSY_FLAG : std_logic; + signal UART_TX_SREG : std_logic_vector(09 downto 0); + signal UART_RX_SREG : std_logic_vector(09 downto 0); + signal UART_TX_BIT_CNT : std_logic_vector(03 downto 0); + signal UART_RX_BIT_CNT : std_logic_vector(03 downto 0); + signal UART_TX_BAUD_CNT : std_logic_vector(15 downto 0); + signal UART_RX_BAUD_CNT : std_logic_vector(15 downto 0); + signal UART_RX_READY : std_logic; + signal UART_RX_READY_SYNC : std_logic; + + -- SPI Registers -- + signal SPI_TX_REG : std_logic_vector(15 downto 0); + signal SPI_RX_REG : std_logic_vector(15 downto 0); + signal SPI_RX_REG_NXT : std_logic_vector(15 downto 0); + signal SPI_CS_REG : std_logic_vector(07 downto 0); + signal COM_CONFIG_REG : std_logic_vector(15 downto 0); + + -- SPI Transceiver -- + signal SPI_IN_BUF : std_logic_vector(01 downto 0); + signal SPI_MOSI_NXT : std_logic; + signal SPI_SCK_NXT : std_logic; + signal SPI_MOSI_FF : std_logic; + signal SPI_CS_FF : std_logic_vector(07 downto 0); + signal SPI_CS_FF_NXT : std_logic_vector(07 downto 0); + signal SPI_IRQ : std_logic; + + -- SPI Arbiter -- + type spi_arb_state_type is (IDLE, START_TRANS, TRANSMIT_0, TRANSMIT_1, FINISH); + signal SPI_ARB_STATE : spi_arb_state_type; + signal SPI_ARB_STATE_NXT : spi_arb_state_type; + signal SPI_BIT_CNT : std_logic_vector(04 downto 0); + signal SPI_BIT_CNT_NXT : std_logic_vector(04 downto 0); + signal SPI_RX_SFT : std_logic_vector(15 downto 0); -- rx shift registers + signal SPI_RX_SFT_NXT : std_logic_vector(15 downto 0); -- rx shift registers + signal SPI_TX_SFT : std_logic_vector(15 downto 0); -- tx shift registers + signal SPI_TX_SFT_NXT : std_logic_vector(15 downto 0); -- tx shift registers + signal SPI_PRSC_CNT : std_logic_vector(15 downto 0); + signal SPI_PRSC_CNT_NXT : std_logic_vector(15 downto 0); + signal SPI_BUSY_FLAG : std_logic; + signal SPI_BUSY_FLAG_NXT : std_logic; + signal SPI_SCK_FF : std_logic; + signal SPI_MISO : std_logic; + + -- PIO Registers -- + signal PIO_OUT_DATA : std_logic_vector(15 downto 0); + signal PIO_IN_DATA : std_logic_vector(15 downto 0); + signal PIO_SYNC : std_logic_vector(15 downto 0); + signal SYS_IO_I_FF : std_logic_vector(07 downto 0); + +begin + + -- Write Access ---------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + W_ACC: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + UART_PRSC_REG <= (others => '0'); + COM_CONFIG_REG <= (others => '0'); + SPI_TX_REG <= (others => '0'); + SPI_CS_REG <= (others => '0'); + PIO_IN_DATA <= (others => '0'); + PIO_OUT_DATA <= (others => '0'); + PIO_SYNC <= (others => '0'); + SYS_IO_O <= (others => '0'); + SYS_IO_I_FF <= (others => '0'); + elsif (ICE_I = '1') then -- interface enable + if (W_EN_I = '1') then -- register update + case (ADR_I) is + when uart_prsc_reg_c => UART_PRSC_REG <= DAT_I; + when com_ctrl_reg_c => COM_CONFIG_REG <= DAT_I; + when spi_data_reg_c => SPI_TX_REG <= DAT_I; + when spi_cs_reg_c => SPI_CS_REG <= DAT_I(07 downto 00); + when pio_out_reg_c => PIO_OUT_DATA <= DAT_I; + when sys_io_reg_c => SYS_IO_O <= DAT_I(15 downto 08); + when others => NULL; + end case; + end if; + end if; + PIO_SYNC <= PIO_IN_DATA; + PIO_IN_DATA <= PIO_IN_I; -- pio input + SYS_IO_I_FF <= SYS_IO_I; + end if; + end process W_ACC; + + -- PIO Output -- + PIO_OUT_O <= PIO_OUT_DATA; + + -- PIO Input pin change IRQ -- + PIO_IRQ_O <= '0' when (PIO_SYNC = PIO_IN_DATA) else '1'; + + + + -- Read Access ----------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + R_ACC: process(ADR_I, UART_TX_BSY_FLAG, UART_RX_READY, UART_RX_REG, UART_PRSC_REG, COM_CONFIG_REG, + SPI_BUSY_FLAG, SPI_CS_REG, SPI_RX_REG, PIO_OUT_DATA, PIO_IN_DATA, SYS_IO_I_FF) + begin + case (ADR_I) is + when uart_rtx_sd_reg_c => DAT_O <= (others => '0'); + DAT_O(7 downto 0) <= UART_RX_REG; + DAT_O(uart_rx_ready_c) <= UART_RX_READY; + when uart_prsc_reg_c => DAT_O <= UART_PRSC_REG; + when com_ctrl_reg_c => DAT_O <= COM_CONFIG_REG; + DAT_O(spi_cr_bsy_c) <= SPI_BUSY_FLAG; + DAT_O(uart_tx_busy_c) <= UART_TX_BSY_FLAG; + when spi_data_reg_c => DAT_O <= SPI_RX_REG; + when spi_cs_reg_c => DAT_O <= x"00" & SPI_CS_REG; + when pio_in_reg_c => DAT_O <= PIO_IN_DATA; + when pio_out_reg_c => DAT_O <= PIO_OUT_DATA; + when sys_io_reg_c => DAT_O <= x"00" & SYS_IO_I_FF; + when others => DAT_O <= x"0000"; + end case; + end process R_ACC; + + + + -- UART Flag Arbiter ----------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + UART_FLAG_CTRL: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + UART_RX_READY <= '0'; + UART_RX_READY_SYNC <= '0'; + else + -- Ready Flag -- + UART_RX_READY_SYNC <= UART_RX_BSY_FLAG; + if (UART_RX_READY = '1') and (R_EN_I = '1') and (ADR_I = uart_rtx_sd_reg_c) and (ICE_I = '1') then + UART_RX_READY <= '0'; + elsif (UART_RX_READY_SYNC = '1') and (UART_RX_BSY_FLAG = '0') then -- falling edge + UART_RX_READY <= '1'; + end if; + end if; + end if; + end process UART_FLAG_CTRL; + + -- Interrupt output -- + UART_RX_IRQ_O <= UART_RX_READY; + UART_TX_IRQ_O <= not UART_TX_BSY_FLAG; + + + + -- Transmitter Unit ------------------------------------------------------------------------------------ + -- -------------------------------------------------------------------------------------------------------- + UART_TRANSMITTER: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + UART_TX_BSY_FLAG <= '0'; + UART_TX_SREG <= (others => '1'); + UART_TX_BIT_CNT <= (others => '0'); + UART_TX_BAUD_CNT <= (others => '0'); + else + -- UART disabled + if (COM_CONFIG_REG(uart_en_c) = '0') then + UART_TX_BSY_FLAG <= '0'; + UART_TX_SREG <= (others => '1'); + UART_TX_BIT_CNT <= (others => '0'); + UART_TX_BAUD_CNT <= (others => '0'); + + -- UART TX register -- + elsif (UART_TX_BSY_FLAG = '0') then + UART_TX_BIT_CNT <= "1010"; -- 10 bits + UART_TX_BAUD_CNT <= UART_PRSC_REG; + if (W_EN_I = '1') and (ADR_I = uart_rtx_sd_reg_c) then + UART_TX_BSY_FLAG <= '1'; + UART_TX_SREG <= '1' & DAT_I(7 downto 0) & '0'; -- stopbit & data & startbit + end if; + else + if (UART_TX_BAUD_CNT = x"0000") then + UART_TX_BAUD_CNT <= UART_PRSC_REG; + if (UART_TX_BIT_CNT /= "0000") then + UART_TX_SREG <= '1' & UART_TX_SREG(9 downto 1); + UART_TX_BIT_CNT <= std_logic_vector(unsigned(UART_TX_BIT_CNT) - 1); + else + UART_TX_BSY_FLAG <= '0'; -- done + end if; + else + UART_TX_BAUD_CNT <= std_logic_vector(unsigned(UART_TX_BAUD_CNT) - 1); + end if; + end if; + end if; + end if; + end process UART_TRANSMITTER; + + -- Transmitter output -- + UART_TXD_O <= UART_TX_SREG(0); + + + + -- UART Receiver Unit ---------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + UART_RECEIVER: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + UART_RX_BSY_FLAG <= '0'; + UART_RX_SREG <= (others => '0'); + UART_RX_BIT_CNT <= (others => '0'); + UART_RX_BAUD_CNT <= (others => '0'); + UART_RX_SYNC <= (others => '1'); + UART_RX_REG <= (others => '0'); + else + -- Synchronizer -- + if (COM_CONFIG_REG(uart_en_c) = '1') then + UART_RX_SYNC <= UART_RXD_I & UART_RX_SYNC(3 downto 1); + end if; + + -- UART disabled -- + if (COM_CONFIG_REG(uart_en_c) = '0') then + UART_RX_BSY_FLAG <= '0'; + UART_RX_SREG <= (others => '0'); + UART_RX_BIT_CNT <= (others => '0'); + UART_RX_BAUD_CNT <= (others => '0'); + UART_RX_SYNC <= (others => '1'); + UART_RX_REG <= (others => '0'); + + -- RX shift reg -- + elsif (UART_RX_BSY_FLAG = '0') then + UART_RX_BIT_CNT <= "1001"; -- 9 bits (startbit + 8 data bits) + UART_RX_BAUD_CNT <= '0' & UART_PRSC_REG(15 downto 1); -- half baud rate, sample in middle + if (UART_RX_SYNC(1 downto 0) = "01") then -- start 'bit' detected (falling logical edge) + UART_RX_BSY_FLAG <= '1'; + end if; + else + if (UART_RX_BAUD_CNT = x"0000") then + UART_RX_BAUD_CNT <= UART_PRSC_REG; + if (UART_RX_BIT_CNT /= "0000") then + UART_RX_SREG <= UART_RX_SYNC(0) & UART_RX_SREG(9 downto 1); + UART_RX_BIT_CNT <= std_logic_vector(unsigned(UART_RX_BIT_CNT) - 1); + else + UART_RX_BSY_FLAG <= '0'; -- done + UART_RX_REG <= UART_RX_SREG(9 downto 2); + end if; + else + UART_RX_BAUD_CNT <= std_logic_vector(unsigned(UART_RX_BAUD_CNT) - 1); + end if; + end if; + end if; + end if; + end process UART_RECEIVER; + + + + -- SPI Transceiver Unit -------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + SPI_ARB_SYNC: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + SPI_ARB_STATE <= IDLE; + SPI_RX_SFT <= (others => '0'); + SPI_TX_SFT <= (others => '0'); + SPI_BIT_CNT <= (others => '0'); + SPI_PRSC_CNT <= (others => '0'); + SPI_RX_REG <= (others => '0'); + SPI_SCK_FF <= '0'; + SPI_MOSI_FF <= '0'; + SPI_IN_BUF <= "00"; + SPI_CS_FF <= (others => '1'); + SPI_BUSY_FLAG <= '0'; + SPI_IRQ_O <= '0'; + else + SPI_ARB_STATE <= SPI_ARB_STATE_NXT; + SPI_RX_SFT <= SPI_RX_SFT_NXT; + SPI_TX_SFT <= SPI_TX_SFT_NXT; + SPI_BIT_CNT <= SPI_BIT_CNT_NXT; + SPI_PRSC_CNT <= SPI_PRSC_CNT_NXT; + SPI_RX_REG <= SPI_RX_REG_NXT; + SPI_SCK_FF <= SPI_SCK_NXT; + SPI_MOSI_FF <= SPI_MOSI_NXT; + SPI_IN_BUF <= SPI_IN_BUF(0) & SPI_MISO; + if (COM_CONFIG_REG(spi_cr_auto_cs_c) = '1') then -- auto apply chip select + SPI_CS_FF <= SPI_CS_FF_NXT; + else -- manually apply chip select + SPI_CS_FF <= not SPI_CS_REG; + end if; + SPI_BUSY_FLAG <= SPI_BUSY_FLAG_NXT; + SPI_IRQ_O <= SPI_IRQ; + end if; + end if; + end process SPI_ARB_SYNC; + + + + SPI_ARB_COMB: process(SPI_ARB_STATE, COM_CONFIG_REG, SPI_RX_SFT, SPI_TX_SFT, SPI_BIT_CNT, SPI_PRSC_CNT, SPI_IN_BUF, + SPI_RX_REG, SPI_MOSI_FF, SPI_CS_FF, SPI_CS_REG, SPI_TX_REG, W_EN_I, ADR_I, SPI_BUSY_FLAG, ICE_I) + variable prsc_match_v : std_logic; + begin + -- Defaults -- + SPI_ARB_STATE_NXT <= SPI_ARB_STATE; -- arbiter state + SPI_RX_SFT_NXT <= SPI_RX_SFT; -- rx shift register + SPI_TX_SFT_NXT <= SPI_TX_SFT; -- tx shift register + SPI_BIT_CNT_NXT <= SPI_BIT_CNT; -- bit counter + SPI_PRSC_CNT_NXT <= SPI_PRSC_CNT; -- SPI clock prescaler + SPI_RX_REG_NXT <= SPI_RX_REG; -- complete received data + SPI_SCK_NXT <= COM_CONFIG_REG(spi_cr_cpol_c); -- clock polarity + SPI_MOSI_NXT <= SPI_MOSI_FF; -- serial data output + SPI_BUSY_FLAG_NXT <= SPI_BUSY_FLAG; -- busy flag + SPI_IRQ <= '0'; -- no interrupt + prsc_match_v := SPI_PRSC_CNT(to_integer(unsigned(COM_CONFIG_REG(spi_cr_prsc_msb_c downto spi_cr_prsc_lsb_c)))); -- prescaler match + + -- State machine -- + case (SPI_ARB_STATE) is -- IDLE, START_TRANS, TRANSMIT, END_TRANS + + when IDLE => -- Wait for transmitter init + SPI_CS_FF_NXT <= (others => '1'); -- deselct all slaves + SPI_BIT_CNT_NXT <= (others => '0'); + SPI_RX_SFT_NXT <= (others => '0'); + SPI_PRSC_CNT_NXT <= (others => '0'); + SPI_MOSI_NXT <= '0'; + SPI_SCK_NXT <= COM_CONFIG_REG(spi_cr_cpol_c); -- idle clk polarity + if (W_EN_I = '1') and (ADR_I = spi_data_reg_c) and (ICE_I = '1') then + SPI_ARB_STATE_NXT <= START_TRANS; + SPI_BUSY_FLAG_NXT <= '1'; + end if; + + when START_TRANS => -- Apply slave select signal + SPI_TX_SFT_NXT <= SPI_TX_REG; + SPI_CS_FF_NXT <= not SPI_CS_REG; + SPI_ARB_STATE_NXT <= TRANSMIT_0; + + when TRANSMIT_0 => -- first half of bit transmission + SPI_CS_FF_NXT <= SPI_CS_FF; -- keep CS alive + SPI_PRSC_CNT_NXT <= std_logic_vector(unsigned(SPI_PRSC_CNT) + 1); + SPI_SCK_NXT <= COM_CONFIG_REG(spi_cr_cpol_c) xor COM_CONFIG_REG(spi_cr_cpha_c); + if (COM_CONFIG_REG(spi_cr_dir_flag_c) = '0') then -- MSB first + SPI_MOSI_NXT <= SPI_TX_SFT(to_integer(unsigned(COM_CONFIG_REG(spi_cr_ln_msb_c downto spi_cr_ln_lsb_c)))); + else -- LSB first + SPI_MOSI_NXT <= SPI_TX_SFT(0); + end if; + if (prsc_match_v = '1') then -- first half completed + SPI_ARB_STATE_NXT <= TRANSMIT_1; + SPI_PRSC_CNT_NXT <= (others => '0'); + end if; + + when TRANSMIT_1 => -- second half of bit transmission + SPI_CS_FF_NXT <= SPI_CS_FF; -- keep CS alive + SPI_PRSC_CNT_NXT <= std_logic_vector(unsigned(SPI_PRSC_CNT) + 1); + SPI_SCK_NXT <= not (COM_CONFIG_REG(spi_cr_cpol_c) xor COM_CONFIG_REG(spi_cr_cpha_c)); + if (prsc_match_v = '1') then -- second half completed + SPI_BIT_CNT_NXT <= std_logic_vector(unsigned(SPI_BIT_CNT) + 1); + SPI_PRSC_CNT_NXT <= (others => '0'); + if (COM_CONFIG_REG(spi_cr_dir_flag_c) = '0') then -- MSB first + SPI_TX_SFT_NXT <= SPI_TX_SFT(14 downto 0) & '0'; -- left shift + SPI_RX_SFT_NXT <= SPI_RX_SFT(14 downto 0) & SPI_IN_BUF(1); -- left shift + else -- LSB first + SPI_TX_SFT_NXT <= '0' & SPI_TX_SFT(15 downto 1); -- right shift + SPI_RX_SFT_NXT <= SPI_IN_BUF(1) & SPI_TX_SFT(15 downto 1); -- right shift + end if; + if (to_integer(unsigned(SPI_BIT_CNT)) = to_integer(unsigned(COM_CONFIG_REG(spi_cr_ln_msb_c downto spi_cr_ln_lsb_c)))) then + SPI_ARB_STATE_NXT <= FINISH; + else + SPI_ARB_STATE_NXT <= TRANSMIT_0; + end if; + end if; + + when FINISH => -- finish transfer + SPI_CS_FF_NXT <= SPI_CS_FF; -- keep CS alive + SPI_BUSY_FLAG_NXT <= '0'; + SPI_RX_REG_NXT <= SPI_RX_SFT; + SPI_MOSI_NXT <= '0'; + SPI_IRQ <= '1'; -- IRQ tick + SPI_ARB_STATE_NXT <= IDLE; + + end case; + end process SPI_ARB_COMB; + + + -- SPI IO Interface -- + SPI_IO: process(SPI_CS_FF, SPI_MOSI_FF, SPI_SCK_FF, SPI_MISO_I) + variable spi_miso_bus_v : std_logic_vector(7 downto 0); + variable spi_miso_v : std_logic; + begin + spi_miso_bus_v := SPI_MISO_I and (not SPI_CS_FF); + spi_miso_v := '0'; + for i in 0 to 7 loop -- for all channels + SPI_MOSI_O(i) <= SPI_MOSI_FF and (not SPI_CS_FF(i)); + SPI_CS_O(i) <= SPI_CS_FF(i); + SPI_SCK_O(i) <= SPI_SCK_FF; + spi_miso_v := spi_miso_v or spi_miso_bus_v(i); + end loop; + SPI_MISO <= spi_miso_v; + end process SPI_IO; + + + +end COM_0_CORE_BEHAV; Index: trunk/rtl/SYS_0_CORE.vhd =================================================================== --- trunk/rtl/SYS_0_CORE.vhd (nonexistent) +++ trunk/rtl/SYS_0_CORE.vhd (revision 21) @@ -0,0 +1,286 @@ +-- ######################################################### +-- # << ATLAS Project - System Controller 0 >> # +-- # ***************************************************** # +-- # -> Interrupt Controller (8 channels) # +-- # -> High Precision Timer (16+16 bit) # +-- # -> Linear-Feedback Shift Register (16 bit) # +-- # ***************************************************** # +-- # Last modified: 29.01.2014 # +-- # ***************************************************** # +-- # 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_0_CORE is + port ( +-- ############################################################################################### +-- ## Host Interface ## +-- ############################################################################################### + + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + +-- ############################################################################################### +-- ## Interrupt Lines ## +-- ############################################################################################### + + TIMER_IRQ_O : out std_logic; -- timer irq + IRQ_I : in std_logic_vector(07 downto 0); -- irq input + IRQ_O : out std_logic -- interrupt request + ); +end SYS_0_CORE; + +architecture SYS_0_CORE_BEHAV of SYS_0_CORE is + + -- Module Addresses -- + constant irq_sm_reg_c : std_logic_vector(02 downto 0) := "000"; -- R/W: Interrupt source and mask + constant irq_conf_reg_c : std_logic_vector(02 downto 0) := "001"; -- R/W: Interrupt type configuration + -- lo byte: '1': level triggered, '0': edge triggered + -- hi byte: '1': high level/rising edge, '0': low level/falling edge + constant timer_cnt_reg_c : std_logic_vector(02 downto 0) := "010"; -- R/W: Timer counter register + constant timer_thr_reg_c : std_logic_vector(02 downto 0) := "011"; -- R/W: Timer threshold register + constant timer_prsc_reg_c : std_logic_vector(02 downto 0) := "100"; -- R/W: Timer prescaler register + constant lfsr_data_reg_c : std_logic_vector(02 downto 0) := "101"; -- R/W: LFSR data register + constant lfsr_poly_reg_c : std_logic_vector(02 downto 0) := "110"; -- R/W: LFSR polynomial register + -- bit 15: '0' new value after read access, '1' free running mode + constant reserved_reg_c : std_logic_vector(02 downto 0) := "111"; -- RESERVED + + -- IRQ Registers -- + signal IRQ_MASK_REG : std_logic_vector(07 downto 0); + signal IRQ_SOURCE_REG : std_logic_vector(02 downto 0); + signal IRQ_CONF_REG : std_logic_vector(15 downto 0); + + -- Internals -- + signal IRQ_SYNC_0 : std_logic_vector(07 downto 0); + signal IRQ_SYNC_1 : std_logic_vector(07 downto 0); + signal IRQ_RAW_REQ : std_logic_vector(07 downto 0); + signal IRQ_BUF : std_logic_vector(07 downto 0); + signal IRQ_ID : std_logic_vector(02 downto 0); + signal IRQ_ACK_MASK : std_logic_vector(07 downto 0); + signal IRQ_ACK_MASK_FF : std_logic_vector(07 downto 0); + signal IRQ_LOCK : std_logic; + + -- Timer Registers -- + signal TMR_CNT_REG : std_logic_vector(15 downto 0); + signal TMR_THR_REG : std_logic_vector(15 downto 0); + signal TMR_PRSC_REG : std_logic_vector(15 downto 0); + signal TMR_PRSC_CNT : std_logic_vector(15 downto 0); + + -- Timer Signals -- + signal TMR_PRSC_MATCH : std_logic; + signal TMR_THRES_ZERO : std_logic; + + -- LFSR Registers -- + signal LFSR_DATA : std_logic_vector(15 downto 0); + signal LFSR_POLY : std_logic_vector(15 downto 0); + signal LFSR_NEW : std_logic_vector(15 downto 0); + signal LFSR_NOISE : std_logic; + +begin + + -- Write Access ---------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + W_ACC: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + IRQ_MASK_REG <= (others => '0'); + IRQ_CONF_REG <= (others => '0'); + TMR_CNT_REG <= (others => '0'); + TMR_THR_REG <= (others => '0'); + TMR_PRSC_REG <= (others => '0'); + TMR_PRSC_CNT <= (others => '0'); + LFSR_DATA <= (others => '0'); + LFSR_POLY <= (others => '0'); + IRQ_SYNC_0 <= (others => '0'); + IRQ_SYNC_1 <= (others => '0'); + else + -- IRQ write access -- + if (W_EN_I = '1') and (ICE_I = '1') and ((ADR_I = irq_sm_reg_c) or (ADR_I = irq_conf_reg_c)) then + if (ADR_I = irq_sm_reg_c) then + IRQ_MASK_REG <= DAT_I(15 downto 08); + else -- (ADR_I = irq_conf_reg_c) + IRQ_CONF_REG <= DAT_I; + end if; + end if; + IRQ_SYNC_1 <= IRQ_SYNC_0; + IRQ_SYNC_0 <= IRQ_I; + + -- TIMER write access -- + if (W_EN_I = '1') and (ICE_I = '1') and ((ADR_I = timer_cnt_reg_c) or (ADR_I = timer_thr_reg_c) or (ADR_I = timer_prsc_reg_c)) then + TMR_PRSC_CNT <= (others => '0'); + if (ADR_I = timer_cnt_reg_c) then + TMR_CNT_REG <= DAT_I; + elsif (ADR_I = timer_thr_reg_c) then + TMR_THR_REG <= DAT_I; + else -- (ADR_I = timer_prsc_reg_c) + TMR_PRSC_REG <= DAT_I; + end if; + else -- auto update + if (TMR_PRSC_MATCH = '1') or (TMR_THRES_ZERO = '1') then -- prescaler increment + TMR_PRSC_CNT <= (others => '0'); + else + TMR_PRSC_CNT <= std_logic_vector(unsigned(TMR_PRSC_CNT) + 1); + end if; + if (TMR_CNT_REG = TMR_THR_REG) then -- counter increment + TMR_CNT_REG <= (others => '0'); + elsif (TMR_THRES_ZERO = '0') and (TMR_PRSC_MATCH = '1') then + TMR_CNT_REG <= std_logic_vector(unsigned(TMR_CNT_REG) + 1); + end if; + end if; + + -- LFSR write access -- + if (W_EN_I = '1') and (ICE_I = '1') and ((ADR_I = lfsr_data_reg_c) or (ADR_I = lfsr_poly_reg_c)) then + if (ADR_I = lfsr_data_reg_c) then + LFSR_DATA <= DAT_I; + else -- (ADR_I = lfsr_poly_reg_c) + LFSR_POLY <= DAT_I; + end if; + else -- auto update + if (LFSR_POLY(15) = '0') then -- access-update? + if (R_EN_I = '1') and (ADR_I = lfsr_data_reg_c) and (ICE_I = '1') then + LFSR_DATA <= LFSR_NEW; + end if; + else -- free-running mode + LFSR_DATA <= LFSR_NEW; + end if; + end if; + end if; + end if; + end process W_ACC; + + -- Timer prescaler match -- + TMR_PRSC_MATCH <= '1' when (TMR_PRSC_CNT = TMR_PRSC_REG) else '0'; + + -- Timer threshold zero test -- + TMR_THRES_ZERO <= '1' when (TMR_THR_REG = x"0000") else '0'; + + -- Timer IRQ -- + TIMER_IRQ_O <= '1' when ((TMR_CNT_REG = TMR_THR_REG) and (TMR_THRES_ZERO = '0')) else '0'; + + + + -- Read Access ----------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + R_ACC: process(ADR_I, IRQ_MASK_REG, IRQ_CONF_REG, IRQ_SOURCE_REG, TMR_CNT_REG, TMR_THR_REG, + TMR_PRSC_REG, LFSR_DATA, LFSR_POLY) + begin + case (ADR_I) is + when irq_sm_reg_c => DAT_O <= IRQ_MASK_REG & "00000" & IRQ_SOURCE_REG; + when irq_conf_reg_c => DAT_O <= IRQ_CONF_REG; + when timer_cnt_reg_c => DAT_O <= TMR_CNT_REG; + when timer_thr_reg_c => DAT_O <= TMR_THR_REG; + when timer_prsc_reg_c => DAT_O <= TMR_PRSC_REG; + when lfsr_data_reg_c => DAT_O <= LFSR_DATA; + when lfsr_poly_reg_c => DAT_O <= LFSR_POLY; + when others => DAT_O <= (others => '0'); + end case; + end process R_ACC; + + + + -- Interrupt Detector ---------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + IRQ_DETECTOR: process(IRQ_MASK_REG, IRQ_CONF_REG, IRQ_SYNC_0, IRQ_SYNC_1) + begin + -- Edge/Level detector -- + IRQ_RAW_REQ <= (others => '0'); + for i in 0 to 7 loop + if (IRQ_MASK_REG(i) = '1') then -- channel enabled + if (IRQ_CONF_REG(i) = '1') then -- level triggered + IRQ_RAW_REQ(i) <= IRQ_CONF_REG(i+8) xnor IRQ_SYNC_0(i); + else -- edge triggered + if (IRQ_CONF_REG(i+8) = '1') then -- rising edge + IRQ_RAW_REQ(i) <= IRQ_SYNC_0(i) and (not IRQ_SYNC_1(i)); + else -- falling edge + IRQ_RAW_REQ(i) <= (not IRQ_SYNC_0(i)) and IRQ_SYNC_1(i); + end if; + end if; + end if; + end loop; + end process IRQ_DETECTOR; + + + + -- Interrupt Request Buffer ---------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + IRQ_BUFFER: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + IRQ_BUF <= (others => '0'); + IRQ_SOURCE_REG <= (others => '0'); + IRQ_ACK_MASK_FF <= (others => '0'); + IRQ_LOCK <= '0'; + else + if (IRQ_LOCK = '0') then -- store ID and mask until ACK + IRQ_ACK_MASK_FF <= IRQ_ACK_MASK; + IRQ_SOURCE_REG <= IRQ_ID; + end if; + if (R_EN_I = '1') and (ADR_I = irq_sm_reg_c) then -- ack on source reg read + IRQ_BUF <= (IRQ_BUF or IRQ_RAW_REQ) and (not IRQ_ACK_MASK_FF); + IRQ_LOCK <= '0'; -- ACK: remove lock + else + IRQ_BUF <= IRQ_BUF or IRQ_RAW_REQ; + if (IRQ_BUF /= x"00") then + IRQ_LOCK <= '1'; + end if; + end if; + end if; + end if; + end process IRQ_BUFFER; + + -- IRQ signal to host -- + IRQ_O <= IRQ_LOCK; + + + + -- Interrupt Priority Encoder -------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + IRQ_PR_ENC: process(IRQ_BUF) + begin + IRQ_ID <= (others => '0'); + IRQ_ACK_MASK <= (others => '0'); + for i in 0 to 7 loop + if (IRQ_BUF(i) = '1') then + IRQ_ID <= std_logic_vector(to_unsigned(i,3)); + IRQ_ACK_MASK(i) <= '1'; + exit; + end if; + end loop; + end process IRQ_PR_ENC; + + + + -- LFSR Update ----------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + LFSR_UPDATE: process(LFSR_DATA, LFSR_POLY, LFSR_NOISE) + begin + for i in 0 to 14 loop + if (LFSR_POLY(i) = '1') then + LFSR_NEW(i) <= LFSR_DATA(i+1) xor LFSR_DATA(0); + else + LFSR_NEW(i) <= LFSR_DATA(i+1); + end if; + end loop; + LFSR_NEW(15) <= LFSR_DATA(0) xor LFSR_NOISE; + end process LFSR_UPDATE; + + -- External noise input -- + LFSR_NOISE <= '0'; -- not used yet + + + +end SYS_0_CORE_BEHAV; Index: trunk/rtl/SYS_1_CORE.vhd =================================================================== --- trunk/rtl/SYS_1_CORE.vhd (nonexistent) +++ trunk/rtl/SYS_1_CORE.vhd (revision 21) @@ -0,0 +1,195 @@ +-- ######################################################### +-- # << ATLAS Project - System Controller 1 >> # +-- # ***************************************************** # +-- # -> Memory Management Unit # +-- # -> Clock Information # +-- # ***************************************************** # +-- # Last modified: 24.01.2014 # +-- # ***************************************************** # +-- # 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_1_CORE is +-- ############################################################################################### +-- ## Clock Speed Configuration ## +-- ############################################################################################### + generic ( + CLK_SPEED_G : std_logic_vector(31 downto 0) := (others => '0') -- clock speed (in Hz) + ); + port ( +-- ############################################################################################### +-- ## Host Interface ## +-- ############################################################################################### + + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + + SYS_MODE_I : in std_logic; -- current operating mode + INT_EXE_I : in std_logic; -- interrupt beeing executed + +-- ############################################################################################### +-- ## Memory Interface ## +-- ############################################################################################### + + MEM_IP_ADR_O : out std_logic_vector(15 downto 0); -- instruction page + MEM_DP_ADR_O : out std_logic_vector(15 downto 0) -- data page + ); +end SYS_1_CORE; + +architecture SYS_1_CORE_BEHAV of SYS_1_CORE is + + -- Register addresses -- + constant mmu_irq_base_c : std_logic_vector(02 downto 0) := "000"; -- R/W: base page for IRQs + constant mmu_sys_i_page_c : std_logic_vector(02 downto 0) := "001"; -- R/W: system mode I page + constant mmu_sys_d_page_c : std_logic_vector(02 downto 0) := "010"; -- R/W: system mode D page + constant mmu_usr_i_page_c : std_logic_vector(02 downto 0) := "011"; -- R/W: user mode I page + constant mmu_usr_d_page_c : std_logic_vector(02 downto 0) := "100"; -- R/W: user mode D page + constant mmu_i_page_link_c : std_logic_vector(02 downto 0) := "101"; -- R: i page link + constant mmu_d_page_link_c : std_logic_vector(02 downto 0) := "110"; -- R: d page link + constant mmu_sys_info_c : std_logic_vector(02 downto 0) := "111"; -- R: system info + + -- Registers -- + signal MMU_IRQ_BASE : std_logic_vector(15 downto 0); + signal MMU_SYS_I_PAGE : std_logic_vector(15 downto 0); + signal MMU_SYS_D_PAGE : std_logic_vector(15 downto 0); + signal MMU_USR_I_PAGE : std_logic_vector(15 downto 0); + signal MMU_USR_D_PAGE : std_logic_vector(15 downto 0); + signal MMU_I_PAGE_LINK : std_logic_vector(15 downto 0); + signal MMU_D_PAGE_LINK : std_logic_vector(15 downto 0); + + -- Buffers / Local signals -- + signal I_SYS_TMP, I_USR_TMP : std_logic_vector(15 downto 0); + signal D_SYS_TMP, D_USR_TMP : std_logic_vector(15 downto 0); + signal MODE_BUF : std_logic_vector(01 downto 0); + signal SYS_INFO : std_logic_vector(15 downto 0); + signal SYS_INFO_ADR : std_logic_vector(01 downto 0); + +begin + + -- MMU Register Update --------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + MMU_REG_UP: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + MMU_IRQ_BASE <= boot_page_c; -- (others => '0'); + MMU_SYS_I_PAGE <= boot_page_c; + MMU_SYS_D_PAGE <= boot_page_c; + MMU_USR_I_PAGE <= boot_page_c; -- (others => '0'); + MMU_USR_D_PAGE <= boot_page_c; -- (others => '0'); + MMU_I_PAGE_LINK <= boot_page_c; -- (others => '0'); + MMU_D_PAGE_LINK <= boot_page_c; -- (others => '0'); + I_SYS_TMP <= boot_page_c; + D_SYS_TMP <= boot_page_c; + I_USR_TMP <= boot_page_c; -- (others => '0'); + D_USR_TMP <= boot_page_c; -- (others => '0'); + MODE_BUF <= system_mode_c & system_mode_c; -- start in system mode + elsif (ICE_I = '1') then + + -- Auto update -- + MODE_BUF <= MODE_BUF(0) & SYS_MODE_I; + I_SYS_TMP <= MMU_SYS_I_PAGE; + D_SYS_TMP <= MMU_SYS_D_PAGE; + I_USR_TMP <= MMU_USR_I_PAGE; + D_USR_TMP <= MMU_USR_D_PAGE; + + -- Exception Processing ---------------------------------------------------------- + -- ---------------------------------------------------------------------------------- + if (INT_EXE_I = '1') then + MMU_SYS_I_PAGE <= MMU_IRQ_BASE; -- system-mode base page for IRQs + MMU_SYS_D_PAGE <= MMU_IRQ_BASE; -- system-mode base page for IRQs + I_SYS_TMP <= MMU_IRQ_BASE; -- system-mode base page for IRQs + D_SYS_TMP <= MMU_IRQ_BASE; -- system-mode base page for IRQs + if (MODE_BUF(1) = user_mode_c) then -- we were in USR mode + MMU_I_PAGE_LINK <= I_USR_TMP; -- save current sys i-page + MMU_D_PAGE_LINK <= D_USR_TMP; -- save current sys d-page + else -- we were in SYS mode + MMU_I_PAGE_LINK <= I_SYS_TMP; -- save current sys i-page + MMU_D_PAGE_LINK <= D_SYS_TMP; -- save current sys d-page + end if; + + -- Data Transfer ----------------------------------------------------------------- + -- ---------------------------------------------------------------------------------- + elsif (W_EN_I = '1') then -- valid write + case (ADR_I) is + when mmu_irq_base_c => MMU_IRQ_BASE <= DAT_I; -- system-mode base page + when mmu_sys_i_page_c => MMU_SYS_I_PAGE <= DAT_I; -- system instruction page + when mmu_sys_d_page_c => MMU_SYS_D_PAGE <= DAT_I; -- system data page + when mmu_usr_i_page_c => MMU_USR_I_PAGE <= DAT_I; -- user instruction page + when mmu_usr_d_page_c => MMU_USR_D_PAGE <= DAT_I; -- user data page +-- when mmu_i_page_link_c => MMU_I_PAGE_LINK <= DAT_I; -- instruction page link +-- when mmu_d_page_link_c => MMU_D_PAGE_LINK <= DAT_I; -- data page link + when others => NULL; -- do nothing + end case; + end if; + end if; + end if; + end process MMU_REG_UP; + + -- Page Output -- + MEM_IP_ADR_O <= I_USR_TMP when (SYS_MODE_I = user_mode_c) else I_SYS_TMP; + MEM_DP_ADR_O <= D_USR_TMP when (SYS_MODE_I = user_mode_c) else D_SYS_TMP; + + + + -- MMU Read Access ------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + R_ACC: process(ADR_I, MMU_IRQ_BASE, MMU_SYS_I_PAGE, MMU_SYS_D_PAGE, MMU_USR_I_PAGE, + MMU_USR_D_PAGE, MMU_I_PAGE_LINK, MMU_D_PAGE_LINK, SYS_INFO) + begin + case (ADR_I) is + when mmu_irq_base_c => DAT_O <= MMU_IRQ_BASE; -- system-mode base page + when mmu_sys_i_page_c => DAT_O <= MMU_SYS_I_PAGE; -- system instruction page + when mmu_sys_d_page_c => DAT_O <= MMU_SYS_D_PAGE; -- system data page + when mmu_usr_i_page_c => DAT_O <= MMU_USR_I_PAGE; -- user instruction page + when mmu_usr_d_page_c => DAT_O <= MMU_USR_D_PAGE; -- user data page + when mmu_i_page_link_c => DAT_O <= MMU_I_PAGE_LINK; -- instruction page link + when mmu_d_page_link_c => DAT_O <= MMU_D_PAGE_LINK; -- data page link + when mmu_sys_info_c => DAT_O <= SYS_INFO; -- system info + when others => DAT_O <= (others => '0'); -- dummy output + end case; + end process R_ACC; + + + + -- System Info Output Control -------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + SYS_INFO_CTRL: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + SYS_INFO_ADR <= (others => '0'); + elsif (R_EN_I = '1') and (ICE_I = '1') and (ADR_I = mmu_sys_info_c) then + SYS_INFO_ADR <= std_logic_vector(unsigned(SYS_INFO_ADR) + 1); + end if; + end if; + end process SYS_INFO_CTRL; + + -- Output selector -- + SYS_INFO_OUT: process(SYS_INFO_ADR) + begin + case (SYS_INFO_ADR) is + when "00" => SYS_INFO <= CLK_SPEED_G(15 downto 00); + when "01" => SYS_INFO <= CLK_SPEED_G(31 downto 16); + when "10" => SYS_INFO <= CLK_SPEED_G(15 downto 00); + when "11" => SYS_INFO <= CLK_SPEED_G(31 downto 16); + when others => SYS_INFO <= (others => '0'); + end case; + end process SYS_INFO_OUT; + + + +end SYS_1_CORE_BEHAV; Index: trunk/rtl/SYSTEM_CP.vhd =================================================================== --- trunk/rtl/SYSTEM_CP.vhd (nonexistent) +++ trunk/rtl/SYSTEM_CP.vhd (revision 21) @@ -0,0 +1,355 @@ +-- ######################################################## +-- # << ATLAS Project - System Coprocessor >> # +-- # **************************************************** # +-- # Top entity of the system extension coprocessor. # +-- # **************************************************** # +-- # Last modified: 15.02.2014 # +-- # **************************************************** # +-- # 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 SYSTEM_CP is +-- ############################################################################################### +-- ## Module Configuration ## +-- ############################################################################################### + generic ( + CLOCK_SPEED_G : std_logic_vector(31 downto 0) := x"00000000" -- clock speed in Hz + ); + port ( +-- ############################################################################################### +-- ## Global Control ## +-- ############################################################################################### + + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + +-- ############################################################################################### +-- ## 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 + CP_IRQ_O : out std_logic; -- unit interrupt request + + SYS_MODE_I : in std_logic; -- current operating mode + INT_EXE_I : in std_logic; -- interrupt beeing executed + +-- ############################################################################################### +-- ## Memory Interface ## +-- ############################################################################################### + + MEM_IP_ADR_O : out std_logic_vector(15 downto 0); -- instruction page + MEM_DP_ADR_O : out std_logic_vector(15 downto 0); -- data page + +-- ############################################################################################### +-- ## Peripheral Communication Interface ## +-- ############################################################################################### + + -- UART -- + UART_RXD_I : in std_logic; -- receiver input + UART_TXD_O : out std_logic; -- UART transmitter output + + -- SPI -- + SPI_MOSI_O : out std_logic_vector(07 downto 0); -- serial data out + SPI_MISO_I : in std_logic_vector(07 downto 0); -- serial data in + SPI_SCK_O : out std_logic_vector(07 downto 0); -- serial clock out + SPI_CS_O : out std_logic_vector(07 downto 0); -- chip select (low active) + + -- Parallel IO -- + PIO_OUT_O : out std_logic_vector(15 downto 0); -- parallel output + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + + -- System IO -- + SYS_OUT_O : out std_logic_vector(07 downto 0); -- system output + SYS_IN_I : in std_logic_vector(07 downto 0); -- system input + + -- IRQs -- + IRQ_I : in std_logic_vector(01 downto 0) -- IRQs + ); +end SYSTEM_CP; + +architecture SYSTEM_CP_BEHAV of SYSTEM_CP is + + -- Module addresses -- + constant sys0_module_c : std_logic_vector(1 downto 0) := "00"; + constant sys1_module_c : std_logic_vector(1 downto 0) := "01"; + constant com0_module_c : std_logic_vector(1 downto 0) := "10"; + constant com1_module_c : std_logic_vector(1 downto 0) := "11"; + + -- Module interface -- + type module_interface_t is record + DATA_O : std_logic_vector(data_width_c-1 downto 0); + W_EN : std_logic; + R_EN : std_logic; + end record; + + signal SYS_0_MODULE : module_interface_t; + signal SYS_1_MODULE : module_interface_t; + signal COM_0_MODULE : module_interface_t; + signal COM_1_MODULE : module_interface_t; + + -- Raw interrupt signals -- + signal INT_ASSIGN : std_logic_vector(7 downto 0); + signal TIMER_IRQ : std_logic; + signal UART_RX_IRQ : std_logic; + signal UART_TX_IRQ : std_logic; + signal SPI_IRQ : std_logic; + signal PIO_IRQ : std_logic; + + -- Internals -- + signal READ_ACC : std_logic; -- true read access + + -- Component: System Controller 0 - Timer, IRQ, LFSR -------------------------------------- + -- ------------------------------------------------------------------------------------------- + component SYS_0_CORE + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + + -- Interrupt Lines -- + TIMER_IRQ_O : out std_logic; -- timer irq + IRQ_I : in std_logic_vector(07 downto 0); -- irq input + IRQ_O : out std_logic -- interrupt request + ); + end component; + + -- Component: System Controller 1 - MMU, Clock-info --------------------------------------- + -- ------------------------------------------------------------------------------------------- + component SYS_1_CORE + generic ( + CLK_SPEED_G : std_logic_vector(31 downto 0) := (others => '0') -- clock speed (inHz) + ); + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + + -- CPU-special -- + SYS_MODE_I : in std_logic; -- current operating mode + INT_EXE_I : in std_logic; -- interrupt beeing executed + + -- Memory Interface -- + MEM_IP_ADR_O : out std_logic_vector(15 downto 0); -- instruction page + MEM_DP_ADR_O : out std_logic_vector(15 downto 0) -- data page + ); + end component; + + -- Component: Communication Controller 0 - SPI, UART, PIO --------------------------------- + -- ------------------------------------------------------------------------------------------- + component COM_0_CORE + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + ICE_I : in std_logic; -- interface clock enable, high-active + W_EN_I : in std_logic; -- write enable + R_EN_I : in std_logic; -- read enable + ADR_I : in std_logic_vector(02 downto 0); -- access address + DAT_I : in std_logic_vector(15 downto 0); -- write data + DAT_O : out std_logic_vector(15 downto 0); -- read data + + -- Interrupt Lines -- + UART_RX_IRQ_O : out std_logic; -- UART IRQ "data available" + UART_TX_IRQ_O : out std_logic; -- UART IRQ "sending done" + SPI_IRQ_O : out std_logic; -- SPI IRQ "transfer done" + PIO_IRQ_O : out std_logic; -- PIO input pin change irq + + -- Peripheral Interface -- + UART_TXD_O : out std_logic; -- UART serial output + UART_RXD_I : in std_logic; -- UART serial input + SPI_MOSI_O : out std_logic_vector(07 downto 0); -- serial data out + SPI_MISO_I : in std_logic_vector(07 downto 0); -- serial data in + SPI_SCK_O : out std_logic_vector(07 downto 0); -- serial clock out + SPI_CS_O : out std_logic_vector(07 downto 0); -- chip select (low active) + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + PIO_OUT_O : out std_logic_vector(15 downto 0); -- parallel output + SYS_IO_I : in std_logic_vector(07 downto 0); -- system input + SYS_IO_O : out std_logic_vector(07 downto 0) -- system output + ); + end component; + +begin + + -- Write Access Logic ---------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + CTRL_W_ACC: process(CP_EN_I, CP_RW_I, CP_OP_I, CP_CMD_I) + variable valid_acc_v : std_logic; + begin + -- Valid Write Access? -- + valid_acc_v := CP_EN_I and CP_RW_I and CP_OP_I; + + -- Address Decoder -- + SYS_0_MODULE.W_EN <= '0'; + SYS_1_MODULE.W_EN <= '0'; + COM_0_MODULE.W_EN <= '0'; + COM_1_MODULE.W_EN <= '0'; + case (CP_CMD_I(cp_op_a_msb_c-1 downto cp_op_a_lsb_c)) is + when sys0_module_c => SYS_0_MODULE.W_EN <= valid_acc_v; + when sys1_module_c => SYS_1_MODULE.W_EN <= valid_acc_v; + when com0_module_c => COM_0_MODULE.W_EN <= valid_acc_v; + when com1_module_c => COM_1_MODULE.W_EN <= valid_acc_v; + when others => NULL; + end case; + end process CTRL_W_ACC; + + + + -- Read Access Logic ----------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + CTRL_R_ACC: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + CP_DAT_O <= (others => '0'); + elsif (ICE_I = '1') then -- clock enabled + if (READ_ACC = '1') then -- valid read + case (CP_CMD_I(cp_op_b_msb_c-1 downto cp_op_b_lsb_c)) is + when sys0_module_c => CP_DAT_O <= SYS_0_MODULE.DATA_O; + when sys1_module_c => CP_DAT_O <= SYS_1_MODULE.DATA_O; + when com0_module_c => CP_DAT_O <= COM_0_MODULE.DATA_O; + when com1_module_c => CP_DAT_O <= COM_1_MODULE.DATA_O; + when others => CP_DAT_O <= (others => '0'); + end case; + else + CP_DAT_O <= (others => '0'); + end if; + end if; + end if; + end process CTRL_R_ACC; + + -- Module connection -- + READ_ACC <= CP_EN_I and (not CP_RW_I) and CP_OP_I; -- true read access + SYS_0_MODULE.R_EN <= '1' when (CP_CMD_I(cp_op_b_msb_c-1 downto cp_op_b_lsb_c) = sys0_module_c) and (READ_ACC = '1') else '0'; + SYS_1_MODULE.R_EN <= '1' when (CP_CMD_I(cp_op_b_msb_c-1 downto cp_op_b_lsb_c) = sys1_module_c) and (READ_ACC = '1') else '0'; + COM_0_MODULE.R_EN <= '1' when (CP_CMD_I(cp_op_b_msb_c-1 downto cp_op_b_lsb_c) = com0_module_c) and (READ_ACC = '1') else '0'; + COM_1_MODULE.R_EN <= '1' when (CP_CMD_I(cp_op_b_msb_c-1 downto cp_op_b_lsb_c) = com1_module_c) and (READ_ACC = '1') else '0'; + + + + -- System Controller 0 --------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + system_ctrl_0: SYS_0_CORE + port map ( + -- Host interface -- + CLK_I => CLK_I, -- global clock line + RST_I => RST_I, -- global reset line, sync, high-active + ICE_I => ICE_I, -- interface clock enable, high-active + W_EN_I => SYS_0_MODULE.W_EN, -- write enable + R_EN_I => SYS_0_MODULE.R_EN, -- read enable + ADR_I => CP_CMD_I(cp_cmd_msb_c downto cp_cmd_lsb_c), -- access address + DAT_I => CP_DAT_I, -- write data + DAT_O => SYS_0_MODULE.DATA_O, -- read data + + -- IRQ lines -- + TIMER_IRQ_O => TIMER_IRQ, -- timer irq + IRQ_I => INT_ASSIGN, -- irq input + IRQ_O => CP_IRQ_O -- interrupt request to cpu + ); + + -- IRQ assignment -- + INT_ASSIGN(0) <= TIMER_IRQ; -- high precision timer irq + INT_ASSIGN(1) <= '0'; -- reserved + INT_ASSIGN(2) <= UART_RX_IRQ; -- UART data received irq + INT_ASSIGN(3) <= UART_TX_IRQ; -- UART data send irq + INT_ASSIGN(4) <= SPI_IRQ; -- SPI transfer done irq + INT_ASSIGN(5) <= PIO_IRQ; -- PIO input change IRQ + INT_ASSIGN(6) <= IRQ_I(0); -- 'external' irq + INT_ASSIGN(7) <= IRQ_I(1); -- 'external' irq + + + + -- System Controller 1 --------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + system_ctrl_1: SYS_1_CORE + generic map ( + CLK_SPEED_G => CLOCK_SPEED_G -- clock speed (inHz) + ) + port map ( + -- Host interface -- + CLK_I => CLK_I, -- global clock line + RST_I => RST_I, -- global reset line, sync, high-active + ICE_I => ICE_I, -- interface clock enable, high-active + W_EN_I => SYS_1_MODULE.W_EN, -- write enable + R_EN_I => SYS_1_MODULE.R_EN, -- read enable + ADR_I => CP_CMD_I(cp_cmd_msb_c downto cp_cmd_lsb_c), -- access address + DAT_I => CP_DAT_I, -- write data + DAT_O => SYS_1_MODULE.DATA_O, -- read data + + -- CPU-special -- + SYS_MODE_I => SYS_MODE_I, -- current operating mode + INT_EXE_I => INT_EXE_I, -- interrupt beeing executed + + -- Memory Interface -- + MEM_IP_ADR_O => MEM_IP_ADR_O, -- instruction page + MEM_DP_ADR_O => MEM_DP_ADR_O -- data page + ); + + + + -- Communication Controller 0 -------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + communication_ctrl_0: COM_0_CORE + port map ( + -- Host interface -- + CLK_I => CLK_I, -- global clock line + RST_I => RST_I, -- global reset line, sync, high-active + ICE_I => ICE_I, -- interface clock enable, high-active + W_EN_I => COM_0_MODULE.W_EN, -- write enable + R_EN_I => COM_0_MODULE.R_EN, -- read enable + ADR_I => CP_CMD_I(cp_cmd_msb_c downto cp_cmd_lsb_c), -- access address + DAT_I => CP_DAT_I, -- write data + DAT_O => COM_0_MODULE.DATA_O, -- read data + + -- Interrupt Lines -- + UART_RX_IRQ_O => UART_RX_IRQ, -- UART IRQ "data available" + UART_TX_IRQ_O => UART_TX_IRQ, -- UART IRQ "sending done" + SPI_IRQ_O => SPI_IRQ, -- SPI IRQ "transfer done" + PIO_IRQ_O => PIO_IRQ, -- PIO input pin change irq + + -- Peripheral Interface -- + UART_TXD_O => UART_TXD_O, -- UART transmitter + UART_RXD_I => UART_RXD_I, -- UART receiver + SPI_MOSI_O => SPI_MOSI_O, -- SPI master out slave in + SPI_MISO_I => SPI_MISO_I, -- SPI master in slave out + SPI_SCK_O => SPI_SCK_O, -- SPI clock out + SPI_CS_O => SPI_CS_O, -- SPI chip select + PIO_IN_I => PIO_IN_I, -- parallel input + PIO_OUT_O => PIO_OUT_O, -- parallel output + SYS_IO_I => SYS_IN_I, -- system input + SYS_IO_O => SYS_OUT_O -- system output + ); + + + + -- Communication Controller 1 -------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + COM_1_MODULE.DATA_O <= (others => '0'); -- reserved for future use + + + +end SYSTEM_CP_BEHAV; Index: trunk/rtl/WB_UNIT.vhd =================================================================== --- trunk/rtl/WB_UNIT.vhd (nonexistent) +++ trunk/rtl/WB_UNIT.vhd (revision 21) @@ -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: trunk/rtl/ATLAS_CPU.vhd =================================================================== --- trunk/rtl/ATLAS_CPU.vhd (nonexistent) +++ trunk/rtl/ATLAS_CPU.vhd (revision 21) @@ -0,0 +1,364 @@ +-- ######################################################## +-- # << ATLAS Project - Atlas CPU Core >> # +-- # **************************************************** # +-- # This is the top entity of the CPU core. # +-- # All submodules are instantiated here. # +-- # **************************************************** # +-- # Last modified: 25.01.2014 # +-- # **************************************************** # +-- # 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_CPU is + port ( +-- ############################################################################################### +-- ## Global Control ## +-- ############################################################################################### + + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + CE_I : in std_logic; -- clock enable, high-active + +-- ############################################################################################### +-- ## 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_CPU; + +architecture ATLAS_CPU_BEHAV of ATLAS_CPU 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 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 output + 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 WAKE_UP_CALL : std_logic; -- wake up from sleep + signal MODE : std_logic; -- current operating mode + signal MODE_FF : std_logic; -- delayed 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 + signal INSTR_REG : std_logic_vector(data_width_c-1 downto 0); -- instruction register + + -- Coprocessor -- + signal CP_PTC : std_logic; -- user coprocessor protection + +begin + + -- Global Signals -------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + G_CLK <= CLK_I; + G_CE <= CE_I; + G_RST <= RST_I; + + + + -- Opcode Decoder -------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + Opcode_Decoder: OP_DEC + port map ( + -- Decoder Interface Input -- + INSTR_I => INSTR_REG, -- instruction input + INSTR_ADR_I => PC_1D, -- corresponding address + T_FLAG_I => T_FLAG, -- T-Flag input + M_FLAG_I => MODE_FF, -- 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 + INSTR_I => INSTR_DAT_I, -- instruction input + INSTR_REG_O => INSTR_REG, -- instruction register + + -- 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 + WAKE_UP_I => WAKE_UP_CALL, -- wake up from sleep + 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 + MA_CTRL_BUS_I => MA_CTRL, -- ma 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 => ALU_RES, -- 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 + WAKE_UP_O => WAKE_UP_CALL, -- wake-up signal + 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 + MODE_FF_O => MODE_FF -- delayed 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 + 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_CPU_BEHAV; Index: trunk/rtl/SYS_REG.vhd =================================================================== --- trunk/rtl/SYS_REG.vhd (nonexistent) +++ trunk/rtl/SYS_REG.vhd (revision 21) @@ -0,0 +1,415 @@ +-- ######################################################## +-- # << ATLAS Project - System Registers >> # +-- # **************************************************** # +-- # The main system registers (MSR & PC) are located # +-- # here. Also the context control and interrupt # +-- # processing circuits are implemented within this # +-- # unit. # +-- # **************************************************** # +-- # Last modified: 25.01.2014 # +-- # **************************************************** # +-- # 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 + MA_CTRL_BUS_I : in std_logic_vector(ctrl_width_c-1 downto 0); -- ma 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 + WAKE_UP_O : out std_logic; -- wake-up signal + 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 + MODE_FF_O : out std_logic -- delayed current 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_TMP : 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(15 downto 0); + signal XINT_SYNC : std_logic_vector(01 downto 0); + + -- Mode Flag Delay Buffer -- + signal MODE_BUFFER : std_logic_vector(02 downto 0); + +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_en_v, xint1_en_v : std_logic; + variable xint0_valid_v, xint1_valid_v : std_logic; + begin + -- external interrupt enable -- + -- => external_int is possible AND int_source is enabled AND global_ints are enabled + xint0_en_v := SYS_REG_MSR(msr_xint0_en_c); + xint1_en_v := SYS_REG_MSR(msr_xint1_en_c); + xint0_valid_v := EXC_POS_I and xint0_en_v and SYS_REG_MSR(msr_xint_en_c); + xint1_valid_v := EXC_POS_I and xint1_en_v and SYS_REG_MSR(msr_xint_en_c); + + -- Wake up signal -- + WAKE_UP_O <= (xint0_en_v and XINT_SYNC(0)) or (xint1_en_v and XINT_SYNC(1)); + + -- exception priority list and encoding -- + if ((xint0_valid_v = '1') and (XINT_SYNC(0) = '1')) then -- external interrupt 0 + INT_REQ <= '1'; + INT_VECTOR <= irq0_int_vec_c; + elsif ((xint1_valid_v = '1') and (XINT_SYNC(1) = '1')) then -- external interrupt 1 + INT_REQ <= '1'; + INT_VECTOR <= irq1_int_vec_c; + elsif ((EXC_POS_I = '1') and (EX_CTRL_BUS_I(ctrl_cmd_err_c) = '1')) then -- msr/reg/coprocessor access violation // undefined instruction + INT_REQ <= '1'; + INT_VECTOR <= cmd_err_int_vec_c; + elsif ((EXC_POS_I = '1') and (EX_CTRL_BUS_I(ctrl_syscall_c) = '1')) then -- software interrupt / system call + INT_REQ <= '1'; + INT_VECTOR <= swi_int_vec_c; + else -- no exception + INT_REQ <= '0'; + INT_VECTOR <= res_int_vec_c; -- irrelevant + 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, MODE_BUFFER) + variable m_msr_acc_v : std_logic_vector(2 downto 0); + begin + -- manual msr access mode (from EX stage) -- + m_msr_acc_v := MODE_BUFFER(1) & 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 <= boot_adr_c; -- boot address + 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_svd_mode_c) <= system_mode_c; + elsif (CE_I = '1') then -- clock enable + + -- Exception MSR Update ------------------------------------------------- + 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_svd_mode_c) <= MODE_BUFFER(1); -- save current mode of instr. in EX stage + SYS_REG_MSR(msr_xint_en_c) <= '0'; -- clear global xint enable flag + + elsif (EX_CTRL_BUS_I(ctrl_en_c) = '1') then -- valid operation + if (MODE_BUFFER(1) = system_mode_c) then -- only system mode (instr. in EX stage) + if (EX_CTRL_BUS_I(ctrl_re_xint_c) = '1') and (EX_CTRL_BUS_I(ctrl_pc_wr_c) = '1') then -- valid pc access and re-enable request? + SYS_REG_MSR(msr_xint_en_c) <= '1'; -- auto re-enable global x_ints + end if; + end if; + + -- Manual MSR Update ---------------------------------------------------- + if (EX_CTRL_BUS_I(ctrl_msr_wr_c) = '1') then -- write operation + case (m_msr_acc_v) is + when "100" => -- system mode: full update + SYS_REG_MSR <= MSR_DATA_I; + when "101" => -- system mode: update 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 update 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 update 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; + + -- Context Change ------------------------------------------------------- + elsif (EX_CTRL_BUS_I(ctrl_ctx_down_c) = '1') or (EX_CTRL_BUS_I(ctrl_restsm_c) = '1') then -- context down/switch + SYS_REG_MSR(msr_svd_mode_c) <= MODE_BUFFER(1); -- save current mode of instr. in EX stage + if (EX_CTRL_BUS_I(ctrl_ctx_down_c) = '1') then + SYS_REG_MSR(msr_mode_flag_c) <= user_mode_c; -- go down to user mode + elsif (EX_CTRL_BUS_I(ctrl_restsm_c) = '1') then + SYS_REG_MSR(msr_mode_flag_c) <= SYS_REG_MSR(msr_svd_mode_c); -- restore old mode + end if; +-- 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; + + -- Automatic MSR Update ------------------------------------------------- + else + if (MODE_BUFFER(1) = user_mode_c) then -- user mode auto alu flag update (instr. in EX stage) + if(EX_CTRL_BUS_I(ctrl_fupdate_c) = '1') then -- allow auto update of ALU flags + 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); + end if; + if (EX_CTRL_BUS_I(ctrl_tf_store_c) = '1') then -- allow user mode update of T-flag + SYS_REG_MSR(msr_usr_t_flag_c) <= FLAG_BUS_I(flag_t_c); + end if; + else -- system mode auto alu flag update + if(EX_CTRL_BUS_I(ctrl_fupdate_c) = '1') then -- allow system mode auto update of ALU flags + 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; + if (EX_CTRL_BUS_I(ctrl_tf_store_c) = '1') then -- allow system mode update of T-flag + SYS_REG_MSR(msr_sys_t_flag_c) <= FLAG_BUS_I(flag_t_c); + end if; + end if; + end if; + end if; + + -- Exception PC Update -------------------------------------------------- + if (INT_REQ = '1') then + if (word_mode_en_c = false) then -- byte-addressed memory + SYS_REG_PC <= INT_VECTOR(14 downto 0) & '0'; + else -- word-addressed memory + SYS_REG_PC <= INT_VECTOR; + end if; + + -- Manual/Branch PC Update ---------------------------------------------- + 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 instruction 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 -- word-addressed memory + 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; + + + + -- MSR Flag Output ------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + FLAG_BUS_O(flag_z_c) <= SYS_REG_MSR(msr_usr_z_flag_c) when (MODE_BUFFER(1) = 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 (MODE_BUFFER(1) = 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 (MODE_BUFFER(1) = 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 (MODE_BUFFER(1) = 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 (MODE_BUFFER(1) = user_mode_c) else SYS_REG_MSR(msr_sys_t_flag_c); + + -- Special Flag output -- + MODE_O <= SYS_REG_MSR(msr_mode_flag_c); -- current operating mode (for PC parallel access) + MODE_FF_O <= MODE_BUFFER(2); -- delayed current operating mode (for OF stage) + + + + -- MSR Data-Read Access -------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + MSR_RD_ACC: process(MA_CTRL_BUS_I, SYS_REG_MSR, MODE_BUFFER) + variable msr_r_mode_v : std_logic_vector(2 downto 0); + begin + msr_r_mode_v := MODE_BUFFER(0) & MA_CTRL_BUS_I(ctrl_msr_am_1_c downto ctrl_msr_am_0_c); -- access from MA stage + RD_MSR_O <= (others => '0'); + case (msr_r_mode_v) is + when "100" => -- system mode: full read access + RD_MSR_O <= SYS_REG_MSR; + when "101" => -- system mode: 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 "110" => -- system mode: 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 => -- system/user mode: 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; + end process MSR_RD_ACC; + + + + -- PC, M-Flag and UCP_P-Flag Delay Generator ----------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + DELAY_GEN: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + PC_1D_TMP <= (others => '0'); + MODE_BUFFER <= (others => '0'); + CP_PTC_O <= '0'; + elsif (CE_I = '1') then + CP_PTC_O <= SYS_REG_MSR(msr_usr_cp_ptc_c); -- user_coprocessor protection + MODE_BUFFER <= SYS_REG_MSR(msr_mode_flag_c) & MODE_BUFFER(2 downto 1); + if (STOP_PC = '0') then + PC_1D_TMP <= SYS_REG_PC; +-- MODE_BUFFER <= SYS_REG_MSR(msr_mode_flag_c) & MODE_BUFFER(2 downto 1); + end if; + end if; + end if; + end process DELAY_GEN; + + -- SYS_REG_MSR(msr_mode_flag_c) -> M-Flag for IF Stage + -- MODE_BUFFER(2) -> M-Flag for OF Stage + -- MODE_BUFFER(1) -> M-Flag for EX Stage + -- MODE_BUFFER(0) -> M-Flag for MA Stage + + -- PC outputs -- + PC_OUT_DRIVER: process(SYS_REG_PC) + begin + PC_O <= SYS_REG_PC; + PC_O(0) <= '0'; + end process PC_OUT_DRIVER; + PC_1D_O <= PC_1D_TMP; -- 1x delayed + + + + -- Branch Detector ------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + BRANCH_DETECTOR: process(EX_CTRL_BUS_I, SYS_REG_MSR, INT_REQ, MODE_BUFFER) + 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 (instruction from EX stage) -- + if (MODE_BUFFER(1) = 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 => valid_v := z_v; -- equal + when cond_ne_c => valid_v := not z_v; -- not equal + when cond_cs_c => valid_v := c_v; -- unsigned higher or same + when cond_cc_c => valid_v := not c_v; -- unsigned lower + when cond_mi_c => valid_v := n_v; -- negative + when cond_pl_c => valid_v := not n_v; -- positive or zero + when cond_os_c => valid_v := o_v; -- overflow + when cond_oc_c => valid_v := not o_v; -- no overflow + when cond_hi_c => valid_v := c_v and (not z_v); -- unisgned higher + when cond_ls_c => valid_v := (not c_v) or z_v; -- unsigned lower or same + when cond_ge_c => valid_v := n_v xnor o_v; -- greater than or equal + when cond_lt_c => valid_v := n_v xor o_v; -- less than + when cond_gt_c => valid_v := (not z_v) and (n_v xnor o_v); -- greater than + when cond_le_c => valid_v := z_v or (n_v xor o_v); -- less than or equal + when cond_ts_c => valid_v := t_v; -- transfer set + when cond_al_c => valid_v := '1'; -- always + when others => valid_v := '0'; -- undefined = never + 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: trunk/rtl/REG_FILE.vhd =================================================================== --- trunk/rtl/REG_FILE.vhd (nonexistent) +++ trunk/rtl/REG_FILE.vhd (revision 21) @@ -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: trunk/rtl/ATLAS_2K_BASE_TOP.vhd =================================================================== --- trunk/rtl/ATLAS_2K_BASE_TOP.vhd (nonexistent) +++ trunk/rtl/ATLAS_2K_BASE_TOP.vhd (revision 21) @@ -0,0 +1,256 @@ +-- ######################################################### +-- # << ATLAS Project - Basic System >> # +-- # ***************************************************** # +-- # This is the top entity of a simple implementation # +-- # of the ATLAS 2k and a compatible memory component. # +-- # # +-- # The number of pages as well as the page size can be # +-- # configured via constant in the 'USER CONFIGURATION' # +-- # section. Both values must be a number of 2! # +-- # Also, the frequency of the 'CLK_I' signal must be # +-- # declared in this section (in Hz). # +-- # # +-- # ***************************************************** # +-- # Last modified: 08.03.2014 # +-- # ***************************************************** # +-- # 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_2K_BASE_TOP is + port ( +-- ############################################################################################### +-- ## Global Signals ## +-- ############################################################################################### + + CLK_I : in std_logic; -- global clock line + RSTN_I : in std_logic; -- global reset line, low-active + +-- ############################################################################################### +-- ## IO Interface ## +-- ############################################################################################### + + -- UART -- + UART_RXD_I : in std_logic; -- receiver input + UART_TXD_O : out std_logic; -- UART transmitter output + + -- SPI -- + SPI_MOSI_O : out std_logic_vector(07 downto 0); -- serial data out + SPI_MISO_I : in std_logic_vector(07 downto 0); -- serial data in + SPI_SCK_O : out std_logic_vector(07 downto 0); -- serial clock out + SPI_CS_O : out std_logic_vector(07 downto 0); -- chip select (low active) + + -- PIO -- + PIO_OUT_O : out std_logic_vector(15 downto 0); -- parallel output + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + + -- System IO -- + SYS_OUT_O : out std_logic_vector(07 downto 0); -- system output + SYS_IN_I : in std_logic_vector(07 downto 0) -- system input + ); +end ATLAS_2K_BASE_TOP; + +architecture ATLAS_2K_BASE_TOP_STRUCTURE of ATLAS_2K_BASE_TOP is + + -- Component: Atlas-2K Processor ---------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + component ATLAS_2K_TOP + generic ( + CLK_SPEED_G : std_logic_vector(31 downto 0) := (others => '0') -- clock speed (in Hz) + ); + port ( + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + CE_I : in std_logic; -- global clock enable, high active + CP_EN_O : out std_logic; -- access to cp0 + CP_ICE_O : out std_logic; -- cp interface clock enable + 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(08 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 + MEM_I_PAGE_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction page + MEM_I_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction adr + MEM_I_EN_O : out std_logic; -- IR update + MEM_I_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- instruction input + MEM_D_EN_O : out std_logic; -- access enable + MEM_D_RW_O : out std_logic; -- read/write + MEM_D_PAGE_O : out std_logic_vector(data_width_c-1 downto 0); -- data page + MEM_D_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- data adr + MEM_D_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- data out + MEM_D_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- data in + CRITICAL_IRQ_I : in std_logic; -- critical error IRQ + UART_RXD_I : in std_logic; -- receiver input + UART_TXD_O : out std_logic; -- UART transmitter output + SPI_MOSI_O : out std_logic_vector(07 downto 0); -- serial data out + SPI_MISO_I : in std_logic_vector(07 downto 0); -- serial data in + SPI_SCK_O : out std_logic_vector(07 downto 0); -- serial clock out + SPI_CS_O : out std_logic_vector(07 downto 0); -- chip select (low active) + PIO_OUT_O : out std_logic_vector(15 downto 0); -- parallel output + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + SYS_OUT_O : out std_logic_vector(07 downto 0); -- system parallel output + SYS_IN_I : in std_logic_vector(07 downto 0); -- system parallel input + IRQ_I : in std_logic_vector(01 downto 0) -- IRQs + ); + end component; + + -- RAM ------------------------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------------- + component INT_RAM + generic ( + MEM_SIZE_G : natural := 256 -- memory size in words + ); + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + I_ADR_I : in std_logic_vector(31 downto 0); -- instruction adr + I_EN_I : in std_logic; -- IR update + I_DAT_O : out std_logic_vector(15 downto 0); -- instruction out + D_EN_I : in std_logic; -- access enable + D_RW_I : in std_logic; -- read/write + D_ADR_I : in std_logic_vector(31 downto 0); -- data adr + D_DAT_I : in std_logic_vector(15 downto 0); -- data in + D_DAT_O : out std_logic_vector(15 downto 0) -- data out + ); + end component; + +-- *** USER CONFIGURATION *** +-- *********************************************************************************************** + constant clk_speed_c : std_logic_vector(31 downto 0) := x"02FAF080"; -- clock speed in Hz + constant num_pages_c : natural := 4; -- number of pages (must be a power of 2) + constant page_size_c : natural := 4096; -- page size in bytes (must be a power of 2) +-- *********************************************************************************************** + + -- Internals... - + constant ram_size_c : natural := num_pages_c*page_size_c; -- internal RAM size in bytes + constant ld_pg_size_c : natural := log2(page_size_c); -- page select address width + constant ld_num_pg_c : natural := log2(num_pages_c); -- page size address width + + -- Global Signals -- + signal G_CLK : std_logic; + signal G_RST : std_logic; + + -- Memory Interface -- + signal I_ADR, D_ADR : std_logic_vector(data_width_c-1 downto 0); + signal I_PAGE, D_PAGE : std_logic_vector(data_width_c-1 downto 0); + signal I_EN, D_EN : std_logic; + signal D_RW : std_logic; + signal I_DAT_O, D_DAT_O : std_logic_vector(data_width_c-1 downto 0); + signal D_DAT_I : std_logic_vector(data_width_c-1 downto 0); + signal MEM_D_ADR : std_logic_vector(31 downto 0); + signal MEM_I_ADR : std_logic_vector(31 downto 0); + + -- IRQ -- + signal CRITICAL_IRQ : std_logic; + +begin + + -- Clock/Reset ----------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + G_RST <= not RSTN_I; + G_CLK <= CLK_I; + + + + -- Core ------------------------------------------------------------------------------------------------ + -- -------------------------------------------------------------------------------------------------------- + the_core_of_the_problem: ATLAS_2K_TOP + generic map ( + CLK_SPEED_G => clk_speed_c -- clock speed (in Hz) + ) + port map ( + CLK_I => G_CLK, -- global clock line + RST_I => G_RST, -- global reset line, sync, high-active + CE_I => '1', -- global clock enable, high active + + CP_EN_O => open, -- access to cp0 + CP_ICE_O => open, -- cp interface clock enable + CP_OP_O => open, -- data transfer/processing + CP_RW_O => open, -- read/write access + CP_CMD_O => open, -- register addresses / cmd + CP_DAT_O => open, -- write data + CP_DAT_I => x"0000", -- read data cp0 + + MEM_I_PAGE_O => I_PAGE, -- instruction page + MEM_I_ADR_O => I_ADR, -- instruction adr + MEM_I_EN_O => I_EN, -- IR update + MEM_I_DAT_I => I_DAT_O, -- instruction input + MEM_D_EN_O => D_EN, -- access enable + MEM_D_RW_O => D_RW, -- read/write + MEM_D_PAGE_O => D_PAGE, -- data page + MEM_D_ADR_O => D_ADR, -- data adr + MEM_D_DAT_O => D_DAT_I, -- data out + MEM_D_DAT_I => D_DAT_O, -- data in + CRITICAL_IRQ_I => CRITICAL_IRQ, -- critical error IRQ + + UART_RXD_I => UART_RXD_I, -- receiver input + UART_TXD_O => UART_TXD_O, -- UART transmitter output + + SPI_SCK_O => SPI_SCK_O, -- serial clock output + SPI_MOSI_O => SPI_MOSI_O, -- serial data output + SPI_MISO_I => SPI_MISO_I, -- serial data input + SPI_CS_O => SPI_CS_O, -- device select - low-active + + PIO_OUT_O => open, -- parallel output + PIO_IN_I => x"0000", -- parallel input + + SYS_OUT_O => SYS_OUT_O, -- system parallel output + SYS_IN_I => SYS_IN_I, -- system parallel input + + IRQ_I => "00" -- IRQs + ); + + + + -- Memory Mapping -------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + MEMORY_MAPPING: process(I_PAGE, D_PAGE, I_ADR, D_ADR) + begin + -- default -- + MEM_I_ADR <= (others => '0'); + MEM_D_ADR <= (others => '0'); + + -- page address -- + MEM_I_ADR(ld_pg_size_c-1 downto 0) <= I_ADR(ld_pg_size_c-1 downto 0); + MEM_D_ADR(ld_pg_size_c-1 downto 0) <= D_ADR(ld_pg_size_c-1 downto 0); + + -- page number -- + MEM_I_ADR((ld_pg_size_c+ld_num_pg_c)-1 downto ld_pg_size_c) <= I_PAGE(ld_num_pg_c-1 downto 0); + MEM_D_ADR((ld_pg_size_c+ld_num_pg_c)-1 downto ld_pg_size_c) <= D_PAGE(ld_num_pg_c-1 downto 0); + end process MEMORY_MAPPING; + + + + -- Internal RAM ---------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + internal_ram: INT_RAM + generic map ( + MEM_SIZE_G => ram_size_c -- memory size in bytes + ) + port map ( + -- Host Interface -- + CLK_I => G_CLK, -- global clock line + I_ADR_I => MEM_I_ADR, -- instruction adr + I_EN_I => I_EN, -- IR update + I_DAT_O => I_DAT_O, -- instruction out + D_EN_I => D_EN, -- access enable + D_RW_I => D_RW, -- read/write + D_ADR_I => MEM_D_ADR, -- data adr + D_DAT_I => D_DAT_I, -- data in + D_DAT_O => D_DAT_O -- data out + ); + + + + -- User Section ---------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + CRITICAL_IRQ <= '0'; + + +end ATLAS_2K_BASE_TOP_STRUCTURE; Index: trunk/rtl/MEM_GATE.vhd =================================================================== --- trunk/rtl/MEM_GATE.vhd (nonexistent) +++ trunk/rtl/MEM_GATE.vhd (revision 21) @@ -0,0 +1,110 @@ +-- ######################################################## +-- # << ATLAS Project - Memory Gateway >> # +-- # **************************************************** # +-- # Gateway between CPU instruction/data interface and # +-- # bootloader ROM / memory/IO bus system. # +-- # **************************************************** # +-- # Last modified: 08.03.2014 # +-- # **************************************************** # +-- # 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_GATE is + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + + I_ADR_I : in std_logic_vector(15 downto 0); -- instruction adr + I_EN_I : in std_logic; -- IR update + I_DAT_O : out std_logic_vector(15 downto 0); -- instruction out + D_REQ_I : in std_logic; -- request access in next cycle + D_RW_I : in std_logic; -- read/write + D_ADR_I : in std_logic_vector(15 downto 0); -- data adr + D_DAT_I : in std_logic_vector(15 downto 0); -- data in + D_DAT_O : out std_logic_vector(15 downto 0); -- data out + MEM_IP_ADR_I : in std_logic_vector(15 downto 0); -- instruction page + MEM_DP_ADR_I : in std_logic_vector(15 downto 0); -- data page + + -- Boot ROM Interface -- + BOOT_I_ADR_O : out std_logic_vector(15 downto 0); -- instruction adr + BOOT_I_EN_O : out std_logic; -- IR update + BOOT_I_DAT_I : in std_logic_vector(15 downto 0); -- instruction out + BOOT_D_EN_O : out std_logic; -- access enable + BOOT_D_RW_O : out std_logic; -- read/write + BOOT_D_ADR_O : out std_logic_vector(15 downto 0); -- data adr + BOOT_D_DAT_O : out std_logic_vector(15 downto 0); -- data in + BOOT_D_DAT_I : in std_logic_vector(15 downto 0); -- data out + + -- Memory Interface -- + MEM_I_PAGE_O : out std_logic_vector(15 downto 0); -- instruction page + MEM_I_ADR_O : out std_logic_vector(15 downto 0); -- instruction adr + MEM_I_EN_O : out std_logic; -- IR update + MEM_I_DAT_I : in std_logic_vector(15 downto 0); -- instruction out + MEM_D_EN_O : out std_logic; -- access enable + MEM_D_RW_O : out std_logic; -- read/write + MEM_D_PAGE_O : out std_logic_vector(15 downto 0); -- data page + MEM_D_ADR_O : out std_logic_vector(15 downto 0); -- data adr + MEM_D_DAT_O : out std_logic_vector(15 downto 0); -- data in + MEM_D_DAT_I : in std_logic_vector(15 downto 0) -- data out + ); +end MEM_GATE; + +architecture MEM_GATE_BEHAV of MEM_GATE is + + -- local signals -- + signal MEM_DACC_FF : std_logic; + signal D_GATE_SEL : std_logic; + signal I_GATE_SEL : std_logic; + +begin + + -- Gateway --------------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + MEM_ACC_FLAG: process(CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + MEM_DACC_FF <= '0'; + else + MEM_DACC_FF <= D_REQ_I; + end if; + end if; + end process MEM_ACC_FLAG; + + -- Switch -- + I_GATE_SEL <= '1' when (MEM_IP_ADR_I(15) = boot_page_c(15)) else '0'; + D_GATE_SEL <= '1' when (MEM_DP_ADR_I(15) = boot_page_c(15)) else '0'; + + -- Bootloader ROM -- + BOOT_I_EN_O <= I_EN_I when (I_GATE_SEL = '1') else '0'; + BOOT_I_ADR_O <= I_ADR_I; + BOOT_D_EN_O <= MEM_DACC_FF when (D_GATE_SEL = '1') else '0'; + BOOT_D_ADR_O <= D_ADR_I when (MEM_DACC_FF = '1') else (others => '0'); -- to reduce switching activity + BOOT_D_DAT_O <= (others => '0'); -- boot MEM is read-only + BOOT_D_RW_O <= D_RW_I; + + -- Memory System -- + MEM_I_EN_O <= I_EN_I when (I_GATE_SEL = '0') else '0'; + MEM_I_PAGE_O <= '0' & MEM_IP_ADR_I(14 downto 0); + MEM_I_ADR_O <= I_ADR_I; + MEM_D_EN_O <= MEM_DACC_FF when (D_GATE_SEL = '0') else '0'; + MEM_D_PAGE_O <= '0' & MEM_DP_ADR_I(14 downto 0); + MEM_D_ADR_O <= D_ADR_I when (MEM_DACC_FF = '1') else (others => '0'); -- to reduce switching activity + MEM_D_DAT_O <= D_DAT_I when (MEM_DACC_FF = '1') else (others => '0'); -- to reduce switching activity + MEM_D_RW_O <= D_RW_I; + + -- CPU -- + I_DAT_O <= BOOT_I_DAT_I when (I_GATE_SEL = '1') else MEM_I_DAT_I; + D_DAT_O <= BOOT_D_DAT_I when (D_GATE_SEL = '1') else MEM_D_DAT_I; + + + +end MEM_GATE_BEHAV; Index: trunk/rtl/ALU.vhd =================================================================== --- trunk/rtl/ALU.vhd (nonexistent) +++ trunk/rtl/ALU.vhd (revision 21) @@ -0,0 +1,494 @@ +-- ######################################################## +-- # << ATLAS Project - Arithmetical/Logical Unit >> # +-- # **************************************************** # +-- # The main data processing is done here. Also the CP # +-- # interface emerges from this unit. # +-- # **************************************************** # +-- # Last modified: 23.11.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 + 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); + + -- Functional Units Output -- + signal FU_ARITH_RES : std_logic_vector(data_width_c-1 downto 0); + signal FU_ARITH_FLG : std_logic_vector(1 downto 0); -- overflow & carry + signal FU_LOGIC_RES : std_logic_vector(data_width_c-1 downto 0); + signal FU_LOGIC_FLG : std_logic_vector(1 downto 0); + signal FU_SHIFT_RES : std_logic_vector(data_width_c-1 downto 0); + signal FU_SHIFT_FLG : std_logic_vector(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 T_FLAG_FUNC : std_logic; + signal PARITY_BIT : std_logic; + 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; + variable op_a_tmp_v : std_logic_vector(data_width_c-1 downto 0); + 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); + + -- OP A Gating -- + if (EX_CTRL_BUS_I(ctrl_en_c) = '1') then + -- OP A Forwarding -- + if (op_a_ma_match_v = '1') then + op_a_tmp_v := MA_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c); -- MA stage + elsif (op_a_wb_match_v = '1') then + op_a_tmp_v := WB_FWD_I(fwd_dat_msb_c downto fwd_dat_lsb_c); -- WB stage + else + op_a_tmp_v := OP_A_FF; + end if; + else + op_a_tmp_v := (others => '0'); + end if; + + -- OP A Mask Unit -- + OP_A_INT <= op_a_tmp_v; + if (EX_CTRL_BUS_I(ctrl_clr_ha_c) = '1') then -- clear high half word + OP_A_INT(data_width_c-1 downto data_width_c/2) <= (others => '0'); + end if; + if (EX_CTRL_BUS_I(ctrl_clr_la_c) = '1') then -- clear low half word + OP_A_INT(data_width_c/2-1 downto 0) <= (others => '0'); + end if; + + -- OP B Gating -- + if (EX_CTRL_BUS_I(ctrl_en_c) = '1') then + -- OP 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; + else + OP_B_INT <= (others => '0'); + end if; + + -- OP 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; + + + + -- Functional Unit: Arithmetic Core -------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + FU_ARITHMETIC_CORE: process(EX_CTRL_BUS_I, OP_A_INT, OP_B_INT, FLAG_BUS_I) + variable op_a_v, op_b_v : std_logic_vector(data_width_c-1 downto 0); + variable cflag_v : std_logic; + 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_c_sel_v : std_logic; + variable adder_carry_in_v : std_logic; + variable adder_tmp_v : std_logic_vector(data_width_c downto 0); + begin + + -- Operand Insulation -- + op_a_v := (others => '0'); + op_b_v := (others => '0'); + cflag_v := '0'; + if (EX_CTRL_BUS_I(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) = alu_adc_c) or + (EX_CTRL_BUS_I(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) = alu_sbc_c) then + op_a_v := OP_A_INT; + op_b_v := OP_B_INT; + cflag_v := FLAG_BUS_I(flag_c_c); + end if; + + -- ADD/SUB Select -- + if (EX_CTRL_BUS_I(ctrl_alu_cf_opt_c) = '0') then -- propagate carry_in + adder_c_sel_v := cflag_v; + else -- invert carry_in + adder_c_sel_v := not cflag_v; + end if; + add_a_v := '0' & op_a_v; + adder_carry_in_v := adder_c_sel_v 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_v); + 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_v; + add_cf_in_v(0) := adder_carry_in_v; + when others => -- other function set, adder irrelevant + add_b_v := '0' & op_b_v; + 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))); + FU_ARITH_RES <= 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 + FU_ARITH_FLG(0) <= adder_tmp_v(data_width_c); + when alu_sbc_c => -- sub + FU_ARITH_FLG(0) <= not adder_tmp_v(data_width_c); + when others => -- other function set, adder irrelevant + FU_ARITH_FLG(0) <= adder_tmp_v(data_width_c); + end case; + + -- Arithmetic overflow flag -- + FU_ARITH_FLG(1) <= ((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))); + end process FU_ARITHMETIC_CORE; + + + + -- Functional Unit: Shifter Core ----------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + FU_SHIFTER_CORE: process(EX_CTRL_BUS_I, OP_A_INT, OP_B_FF, FLAG_BUS_I) + variable op_a_v, op_b_v : std_logic_vector(data_width_c-1 downto 0); + variable cflag_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; + begin + + -- Operand Insulation -- + op_a_v := (others => '0'); + op_b_v := (others => '0'); + cflag_v := '0'; + if (EX_CTRL_BUS_I(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) = alu_sft_c) then + op_a_v := OP_A_INT; + op_b_v := OP_B_FF; + cflag_v := FLAG_BUS_I(flag_c_c); + end if; + + -- Shifter Core -- + case (op_b_v(2 downto 0)) is + when sft_asr_c => -- arithmetical right shift + shifter_dat_v := op_a_v(data_width_c-1) & op_a_v(data_width_c-1 downto 1); + FU_SHIFT_FLG(0) <= op_a_v(0); + when sft_rol_c => -- rotate left + shifter_dat_v := op_a_v(data_width_c-2 downto 0) & op_a_v(data_width_c-1); + FU_SHIFT_FLG(0) <= op_a_v(data_width_c-1); + when sft_ror_c => -- rotate right + shifter_dat_v := op_a_v(0) & op_a_v(data_width_c-1 downto 1); + FU_SHIFT_FLG(0) <= op_a_v(0); + when sft_lsl_c => -- logical shift left + shifter_dat_v := op_a_v(data_width_c-2 downto 0) & '0'; + FU_SHIFT_FLG(0) <= op_a_v(data_width_c-1); + when sft_lsr_c => -- logical shift right + shifter_dat_v := '0' & op_a_v(data_width_c-1 downto 1); + FU_SHIFT_FLG(0) <= op_a_v(0); + when sft_rlc_c => -- rotate left through carry + shifter_dat_v := op_a_v(data_width_c-2 downto 0) & cflag_v; + FU_SHIFT_FLG(0) <= op_a_v(data_width_c-1); + when sft_rrc_c => -- rotate right through carry + shifter_dat_v := cflag_v & op_a_v(data_width_c-1 downto 1); + FU_SHIFT_FLG(0) <= op_a_v(0); + when others => -- swap halfwords (sft_swp_c) + shifter_dat_v := op_a_v(data_width_c/2-1 downto 0) & op_a_v(data_width_c-1 downto data_width_c/2); + FU_SHIFT_FLG(0) <= op_a_v(data_width_c-1); + end case; + FU_SHIFT_RES <= shifter_dat_v; + + -- Overflow flag -- + FU_SHIFT_FLG(1) <= op_a_v(data_width_c-1) xor shifter_dat_v(data_width_c-1); + + end process FU_SHIFTER_CORE; + + + + -- Functional Unit: Logical Core ----------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + FU_LOGIC_CORE: process(EX_CTRL_BUS_I, OP_A_INT, OP_B_INT, FLAG_BUS_I) + begin + -- Keep Flags -- + FU_LOGIC_FLG(0) <= FLAG_BUS_I(flag_c_c); + FU_LOGIC_FLG(1) <= FLAG_BUS_I(flag_o_c); + + -- Logic Function -- + case (EX_CTRL_BUS_I(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c)) is + when alu_and_c => FU_LOGIC_RES <= OP_A_INT and OP_B_INT; + when alu_nand_c => FU_LOGIC_RES <= OP_A_INT nand OP_B_INT; + when alu_orr_c => FU_LOGIC_RES <= OP_A_INT or OP_B_INT; + when alu_eor_c => FU_LOGIC_RES <= OP_A_INT xor OP_B_INT; + when alu_bic_c => FU_LOGIC_RES <= OP_A_INT and (not OP_B_INT); + when others => FU_LOGIC_RES <= (others => '0'); + FU_LOGIC_FLG(0) <= '0'; + FU_LOGIC_FLG(1) <= '0'; + end case; + end process FU_LOGIC_CORE; + + + + -- Function Selector ----------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + -- Data result -- + ALU_RES_INT <= FU_ARITH_RES or FU_SHIFT_RES or FU_LOGIC_RES; + + -- Carry Flag -- + FLAG_BUS_O(flag_c_c) <= FU_ARITH_FLG(0) or FU_SHIFT_FLG(0) or FU_LOGIC_FLG(0); + + -- Overflow Flag -- + FLAG_BUS_O(flag_o_c) <= FU_ARITH_FLG(1) or FU_SHIFT_FLG(1) or FU_LOGIC_FLG(0); + + + + -- Parity Computation ---------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + PARITY_GEN: process(OP_A_INT) + variable par_v : std_logic; + begin + par_v := '0'; + for i in 0 to data_width_c-1 loop + par_v := par_v xor OP_A_INT(i); + end loop; + PARITY_BIT <= par_v; + end process PARITY_GEN; + + + + -- Additional Flag Computation ------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + + -- 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) when (EX_CTRL_BUS_I(ctrl_alu_zf_opt_c) = '0') else (FLAG_BUS_I(flag_z_c) or 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; -- (extended) 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(OP_B_INT(3 downto 0)))); -- selected bit + T_FLAG_FUNC <= PARITY_BIT when (EX_CTRL_BUS_I(ctrl_get_par_c) = '1') else SEL_BIT; -- parity or selected bit + INV_BIT <= (not T_FLAG_FUNC) when (EX_CTRL_BUS_I(ctrl_tf_inv_c) = '1') else T_FLAG_FUNC; -- 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 (this is some kind of forwarding to the opcode decoder) -- + 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); + + + + -- MAC Operand Buffer ---------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + 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') and (build_mac_c = true) then -- load mac buffer + MAC_BUF <= OP_C_I; + else + MAC_BUF <= (others => '0'); + end if; + end if; + end if; + end process MAC_BUFFER; + + + + -- MAC Kernel ------------------------------------------------------------------------------------------ + -- -------------------------------------------------------------------------------------------------------- + MULTIPLIER: process(EX_CTRL_BUS_I, OP_A_INT, OP_B_INT, MAC_BUF) + variable mul_op_a_v : std_logic_vector(data_width_c-1 downto 0); + variable mul_op_b_v : std_logic_vector(data_width_c-1 downto 0); + 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 + -- Operand Gating -- + mul_op_a_v := (others => '0'); + mul_op_b_v := (others => '0'); + if (build_mul_c = true) and (EX_CTRL_BUS_I(ctrl_use_mac_c) = '1') then + mul_op_a_v := OP_A_INT; + mul_op_b_v := OP_B_INT; + end if; + + -- Multiplier Core -- + mul_res_v := (others => '0'); + if (build_mul_c = true) then + mul_res_v := std_logic_vector(unsigned(mul_op_a_v) * unsigned(mul_op_b_v)); + end if; + + -- Offset -- + mac_ofs_v := (others => '0'); + if (EX_CTRL_BUS_I(ctrl_use_offs_c) = '1') and (build_mac_c = true) then + mac_ofs_v := MAC_BUF; + end if; + + -- Accumulate -- + MAC_RES_O <= mul_res_v(data_width_c-1 downto 0); + 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)); + 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) when (EX_CTRL_BUS_I(ctrl_cp_acc_c) = '1') else (others => '0'); -- 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) when (EX_CTRL_BUS_I(ctrl_cp_acc_c) = '1') else (others => '0'); -- 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) when (EX_CTRL_BUS_I(ctrl_cp_acc_c) = '1') else (others => '0'); -- cp command + + -- Data Output -- + MSR_DATA_O <= OP_B_INT; -- MSR 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: trunk/rtl/ATLAS_2K_TOP.vhd =================================================================== --- trunk/rtl/ATLAS_2K_TOP.vhd (nonexistent) +++ trunk/rtl/ATLAS_2K_TOP.vhd (revision 21) @@ -0,0 +1,310 @@ +-- ######################################################## +-- # << ATLAS Project - ATLAS 2k Processor >> # +-- # **************************************************** # +-- # This is the top entity oth ATLAS 2k processor. # +-- # See the core's data sheet for more information. # +-- # **************************************************** # +-- # Last modified: 08.03.2014 # +-- # **************************************************** # +-- # 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_2K_TOP is +-- ############################################################################################### +-- ## Configuration ## +-- ############################################################################################### + generic ( + CLK_SPEED_G : std_logic_vector(31 downto 0) := x"00000000" -- clock speed (in Hz) + ); +-- ############################################################################################### +-- ## Global Control ## +-- ############################################################################################### + port ( + CLK_I : in std_logic; -- global clock line + RST_I : in std_logic; -- global reset line, sync, high-active + CE_I : in std_logic; -- global clock enable, high active + +-- ############################################################################################### +-- ## Coprocessor Interface ## +-- ############################################################################################### + + CP_EN_O : out std_logic; -- access to cp0 + CP_ICE_O : out std_logic; -- cp interface clock enable + 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(08 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 + +-- ############################################################################################### +-- ## Memory Interface ## +-- ############################################################################################### + + MEM_I_PAGE_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction page + MEM_I_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- instruction adr + MEM_I_EN_O : out std_logic; -- IR update + MEM_I_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- instruction input + + MEM_D_EN_O : out std_logic; -- access enable + MEM_D_RW_O : out std_logic; -- read/write + MEM_D_PAGE_O : out std_logic_vector(data_width_c-1 downto 0); -- data page + MEM_D_ADR_O : out std_logic_vector(data_width_c-1 downto 0); -- data adr + MEM_D_DAT_O : out std_logic_vector(data_width_c-1 downto 0); -- data out + MEM_D_DAT_I : in std_logic_vector(data_width_c-1 downto 0); -- data in + + CRITICAL_IRQ_I : in std_logic; -- critical error IRQ + +-- ############################################################################################### +-- ## IO Interface ## +-- ############################################################################################### + + -- UART -- + UART_RXD_I : in std_logic; -- UART receiver input + UART_TXD_O : out std_logic; -- UART transmitter output + + -- SPI -- + SPI_MOSI_O : out std_logic_vector(07 downto 0); -- serial data out + SPI_MISO_I : in std_logic_vector(07 downto 0); -- serial data in + SPI_SCK_O : out std_logic_vector(07 downto 0); -- serial clock out + SPI_CS_O : out std_logic_vector(07 downto 0); -- chip select (low active) + + -- Parallel IO -- + PIO_OUT_O : out std_logic_vector(15 downto 0); -- parallel output + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + + -- System IO -- + SYS_OUT_O : out std_logic_vector(07 downto 0); -- system output + SYS_IN_I : in std_logic_vector(07 downto 0); -- system input + + -- IRQs -- + IRQ_I : in std_logic_vector(01 downto 0) -- IRQs + ); +end ATLAS_2K_TOP; + +architecture ATLAS_2K_TOP_BEHAV of ATLAS_2K_TOP is + + -- Global Control -- + signal SYS_MODE : std_logic; -- current processor mode + signal SYS_INT_EXE : std_logic; -- processing IRQ + + -- 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(08 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 + + -- CPU Bus -- + signal CPU_D_REQ : std_logic; -- data access request + signal CPU_D_RW : std_logic; -- read/write access + signal CPU_D_ADR : std_logic_vector(data_width_c-1 downto 0); -- access address + signal CPU_D_W_DATA : std_logic_vector(data_width_c-1 downto 0); -- write data + signal CPU_D_R_DATA : std_logic_vector(data_width_c-1 downto 0); -- read data + signal CPU_I_EN : std_logic; -- instruction reg enable + signal CPU_I_ADR : std_logic_vector(data_width_c-1 downto 0); -- instruction address + signal CPU_I_DATA : std_logic_vector(data_width_c-1 downto 0); -- instruction word + signal CP_DAT_I_SYNC : std_logic_vector(data_width_c-1 downto 0); -- external input sync + + -- MMU -- + signal I_PAGE : std_logic_vector(data_width_c-1 downto 0); -- instruction page + signal D_PAGE : std_logic_vector(data_width_c-1 downto 0); -- data page + + -- Boot Mem -- + signal BOOT_I_ADR : std_logic_vector(15 downto 0); -- instruction adr + signal BOOT_I_EN : std_logic; -- IR update + signal BOOT_I_DAT : std_logic_vector(15 downto 0); -- instruction out + signal BOOT_D_EN : std_logic; -- access enable + signal BOOT_D_RW : std_logic; -- read/write + signal BOOT_D_ADR : std_logic_vector(15 downto 0); -- data adr + signal BOOT_D_DAT_O : std_logic_vector(15 downto 0); -- data in + signal BOOT_D_DAT_I : std_logic_vector(15 downto 0); -- data out + + -- IRQ Lines -- + signal SYS_CP_IRQ : std_logic; -- IRQ from system coprocessor + +begin + + -- Atlas CPU Core -------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + cpu_core: ATLAS_CPU + port map ( + -- Global Control -- + CLK_I => CLK_I, -- global clock line + RST_I => RST_I, -- global reset line, sync, high-active + CE_I => CE_I, -- clock enable + + -- Instruction Interface -- + INSTR_ADR_O => CPU_I_ADR, -- instruction byte adr + INSTR_DAT_I => CPU_I_DATA, -- instruction input + INSTR_EN_O => CPU_I_EN, -- allow IR update + + -- Data Interface -- + SYS_MODE_O => SYS_MODE, -- current operating mode + SYS_INT_O => SYS_INT_EXE, -- interrupt processing + MEM_REQ_O => CPU_D_REQ, -- mem access in next cycle + MEM_RW_O => CPU_D_RW, -- read write + MEM_ADR_O => CPU_D_ADR, -- data byte adr + MEM_DAT_O => CPU_D_W_DATA, -- write data + MEM_DAT_I => CPU_D_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 => CRITICAL_IRQ_I, -- critical error irq + EXT_INT_1_I => SYS_CP_IRQ -- sys cp irq + ); + + -- External CP data in sync -- + CP_DAT_IN_SYNC: process (CLK_I) + begin + if rising_edge(CLK_I) then + if (RST_I = '1') then + CP_DAT_I_SYNC <= (others => '0'); + elsif (CE_I = '1') then + if (USR_CP_EN = '1') then + CP_DAT_I_SYNC <= CP_DAT_I; + else + CP_DAT_I_SYNC <= (others => '0'); + end if; + end if; + end if; + end process CP_DAT_IN_SYNC; + + -- External Coprocessor Interface -- + CP_EN_O <= USR_CP_EN; + CP_OP_O <= CP_OP; + CP_RW_O <= CP_RW; + CP_CMD_O <= CP_CMD; + CP_DAT_O <= CP_W_DATA; + CP_DATA_RB <= SYS_CP_DRB or CP_DAT_I_SYNC; + CP_ICE_O <= CE_I; + + + + -- System Coprocessor ---------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + system_coprocessor: SYSTEM_CP + generic map ( + CLOCK_SPEED_G => CLK_SPEED_G -- clock speed in Hz + ) + port map ( + -- Global Control -- + CLK_I => CLK_I, -- global clock line + RST_I => RST_I, -- global reset line, sync, high-active + ICE_I => CE_I, -- interface clock enable, high-active + + -- 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 + CP_IRQ_O => SYS_CP_IRQ, -- unit interrupt request + + SYS_MODE_I => SYS_MODE, -- current operating mode + INT_EXE_I => SYS_INT_EXE, -- interrupt beeing executed + + -- Memory Interface -- + MEM_IP_ADR_O => I_PAGE, -- instruction page + MEM_DP_ADR_O => D_PAGE, -- data page + + -- IO Interface -- + UART_RXD_I => UART_RXD_I, -- receiver input + UART_TXD_O => UART_TXD_O, -- UART transmitter output + SPI_SCK_O => SPI_SCK_O, -- serial clock output + SPI_MOSI_O => SPI_MOSI_O, -- serial data output + SPI_MISO_I => SPI_MISO_I, -- serial data input + SPI_CS_O => SPI_CS_O, -- device select + PIO_OUT_O => PIO_OUT_O, -- parallel output + PIO_IN_I => PIO_IN_I, -- parallel input + + -- System IO -- + SYS_OUT_O => SYS_OUT_O, -- system parallel output + SYS_IN_I => SYS_IN_I, -- system parallel input + + -- IRQ Lines -- + IRQ_I => IRQ_I -- external IRQs + ); + + + -- Memory Gate ----------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + memory_gate: MEM_GATE + port map ( + -- Host Interface -- + CLK_I => CLK_I, -- global clock line + RST_I => RST_I, -- global reset line, sync, high-active + + I_ADR_I => CPU_I_ADR, -- instruction adr + I_EN_I => CPU_I_EN, -- IR update + I_DAT_O => CPU_I_DATA, -- instruction out + D_REQ_I => CPU_D_REQ, -- request access in next cycle + D_RW_I => CPU_D_RW, -- read/write + D_ADR_I => CPU_D_ADR, -- data adr + D_DAT_I => CPU_D_W_DATA, -- data in + D_DAT_O => CPU_D_R_DATA, -- data out + MEM_IP_ADR_I => I_PAGE, -- instruction page + MEM_DP_ADR_I => D_PAGE, -- data page + + -- Boot ROM Interface -- + BOOT_I_ADR_O => BOOT_I_ADR, -- instruction adr + BOOT_I_EN_O => BOOT_I_EN, -- IR update + BOOT_I_DAT_I => BOOT_I_DAT, -- instruction out + BOOT_D_EN_O => BOOT_D_EN, -- access enable + BOOT_D_RW_O => BOOT_D_RW, -- read/write + BOOT_D_ADR_O => BOOT_D_ADR, -- data adr + BOOT_D_DAT_O => BOOT_D_DAT_O, -- data in + BOOT_D_DAT_I => BOOT_D_DAT_I, -- data out + + -- Memory Interface -- + MEM_I_PAGE_O => MEM_I_PAGE_O, -- instruction page + MEM_I_ADR_O => MEM_I_ADR_O, -- instruction adr + MEM_I_EN_O => MEM_I_EN_O, -- IR update + MEM_I_DAT_I => MEM_I_DAT_I, -- instruction out + MEM_D_EN_O => MEM_D_EN_O, -- access enable + MEM_D_RW_O => MEM_D_RW_O, -- read/write + MEM_D_PAGE_O => MEM_D_PAGE_O, -- instruction page + MEM_D_ADR_O => MEM_D_ADR_O, -- data adr + MEM_D_DAT_O => MEM_D_DAT_O, -- data in + MEM_D_DAT_I => MEM_D_DAT_I -- data out + ); + + + + -- Bootloader Memory ----------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + bootloader_mem: BOOT_MEM + port map ( + -- Host Interface -- + CLK_I => CLK_I, -- global clock line + I_ADR_I => BOOT_I_ADR, -- instruction adr + I_EN_I => BOOT_I_EN, -- IR update + I_DAT_O => BOOT_I_DAT, -- instruction out + D_EN_I => BOOT_D_EN, -- access enable + D_RW_I => BOOT_D_RW, -- read/write + D_ADR_I => BOOT_D_ADR, -- data adr + D_DAT_I => BOOT_D_DAT_O, -- data in + D_DAT_O => BOOT_D_DAT_I -- data out + ); + + + +end ATLAS_2K_TOP_BEHAV; Index: trunk/rtl/MEM_ACC.vhd =================================================================== --- trunk/rtl/MEM_ACC.vhd (nonexistent) +++ trunk/rtl/MEM_ACC.vhd (revision 21) @@ -0,0 +1,200 @@ +-- ######################################################## +-- # << 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: 01.02.2014 # +-- # **************************************************** # +-- # 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 + 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) and MA_CTRL_BUS_I(ctrl_en_c); + + + + -- Stage Data Multiplexer ------------------------------------------------------------------------------ + -- -------------------------------------------------------------------------------------------------------- + no_mac_mul_units: -- syntheszie no MAC and no MUL unit + if (build_mul_c = false) and (build_mac_c = false) generate + ALU_MAC_DAT <= ALU_RES_FF; + end generate no_mac_mul_units; + synhesize_mac_mul_units: -- synthesize MAC and/or MUL unit + if (build_mul_c = true) or (build_mac_c = true) generate + ALU_MAC_DAT <= MAC_RES_FF when (MA_CTRL_BUS_I(ctrl_use_mac_c) = '1') else ALU_RES_FF; + end generate synhesize_mac_mul_units; + + -- Coprocessor input -- + SYS_CP_R_DAT <= CP_DATA_I when (MA_CTRL_BUS_I(ctrl_rd_cp_acc_c) = '1') else RD_MSR_I; + + -- Multiplexers -- + 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: trunk/rtl/OP_DEC.vhd =================================================================== --- trunk/rtl/OP_DEC.vhd (nonexistent) +++ trunk/rtl/OP_DEC.vhd (revision 21) @@ -0,0 +1,501 @@ +-- ######################################################## +-- # << ATLAS Project - OpCode Decoder >> # +-- # **************************************************** # +-- # OpCode decoding unit. # +-- # **************************************************** # +-- # Last modified: 15.02.2014 # +-- # **************************************************** # +-- # 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 + INSTR_ADR_I : in std_logic_vector(data_width_c-1 downto 0); -- corresponding address + 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 + + -- formated instruction -- + signal INSTR_INT : std_logic_vector(15 downto 0); + +begin + + -- Data Format Converter ------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + DATA_CONV: process(INSTR_I, INSTR_ADR_I) + variable instr_sel_v : std_logic_vector(31 downto 0); + variable instr_tmp_v : std_logic_vector(15 downto 0); + begin + instr_sel_v := (others => '0'); + for i in 0 to data_width_c-1 loop + instr_sel_v(i) := INSTR_I(i); + end loop; + if (data_width_c = 16) then -- 16-bit mode + instr_tmp_v := instr_sel_v(15 downto 0); + else -- 32-bit mode + if (INSTR_ADR_I(1) = '0') then + instr_tmp_v := instr_sel_v(15 downto 0); + else + instr_tmp_v := instr_sel_v(31 downto 16); + end if; + end if; + if (big_endian_c = true) then -- endian converter + INSTR_INT <= instr_tmp_v(7 downto 0) & instr_tmp_v(15 downto 8); + else + INSTR_INT <= instr_tmp_v; + end if; + end process DATA_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); + variable redundant_reg_v : std_logic; + 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(6 downto 4); -- operand A register + CTRL_O(ctrl_rb_3_c downto ctrl_rb_0_c) <= M_FLAG_I & INSTR_INT(2 downto 0); -- operand B register + CTRL_O(ctrl_rd_3_c downto ctrl_rd_0_c) <= M_FLAG_I & INSTR_INT(9 downto 7); -- destination register + CTRL_O(ctrl_cond_3_c downto ctrl_cond_0_c) <= INSTR_INT(13 downto 10); -- branch condition + + -- both operands have same addresses -- + redundant_reg_v := '0'; + if (INSTR_INT(6 downto 4) = INSTR_INT(2 downto 0)) then + redundant_reg_v := '1'; + end if; + + -- 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 (redundant_reg_v = '1') 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_cmd_err_c) <= '1'; -- access violation - cmd_err trap + 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 (redundant_reg_v = '1') 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_cmd_err_c) <= '1'; -- access violation - cmd_err trap + 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); + CTRL_O(ctrl_msr_am_0_c) <= INSTR_INT(5); + 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_cmd_err_c) <= '1'; -- access violation - cmd_err trap + 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); -- only for MSR immediate write access + CTRL_O(ctrl_msr_am_0_c) <= INSTR_INT(5); -- only for MSR immediate write access + IMM_O(msr_sys_z_flag_c) <= INSTR_INT(0); -- only for MSR immediate write access + IMM_O(msr_usr_z_flag_c) <= INSTR_INT(0); -- only for MSR immediate write access + IMM_O(msr_sys_c_flag_c) <= INSTR_INT(1); -- only for MSR immediate write access + IMM_O(msr_usr_c_flag_c) <= INSTR_INT(1); -- only for MSR immediate write access + IMM_O(msr_sys_o_flag_c) <= INSTR_INT(2); -- only for MSR immediate write access + IMM_O(msr_usr_o_flag_c) <= INSTR_INT(2); -- only for MSR immediate write access + IMM_O(msr_sys_n_flag_c) <= INSTR_INT(7); -- only for MSR immediate write access + IMM_O(msr_usr_n_flag_c) <= INSTR_INT(7); -- only for MSR immediate write access + IMM_O(msr_sys_t_flag_c) <= INSTR_INT(8); -- only for MSR immediate write access + IMM_O(msr_usr_t_flag_c) <= INSTR_INT(8); -- only for MSR immediate write access + if (INSTR_INT(3) = '0') then -- store to MSR + if ((M_FLAG_I = user_mode_c) and (INSTR_INT(6 downto 5) /= "11")) then + CTRL_O(ctrl_cmd_err_c) <= '1'; -- access violation -> cmd_err trap + 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 + CTRL_O(ctrl_rb_is_imm_c) <= INSTR_INT(4); -- store immediate + 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") or (INSTR_INT(7) = '1'))) then + CTRL_O(ctrl_cmd_err_c) <= '1'; -- access violation - cmd_err trap + 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 => '0'); -- zero + CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_orr_c; -- logical or with 0 + 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 + CTRL_O(ctrl_link_c) <= INSTR_INT(2); -- link + CTRL_O(ctrl_rd_wb_c) <= INSTR_INT(2); -- allow write back for linking + CTRL_O(ctrl_restsm_c) <= INSTR_INT(7); -- restore saved mode + 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 => -- immediate subtraction + CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_sbc_c; + + when fs_sub_c => -- subtraction + CTRL_O(ctrl_alu_fs_2_c downto ctrl_alu_fs_0_c) <= alu_sbc_c; + if (redundant_reg_v = '1') then -- SUB instruction with Ra = Rb: Rd = 0 - Ra (NEG Rd, Ra) + 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 + end if; + + 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 + if (redundant_reg_v = '1') then -- SBC instruction with Ra = Rb: Rd = 0 - Ra - C (NEC Rd, Ra) + 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 + end if; + + 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 (without 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 + CTRL_O(ctrl_clr_la_c) <= '1'; -- set low byte of A to 0 + IMM_O(7 downto 0) <= INSTR_INT(10) & INSTR_INT(6 downto 0); + if (ldil_sign_ext_c = true) then -- use sign extension + for i in 8 to data_width_c-1 loop -- sign extension + IMM_O(i) <= INSTR_INT(10); + end loop; + CTRL_O(ctrl_clr_ha_c) <= '1'; -- set high byte of A to 0 + end if; + 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 => -- "11" -- T-flag transfer, store to T + IMM_O(3 downto 0) <= INSTR_INT(3 downto 0); + CTRL_O(ctrl_rb_is_imm_c) <= not INSTR_INT(9); -- B is an immediate or REG + CTRL_O(ctrl_tf_store_c) <= '1'; -- store to t-flag + CTRL_O(ctrl_tf_inv_c) <= INSTR_INT(7); -- invert bit to be transfered to T-flag + CTRL_O(ctrl_get_par_c) <= INSTR_INT(8); -- get parity bit of OP_A + 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') and (INSTR_INT(10) = '0')) or (INSTR_INT(10) = '1') then -- unauthorized acces? + CTRL_O(ctrl_cmd_err_c) <= '1'; -- access violation/undefined instruction - cmd_err trap + 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 + -- -------------------------------------------------------------------------------- + CTRL_O(ctrl_rd_wb_c) <= '1'; -- allow write back + 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_cmd_err_c) <= '1'; -- invalid instruction - cmd_err trap + 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_cmd_err_c) <= '1'; -- invalid instruction - cmd_err trap + end if; + end if; + + + when "01" => -- Class 3c1: Special (Sleep, Reg-based branch) + -- -------------------------------------------------------------------------------- + if (INSTR_INT(9) = '0') then -- SLEEP mode + CTRL_O(ctrl_sleep_c) <= '1'; -- go to sleep + elsif (reg_branches_en_c = true) then -- register-based branch + CTRL_O(ctrl_cond_3_c downto ctrl_cond_0_c) <= INSTR_INT(6 downto 3); -- branch condition + 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 (without carry) + CTRL_O(ctrl_branch_c) <= '1'; -- this is a branch + CTRL_O(ctrl_link_c) <= INSTR_INT(7); -- link? + CTRL_O(ctrl_rd_wb_c) <= INSTR_INT(7); -- allow write back for linking + CTRL_O(ctrl_ra_is_pc_c) <= '1'; -- operand A is the pc + CTRL_O(ctrl_clr_la_c) <= INSTR_INT(8); -- set low byte of A to 0 + CTRL_O(ctrl_clr_ha_c) <= INSTR_INT(8); -- set high byte of A to 0 + else + CTRL_O(ctrl_cmd_err_c) <= '1'; -- undefined instruction - cmd_err trap + end if; + + + when "10" => -- Class 3c2: Undefined Instruction + -- -------------------------------------------------------------------------------- + CTRL_O(ctrl_cmd_err_c) <= '1'; -- undefined instruction - cmd_err trap + + + 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: trunk/rtl/INT_RAM.vhd =================================================================== --- trunk/rtl/INT_RAM.vhd (nonexistent) +++ trunk/rtl/INT_RAM.vhd (revision 21) @@ -0,0 +1,91 @@ +-- ######################################################## +-- # << ATLAS Project - Demo RAM >> # +-- # **************************************************** # +-- # Core-compatible example RAM component. # +-- # **************************************************** # +-- # Last modified: 02.03.2014 # +-- # **************************************************** # +-- # 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 INT_RAM is + generic ( + MEM_SIZE_G : natural := 256 -- memory size in bytes + ); + port ( + -- Host Interface -- + CLK_I : in std_logic; -- global clock line + I_ADR_I : in std_logic_vector(31 downto 0); -- instruction adr + I_EN_I : in std_logic; -- IR update + I_DAT_O : out std_logic_vector(15 downto 0); -- instruction out + D_EN_I : in std_logic; -- access enable + D_RW_I : in std_logic; -- read/write + D_ADR_I : in std_logic_vector(31 downto 0); -- data adr + D_DAT_I : in std_logic_vector(15 downto 0); -- data in + D_DAT_O : out std_logic_vector(15 downto 0) -- data out + ); +end INT_RAM; + +architecture INT_RAM_STRUCTURE of INT_RAM is + + -- Internal Constants -- + constant log2_mem_size_c : natural := log2(MEM_SIZE_G/2); -- address width + + -- Memory Type -- + type int_mem_file_t is array (0 to (MEM_SIZE_G/2)-1) of std_logic_vector(data_width_c-1 downto 0); + +-- ====================================================================== + signal MEM_FILE : int_mem_file_t; -- use this for implementation +-- signal MEM_FILE : int_mem_file_t := -- use this for simulation only +-- ( +-- others => x"0000" -- replace this with simulation memory content +-- ); +-- ====================================================================== + + -- RAM attribute to inhibit bypass-logic - ALTERA ONLY! -- + attribute ramstyle : string; + attribute ramstyle of MEM_FILE : signal is "no_rw_check"; + +begin + + -- Memory Access and Handshake ------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + MEM_FILE_ACCESS: process(CLK_I) + begin + if rising_edge(CLK_I) then + -- Data Read(/Write) -- + if (D_EN_I = '1') then -- valid access + if (D_RW_I = '1') then -- write data access + if (word_mode_en_c = true) then + MEM_FILE(to_integer(unsigned(D_ADR_I(log2_mem_size_c-1 downto 0)))) <= D_DAT_I; + else + MEM_FILE(to_integer(unsigned(D_ADR_I(log2_mem_size_c downto 1)))) <= D_DAT_I; + end if; + end if; + if (word_mode_en_c = true) then + D_DAT_O <= MEM_FILE(to_integer(unsigned(D_ADR_I(log2_mem_size_c-1 downto 0)))); + else + D_DAT_O <= MEM_FILE(to_integer(unsigned(D_ADR_I(log2_mem_size_c downto 1)))); + end if; + end if; + -- Instruction Read -- + if (I_EN_I = '1') then + if (word_mode_en_c = true) then + I_DAT_O <= MEM_FILE(to_integer(unsigned(I_ADR_I(log2_mem_size_c-1 downto 0)))); + else + I_DAT_O <= MEM_FILE(to_integer(unsigned(I_ADR_I(log2_mem_size_c downto 1)))); + end if; + end if; + end if; + end process MEM_FILE_ACCESS; + + + +end INT_RAM_STRUCTURE; Index: trunk/doc/Atlas 2k Processor Documentary.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/Atlas 2k Processor Documentary.pdf =================================================================== --- trunk/doc/Atlas 2k Processor Documentary.pdf (nonexistent) +++ trunk/doc/Atlas 2k Processor Documentary.pdf (revision 21)
trunk/doc/Atlas 2k Processor Documentary.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/sim/atlas_2k_base_tb.vhd =================================================================== --- trunk/sim/atlas_2k_base_tb.vhd (nonexistent) +++ trunk/sim/atlas_2k_base_tb.vhd (revision 21) @@ -0,0 +1,110 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.atlas_core_package.all; + +entity atlas_2k_base_tb is +end atlas_2k_base_tb; + +architecture atlas_2k_base_tb_structure of atlas_2k_base_tb is + + -- Component: Atlas-2K Processor ---------------------------------------------------------- + -- ------------------------------------------------------------------------------------------- + component ATLAS_2K_BASE_TOP + port ( + -- Globals -- + CLK_I : in std_logic; -- global clock line + RSTN_I : in std_logic; -- global reset line, low-active + + -- UART -- + UART_RXD_I : in std_logic; -- receiver input + UART_TXD_O : out std_logic; -- UART transmitter output + + -- SPI -- + SPI_MOSI_O : out std_logic_vector(07 downto 0); -- serial data out + SPI_MISO_I : in std_logic_vector(07 downto 0); -- serial data in + SPI_SCK_O : out std_logic_vector(07 downto 0); -- serial clock out + SPI_CS_O : out std_logic_vector(07 downto 0); -- chip select (low active) + + -- PIO -- + PIO_OUT_O : out std_logic_vector(15 downto 0); -- parallel output + PIO_IN_I : in std_logic_vector(15 downto 0); -- parallel input + + -- System IO -- + SYS_OUT_O : out std_logic_vector(07 downto 0); -- system output + SYS_IN_I : in std_logic_vector(07 downto 0) -- system input + ); + end component; + + -- Global Signals -- + signal CLK_GEN : std_logic := '0'; + signal RSTN_GEN : std_logic := '0'; + + -- IO -- + signal RXD, TXD : std_logic; -- UART + signal PIO_OUT, PIO_IN : std_logic_vector(15 downto 0); -- PIO + signal BOOT_C_IN : std_logic_vector(07 downto 0); -- Boot/sys condfig + signal BOOT_C_OUT : std_logic_vector(07 downto 0); -- Boot/sys status + signal SPI_MISO : std_logic_vector(07 downto 0); -- SPI master out slave in + signal SPI_MOSI : std_logic_vector(07 downto 0); -- SPI master in slave out + signal SPI_CSN : std_logic_vector(07 downto 0); -- SPI chip select (low-active) + signal SPI_SCK : std_logic_vector(07 downto 0); -- SPI master clock out + +begin + + -- Clock/Reset Generator ------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + CLK_GEN <= not CLK_GEN after 10 ns; -- 50Mhz + RSTN_GEN <= '0', '1' after 35 ns; + + + + -- Processor Core -------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + DUT: ATLAS_2K_BASE_TOP + port map ( + -- Globals -- + CLK_I => CLK_GEN, -- global clock line + RSTN_I => RSTN_GEN, -- global reset line, low-active + + -- UART -- + UART_RXD_I => RXD, -- receiver input + UART_TXD_O => TXD, -- UART transmitter output + + -- SPI -- + SPI_MOSI_O => SPI_MOSI, -- serial data out + SPI_MISO_I => SPI_MISO, -- serial data in + SPI_SCK_O => SPI_SCK, -- serial clock out + SPI_CS_O => SPI_CSN, -- chip select (low active) + + -- PIO -- + PIO_OUT_O => PIO_OUT, -- parallel output + PIO_IN_I => PIO_IN, -- parallel input + + -- System IO -- + SYS_OUT_O => BOOT_C_OUT, -- system output + SYS_IN_I => BOOT_C_IN -- system input + ); + + -- BOOT CONFIG -- + BOOT_C_IN(7 downto 2) <= "000000"; -- unused + BOOT_C_IN(1 downto 0) <= "11"; -- BOOT FROM INTERNAL MEMORY!!! + + + + -- Stimulus -------------------------------------------------------------------------------------------- + -- -------------------------------------------------------------------------------------------------------- + STIMULUS: process + begin + -- all idle -- + RXD <= '1'; -- idle + SPI_MISO <= "00000000"; + PIO_IN <= x"0000"; + wait; + end process STIMULUS; + + + +end atlas_2k_base_tb_structure; Index: trunk/sim/xilinx_isim_atlas_2k_base_tb_wave.wcfg =================================================================== --- trunk/sim/xilinx_isim_atlas_2k_base_tb_wave.wcfg (nonexistent) +++ trunk/sim/xilinx_isim_atlas_2k_base_tb_wave.wcfg (revision 21) @@ -0,0 +1,729 @@ + + + + + + + + + + + + + + + + + Global Control + label + #000080 + 230 230 230 + + + clk_i + clk_i + + + rst_i + rst_i + + + ce_i + ce_i + + + Pipeline + label + #000080 + 230 230 230 + HEXRADIX + + + sys_reg_pc[15:0] + sys_reg_pc[15:0] + UNSIGNEDDECRADIX + true + #ff0000 + + + instr_i[15:0] + instr_i[15:0] + HEXRADIX + true + #ffff00 + + + of_ctrl_bus_o[52:0] + of_ctrl_bus_o[52:0] + + + ex_ctrl_bus_o[52:0] + ex_ctrl_bus_o[52:0] + + + ma_ctrl_bus_o[52:0] + ma_ctrl_bus_o[52:0] + + + wb_ctrl_bus_o[52:0] + wb_ctrl_bus_o[52:0] + + + [0] + of_ctrl_bus_o[0] + + + [0] + ex_ctrl_bus_o[0] + + + [0] + ma_ctrl_bus_o[0] + + + [0] + wb_ctrl_bus_o[0] + + + Arbitration + label + #000080 + 230 230 230 + HEXRADIX + + + valid_branch_i + valid_branch_i + + + exc_taken_i + exc_taken_i + + + dis_cycle + dis_cycle + + + mem_dependecy + mem_dependecy + + + sleep_flag + sleep_flag + + + Executor + label + #000080 + 230 230 230 + HEXRADIX + + + op_b_int[15:0] + op_b_int[15:0] + HEXRADIX + + + op_a_int[15:0] + op_a_int[15:0] + HEXRADIX + + + op_c_int[15:0] + op_c_int[15:0] + HEXRADIX + + + flag_bus_i[4:0] + flag_bus_i[4:0] + BINARYRADIX + + + flag_bus_o[4:0] + flag_bus_o[4:0] + BINARYRADIX + + + alu_res_o[15:0] + alu_res_o[15:0] + HEXRADIX + + + mac_res_o[15:0] + mac_res_o[15:0] + HEXRADIX + + + msr_data_o[15:0] + msr_data_o[15:0] + HEXRADIX + + + Interrupts + label + #000080 + 230 230 230 + + + ext_int_req0_i + ext_int_req0_i + + + ext_int_req1_i + ext_int_req1_i + + + int_req + int_req + + + exc_executed_o + exc_executed_o + + + int_vector[15:0] + int_vector[15:0] + HEXRADIX + + + Machine Status + label + #000080 + 230 230 230 + + + sys_reg_msr[15:0] + sys_reg_msr[15:0] + HEXRADIX + true + #ffff00 + + + Operand Fetch + label + #000080 + 230 230 230 + HEXRADIX + + + reg_file_mem[15:0] + reg_file_mem[15:0] + HEXRADIX + true + #0000ff + + [15] + reg_file_mem[15] + HEXRADIX + true + #0000ff + + + [14] + reg_file_mem[14] + HEXRADIX + true + #0000ff + + + [13] + reg_file_mem[13] + HEXRADIX + true + #0000ff + + + [12] + reg_file_mem[12] + HEXRADIX + true + #0000ff + + + [11] + reg_file_mem[11] + HEXRADIX + true + #0000ff + + + [10] + reg_file_mem[10] + HEXRADIX + true + #0000ff + + + [9] + reg_file_mem[9] + HEXRADIX + true + #0000ff + + + [8] + reg_file_mem[8] + HEXRADIX + true + #0000ff + + + [7] + reg_file_mem[7] + HEXRADIX + true + #0000ff + + + [6] + reg_file_mem[6] + HEXRADIX + true + #0000ff + + + [5] + reg_file_mem[5] + HEXRADIX + true + #0000ff + + + [4] + reg_file_mem[4] + HEXRADIX + true + #0000ff + + + [3] + reg_file_mem[3] + HEXRADIX + true + #0000ff + + + [2] + reg_file_mem[2] + HEXRADIX + true + #0000ff + + + [1] + reg_file_mem[1] + HEXRADIX + true + #0000ff + + + [0] + reg_file_mem[0] + HEXRADIX + true + #0000ff + + + + CP - Interface + label + #ffa500 + 230 230 230 + HEXRADIX + + + usr_cp_en_o + usr_cp_en_o + + + sys_cp_en_o + sys_cp_en_o + + + cp_op_o + cp_op_o + + + cp_rw_o + cp_rw_o + + + cp_cmd_o[8:0] + cp_cmd_o[8:0] + HEXRADIX + + + cp_dat_o[15:0] + cp_dat_o[15:0] + HEXRADIX + + + cp_dat_i[15:0] + cp_dat_i[15:0] + HEXRADIX + + + CP - SYS_0 + label + #ffa500 + 230 230 230 + HEXRADIX + + + irq_i[7:0] + irq_i[7:0] + + + irq_mask_reg[7:0] + irq_mask_reg[7:0] + HEXRADIX + + + irq_source_reg[2:0] + irq_source_reg[2:0] + HEXRADIX + + + irq_conf_reg[15:0] + irq_conf_reg[15:0] + HEXRADIX + + + irq_o + irq_o + + + tmr_cnt_reg[15:0] + tmr_cnt_reg[15:0] + HEXRADIX + + + tmr_thr_reg[15:0] + tmr_thr_reg[15:0] + HEXRADIX + + + lfsr_data[15:0] + lfsr_data[15:0] + HEXRADIX + + + lfsr_poly[15:0] + lfsr_poly[15:0] + HEXRADIX + + + CP - SYS_1 + label + #ffa500 + 230 230 230 + HEXRADIX + + + mmu_sys_i_page[15:0] + mmu_sys_i_page[15:0] + HEXRADIX + + + mmu_sys_d_page[15:0] + mmu_sys_d_page[15:0] + HEXRADIX + + + mmu_usr_i_page[15:0] + mmu_usr_i_page[15:0] + HEXRADIX + + + mmu_usr_d_page[15:0] + mmu_usr_d_page[15:0] + HEXRADIX + + + mmu_i_page_link[15:0] + mmu_i_page_link[15:0] + HEXRADIX + + + mmu_d_page_link[15:0] + mmu_d_page_link[15:0] + HEXRADIX + + + mmu_irq_base[15:0] + mmu_irq_base[15:0] + HEXRADIX + + + mem_ip_adr_o[15:0] + mem_ip_adr_o[15:0] + HEXRADIX + true + #ffff00 + + + mem_dp_adr_o[15:0] + mem_dp_adr_o[15:0] + HEXRADIX + true + #ffff00 + + + CP - COM_0 + label + #ffa500 + 230 230 230 + HEXRADIX + + + uart_tx_sreg[9:0] + uart_tx_sreg[9:0] + HEXRADIX + + + uart_rx_sreg[9:0] + uart_rx_sreg[9:0] + HEXRADIX + + + com_config_reg[15:0] + com_config_reg[15:0] + HEXRADIX + + + spi_tx_reg[15:0] + spi_tx_reg[15:0] + HEXRADIX + + + spi_rx_reg[15:0] + spi_rx_reg[15:0] + HEXRADIX + + + spi_cs_reg[7:0] + spi_cs_reg[7:0] + HEXRADIX + + + pio_out_data[15:0] + pio_out_data[15:0] + HEXRADIX + + + pio_in_data[15:0] + pio_in_data[15:0] + HEXRADIX + + + UART + label + #ffa500 + 230 230 230 + HEXRADIX + + + uart_rxd_i + uart_rxd_i + + + uart_txd_o + uart_txd_o + + + SPI + label + #ffa500 + 230 230 230 + HEXRADIX + + + spi_cs_o[7:0] + spi_cs_o[7:0] + BINARYRADIX + + + spi_sck_o[7:0] + spi_sck_o[7:0] + BINARYRADIX + + + spi_mosi_o[7:0] + spi_mosi_o[7:0] + BINARYRADIX + + + spi_miso_i[7:0] + spi_miso_i[7:0] + BINARYRADIX + + + PIO + label + #ffa500 + 230 230 230 + HEXRADIX + + + pio_in_i[15:0] + pio_in_i[15:0] + + + pio_out_o[15:0] + pio_out_o[15:0] + + + sys_in_i[7:0] + sys_in_i[7:0] + + + sys_out_o[7:0] + sys_out_o[7:0] + + + IRQ + label + #ffa500 + 230 230 230 + HEXRADIX + + + critical_irq_i + critical_irq_i + + + irq_i[1:0] + irq_i[1:0] + BINARYRADIX + + + Memory Access + label + #800080 + 230 230 230 + + + mem_i_en_o + mem_i_en_o + + + mem_i_page_o[15:0] + mem_i_page_o[15:0] + HEXRADIX + + + mem_i_adr_o[15:0] + mem_i_adr_o[15:0] + HEXRADIX + + + mem_i_dat_i[15:0] + mem_i_dat_i[15:0] + HEXRADIX + + + mem_d_en_o + mem_d_en_o + + + mem_d_rw_o + mem_d_rw_o + + + mem_d_page_o[15:0] + mem_d_page_o[15:0] + HEXRADIX + + + mem_d_adr_o[15:0] + mem_d_adr_o[15:0] + HEXRADIX + + + mem_d_dat_o[15:0] + mem_d_dat_o[15:0] + HEXRADIX + + + mem_d_dat_i[15:0] + mem_d_dat_i[15:0] + HEXRADIX + + + Internal RAM + label + #800080 + 230 230 230 + + + i_en_i + i_en_i + + + i_adr_i[31:0] + i_adr_i[31:0] + HEXRADIX + + + i_dat_o[15:0] + i_dat_o[15:0] + HEXRADIX + + + d_en_i + d_en_i + + + d_rw_i + d_rw_i + + + d_adr_i[31:0] + d_adr_i[31:0] + HEXRADIX + + + d_dat_i[15:0] + d_dat_i[15:0] + HEXRADIX + + + d_dat_o[15:0] + d_dat_o[15:0] + HEXRADIX + + + Boot ROM + label + #800080 + 230 230 230 + + + i_en_i + i_en_i + + + i_adr_i[15:0] + i_adr_i[15:0] + HEXRADIX + + + i_dat_o[15:0] + i_dat_o[15:0] + HEXRADIX + + + d_en_i + d_en_i + + + d_adr_i[15:0] + d_adr_i[15:0] + HEXRADIX + + + d_dat_o[15:0] + d_dat_o[15:0] + HEXRADIX + + Index: trunk/software/bootloader/atlas2k_bootloader.asm =================================================================== --- trunk/software/bootloader/atlas2k_bootloader.asm (nonexistent) +++ trunk/software/bootloader/atlas2k_bootloader.asm (revision 21) @@ -0,0 +1,1255 @@ +; ***************************************************************************************************************** +; ***************************************************************************************************************** +; ATLAS 2K Bootloader +; +; Bootloader MEM (ROM) pages starting at 0x8000 +; +; Options: +; -> load image via UART +; -> execute image in memory (page: 0x0000, address: 0x0000) +; -> load image from SPI EEPROM +; -> burn image to SPI EEPROM +; -> make hex dump from memory (any page) +; +; Boot configuration via CP1.COM_0_CORE.SYS_IN (bits 1 downto 0): +; -> "00": Launch console +; -> "01": Boot from UART +; -> "10": Boot from SPI EEPROM (CS0) +; -> "11": Boot from memory (page: 0x0000, address: 0x0000) +; +; SPI-EEPROM at CS0 (boot EEPROM) must have 16-bit data address (!) -> max size is 64kB - 16 bytes +; => e.g. 25LCD512 +; +; Terminal configuration (CP1.COM_0_CORE.UART): 2400-8-N-1 +; This bootloader does not need any RAM at all, thus the baud rate must be low +; to allow burning of the EEPROM 'on the fly'. +; +; For version info see the string section. +; +; 'Global variables' +; usr_r0: Image size +; usr_r1: Image checksum +; usr_r2: Image name (0,1) +; usr_r3: Image name (2,3) +; usr_r4: Image name (4,5) +; usr_r5: Image name (6,7) +; usr_r6: Image name (8,9) +; usr_r7: Checksum computation +; ***************************************************************************************************************** +; ***************************************************************************************************************** + +; ----------------------------------------------------------------------------- +; Processor register definitions +; ----------------------------------------------------------------------------- +.equ sp r6 ; stack pointer +.equ lr r7 ; link register + +; ----------------------------------------------------------------------------- +; CPU function cores +; ----------------------------------------------------------------------------- +.equ sys0_core c0 +.equ sys1_core c1 +.equ com0_core c2 + +; ----------------------------------------------------------------------------- +; MSR bits +; ----------------------------------------------------------------------------- +.equ msr_gxint_en #11 ; global external interrupt enable +.equ msr_xint0_en #12 ; enable external interrupt line 0 +.equ msr_xint1_en #13 ; enable external interrupt line 1 + +; ----------------------------------------------------------------------------- +; Configuration constans +; ----------------------------------------------------------------------------- +.equ uart_baud_c #2400 ; com0_core.UART default baud rate +; keep the baud rate low - eeprom programming is done without buffering! + + +; ***************************************************************************************************************** +; Exception Vector Table +; ***************************************************************************************************************** + +reset_vec: b reset +x_int0_vec: b boot_irq_error ; fatal error +x_int1_vec: b boot_irq_error ; fatal error +cmd_err_vec: b boot_irq_error ; fatal error +swi_vec: b boot_irq_error ; fatal error + + +; ***************************************************************************************************************** +; Interrupt service routine - this is fatal! +; ***************************************************************************************************************** +boot_irq_error: + ; restore bootloader page + ldil r0, #0x00 ; = 0x8000 + ldih r0, #0x80 + mcr #1, sys1_core, r0, #2 ; set d-page + + ; set alarm lights + mcr #1, com0_core, r0, #7 ; set system output + + ; print error message + bl uart_linebreak__ + ldil r2, low[string_err_irq] + ldih r2, high[string_err_irq] + bl uart_print_br__ + + b #+0 ; freeze + + +; ***************************************************************************************************************** +; Main Program +; ***************************************************************************************************************** +reset: ; init MSR + ldil r0, #0x00 + ldih r0, #0xF8 ; sys_mode, prv_sys_mode, g_irq_en, int1_en, int0_en + stsr r0 + + ; set mmu pages + mrc #1, r0, sys1_core, #1 ; get sys i-page + mcr #1, sys1_core, r0, #0 + mcr #1, sys1_core, r0, #2 + + ; re-init lfsr, timer and IRQ controller + ldil r0, #0x00 + mcr #1, sys0_core, r0, #0 ; clear irq mask register + mcr #1, sys0_core, r0, #1 ; clear irq config register + mcr #1, sys0_core, r0, #2 ; clear timer counter + mcr #1, sys0_core, r0, #3 ; clear timer threshold + mcr #1, sys0_core, r0, #4 ; clear timer prescaler + mcr #1, sys0_core, r0, #5 ; clear lfsr data register + mcr #1, sys0_core, r0, #6 ; clear lfsr polynomial register + mrc #1, r0, sys0_core, #0 ; ack pending IRQs + + ; alive LED + ldih r0, #1 + mcr #1, com0_core, r0, #7 ; set system output + + ; get system clock frequency + mrc #1, r0, sys1_core, #7 ; clock low + mrc #1, r1, sys1_core, #7 ; clock high + + ; baud rate + ldil r2, low[uart_baud_c] + ldih r2, high[uart_baud_c] + ldil r3, #15 + add r2, r2, r3 ; +15 to compensate UART's latency + + ; compute and set UART prescaler + clr r3 + clr r4 +main_baud_loop: + subs r0, r0, r2 ; do bad division... + sbcs r1, r1, r3 + bmi #+3 + inc r4, r4, #1 + b main_baud_loop + mcr #1, com0_core, r4, #1 ; set UART prescaler + + ; activate UART core + mrc #1, r0, com0_core, #2 ; com ctrl reg + sbr r0, r0, #6 ; UART EN + mcr #1, com0_core, r0, #2 ; com ctrl reg + + ; print intro + bl uart_linebreak__ + bl uart_linebreak__ + ldil r2, low[string_intro0] + ldih r2, high[string_intro0] + bl uart_print_br__ + ldil r2, low[string_intro1] + ldih r2, high[string_intro1] + bl uart_print_br__ + ldil r2, low[string_intro2] + ldih r2, high[string_intro2] + bl uart_print_br__ + bl uart_linebreak__ + + ; print boot page + ldil r2, low[string_intro3] + ldih r2, high[string_intro3] + bl uart_print__ + mrc #1, r4, sys1_core, #1 ; get sys i-page + bl print_hex_string__ + bl uart_linebreak__ + + ; print clock speed + ldil r2, low[string_intro4] + ldih r2, high[string_intro4] + bl uart_print__ + mrc #1, r5, sys1_core, #7 ; clock low + mrc #1, r4, sys1_core, #7 ; clock high + bl print_hex_string__ ; print clock high + mov r4, r5 + bl print_hex_string__ ; print clock low + bl uart_linebreak__ + + ; check boot config switches + mrc #1, r0, com0_core, #7 ; parallel input + ldil r1, #0x03 ; bit mask + and r0, r0, r1 + + ; option selection + ldil r6, #'0' + add r6, r6, r0 ; add ascii offset to selection + b console_selector + + +; ----------------------------------------------------------------------------------- +; Terminal console +; ----------------------------------------------------------------------------------- +start_console: + ; print menu + bl uart_linebreak__ + ldil r2, low[string_menu_hd] + ldih r2, high[string_menu_hd] + bl uart_print_br__ + ldil r2, low[string_menu0] + ldih r2, high[string_menu0] + bl uart_print_br__ + ldil r2, low[string_menu1] + ldih r2, high[string_menu1] + bl uart_print_br__ + ldil r2, low[string_menu2] + ldih r2, high[string_menu2] + bl uart_print_br__ + ldil r2, low[string_menu3] + ldih r2, high[string_menu3] + bl uart_print_br__ + ldil r2, low[string_menup] + ldih r2, high[string_menup] + bl uart_print_br__ + ldil r2, low[string_menud] + ldih r2, high[string_menud] + bl uart_print_br__ + ldil r2, low[string_menur] + ldih r2, high[string_menur] + bl uart_print_br__ + +console_input: + ldil r2, low[string_menux] + ldih r2, high[string_menux] + bl uart_print__ ; print prompt + + ; process unser input +console_wait: + bl uart_receivebyte__ ; wait for user input + mov r6, r0 ; backup for selector + mov r1, r6 ; backup for echo + bl uart_sendbyte__ ; echo selection + bl uart_linebreak__ + + ; go to submenu +console_selector: + ldil r1, #'0' + cmp r1, r6 + beq start_console ; restart console + + ldil r1, #'1' + cmp r1, r6 + beq boot_uart ; boot from uart + + ldil r1, #'2' + cmp r1, r6 + beq boot_eeprom ; boot from eeprom + + ldil r1, #'3' + cmp r1, r6 + beq boot_memory ; boot from memory + + ldil r5, low[burn_eeprom] + ldih r5, high[burn_eeprom] + ldil r1, #'p' + cmp r1, r6 + rbaeq r5 ; program eeprom + + ldil r5, low[mem_dump] + ldih r5, high[mem_dump] + ldil r1, #'d' + cmp r1, r6 + rbaeq r5 ; ram dump + + ldil r1, #'r' + cmp r1, r6 + bne console_input ; invalid input + + ; do 'hard' reset + clr r0 + ldil r1, #0x00 + ldih r1, #0x80 ; start of boot pages + mcr #1, sys1_core, r1, #1 + gt r0 + + +; ----------------------------------------------------------------------------------- +; Booting from memory +; ----------------------------------------------------------------------------------- +boot_memory: + ldil r2, low[string_boot_mem] + ldih r2, high[string_boot_mem] + bl uart_print_br__ + + ; print no image info on start-up + clr r0 + stub r2, r0 + + b start_image + + +; ----------------------------------------------------------------------------------- +; Intermediate Brach Stops - Stop 2 +; ----------------------------------------------------------------------------------- +uart_print_br__: b uart_print_br_ +uart_print__: b uart_print_ +uart_linebreak__: b uart_linebreak_ +uart_sendbyte__: b uart_sendbyte_ +uart_receivebyte__: b uart_receivebyte_ +print_hex_string__: b print_hex_string_ + + +; ----------------------------------------------------------------------------------- +; Booting from SPI EEPROM +; ----------------------------------------------------------------------------------- +boot_eeprom: + ; intro + ldil r2, low[string_boot_spi] + ldih r2, high[string_boot_spi] + bl uart_print_br_ + + ; get signature + ldil r2, #0 + bl spi_eeprom_read_byte__ ; read byte from eeprom + sft r5, r3, #swp + ldil r2, #1 + bl spi_eeprom_read_byte__ ; read byte from eeprom + orr r5, r5, r3 + ldil r0, #0xFE + ldih r0, #0xCA + cmp r0, r5 + bne signature_err_ + + ; get size + ldil r2, #2 + bl spi_eeprom_read_byte__ ; read byte from eeprom + sft r5, r3, #swp + ldil r2, #3 + bl spi_eeprom_read_byte__ ; read byte from eeprom + orr r5, r5, r3 + stub r0, r5 + + ; get checksum + ldil r2, #4 + bl spi_eeprom_read_byte__ ; read byte from eeprom + sft r5, r3, #swp + ldil r2, #5 + bl spi_eeprom_read_byte__ ; read byte from eeprom + orr r5, r5, r3 + stub r1, r5 + + ; get image name + ldil r2, #6 + bl spi_eeprom_read_byte__ ; read byte from eeprom + sft r5, r3, #swp + ldil r2, #7 + bl spi_eeprom_read_byte__ ; read byte from eeprom + orr r5, r5, r3 + stub r2, r5 + + ldil r2, #8 + bl spi_eeprom_read_byte__ ; read byte from eeprom + sft r5, r3, #swp + ldil r2, #9 + bl spi_eeprom_read_byte__ ; read byte from eeprom + orr r5, r5, r3 + stub r3, r5 + + ldil r2, #10 + bl spi_eeprom_read_byte__ ; read byte from eeprom + sft r5, r3, #swp + ldil r2, #11 + bl spi_eeprom_read_byte__ ; read byte from eeprom + orr r5, r5, r3 + stub r4, r5 + + ldil r2, #12 + bl spi_eeprom_read_byte__ ; read byte from eeprom + sft r5, r3, #swp + ldil r2, #13 + bl spi_eeprom_read_byte__ ; read byte from eeprom + orr r5, r5, r3 + stub r5, r5 + + ldil r2, #14 + bl spi_eeprom_read_byte__ ; read byte from eeprom + sft r5, r3, #swp + ldil r2, #15 + bl spi_eeprom_read_byte__ ; read byte from eeprom + orr r5, r5, r3 + stub r6, r5 + + ; download program + ldil r6, #0 ; base address MEMORY = 0x0000 + mcr #1, sys1_core, r6, #2 ; set system d-page + stub r7, r6 ; init checksum computation + +boot_eeprom_loop: + ldil r0, #16 + add r2, r6, r0 ; high = base EEPROM = base MEM +16 + bl spi_eeprom_read_byte__ ; get high-byte + sft r5, r3, #swp ; swap bytes + + ldil r0, #17 + add r2, r6, r0 ; low = base EEPROM = base MEM +17 + bl spi_eeprom_read_byte__ ; get low-byte + orr r5, r5, r3 ; construct word + + str r5, r6, +#2, post, ! ; save to data mem + + ; update checksum + ldub r0, r7 + eor r0, r0, r5 + stub r7, r0 + + ldub r0, r0 + cmp r6, r0 ; done? + bne boot_eeprom_loop + + b download_completed + + +; ----------------------------------------------------------------------------------- +; Booting from UART +; ----------------------------------------------------------------------------------- +boot_uart: ldil r2, low[string_boot_uart] + ldih r2, high[string_boot_uart] + bl uart_print_br_ + ldil r2, low[string_boot_wimd] + ldih r2, high[string_boot_wimd] + bl uart_print_br_ + + ; check signature (2 byte) + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + ldil r0, #0xFE + ldih r0, #0xCA + cmp r1, r0 ; signature test + bne signature_err_ + + ; get program size (2 byte) + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + sft r1, r1, #lsl ; #bytes = 2*#words + stub r0, r1 + + ; get checksum (2 byte) + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + stub r1, r1 + + ; get image name (10 byte) + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + stub r2, r1 + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + stub r3, r1 + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + stub r4, r1 + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + stub r5 r1 + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + stub r6, r1 + + ; init download + clr r5 ; address = 0x00000000 + mcr #1, sys1_core, r5, #2 ; set system d-page + stub r7, r5 ; init checksum computation + + ; downloader +uart_downloader: + bl uart_receivebyte_ ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte_ ; get low-byte + orr r1, r1, r0 ; construct word + str r1, r5, +#2, post, ! ; save to data mem + + ; update checksum + ldub r0, r7 + eor r0, r0, r1 + stub r7, r0 + + ldub r0, r0 + cmp r5, r0 ; done? + bne uart_downloader + +download_completed: + ; re-init system d page + ldil r0, #0x00 + ldih r0, #0x80 + mcr #1, sys1_core, r0, #2 ; set system d-page + + ; transfer done - check checksum + ldub r0, r7 + ldub r1, r1 + cmp r0, r1 + beq start_image + + ; checksum error! + ldil r2, low[string_err_check] + ldih r2, high[string_err_check] + bl uart_print_br_ + ldil r2, low[string_err_res] + ldih r2, high[string_err_res] + bl uart_print_br_ + bl uart_receivebyte_ ; wait for any key input + clr r0 + gt r0 ; restart + + +; ----------------------------------------------------------------------------------- +; Intermediate Brach Stops - Stop 1 +; ----------------------------------------------------------------------------------- +uart_print_br_: b uart_print_br +uart_print_: b uart_print +uart_linebreak_: b uart_linebreak +uart_sendbyte_: b uart_sendbyte +uart_receivebyte_: b uart_receivebyte +spi_eeprom_read_byte__: b spi_eeprom_read_byte_ +signature_err_: b signature_err +console_input_: b console_input +print_hex_string_: b print_hex_string0 + + +; ----------------------------------------------------------------------------------- +; Start image from memory +; ----------------------------------------------------------------------------------- +start_image: + ldil r2, low[string_start_im] + ldih r2, high[string_start_im] + bl uart_print + + ; print image name + ldubs r1, r2 + beq start_image_no_text ; print image info? + + ldil r1, #34 ;'"' + bl uart_sendbyte + ldub r1, r2 + sft r1, r1, #swp + bl uart_sendbyte + sft r1, r1, #swp + bl uart_sendbyte + ldub r1, r3 + sft r1, r1, #swp + bl uart_sendbyte + sft r1, r1, #swp + bl uart_sendbyte + ldub r1, r4 + sft r1, r1, #swp + bl uart_sendbyte + sft r1, r1, #swp + bl uart_sendbyte + ldub r1, r5 + sft r1, r1, #swp + bl uart_sendbyte + sft r1, r1, #swp + bl uart_sendbyte + ldub r1, r6 + sft r1, r1, #swp + bl uart_sendbyte + sft r1, r1, #swp + bl uart_sendbyte + ldil r1, #34 ;'"' + bl uart_sendbyte + bl uart_linebreak + + ; print checksum + ldil r2, low[string_checksum] + ldih r2, high[string_checksum] + bl uart_print + ldub r4, r7 ; print computed checksum + bl print_hex_string0 + + ; some final line breaks +start_image_no_text: + bl uart_linebreak + bl uart_linebreak + + clr r0 ; ZERO! + + ; re-init MSR + sbr r3, r0, #14 ; prv_sys_mode + sbr r3, r3, #15 ; sys_mode + stsr r3 + + ; clear alive LED + mcr #1, com0_core, r0, #7 ; set system output + + ; set mmu pages, address: 0x0000 + mcr #1, sys1_core, r0, #0 + mcr #1, sys1_core, r0, #3 + mcr #1, sys1_core, r0, #4 + mcr #1, sys1_core, r0, #2 ; d-page - set first + mcr #1, sys1_core, r0, #1 ; i-page + gt r0 ; start image at 0x0000 & 0x0000 + + +; ----------------------------------------------------------------------------------- +; RAM page dump via console +; ----------------------------------------------------------------------------------- +mem_dump: ldil r2, low[string_edpage] + ldih r2, high[string_edpage] + bl uart_print + + ; get d-page + bl receive_hex_word + + ; wait for enter/abort +mem_dump_wait: + bl uart_receivebyte + ldil r1, #0x0D ; CR - enter + cmp r0, r1 + beq mem_dump_continue + ldil r1, #0x08 ; Backspace - abort + cmp r0, r1 + bne mem_dump_wait + bl uart_linebreak + b console_input_ ; restart terminal prompt + +mem_dump_continue: + mcr #1, sys1_core, r4, #2 ; set d-page + bl uart_linebreak + + ; hex word loop + ldil r5, #0x00 ; reset byte counter +mem_dump_loop: + ; display address? + ldil r0, #0x0F + ands r0, r5, r0 + bne mem_dump_loop_2 + + ; display! + bl uart_linebreak + ldil r1, #36 ; '$' + bl uart_sendbyte + mov r4, r5 + bl print_hex_string ; print 4hex address + ldil r1, #58 ; ':' + bl uart_sendbyte + ldil r1, #32 ; ' ' + bl uart_sendbyte + +mem_dump_loop_2: + ldr r4, r5, +#2, post, ! ; get one word + + ; display hex data + ldil r1, #32 ; ' ' + bl uart_sendbyte + bl print_hex_string ; print 4hex data + + ; print ASCII data? + ldil r0, #0x0F + ands r0, r5, r0 + bne mem_dump_loop_3 + + ; display! + ldil r1, #32 ; ' ' + bl uart_sendbyte + bl uart_sendbyte + ldil r0, #16 + sub r4, r5, r0 + ldil r0, #0xF0 + and r4, r4, r0 +mem_dump_ascii: + ldr r1, r4, +#1, post, ! ; get one byte + sft r1, r1, #swp + ldih r1, #0x00 ; clear high byte + ldil r0, #32 ; ' ' + cmp r1, r0 ; is ASCII command? + bls #+2 + ldil r1, #46 ; '.' + bl uart_sendbyte + ldil r1, #0x0F + and r0, r1, r4 + teq r0, r1 + bne mem_dump_ascii + + ; user console interrupt? +mem_dump_loop_3: + mrc #1, r0, com0_core, #0 ; get uart RTX register + stb r0, #15 ; copy uart rx_ready flag to T-flag + bts mem_dump_end + + ; check pointer + ldil r3, #0xFE ; last address + teq r3, r5 + bne mem_dump_loop + +mem_dump_end: + bl uart_receivebyte ; wait for enter + clr r0 + gt r0 ; restart bootloader + + +; ----------------------------------------------------------------------------------- +; Intermediate Brach Stops - Stop 0 +; ----------------------------------------------------------------------------------- +spi_eeprom_read_byte_: b spi_eeprom_read_byte0 +print_hex_string0: b print_hex_string + + +; ----------------------------------------------------------------------------------- +; Burn SPI EEPROM +; ----------------------------------------------------------------------------------- +burn_eeprom: + ; disable write protection + ldil r0, #1 ; CS0 + mcr #1, com0_core, r0, #4 ; set CS + ldil r0, 0b01010000 ; UART EN, auto CS, MSB first, mode 0 + ldih r0, 0b00111111 ; prsc 3, length = 16 bit + mcr #1, com0_core, r0, #2 ; SPI config + + ldil r0, #0x00 + ldih r0, #0x01 ; write status reg + bl spi_trans ; iniatiate transmission + + ; we are ready! - waiting for image data... + ldil r2, low[string_prog_eep] + ldih r2, high[string_prog_eep] + bl uart_print_br + ldil r2, low[string_boot_wimd] + ldih r2, high[string_boot_wimd] + bl uart_print_br + + ; get signature + bl uart_receivebyte ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte ; get low-byte + orr r0, r1, r0 ; construct word + ldil r1, #0xFE + ldih r1, #0xCA + cmp r0, r1 + bne signature_err + + ; write signature (2 bytes) + ldil r2, #0 + ldil r3, #0xCA + bl spi_eeprom_write_byte + ldil r2, #1 + ldil r3, #0xFE + bl spi_eeprom_write_byte + + ; get image size + bl uart_receivebyte ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte ; get low-byte + orr r5, r1, r0 ; construct word + sft r5, r5, #lsl ; #bytes = 2*#words + stub r0, r5 + + ; write image size (2 bytes) + ldil r2, #2 + sft r3, r5, #swp + bl spi_eeprom_write_byte + ldil r2, #3 + mov r3, r5 + bl spi_eeprom_write_byte + + ; get checksum + bl uart_receivebyte ; get high-byte + sft r1, r0, #swp ; swap bytes + bl uart_receivebyte ; get low-byte + orr r5, r1, r0 ; construct word + stub r1, r5 + + ; write checksum (2 bytes) + ldil r2, #4 + sft r3, r5, #swp + bl spi_eeprom_write_byte + ldil r2, #5 + mov r3, r5 + bl spi_eeprom_write_byte + + ; write image name (10 bytes) + ldil r2, #6 ; base address +burn_eeprom_image_name: + bl uart_receivebyte ; get byte + mov r3, r0 + bl spi_eeprom_write_byte + inc r2, r2, #1 + ldil r0, #16 ; end address + cmp r2, r0 + bne burn_eeprom_image_name + + ; write image data + ldil r2, #16 ; base address + clr r5 ; byte counter +burn_eeprom_image_data: + bl uart_receivebyte ; get byte + mov r3, r0 + bl spi_eeprom_write_byte + inc r2, r2, #1 + ldub r0, r0 ; get absolute size + inc r5, r5, #1 + cmp r5, r0 + bne burn_eeprom_image_data + + ; set global write protection + ldil r0, #1 ; CS0 + mcr #1, com0_core, r0, #4 ; set CS + ldil r0, 0b01010000 ; UART EN, auto CS, MSB first, mode 0 + ldih r0, 0b00111111 ; prsc 3, length = 16 bit + mcr #1, com0_core, r0, #2 ; SPI config + + ldil r0, #0x0C ; protect all + ldih r0, #0x01 ; status reg write + bl spi_trans ; iniatiate transmission + + ; we are done! + ldil r2, low[string_done] + ldih r2, high[string_done] + bl uart_print_br + + ; return to main console + ldil r5, low[start_console] + ldih r5, high[start_console] + gt r5 + + +; ----------------------------------------------------------------------------------- +; Signature error +; ----------------------------------------------------------------------------------- +signature_err: + ldil r2, low[string_err_image] + ldih r2, high[string_err_image] + bl uart_print_br + ldil r2, low[string_err_res] + ldih r2, high[string_err_res] + bl uart_print_br + bl uart_receivebyte + clr r0 + gt r0 ; restart + + +; ***************************************************************************************************************** +; Communication subroutines +; ***************************************************************************************************************** + +; ----------------------------------------------------------------------------------- +; Intermediate Brach Stops +; ----------------------------------------------------------------------------------- +spi_eeprom_read_byte0: b spi_eeprom_read_byte + + +; -------------------------------------------------------------------------------------------------------- +; Print char-string (bytes) via CP0.COM_0.UART and send linebreak +; Arguments: r2 = address of string (string must be zero-terminated!) +; Results: - +; Used registers: r0, r1, r2, r3, r4, lr +uart_print_br: +; -------------------------------------------------------------------------------------------------------- + ldil r3, #0xFF + mov r4, lr + b uart_print_loop + + +; -------------------------------------------------------------------------------------------------------- +; Print char-string (bytes) via CP0.COM_0.UART +; Arguments: r2 = address of string (string must be zero-terminated!) +; Results: - +; Used registers: r0, r1, r2, r3, r4, lr +uart_print: +; -------------------------------------------------------------------------------------------------------- + clr r3 + mov r4, lr + +uart_print_loop: + ldr r0, r2, +#1, post, ! ; get one string byte + ldil r1, #0x00 ; upper byte mask + ldih r1, #0xFF + and r1, r0, r1 + sfts r1, r1, #swp ; swap bytes and test if zero + beq uart_print_loop_end + bl uart_sendbyte + b uart_print_loop + +uart_print_loop_end: + mov lr, r4 + teq r3, r3 ; do linebreak? + rbaeq lr +; b uart_linebreak + + +; -------------------------------------------------------------------------------------------------------- +; Print linebreak +; Arguments: - +; Results: - +; Used registers: r0, r1, r2, lr +uart_linebreak: +; -------------------------------------------------------------------------------------------------------- + mov r2, lr + ldil r1, #0x0D ; carriage return + bl uart_sendbyte + ldil r1, #0x0A ; line feed + mov lr, r2 +; b uart_sendbyte + + +; -------------------------------------------------------------------------------------------------------- +; Print char (byte) via CP0.COM_0.UART +; Arguments: r1 = char (low byte) +; Results: - +; Used registers: r0, r1 +uart_sendbyte: +; -------------------------------------------------------------------------------------------------------- + mrc #1, r0, com0_core, #2 ; get com control register + stb r0, #5 ; copy uart tx_busy flag to T-flag + bts uart_sendbyte ; still set, keep on waiting + mcr #1, com0_core, r1, #0 ; send data + ret lr + + +; -------------------------------------------------------------------------------------------------------- +; Receive a byte via CP0.COM_0.UART +; Arguments: - +; Results: r0 (low byte) +; Used registers: r0 +uart_receivebyte: +; -------------------------------------------------------------------------------------------------------- + mrc #1, r0, com0_core, #0 ; get uart status/data register + stbi r0, #15 ; copy inverted uart rx_ready flag to T-flag + bts uart_receivebyte ; nothing received, keep on waiting + ldih r0, #0x00 ; clear upper byte + ret lr + + +; -------------------------------------------------------------------------------------------------------- +; Reads 16 bit data as 4x hex chars via UART (and echo them) +; Arguments: - +; Results: +; r4 = data +; Used registers: r0, r1, r2, r3, r4, lr +receive_hex_word: +; -------------------------------------------------------------------------------------------------------- + mov r2, lr ; backup link regsiter + ldil r4, #0 ; clear data register + ldil r3, #4 ; number of chars + +receive_hex_word_loop: + bl uart_receivebyte ; get one char + + ; convert to higher case + ldil r1, #'F' + cmp r0, r1 + bmi #+3 ; skip decrement + ldil r1, #32 ; -> to lower case + sub r0, r0, r1 + + ; is valid? + ldil r1, #'0' + cmp r0, r1 + bmi receive_hex_word_loop ; if less than '0' + + ldil r1, #'F' + cmp r1, r0 + bmi receive_hex_word_loop ; if higher than 'F' + + ldil r1, #'9' + cmp r1, r0 + bls receive_hex_word_echo ; if less than '9' + + ldil r1, #'A' + cmp r0, r1 + bhi receive_hex_word_loop ; if less than 'A' + + ; echo char +receive_hex_word_echo: + mov r1, r0 + bl uart_sendbyte + + ; do conversion + ldil r0, #'0' + sub r1, r1, r0 + ldil r0, #9 + cmp r0, r1 + bls #+2 ; '0'..'9' -> ok + dec r1, r1, #7 ; 'A' - '0' - 10 = 7 -> 'A'..'F' -> ok + + ; save conversion data + sft r4, r4, #rol + sft r4, r4, #rol + sft r4, r4, #rol + sft r4, r4, #rol + orr r4, r4, r1 + + ; loop controller + decs r3, r3, #1 + bne receive_hex_word_loop + + ret r2 ; return + + +; -------------------------------------------------------------------------------------------------------- +; Prints 16bit data as 4x char hex value +; Arguments: +; r4 = data +; Results: - +; Used registers: r0, r1, r2, r3, r4, r6, lr +print_hex_string: +; -------------------------------------------------------------------------------------------------------- + mov r6, lr ; backup link regiiter + + ; char 3 + sft r2, r4, #rol + sft r2, r2, #rol + sft r2, r2, #rol + sft r2, r2, #rol + bl conv_hex_comp + bl uart_sendbyte + + ; char 2 + sft r2, r4, #swp + bl conv_hex_comp + bl uart_sendbyte + + ; char 1 + sft r2, r4, #lsr + sft r2, r2, #lsr + sft r2, r2, #lsr + sft r2, r2, #lsr + bl conv_hex_comp + bl uart_sendbyte + + ; char 0 + mov r2, r4 + bl conv_hex_comp + bl uart_sendbyte + + ret r6 + +; compute hex-char from 4-bit value of r2, result in r1 +conv_hex_comp: ldil r1, #0x0f ; mask for lowest 4 bit + and r2, r2, r1 + + ldil r1, #9 + cmp r1, r2 + bcs #+3 + + ldil r1, #48 ; this is a '0' + b #+2 + ldil r1, #55 ; this is an 'A'-10 + add r1, r1, r2 ; resulting char in lower byte + ret lr + + +; -------------------------------------------------------------------------------------------------------- +; Starts SPI transmission and waits for transmission to finish +; Arguments: +; r0 = TX data +; Results: +; r0 = RX data +; Used registers: r0 +spi_trans: +; -------------------------------------------------------------------------------------------------------- + mcr #1, com0_core, r0, #3 ; set SPI data - start transfer + + ; wait for end + mrc #1, r0, com0_core, #2 ; get status reg + stb r0, #3 ; busy flag + bts #-2 ; still set? + + mrc #1, r0, com0_core, #3 ; get received data + + ret lr + + +; -------------------------------------------------------------------------------------------------------- +; Writes 1 byte to serial EEPROM @ CS0 +; Arguments: +; r2 = Address word +; r3 = Data byte (low part) +; Results: - +; Used registers: r0, r1, r2, r3, lr +spi_eeprom_write_byte: +; -------------------------------------------------------------------------------------------------------- + mov r1, lr ; save link register + + ; set write-enable latch + ; ------------------------------------------- + ldil r0, 0b01010000 ; UART EN, auto CS, MSB first, mode 0 + ldih r0, 0b00110111 ; prsc 3, length = 8 bit + mcr #1, com0_core, r0, #2 ; SPI config + ldil r0, #1 ; CS0 + mcr #1, com0_core, r0, #4 ; config CS + ldil r0, #0x06 ; write enable command + bl spi_trans ; iniatiate transmission + + ; check status reg + ; ------------------------------------------- + ldil r0, 0b01010000 ; UART EN, auto CS, MSB first, mode 0 + ldih r0, 0b00111111 ; prsc 3, length = 16 bit + mcr #1, com0_core, r0, #2 ; SPI config + ldil r0, #0x00 + ldih r0, #0x05 ; read SREG command + bl spi_trans ; iniatiate transmission + + ; check WIP flag + stb r0, #1 ; WEL flag + bts spi_eeprom_write + + ; EEPROM ACCESS ERROR! + ldil r2, low[string_err_eep] + ldih r2, high[string_err_eep] + bl uart_print_br + ldil r2, low[string_err_res] + ldih r2, high[string_err_res] + bl uart_print_br + bl uart_receivebyte + clr r0 + gt r0 ; restart + +spi_eeprom_write: + ; send write instruction and + ; high address byte (16 bit trans) + ; ------------------------------------------- + ldil r0, 0b01000000 ; UART EN, manual CS, MSB first, mode 0 + ldih r0, 0b00111111 ; prsc 3, length = 16 bit + mcr #1, com0_core, r0, #2 ; SPI config + + ldil r0, #1 ; CS0 + mcr #1, com0_core, r0, #4 ; pre-assert CS + + sft r0, r2, #swp ; swap high address byte to low byte + ldih r0, #0x02 ; write command + bl spi_trans ; iniatiate transmission + + ; send low address byte and + ; send data byte (16 bit trans) + ; ------------------------------------------- + mov lr, r2 ; copy address + ldih lr, #0x00 ; clear high part + sft lr, lr, #swp ; swap bytes + mov r0, r3 ; copy data byte + ldih r0, #0x00 ; clear high data byte + orr r0, r0, lr ; merge low address and data byte + bl spi_trans ; iniatiate transmission + + clr r0 + mcr #1, com0_core, r0, #4 ; de-assert CS + + ; wait for write command to finish + ; 16 bit transfer + ; ------------------------------------------- + ldil r0, 0b01010000 ; UART EN, auto CS, MSB first, mode 0 + ldih r0, 0b00111111 ; prsc 3, length = 16 bit + mcr #1, com0_core, r0, #2 ; SPI config + ldil r0, #1 ; CS0 + mcr #1, com0_core, r0, #4 ; set CS + +spi_eeprom_write_byte_bsy: + ldil r0, #0x00 + ldih r0, #0x05 ; read SREG command + bl spi_trans ; iniatiate transmission + + ; check WIP flag + stb r0, #0 ; WIP flag + bts spi_eeprom_write_byte_bsy + + ret r1 + + +; -------------------------------------------------------------------------------------------------------- +; Reads 1 byte from serial EEPROM @ CS0 +; Arguments: +; r2 = Address word +; Results: +; r3 = Data byte (low part) +; Used registers: r0, r1, r2, r3, lr +spi_eeprom_read_byte: +; -------------------------------------------------------------------------------------------------------- + mov r1, lr ; save link register + + ; config SPI + ldil r0, 0b01000000 ; UART EN, manual CS, MSB first, mode 0 + ldih r0, 0b00111111 ; prsc 3, length = 16 bit + mcr #1, com0_core, r0, #2 ; SPI config + ldil r0, #1 ; CS0 + mcr #1, com0_core, r0, #4 ; pre-assert CS + + ; send read instruction and + ; high address (16 bit trans) + ; ------------------------------------------- + sft r0, r2, #swp ; swap high address byte to low byte + ldih r0, #0x03 ; read command + bl spi_trans ; iniatiate transmission + + ; send low address byte and + ; read data byte (16 bit trans) + ; ------------------------------------------- + mov r0, r2 ; copy address + ldih r0, #0x00 ; data tranfer dummy + sft r0, r0, #swp ; swap data and address bytes + bl spi_trans ; iniatiate transmission + + clr r3 + mcr #1, com0_core, r3, #4 ; deassert CS + mov r3, r0 + ldih r3, #0x00 ; clear high byte + + ret r1 + + +; ***************************************************************************************************************** +; ROM: Text strings +; ***************************************************************************************************************** + +string_intro0: .stringz "ATLAS-2K Bootloader - Version 2014.03.08" +string_intro1: .stringz "by Stephan Nolting, stnolting@gmail.com" +string_intro2: .stringz "www.opencores.org/project,atlas_core" +string_intro3: .stringz "Bootloader start: 0x" +string_intro4: .stringz "Clock speed (Hz): 0x" + +string_boot_spi: .stringz "Booting from SPI EEPROM" +string_boot_uart: .stringz "Booting from UART" +string_prog_eep: .stringz "Burning EEPROM" +string_boot_wimd: .stringz "Waiting for image data..." +string_boot_mem: .stringz "Booting from memory..." +string_start_im: .stringz "Starting image " +string_done: .stringz "Download completed!" +string_edpage: .stringz "Enter page (4hex): 0x" +string_checksum: .stringz "Checksum: 0x" + +string_menu_hd: .stringz "Command/boot switch" +string_menu0: .stringz " 0/'00': Restart console" +string_menu1: .stringz " 1/'01': Boot from UART" +string_menu2: .stringz " 2/'10': Boot from EEPROM" +string_menu3: .stringz " 3/'11': Boot from memory" +string_menup: .stringz " p: Program EEPROM" +string_menud: .stringz " d: RAM dump" +string_menur: .stringz " r: Reset" +string_menux: .stringz "cmd:> " + +string_err_image: .stringz "IMAGE ERROR!" +string_err_irq: .stringz "IRQ ERROR!" +string_err_check: .stringz "CHECKSUM ERROR!" +string_err_eep: .stringz "SPI/EEPROM ERROR!" +string_err_res: .stringz "Press any key" Index: trunk/software/examples/demo.asm =================================================================== --- trunk/software/examples/demo.asm (nonexistent) +++ trunk/software/examples/demo.asm (revision 21) @@ -0,0 +1,48 @@ +; ************************************************************************************************************** +; DEMO - Simple blink test +; ************************************************************************************************************** + +.equ lr r7 ; link register + +.equ sys0_core c0 +.equ sys1_core c1 +.equ com0_core c2 + + +; ************************************************************************************************************** +; Exception Vector Table +; ************************************************************************************************************** + +reset_vec: b reset +x_int0_vec: b x_int0_vec ; freeze +x_int1_vec: b x_int1_vec ; freeze +cmd_err_vec: b cmd_err_vec ; freeze +swi_vec: b swi_vec ; freeze + + +; ************************************************************************************************************** +; Main Program +; ************************************************************************************************************** +reset: clr r0 + mcr #1, com0_core, r0, #7 ; clear system output +forever: + ldil r5, #50 + bl delay ; wait some time + + mcr #1, com0_core, r0, #7 ; read system output + sft r0, r0, #swp ; swap bytes + inc r0, r0, #1 ; increment + ldil r1, #0x0F + and r0, r0, r1 ; apply 4-bit mask + sft r0, r0, #swp ; swap bytes again + mcr #1, com0_core, r0, #7 ; set system output + + b forever ; repeat forever + +; wait subroutine +delay: ldil r6, #0xff + decs r6, r6, #1 + bne #-1 + decs r5, r5, #1 + bne delay + ret lr Index: trunk/software/examples/random_numbers.asm =================================================================== --- trunk/software/examples/random_numbers.asm (nonexistent) +++ trunk/software/examples/random_numbers.asm (revision 21) @@ -0,0 +1,301 @@ +; ************************************************************************************************************** +; Print Random Numbers - LFSR Test +; +; Print random hex numbers from the LFSR via UART +; Uses BAUD rate from bootloader config!!! +; ************************************************************************************************************** + + +; ************************************************************************************************************** +; Defintions +; ************************************************************************************************************** + +.equ sys0_core c0 +.equ com0_core c2 +.equ lr r7 ; link register + + +; ************************************************************************************************************** +; Exception Vector Table +; ************************************************************************************************************** + +reset_vec: b reset +x_int0_vec: b err_handler +x_int1_vec: b err_handler +cmd_err_vec: b err_handler +swi_vec: b err_handler + + +; ************************************************************************************************************** +; IRQ/SWI/CMD_ERR: Terminate +; ************************************************************************************************************** + +err_handler: bl uart_linebreak + ldil r2, low[err_string] + ldih r2, high[err_string] + bl uart_print + bl uart_linebreak + b #+0 ; freeze + + +; ************************************************************************************************************** +; Main Program +; ************************************************************************************************************** + +reset: ; print intro + ldil r2, low[string_intro] + ldih r2, high[string_intro] + bl uart_print_br + +restart: ; get seed + ldil r2, low[string_seed] + ldih r2, high[string_seed] + bl uart_print + bl receive_hex_word + mcr #1, sys0_core, r4, #5 ; set lfsr data register + bl uart_linebreak + + ; get taps + ldil r2, low[string_taps] + ldih r2, high[string_taps] + bl uart_print + bl receive_hex_word + cbr r4, r4, #15 ; new value after read access + mcr #1, sys0_core, r4, #6 ; set lfsr polynomial register + bl uart_linebreak + + ; read and print hex random numbers +forever: ldil r1, #'0' + bl uart_sendbyte + ldil r1, #'x' + bl uart_sendbyte + + ; get and print + mrc #1, r4, sys0_core, #5 ; get lfsr data + bl print_hex_string + bl uart_linebreak + + ; user console interrupt? + mrc #1, r0, com0_core, #0 ; get uart RTX register + stb r0, #15 ; copy uart rx_ready flag to T-flag + bts restart + + ; repeat forever + b forever + + +; ************************************************************************************************************** +; Communication Subroutines +; ************************************************************************************************************** + + +; -------------------------------------------------------------------------------------------------------- +; Print char-string (bytes) via CP0.COM_0.UART and send linebreak +; Arguments: r2 = address of string (string must be zero-terminated!) +; Results: - +; Used registers: r0, r1, r2, r3, r4, lr +uart_print_br: +; -------------------------------------------------------------------------------------------------------- + ldil r3, #0xFF + mov r4, lr + b uart_print_loop + + +; -------------------------------------------------------------------------------------------------------- +; Print char-string (bytes) via CP0.COM_0.UART +; Arguments: r2 = address of string (string must be zero-terminated!) +; Results: - +; Used registers: r0, r1, r2, r3, r4, lr +uart_print: +; -------------------------------------------------------------------------------------------------------- + clr r3 + mov r4, lr + +uart_print_loop: + ldr r0, r2, +#1, post, ! ; get one string byte + ldil r1, #0x00 ; upper byte mask + ldih r1, #0xFF + and r1, r0, r1 + sfts r1, r1, #swp ; swap bytes and test if zero + beq uart_print_loop_end + bl uart_sendbyte + b uart_print_loop + +uart_print_loop_end: + mov lr, r4 + teq r3, r3 ; do linebreak? + rbaeq lr +; b uart_linebreak + + +; -------------------------------------------------------------------------------------------------------- +; Print linebreak +; Arguments: - +; Results: - +; Used registers: r0, r1, r2, lr +uart_linebreak: +; -------------------------------------------------------------------------------------------------------- + mov r2, lr + ldil r1, #0x0D ; carriage return + bl uart_sendbyte + ldil r1, #0x0A ; line feed + mov lr, r2 +; b uart_sendbyte + + +; -------------------------------------------------------------------------------------------------------- +; Print char (byte) via CP0.COM_0.UART +; Arguments: r1 = char (low byte) +; Results: - +; Used registers: r0, r1 +uart_sendbyte: +; -------------------------------------------------------------------------------------------------------- + mrc #1, r0, com0_core, #2 ; get com control register + stb r0, #5 ; copy uart tx_busy flag to T-flag + bts uart_sendbyte ; still set, keep on waiting + mcr #1, com0_core, r1, #0 ; send data + ret lr + + +; -------------------------------------------------------------------------------------------------------- +; Receive a byte via CP0.COM_0.UART +; Arguments: - +; Results: r0 (low byte) +; Used registers: r0 +uart_receivebyte: +; -------------------------------------------------------------------------------------------------------- + mrc #1, r0, com0_core, #0 ; get uart status/data register + stbi r0, #15 ; copy inverted uart rx_ready flag to T-flag + bts uart_receivebyte ; nothing received, keep on waiting + ldih r0, #0x00 ; clear upper byte + ret lr + + +; -------------------------------------------------------------------------------------------------------- +; Reads 16 bit data as 4x hex chars via UART (+ECHO) +; Arguments: - +; Results: +; r4 = data +; Used registers: r0, r1, r2, r3, r4, lr +receive_hex_word: +; -------------------------------------------------------------------------------------------------------- + mov r2, lr ; backup link regsiter + ldil r4, #0 ; clear data register + ldil r3, #4 ; number of chars + +receive_hex_word_loop: + bl uart_receivebyte ; get one char + + ; convert to higher case + ldil r1, #'F' + cmp r0, r1 + bmi #+3 ; skip decrement + ldil r1, #32 ; -> to lower case + sub r0, r0, r1 + + ; is valid? + ldil r1, #'0' + cmp r0, r1 + bmi receive_hex_word_loop ; if less than '0' + + ldil r1, #'F' + cmp r1, r0 + bmi receive_hex_word_loop ; if higher than 'F' + + ldil r1, #'9' + cmp r1, r0 + bls receive_hex_word_echo ; if less than '9' + + ldil r1, #'A' + cmp r0, r1 + bhi receive_hex_word_loop ; if less than 'A' + + ; echo char +receive_hex_word_echo: + mov r1, r0 + bl uart_sendbyte + + ; do conversion + ldil r0, #'0' + sub r1, r1, r0 + ldil r0, #9 + cmp r0, r1 + bls #+2 ; 0..9 -> ok + dec r1, r1, #7 ; 'A' - '0' - 10 = 7 -> A..F -> ok + + ; save conversion data + sft r4, r4, #rol + sft r4, r4, #rol + sft r4, r4, #rol + sft r4, r4, #rol + orr r4, r4, r1 + + ; loop controller + decs r3, r3, #1 + bne receive_hex_word_loop + + ret r2 ; return + + +; -------------------------------------------------------------------------------------------------------- +; Prints 16bit data as 4x char hex value +; Arguments: +; r4 = data +; Results: - +; Used registers: r0, r1, r2, r3, r4, r6, lr +print_hex_string: +; -------------------------------------------------------------------------------------------------------- + mov r6, lr ; backup link regiiter + + ; char 3 + sft r2, r4, #rol + sft r2, r2, #rol + sft r2, r2, #rol + sft r2, r2, #rol + bl conv_hex_comp + bl uart_sendbyte + + ; char 2 + sft r2, r4, #swp + bl conv_hex_comp + bl uart_sendbyte + + ; char 1 + sft r2, r4, #lsr + sft r2, r2, #lsr + sft r2, r2, #lsr + sft r2, r2, #lsr + bl conv_hex_comp + bl uart_sendbyte + + ; char 0 + mov r2, r4 + bl conv_hex_comp + bl uart_sendbyte + + ret r6 + +; compute hex-char from 4-bit value of r2, result in r1 +conv_hex_comp: ldil r1, #0x0f ; mask for lowest 4 bit + and r2, r2, r1 + + ldil r1, #9 + cmp r1, r2 + bcs #+3 + + ldil r1, #48 ; this is a '0' + b #+2 + ldil r1, #55 ; this is an 'A'-10 + add r1, r1, r2 ; resulting char in lower byte + ret lr + + +; ************************************************************************************************************** +; Constants +; ************************************************************************************************************** + +; -- strings -- +err_string: .stringz "Exception/interrupt error!" +string_intro: .stringz "Random Number Generator" +string_seed: .stringz "Enter LFSR seed (4hex): 0x" +string_taps: .stringz "Enter LFSR taps (4hex): 0x" Index: trunk/software/examples/test.asm =================================================================== --- trunk/software/examples/test.asm (nonexistent) +++ trunk/software/examples/test.asm (revision 21) @@ -0,0 +1,141 @@ +; ------------------------------------------------------------------------------------------------- +; ATLAS ASSEMBLER test/example program file +; ------------------------------------------------------------------------------------------------- + +; -> 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 +cmd_err_vec: b cmd_err_vec ; undefined instruction / illegal msr/reg/cp access +swi_vec: b swi_handler ; software interrupt exception handler + + +; Exception handlers (system mode) +; ------------------------------------------------------------------------------------------------- +swi_handler: ; SOFTWARE INTERRUPT 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: ; EXTERNAL INTERRUPT 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 ; copy machine status register to r1 + sbr r1, r1, msr_xint0_en ; enable external interrupt 0 mask, no '#'-prefix when using a constant definition! + stsr r1 ; store r1 to machine status register + + gtui 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 + + ldil data, #0xAB ; hex init + ldil data, #0b11001100 ; bin init + 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 +.stringz "This is a zero-terminated character string" + +.include "other_stuff.asm" ; include (AT THIS POINT) the file "other_stuff.asm"

powered by: WebSVN 2.1.0

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