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/trunk
- from Rev 20 to Rev 21
- ↔ Reverse comparison
Rev 20 → Rev 21
/asm/atlas_asm.exe
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
asm/atlas_asm.exe
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: asm/src/atlas_asm.layout
===================================================================
--- asm/src/atlas_asm.layout (nonexistent)
+++ 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: asm/src/atlas_asm.dev
===================================================================
--- asm/src/atlas_asm.dev (nonexistent)
+++ 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: asm/src/job.xasm
===================================================================
--- asm/src/job.xasm (nonexistent)
+++ 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: asm/src/main.cpp
===================================================================
--- asm/src/main.cpp (nonexistent)
+++ 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: asm/src/Makefile.win
===================================================================
--- asm/src/Makefile.win (nonexistent)
+++ 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: asm/src/included.xasm
===================================================================
--- asm/src/included.xasm (nonexistent)
+++ 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: rtl/BOOT_MEM.vhd
===================================================================
--- rtl/BOOT_MEM.vhd (nonexistent)
+++ 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: rtl/CTRL.vhd
===================================================================
--- rtl/CTRL.vhd (nonexistent)
+++ 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: rtl/ATLAS_pkg.vhd
===================================================================
--- rtl/ATLAS_pkg.vhd (nonexistent)
+++ 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: rtl/COM_0_CORE.vhd
===================================================================
--- rtl/COM_0_CORE.vhd (nonexistent)
+++ 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: rtl/SYS_0_CORE.vhd
===================================================================
--- rtl/SYS_0_CORE.vhd (nonexistent)
+++ 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: rtl/SYS_1_CORE.vhd
===================================================================
--- rtl/SYS_1_CORE.vhd (nonexistent)
+++ 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: rtl/SYSTEM_CP.vhd
===================================================================
--- rtl/SYSTEM_CP.vhd (nonexistent)
+++ 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: rtl/WB_UNIT.vhd
===================================================================
--- rtl/WB_UNIT.vhd (nonexistent)
+++ 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: rtl/ATLAS_CPU.vhd
===================================================================
--- rtl/ATLAS_CPU.vhd (nonexistent)
+++ 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: rtl/SYS_REG.vhd
===================================================================
--- rtl/SYS_REG.vhd (nonexistent)
+++ 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: rtl/REG_FILE.vhd
===================================================================
--- rtl/REG_FILE.vhd (nonexistent)
+++ 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: rtl/ATLAS_2K_BASE_TOP.vhd
===================================================================
--- rtl/ATLAS_2K_BASE_TOP.vhd (nonexistent)
+++ 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: rtl/MEM_GATE.vhd
===================================================================
--- rtl/MEM_GATE.vhd (nonexistent)
+++ 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: rtl/ALU.vhd
===================================================================
--- rtl/ALU.vhd (nonexistent)
+++ 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: rtl/ATLAS_2K_TOP.vhd
===================================================================
--- rtl/ATLAS_2K_TOP.vhd (nonexistent)
+++ 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: rtl/MEM_ACC.vhd
===================================================================
--- rtl/MEM_ACC.vhd (nonexistent)
+++ 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: rtl/OP_DEC.vhd
===================================================================
--- rtl/OP_DEC.vhd (nonexistent)
+++ 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: rtl/INT_RAM.vhd
===================================================================
--- rtl/INT_RAM.vhd (nonexistent)
+++ 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: doc/Atlas 2k Processor Documentary.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: doc/Atlas 2k Processor Documentary.pdf
===================================================================
--- doc/Atlas 2k Processor Documentary.pdf (nonexistent)
+++ doc/Atlas 2k Processor Documentary.pdf (revision 21)
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: sim/atlas_2k_base_tb.vhd
===================================================================
--- sim/atlas_2k_base_tb.vhd (nonexistent)
+++ 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: sim/xilinx_isim_atlas_2k_base_tb_wave.wcfg
===================================================================
--- sim/xilinx_isim_atlas_2k_base_tb_wave.wcfg (nonexistent)
+++ 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: software/bootloader/atlas2k_bootloader.asm
===================================================================
--- software/bootloader/atlas2k_bootloader.asm (nonexistent)
+++ 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: software/examples/demo.asm
===================================================================
--- software/examples/demo.asm (nonexistent)
+++ 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: software/examples/random_numbers.asm
===================================================================
--- software/examples/random_numbers.asm (nonexistent)
+++ 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: software/examples/test.asm
===================================================================
--- software/examples/test.asm (nonexistent)
+++ 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"