/* Symbol Table */ // CRC_send_loop = LABEL: 128 // ISR = LABEL: 997 // ISR_preserve_s0 = CONSTANT: 0 // LCD_DB4 = CONSTANT: 16 // LCD_DB5 = CONSTANT: 32 // LCD_DB6 = CONSTANT: 64 // LCD_DB7 = CONSTANT: 128 // LCD_E = CONSTANT: 1 // LCD_RS = CONSTANT: 4 // LCD_RW = CONSTANT: 2 // LCD_clear = LABEL: 825 // LCD_cursor = LABEL: 830 // LCD_drive = CONSTANT: 8 // LCD_input_port = CONSTANT: 3 // LCD_output_port = CONSTANT: 32 // LCD_pulse_E = LABEL: 741 // LCD_read_DB4 = CONSTANT: 16 // LCD_read_DB5 = CONSTANT: 32 // LCD_read_DB6 = CONSTANT: 64 // LCD_read_DB7 = CONSTANT: 128 // LCD_read_data8 = LABEL: 783 // LCD_read_spare0 = CONSTANT: 1 // LCD_read_spare1 = CONSTANT: 2 // LCD_read_spare2 = CONSTANT: 4 // LCD_read_spare3 = CONSTANT: 8 // LCD_reset = LABEL: 808 // LCD_write_data = LABEL: 766 // LCD_write_inst4 = LABEL: 747 // LCD_write_inst8 = LABEL: 751 // Menu = LABEL: 60 // SF_addr_hi_port = CONSTANT: 131 // SF_addr_lo_port = CONSTANT: 129 // SF_addr_mi_port = CONSTANT: 130 // SF_byte_read = LABEL: 257 // SF_byte_write = LABEL: 267 // SF_ce = CONSTANT: 2 // SF_control_port = CONSTANT: 64 // SF_data_in_port = CONSTANT: 2 // SF_data_out_port = CONSTANT: 128 // SF_erase_block = LABEL: 228 // SF_init = LABEL: 225 // SF_read = CONSTANT: 1 // SF_single_byte_write = LABEL: 236 // SF_we = CONSTANT: 4 // UART_data = REGISTER: 15 // UART_read_port = CONSTANT: 1 // UART_write = LABEL: 295 // UART_write_port = CONSTANT: 8 // auth_byte_loop = LABEL: 180 // auth_check2 = LABEL: 156 // auth_check3 = LABEL: 160 // auth_check4 = LABEL: 164 // auth_failure = LABEL: 54 // auth_line_loop = LABEL: 177 // auth_passed = LABEL: 51 // auth_read_delay = LABEL: 171 // auth_read_loop = LABEL: 151 // auth_write_check2 = LABEL: 200 // auth_write_check3 = LABEL: 206 // auth_write_check4 = LABEL: 212 // auth_write_loop = LABEL: 193 // authentication_CRC0 = CONSTANT: 26 // authentication_CRC1 = CONSTANT: 27 // authentication_control_port = CONSTANT: 16 // authentication_status = CONSTANT: 28 // authorise_command = LABEL: 79 // character_0 = CONSTANT: 48 // character_1 = CONSTANT: 49 // character_2 = CONSTANT: 50 // character_3 = CONSTANT: 51 // character_4 = CONSTANT: 52 // character_5 = CONSTANT: 53 // character_6 = CONSTANT: 54 // character_7 = CONSTANT: 55 // character_8 = CONSTANT: 56 // character_9 = CONSTANT: 57 // character_A = CONSTANT: 65 // character_B = CONSTANT: 66 // character_BS = CONSTANT: 8 // character_C = CONSTANT: 67 // character_CR = CONSTANT: 13 // character_D = CONSTANT: 68 // character_E = CONSTANT: 69 // character_F = CONSTANT: 70 // character_G = CONSTANT: 71 // character_H = CONSTANT: 72 // character_I = CONSTANT: 73 // character_J = CONSTANT: 74 // character_K = CONSTANT: 75 // character_L = CONSTANT: 76 // character_M = CONSTANT: 77 // character_N = CONSTANT: 78 // character_O = CONSTANT: 79 // character_P = CONSTANT: 80 // character_Q = CONSTANT: 81 // character_R = CONSTANT: 82 // character_S = CONSTANT: 83 // character_T = CONSTANT: 84 // character_U = CONSTANT: 85 // character_V = CONSTANT: 86 // character_W = CONSTANT: 87 // character_X = CONSTANT: 88 // character_Y = CONSTANT: 89 // character_Z = CONSTANT: 90 // character_a = CONSTANT: 97 // character_b = CONSTANT: 98 // character_c = CONSTANT: 99 // character_colon = CONSTANT: 58 // character_comma = CONSTANT: 44 // character_d = CONSTANT: 100 // character_divide = CONSTANT: 47 // character_dollar = CONSTANT: 36 // character_e = CONSTANT: 101 // character_equals = CONSTANT: 61 // character_exclaim = CONSTANT: 33 // character_f = CONSTANT: 102 // character_fullstop = CONSTANT: 46 // character_g = CONSTANT: 103 // character_greater_than = CONSTANT: 62 // character_h = CONSTANT: 104 // character_i = CONSTANT: 105 // character_j = CONSTANT: 106 // character_k = CONSTANT: 107 // character_l = CONSTANT: 108 // character_less_than = CONSTANT: 60 // character_m = CONSTANT: 109 // character_minus = CONSTANT: 45 // character_n = CONSTANT: 110 // character_o = CONSTANT: 111 // character_p = CONSTANT: 112 // character_plus = CONSTANT: 43 // character_q = CONSTANT: 113 // character_question = CONSTANT: 63 // character_r = CONSTANT: 114 // character_s = CONSTANT: 115 // character_semi_colon = CONSTANT: 59 // character_space = CONSTANT: 32 // character_t = CONSTANT: 116 // character_u = CONSTANT: 117 // character_v = CONSTANT: 118 // character_w = CONSTANT: 119 // character_x = CONSTANT: 120 // character_y = CONSTANT: 121 // character_z = CONSTANT: 122 // cold_start = LABEL: 0 // compute_CRC16 = LABEL: 134 // compute_seeded_CRC = LABEL: 127 // computed_CRC0 = CONSTANT: 24 // computed_CRC1 = CONSTANT: 25 // crc16_loop = LABEL: 135 // crc16_shift = LABEL: 141 // delay_1ms = LABEL: 849 // delay_1s = LABEL: 859 // delay_1us = LABEL: 840 // delay_1us_constant = CONSTANT: 11 // delay_20ms = LABEL: 854 // delay_40us = LABEL: 844 // delay_Ns = LABEL: 864 // disable_app_hardware = LABEL: 86 // disp_Authentication = LABEL: 937 // disp_FLASH_Serial_No = LABEL: 904 // disp_Failed = LABEL: 982 // disp_Passed = LABEL: 968 // disp_PicoBlaze = LABEL: 868 // disp_SN_loop = LABEL: 119 // disp_Security = LABEL: 887 // disp_hex_byte = LABEL: 333 // disp_serial_number = LABEL: 112 // end_ISR = LABEL: 1016 // end_disp_SN = LABEL: 125 // end_read_SN = LABEL: 255 // end_send_SN = LABEL: 110 // erase_authentication = LABEL: 222 // erase_command = LABEL: 75 // hex_byte_to_ASCII = LABEL: 303 // hex_to_ASCII = LABEL: 315 // link_FIFO_write_port = CONSTANT: 4 // next_auth_read = LABEL: 168 // number_char = LABEL: 318 // pass_token = LABEL: 1010 // random_value_port = CONSTANT: 4 // read_SF_serial_number = LABEL: 242 // read_SN_loop = LABEL: 248 // read_authentication = LABEL: 148 // read_character = LABEL: 289 // read_command = LABEL: 70 // read_from_UART = LABEL: 285 // rx_data_present = CONSTANT: 4 // rx_full = CONSTANT: 16 // rx_half_full = CONSTANT: 8 // s0 = REGISTER: 0 // s1 = REGISTER: 1 // s2 = REGISTER: 2 // s3 = REGISTER: 3 // s4 = REGISTER: 4 // s5 = REGISTER: 5 // s6 = REGISTER: 6 // s7 = REGISTER: 7 // s8 = REGISTER: 8 // s9 = REGISTER: 9 // sA = REGISTER: 10 // sB = REGISTER: 11 // sC = REGISTER: 12 // sD = REGISTER: 13 // sE = REGISTER: 14 // sF = REGISTER: 15 // security_disable_interrupts = CONSTANT: 1 // security_disable_outputs = CONSTANT: 2 // send_Auth = LABEL: 527 // send_Authentication = LABEL: 562 // send_Authoris = LABEL: 536 // send_Authorisation = LABEL: 546 // send_Authorise = LABEL: 558 // send_CR = LABEL: 340 // send_CRC = LABEL: 585 // send_Computed_CRC = LABEL: 594 // send_Copyright = LABEL: 436 // send_Erase = LABEL: 611 // send_Erase_in_progress = LABEL: 623 // send_FAILED = LABEL: 655 // send_FLASH = LABEL: 487 // send_FLASH_CRC = LABEL: 584 // send_FLASH_Serial_Number = LABEL: 498 // send_Menu = LABEL: 700 // send_OK = LABEL: 649 // send_PASSED = LABEL: 669 // send_SN_loop = LABEL: 103 // send_Writing = LABEL: 682 // send_auth_page = LABEL: 174 // send_dash = LABEL: 351 // send_equals = LABEL: 346 // send_hex_3bytes = LABEL: 326 // send_hex_byte = LABEL: 320 // send_serial_number = LABEL: 101 // send_space = LABEL: 343 // send_to_UART = LABEL: 291 // send_welcome = LABEL: 356 // serial_number0 = CONSTANT: 16 // serial_number1 = CONSTANT: 17 // serial_number2 = CONSTANT: 18 // serial_number3 = CONSTANT: 19 // serial_number4 = CONSTANT: 20 // serial_number5 = CONSTANT: 21 // serial_number6 = CONSTANT: 22 // serial_number7 = CONSTANT: 23 // set_SF_read_array_mode = LABEL: 277 // set_line2 = LABEL: 836 // spare1 = CONSTANT: 32 // spare2 = CONSTANT: 64 // status_port = CONSTANT: 0 // strataflash_sts = CONSTANT: 128 // tx_full = CONSTANT: 2 // tx_half_full = CONSTANT: 1 // upper_case = LABEL: 297 // wait_1ms = LABEL: 850 // wait_1s = LABEL: 860 // wait_1us = LABEL: 841 // wait_20ms = LABEL: 855 // wait_40us = LABEL: 845 // wait_SF_ready = LABEL: 280 // warm_start = LABEL: 8 // write_auth = LABEL: 218 // write_authentication = LABEL: 190 /* Program Code */ // #1: ; KCPSM3 Program - Security control and design authentication. // #2: ; // #3: ; This program is provided for use with the reference design // #4: ; 'low_cost_design_authentication_for_spartan_3e.vhd' implemented on the Spartan-3E Starter // #5: ; Kit. The program provides design authentication control over the 'real' application as well // #6: ; as providing features to enable evaluation of the design authentication method. // #7: ; // #8: ; Ken Chapman - Xilinx Ltd // #9: ; // #10: ; Version v1.00 - 1st November 2006 // #11: ; // #12: ; This code communicates with the StrataFLASH memory to implement a design authentication // #13: ; algorithm which then enables the main application design in various ways. To facilitate // #14: ; evaluation of design authentication this design also interacts with the LCD display // #15: ; and PC (via UART based RS232 link) to indicate authentication status and allow control // #16: ; over the authentication validity of the design. Therefore this program includes:- // #17: ; // #18: ; 1) Code required to check authorisation which would be included in a production design. // #19: ; 2) Code required to program the authentication value into FLASH memory which would // #20: ; typically only be implemented in a special design used at a secure programming // #21: ; facility as part of the production programming procedure. // #22: ; 3) Code to allow you to see what is happening at all stages which is code that should // #23: ; never be included in a real production design as it reveals secrets that should remain // #24: ; hidden in order to make the task of breaking the security as difficult as possible. // #25: ; // #26: ; IMPORTANT - Feel free to use this code as a reference for your own security scheme but // #27: ; never use this code unmodified. // #28: ; // #29: ; // #30: ;************************************************************************************** // #31: ; NOTICE: // #32: ; // #33: ; Copyright Xilinx, Inc. 2006. This code may be contain portions patented by other // #34: ; third parties. By providing this core as one possible implementation of a standard, // #35: ; Xilinx is making no representation that the provided implementation of this standard // #36: ; is free from any claims of infringement by any third party. Xilinx expressly // #37: ; disclaims any warranty with respect to the adequacy of the implementation, including // #38: ; but not limited to any warranty or representation that the implementation is free // #39: ; from claims of any third party. Furthermore, Xilinx is providing this core as a // #40: ; courtesy to you and suggests that you contact all third parties to obtain the // #41: ; necessary rights to use this implementation. // #42: ; // #43: ; // #44: ;************************************************************************************** // #45: ; Port definitions // #46: ;************************************************************************************** // #47: ; // #48: ; // #49: ; UART ports // #50: ; // #51: ; Connection to PC to allow display of progress information and to operate simple // #52: ; menu of commands. // #53: ; // #54: CONSTANT(status_port,0) ;UART and memory status // #55: CONSTANT(tx_half_full,1) ; Transmitter half full - bit0 // #56: CONSTANT(tx_full,2) ; FIFO tx_full - bit1 // #57: CONSTANT(rx_data_present,4) ; Receiver data present - bit2 // #58: CONSTANT(rx_half_full,8) ; FIFO half full - bit3 // #59: CONSTANT(rx_full,16) ; rx_full - bit4 // #60: CONSTANT(spare1,32) ; spare '0' - bit5 // #61: CONSTANT(spare2,64) ; spare '0' - bit6 // #62: CONSTANT(strataflash_sts,128) ; StrataFLASH STS - bit7 // #63: ; // #64: CONSTANT(UART_read_port,1) ;UART Rx data input // #65: ; // #66: CONSTANT(UART_write_port,8) ;UART Tx data output // #67: ; // #68: ; // #69: ; LCD Display // #70: ; // #71: ;The master enable signal is not used by the LCD display itself // #72: ;but is used to prevent any contention with the StrataFLASH memory that // #73: ;is connected to the same data pins. In this design the StrataFLASH memory is // #74: ;used in 8-bit mode so not contention should exist but this master enable // #75: ;facilty is then available for anyone wanting to modify the design for use // #76: ;with a 16-bit interface. // #77: ; // #78: CONSTANT(LCD_output_port,32) ;LCD character module output data and control // #79: CONSTANT(LCD_E,1) ; active High Enable E - bit0 // #80: CONSTANT(LCD_RW,2) ; Read=1 Write=0 RW - bit1 // #81: CONSTANT(LCD_RS,4) ; Instruction=0 Data=1 RS - bit2 // #82: CONSTANT(LCD_drive,8) ; Master enable (active High) - bit3 // #83: CONSTANT(LCD_DB4,16) ; 4-bit Data DB4 - bit4 // #84: CONSTANT(LCD_DB5,32) ; interface Data DB5 - bit5 // #85: CONSTANT(LCD_DB6,64) ; Data DB6 - bit6 // #86: CONSTANT(LCD_DB7,128) ; Data DB7 - bit7 // #87: ; // #88: ; // #89: CONSTANT(LCD_input_port,3) ;LCD character module input data // #90: CONSTANT(LCD_read_spare0,1) ; Spare bits - bit0 // #91: CONSTANT(LCD_read_spare1,2) ; are zero - bit1 // #92: CONSTANT(LCD_read_spare2,4) ; - bit2 // #93: CONSTANT(LCD_read_spare3,8) ; - bit3 // #94: CONSTANT(LCD_read_DB4,16) ; 4-bit Data DB4 - bit4 // #95: CONSTANT(LCD_read_DB5,32) ; interface Data DB5 - bit5 // #96: CONSTANT(LCD_read_DB6,64) ; Data DB6 - bit6 // #97: CONSTANT(LCD_read_DB7,128) ; Data DB7 - bit7 // #98: ; // #99: ; // #100: ; // #101: ; StrataFLASH memory ports // #102: ; // #103: ; The FLASH memory is used to hold the authentication value as well as provide the // #104: ; unique serial number from which the authentication algorithm computes the value. // #105: ; In practice, the FLASH will also hold the configuration image for the Spartan device. // #106: ; // #107: ; // #108: CONSTANT(SF_data_in_port,2) ;Read data from StrataFLASH device // #109: ; // #110: CONSTANT(SF_data_out_port,128) ;Data to write into StrataFLASH device // #111: ; // #112: CONSTANT(SF_addr_hi_port,131) ;StrataFLASH address[21:16] (6 LSB's) // #113: CONSTANT(SF_addr_mi_port,130) ;StrataFLASH address[15:8] // #114: CONSTANT(SF_addr_lo_port,129) ;StrataFLASH address[7:0] // #115: ; // #116: CONSTANT(SF_control_port,64) ;StrataFLASH control // #117: CONSTANT(SF_read,1) ; active High read - bit0 // #118: CONSTANT(SF_ce,2) ; active Low device enable - bit1 // #119: CONSTANT(SF_we,4) ; active Low write - bit2 // #120: ; // #121: ; // #122: ; Design Authentication enable/disable signals. // #123: ; // #124: ; Hardware controls over the 'real' application. // #125: ; // #126: CONSTANT(authentication_control_port,16) ;Design disable control port // #127: CONSTANT(security_disable_interrupts,1) ; active High disable of interrupt generation - bit0 // #128: CONSTANT(security_disable_outputs,2) ; active High disable of output pins - bit1 // #129: ; // #130: ; Pseudo Random number generator // #131: ; // #132: CONSTANT(random_value_port,4) ;read LFSR counter value // #133: ; // #134: ; // #135: ; Link FIFO buffer // #136: ; // #137: ; Provides a connection to the 'real' application such that 'soft tokens' in the // #138: ; form of short messages to be passed to the 'real' application to enable or disable // #139: ; it depending on the authentication status. // #140: ; // #141: CONSTANT(link_FIFO_write_port,4) ;write data to FIFO // #142: ; // #143: ; // #144: ;************************************************************************************** // #145: ; Special Register usage // #146: ;************************************************************************************** // #147: ; // #148: NAMEREG(sF,UART_data) ;used to pass data to and from the UART // #149: ; // #150: ; // #151: ; // #152: ;************************************************************************************** // #153: ;Scratch Pad Memory Locations // #154: ;************************************************************************************** // #155: ; // #156: CONSTANT(ISR_preserve_s0,0) ;preserve register contents during Interrupt Service Routine // #157: ; // #158: ; // #159: CONSTANT(serial_number0,16) ;64-bit serial number of StrataFlash // #160: CONSTANT(serial_number1,17) ;LS-Byte first // #161: CONSTANT(serial_number2,18) // #162: CONSTANT(serial_number3,19) // #163: CONSTANT(serial_number4,20) // #164: CONSTANT(serial_number5,21) // #165: CONSTANT(serial_number6,22) // #166: CONSTANT(serial_number7,23) // #167: ; // #168: ; // #169: CONSTANT(computed_CRC0,24) ;computed 16-bit CRC based on the // #170: CONSTANT(computed_CRC1,25) ; StrataFlash unique serial number (LS-Byte first) // #171: ; // #172: ; // #173: CONSTANT(authentication_CRC0,26) ;16-bit CRC value read from authentication // #174: CONSTANT(authentication_CRC1,27) ; area of StrataFLASH memory (LS-Byte first) // #175: ; // #176: ; // #177: CONSTANT(authentication_status,28) ;Status of design authentication // #178: ; // #179: ; // #180: ;************************************************************************************** // #181: ;Useful data constants // #182: ;************************************************************************************** // #183: ; // #184: ; // #185: ; // #186: ;Constant to define a software delay of 1us. This must be adjusted to reflect the // #187: ;clock applied to KCPSM3. Every instruction executes in 2 clock cycles making the // #188: ;calculation highly predictable. The '6' in the following equation even allows for // #189: ;'CALL delay_1us' instruction in the initiating code. // #190: ; // #191: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz // #192: ; // #193: ;Example: For a 50MHz clock the constant value is (10-6)/4 = 11 (0B Hex). // #194: ;For clock rates below 10MHz the value of 1 must be used and the operation will // #195: ;become lower than intended. // #196: ; // #197: CONSTANT(delay_1us_constant,11) // #198: ; // #199: ; // #200: ; // #201: ; // #202: ;ASCII table // #203: ; // #204: CONSTANT(character_a,97) // #205: CONSTANT(character_b,98) // #206: CONSTANT(character_c,99) // #207: CONSTANT(character_d,100) // #208: CONSTANT(character_e,101) // #209: CONSTANT(character_f,102) // #210: CONSTANT(character_g,103) // #211: CONSTANT(character_h,104) // #212: CONSTANT(character_i,105) // #213: CONSTANT(character_j,106) // #214: CONSTANT(character_k,107) // #215: CONSTANT(character_l,108) // #216: CONSTANT(character_m,109) // #217: CONSTANT(character_n,110) // #218: CONSTANT(character_o,111) // #219: CONSTANT(character_p,112) // #220: CONSTANT(character_q,113) // #221: CONSTANT(character_r,114) // #222: CONSTANT(character_s,115) // #223: CONSTANT(character_t,116) // #224: CONSTANT(character_u,117) // #225: CONSTANT(character_v,118) // #226: CONSTANT(character_w,119) // #227: CONSTANT(character_x,120) // #228: CONSTANT(character_y,121) // #229: CONSTANT(character_z,122) // #230: CONSTANT(character_A,65) // #231: CONSTANT(character_B,66) // #232: CONSTANT(character_C,67) // #233: CONSTANT(character_D,68) // #234: CONSTANT(character_E,69) // #235: CONSTANT(character_F,70) // #236: CONSTANT(character_G,71) // #237: CONSTANT(character_H,72) // #238: CONSTANT(character_I,73) // #239: CONSTANT(character_J,74) // #240: CONSTANT(character_K,75) // #241: CONSTANT(character_L,76) // #242: CONSTANT(character_M,77) // #243: CONSTANT(character_N,78) // #244: CONSTANT(character_O,79) // #245: CONSTANT(character_P,80) // #246: CONSTANT(character_Q,81) // #247: CONSTANT(character_R,82) // #248: CONSTANT(character_S,83) // #249: CONSTANT(character_T,84) // #250: CONSTANT(character_U,85) // #251: CONSTANT(character_V,86) // #252: CONSTANT(character_W,87) // #253: CONSTANT(character_X,88) // #254: CONSTANT(character_Y,89) // #255: CONSTANT(character_Z,90) // #256: CONSTANT(character_0,48) // #257: CONSTANT(character_1,49) // #258: CONSTANT(character_2,50) // #259: CONSTANT(character_3,51) // #260: CONSTANT(character_4,52) // #261: CONSTANT(character_5,53) // #262: CONSTANT(character_6,54) // #263: CONSTANT(character_7,55) // #264: CONSTANT(character_8,56) // #265: CONSTANT(character_9,57) // #266: CONSTANT(character_colon,58) // #267: CONSTANT(character_fullstop,46) // #268: CONSTANT(character_semi_colon,59) // #269: CONSTANT(character_minus,45) // #270: CONSTANT(character_divide,47) ;'/' // #271: CONSTANT(character_plus,43) // #272: CONSTANT(character_comma,44) // #273: CONSTANT(character_less_than,60) // #274: CONSTANT(character_greater_than,62) // #275: CONSTANT(character_equals,61) // #276: CONSTANT(character_space,32) // #277: CONSTANT(character_CR,13) ;carriage return // #278: CONSTANT(character_question,63) ;'?' // #279: CONSTANT(character_dollar,36) // #280: CONSTANT(character_exclaim,33) ;'!' // #281: CONSTANT(character_BS,8) ;Back Space command character // #282: ; // #283: ; // #284: ; // #285: ; // #286: ; // #287: ;************************************************************************************** // #288: ;Initialise the system // #289: ;************************************************************************************** // #290: ; // @000 #291: [cold_start] 300e1 // @000 #291: CALL(SF_init) ;initialise StrataFLASH controls 00000 // @001 #292: LOAD(s0,0) ;Start with application enabled in hardware 2c010 // @002 #293: OUTPUT(s0,authentication_control_port) 00050 // @003 #294: LOAD(s0,character_P) ;start with design enabled by software (see ISR) 2e01c // @004 #295: STORE(s0,authentication_status) 3035b // @005 #296: CALL(delay_1s) ;delay to allow system to settle 30328 // @006 #297: CALL(LCD_reset) ;Initialise the LCD // #298: ; 3c001 // @007 #299: ENABLE(INTERRUPT) ;interrupts to provide software enable to application // #300: ; // #301: ;************************************************************************************** // #302: ; Main program // #303: ;************************************************************************************** // #304: ; // #305: ; The main program follows a logical sequence of events describing the power on and // #306: ; authentication process of a design. This process will is either successfully authorises // #307: ; the 'real' application to operate or fail to authenticate and disable the 'real' // #308: ; application in a similar way to a production design. The only difference that it keeps // #309: ; you informed about what it is doing on both the LCD display and PC terminal via the UART. // #310: ; A real production design should keep all details hidden. // #311: ; // #312: ; Following the authentication check and control over the 'real' application a simple menu // #313: ; is provided on the PC terminal to allow you to read, write and erase the authentication // #314: ; area of the StrataFLASH memory and therefore evaluate the design authentication security // #315: ; of this reference design. // #316: ; // #317: ; // #318: ; // #319: ; Write welcome message to LCD display // #320: ; // @008 #321: [warm_start] 00512 // @008 #321: LOAD(s5,18) ;Line 1 position 2 3033e // @009 #322: CALL(LCD_cursor) 30364 // @00a #323: CALL(disp_PicoBlaze) ;Display 'PicoBlaze' 00525 // @00b #324: LOAD(s5,37) ;Line 2 position 5 3033e // @00c #325: CALL(LCD_cursor) 30377 // @00d #326: CALL(disp_Security) ;Display 'Security' // #327: ; // #328: ; Write welcome message to PC via UART // #329: ; 30164 // @00e #330: CALL(send_welcome) // #331: ; // #332: ; // #333: ; Display 'Copyright Ken Chapman 2006' via the UART. // #334: ; // #335: ; This message is significant because it demonstrates that the design now has a 'watermark'. // #336: ; The ASCII codes for this string are part of the PicoBlaze program stored in a Block // #337: ; Memory and therefore are also part of the configuration bit stream. If someone tries to // #338: ; change or delete this copyright message the hardware design will detect the change to the // #339: ; Block memory contents and also inhibit the design. // #340: ; 301b4 // @00f #341: CALL(send_Copyright) // #342: ; // #343: ; // #344: ; // #345: ; Delay of 10 seconds before performing any security checks. // #346: ; // #347: ; This allows the design to work for a short time which could be important for // #348: ; production testing. // #349: ; // #350: ; Having a significant time delay (days or weeks) before security checks means that someone // #351: ; attempting to clone the product may not be aware that there is any form of design security // #352: ; at all until products are in the field are failing. A time delay also impedes the ability to // #353: ; attempt to break the security and confirm if an attempt is or is not successful. // #354: ; 0050a // @010 #355: LOAD(s5,10) ;delay of 10 seconds. 30360 // @011 #356: CALL(delay_Ns) // #357: ; // #358: ; // #359: ; // #360: ; Read serial number of the StrataFLASH memory. // #361: ; The whole principle of low cost design security is based on this unique number. Clearly this // #362: ; number is not a secret, but what we then go on to do with it should normally be kept secret. // #363: ; 300f2 // @012 #364: CALL(read_SF_serial_number) ;read serial number from FLASH memory 30065 // @013 #365: CALL(send_serial_number) ;send value to UART for display on PC 30070 // @014 #366: CALL(disp_serial_number) ;display serial number on LCD display. 30154 // @015 #367: CALL(send_CR) // #368: ; // #369: ; // #370: ; 0050a // @016 #371: LOAD(s5,10) ;delay of 10 seconds to read messages. 30360 // @017 #372: CALL(delay_Ns) // #373: ; // #374: ; // #375: ; // #376: ; Compute the 16-bit CRC for the serial number as an authentication value for the design. // #377: ; The CRC value is formed in register pair [sE,sD]. To complicate the authentication value // #378: ; the initial contents of the registers are seeded with a 'secret' number. // #379: ; Hint 1 - The CRC computation could be implemented in hardware where it is less visible. // #380: ; Hint 2 - There are more secure algorithms such as SHA-1 which could be used to generate // #381: ; authentication values that are extremely difficult to decode. // #382: ; // #383: ; 00e15 // @018 #384: LOAD(sE,21) ;seed CRC register with an initial value provided by my daughter when asked :-) 00d8e // @019 #385: LOAD(sD,142) 3007f // @01a #386: CALL(compute_seeded_CRC) ;compute CRC for serial number and configuration memory // #387: ; // #388: ; Store CRC value in scratch pad memory and display computed CRC value on the PC via UART. // #389: ; 2ed18 // @01b #390: STORE(sD,computed_CRC0) ;store CRC value 2ee19 // @01c #391: STORE(sE,computed_CRC1) 30252 // @01d #392: CALL(send_Computed_CRC) ;display computed CRC value on PC via UART 010e0 // @01e #393: LOAD(s0,sE) 30140 // @01f #394: CALL(send_hex_byte) 010d0 // @020 #395: LOAD(s0,sD) 30140 // @021 #396: CALL(send_hex_byte) 30154 // @022 #397: CALL(send_CR) // #398: ; // #399: ; // #400: ; // #401: ; Read the authenticated CRC value stored in StrataFLASH memory. // #402: ; 16-bit value is hidden in 256 bytes of random numbers to make it more difficult // #403: ; for an attacker to identify. // #404: ; Read value is stored in scratch pad memory and displayed on the PC via UART. // #405: ; 30094 // @023 #406: CALL(read_authentication) ;read StrataFLASH memory into [sB,sA] 2ea1a // @024 #407: STORE(sA,authentication_CRC0) ;store CRC value 2eb1b // @025 #408: STORE(sB,authentication_CRC1) 30248 // @026 #409: CALL(send_FLASH_CRC) ;display CRC value from FLASH on PC via UART 010b0 // @027 #410: LOAD(s0,sB) 30140 // @028 #411: CALL(send_hex_byte) 010a0 // @029 #412: LOAD(s0,sA) 30140 // @02a #413: CALL(send_hex_byte) 30154 // @02b #414: CALL(send_CR) // #415: ; // #416: ; // #417: ; Compare the computed CRC value with the authentication value stored in StrataFLASH // #418: ; and determine if the design is authenticated. Then decide course of action. // #419: ; 30339 // @02c #420: CALL(LCD_clear) ;clear LCD display 303a9 // @02d #421: CALL(disp_Authentication) ;prepare LCD display for result of authentication 30232 // @02e #422: CALL(send_Authentication) ;prepare PC display for result of authentication // #423: ; 15ad0 // @02f #424: COMPARE(sA,sD) ;Perform comparison of CRC values 35436 // @030 #425: JUMP(NZ,auth_failure) 15be0 // @031 #426: COMPARE(sB,sE) 35436 // @032 #427: JUMP(NZ,auth_failure) // #428: ; // #429: ; // #430: ; Authentication Successful Process // #431: ; // #432: ; In this mode the design continues to operate and for evaluation // #433: ; purposes this design transfers control to the simple menu immediately. // #434: ; // @033 #435: [auth_passed] 303c8 // @033 #435: CALL(disp_Passed) ;display successful authentication on LCD display 3029d // @034 #436: CALL(send_PASSED) ;display successful authentication on PC via UART 3403c // @035 #437: JUMP(Menu) // #438: ; // #439: ; Authentication Failure Process // #440: ; // #441: ; When the authentication fails two hardware based disable methods are demonstrated. Then // #442: ; the failed status is remembered for future software token messages to demonstrate software // #443: ; based disabling of the 'real' application. Finally the simple menu of options is presented // #444: ; to allow evaluation to continue. // #445: ; // #446: ; // @036 #447: [auth_failure] 303d6 // @036 #447: CALL(disp_Failed) ;display failure to authenticate on LCD display 3028f // @037 #448: CALL(send_FAILED) ;display failure to authenticate on PC via UART 30154 // @038 #449: CALL(send_CR) 30056 // @039 #450: CALL(disable_app_hardware) ;sequence hardware disable signals 00046 // @03a #451: LOAD(s0,character_F) ;change authentication status to 'F' for failed. 2e01c // @03b #452: STORE(s0,authentication_status) ; so that application software disable is demonstrated // #453: ; // #454: ; // #455: ; // #456: ; Menu of options for authentication processing // #457: ; // @03c #458: [Menu] 302bc // @03c #458: CALL(send_Menu) ;display menu and prompt 3011d // @03d #459: CALL(read_from_UART) ;read character from PC 30129 // @03e #460: CALL(upper_case) ;convert to upper case 14f52 // @03f #461: COMPARE(UART_data,character_R) 35046 // @040 #462: JUMP(Z,read_command) 14f45 // @041 #463: COMPARE(UART_data,character_E) 3504b // @042 #464: JUMP(Z,erase_command) 14f41 // @043 #465: COMPARE(UART_data,character_A) 3504f // @044 #466: JUMP(Z,authorise_command) 3403c // @045 #467: JUMP(Menu) ;repeat menu for invalid selection // #468: ; // #469: ; // #470: ; // @046 #471: [read_command] 30154 // @046 #471: CALL(send_CR) 300ae // @047 #472: CALL(send_auth_page) 30154 // @048 #473: CALL(send_CR) 30154 // @049 #474: CALL(send_CR) 3403c // @04a #475: JUMP(Menu) // #476: ; // #477: ; // #478: ; // @04b #479: [erase_command] 3026f // @04b #479: CALL(send_Erase_in_progress) 300de // @04c #480: CALL(erase_authentication) 30289 // @04d #481: CALL(send_OK) 3403c // @04e #482: JUMP(Menu) // #483: ; // #484: ; // #485: ; // @04f #486: [authorise_command] 302aa // @04f #486: CALL(send_Writing) ;Send 'Writing Authorisation' message 30154 // @050 #487: CALL(send_CR) 06d18 // @051 #488: FETCH(sD,computed_CRC0) ;fetch computed CRC value 06e19 // @052 #489: FETCH(sE,computed_CRC1) 300be // @053 #490: CALL(write_authentication) ;write computed CRC to FLASH with random data 30289 // @054 #491: CALL(send_OK) 3403c // @055 #492: JUMP(Menu) // #493: ; // #494: ; // #495: ;************************************************************************************** // #496: ; Drive failure signals to the application. // #497: ;************************************************************************************** // #498: ; // #499: ; When the design fails to authorise, these controls cause the application to behave in // #500: ; a strange way! // #501: ; // #502: ; // #503: ; Disable interrupts to application PicoBlaze to stop PWM generation completely for 5 seconds // #504: ; // @056 #505: [disable_app_hardware] 00001 // @056 #505: LOAD(s0,security_disable_interrupts) 2c010 // @057 #506: OUTPUT(s0,authentication_control_port) 00505 // @058 #507: LOAD(s5,5) 30360 // @059 #508: CALL(delay_Ns) // #509: ; // #510: ; Enable application for 5 seconds // #511: ; 00000 // @05a #512: LOAD(s0,0) 2c010 // @05b #513: OUTPUT(s0,authentication_control_port) 00505 // @05c #514: LOAD(s5,5) 30360 // @05d #515: CALL(delay_Ns) // #516: ; // #517: ; Disable and/or scramble outputs connected to application PicoBlaze for 5 seconds // #518: ; 00002 // @05e #519: LOAD(s0,security_disable_outputs) 2c010 // @05f #520: OUTPUT(s0,authentication_control_port) 00505 // @060 #521: LOAD(s5,5) 30360 // @061 #522: CALL(delay_Ns) // #523: ; // #524: ; // #525: ; Enable application in hardware so that software disable function can then be // #526: ; demonstrated until the design is reconfigured and authentication test repeated. // #527: ; 00000 // @062 #528: LOAD(s0,0) 2c010 // @063 #529: OUTPUT(s0,authentication_control_port) 2a000 // @064 #530: RETURN // #531: ; // #532: ; // #533: ; // #534: ;************************************************************************************** // #535: ; Send the 64-bit serial number stored in scratch pad memory to the UART // #536: ;************************************************************************************** // #537: ; // #538: ; The serial number should previously have been copied into the 8 ascending scratch pad // #539: ; memory locations called 'serial_number0' through to 'serial_number7'. // #540: ; // #541: ; The serial number is displayed MS-Byte first. // #542: ; // #543: ; Registers used s0,s1,s2,s3 // #544: ; // @065 #545: [send_serial_number] 301f2 // @065 #545: CALL(send_FLASH_Serial_Number) ;display text message 00317 // @066 #546: LOAD(s3,serial_number7) ;pointer to scratch pad memory // @067 #547: [send_SN_loop] 07030 // @067 #547: FETCH(s0,s3) ;read serial number byte 30140 // @068 #548: CALL(send_hex_byte) ;display byte 30157 // @069 #549: CALL(send_space) ;display byte 14310 // @06a #550: COMPARE(s3,serial_number0) ;check for 8 bytes sent to UART 3506e // @06b #551: JUMP(Z,end_send_SN) 1c301 // @06c #552: SUB(s3,1) ;increment memory pointer 34067 // @06d #553: JUMP(send_SN_loop) // #554: ; // @06e #555: [end_send_SN] 30154 // @06e #555: CALL(send_CR) 2a000 // @06f #556: RETURN // #557: ; // #558: ; // #559: ; // #560: ;************************************************************************************** // #561: ; Display the 64-bit serial number stored in scratch pad memory on the LCD display // #562: ;************************************************************************************** // #563: ; // #564: ; The serial number should previously have been copied into the 8 ascending scratch pad // #565: ; memory locations called 'serial_number0' through to 'serial_number7'. // #566: ; // #567: ; The serial number is displayed MS-Byte first. // #568: ; // #569: ; Registers used s0,s1,s2,s3,s4,s5,s6 // #570: ; // @070 #571: [disp_serial_number] 30339 // @070 #571: CALL(LCD_clear) ;clear LCD display 00510 // @071 #572: LOAD(s5,16) ;Line 1 position 0 3033e // @072 #573: CALL(LCD_cursor) 30388 // @073 #574: CALL(disp_FLASH_Serial_No) ;display text message 00520 // @074 #575: LOAD(s5,32) ;Line 2 position 0 3033e // @075 #576: CALL(LCD_cursor) 00617 // @076 #577: LOAD(s6,serial_number7) ;pointer to scratch pad memory // @077 #578: [disp_SN_loop] 07060 // @077 #578: FETCH(s0,s6) ;read serial number byte 3014d // @078 #579: CALL(disp_hex_byte) ;display byte 14610 // @079 #580: COMPARE(s6,serial_number0) ;check for 8 bytes sent to UART 3507d // @07a #581: JUMP(Z,end_disp_SN) 1c601 // @07b #582: SUB(s6,1) ;increment memory pointer 34077 // @07c #583: JUMP(disp_SN_loop) // #584: ; // @07d #585: [end_disp_SN] 30154 // @07d #585: CALL(send_CR) 2a000 // @07e #586: RETURN // #587: ; // #588: ; // #589: ;************************************************************************************** // #590: ; Compute a 16-bit CRC value for the StrataFLASH 64-bit serial number. // #591: ;************************************************************************************** // #592: ; // #593: ; This routing performs a 16-bit CRC calculation for the 64-bit unique serial number // #594: ; of the StrataFLASH memory which forms the authentication value for the design. // #595: ; // #596: ; The 16-bit CRC value returned in register pair [sE,sD] will be reflective of the unique // #597: ; serial number. This will be used as the authentication value for the design which is // #598: ; stored at known locations in the FLASH memory. // #599: ; // #600: ; A direct copy of the FLASH contents will not authorise a design to operate because the // #601: ; authentication value will not match the CRC value generated from the different serial number. // #602: ; // #603: ; To complicate the CRC value generation the CRC register can be seeded with a value rather // #604: ; than starting with a clear register. // #605: ; // #606: ; // #607: ; Registers used s0,s1,s2,s3 // #608: ; // @07f #609: [compute_seeded_CRC] 00410 // @07f #609: LOAD(s4,serial_number0) ;pointer to scratch pad memory holding serial number // @080 #610: [CRC_send_loop] 07340 // @080 #610: FETCH(s3,s4) ;read serial number byte 30086 // @081 #611: CALL(compute_CRC16) ;compute CRC for value in 's3' 14417 // @082 #612: COMPARE(s4,serial_number7) ;check for 8 bytes processed 2b000 // @083 #613: RETURN(Z) 18401 // @084 #614: ADD(s4,1) ;increment memory pointer 34080 // @085 #615: JUMP(CRC_send_loop) // #616: ; // #617: ; // #618: ;************************************************************************************** // #619: ; Compute 16-bit CRC using the polynomial X16 + X15 + X2 + 1. // #620: ;************************************************************************************** // #621: ; // #622: ; // #623: ; This routine computes a 16-bit CRC in the register pair [sE,sD] and these // #624: ; registers must not be disturbed between calls of this routine. // #625: ; // #626: ; This routine has been written such that the CRC can be computed one // #627: ; byte at a time. The byte to be processed should be provided in register 's3' // #628: ; and the contents of this register are preserved. // #629: ; // #630: ; Before starting a CRC computation either clear or pre-load (seed) the register pair // #631: ; [sE,sD] and do not disturb the value of the register pair between calling this routine. // #632: ; // #633: ; Registers used s0,s1,s3,sD,sE // #634: ; s3 is preserved. // #635: ; sD and sE should not be disturbed between calls if CRC value is required. // #636: ; // #637: ; // #638: ; // @086 #639: [compute_CRC16] 00108 // @086 #639: LOAD(s1,8) ;8-bits to shift // @087 #640: [crc16_loop] 010d0 // @087 #640: LOAD(s0,sD) ;copy current CRC value 0f030 // @088 #641: XOR(s0,s3) ;Need to know LSB XOR next input bit 12001 // @089 #642: TEST(s0,1) ;test result of XOR in LSB 35c8d // @08a #643: JUMP(NC,crc16_shift) 0ed02 // @08b #644: XOR(sD,2) ;compliment bit 1 of CRC 0ee40 // @08c #645: XOR(sE,64) ;compliment bit 14 of CRC // @08d #646: [crc16_shift] 2000e // @08d #646: SR0(s0) ;Carry gets LSB XOR next input bit 20e08 // @08e #647: SRA(sE) ;shift Carry into MSB to form new CRC value 20d08 // @08f #648: SRA(sD) 2030c // @090 #649: RR(s3) ;shift input value 1c101 // @091 #650: SUB(s1,1) ;count bits 35487 // @092 #651: JUMP(NZ,crc16_loop) ;next bit 2a000 // @093 #652: RETURN // #653: ; // #654: ; // #655: ;************************************************************************************** // #656: ; Read 256 bytes of StrataFLASH memory including the authentication value. // #657: ;************************************************************************************** // #658: ; // #659: ; This routine reads the authentication value from the StrataFLASH memory. In this // #660: ; design the authentication value is only 2 bytes which once read will be returned // #661: ; in the register pair [sB,sA]. // #662: ; // #663: ; To make the authentication value more difficult to identify, it is hidden in 256 bytes // #664: ; of pseudo random values which will also appear different in each FLASH device inspected. // #665: ; This routine deliberately reads all 256 bytes that are stored and abstracts the required // #666: ; 2 bytes of information from them otherwise it would be easy to observe which addresses // #667: ; of the block were being accessed. // #668: ; // #669: ; Another way that an attacker may deduce which address locations are important would be to // #670: ; observe the time between read accesses and note when there is any difference. In this case // #671: ; the attacker is attempting to detect when PicoBlaze takes slightly longer to execute the // #672: ; instructions which store the important bytes in scratch pad memory. So to avoid this // #673: ; detection this routine inserts an additional random delay between reads to mask any code // #674: ; execution differences. // #675: ; // #676: ; The 256 bytes are stored at addresses 060000 to 0600FF hex (the first block above the // #677: ; XC3S500E configuration image which occupies 000000 to 04547F hex). The 2 bytes forming the // #678: ; actual authentication value are stored as 4-bit nibbles in 4 different locations in this range. // #679: ; // #680: ; // #681: ; High Order Nibble Low Order Nibble // #682: ; (NNNNxxxx) (xxxxNNNN) // #683: ; // #684: ; LS-Byte in 'sA' Addr=060010 Addr=06007F // #685: ; MS-Byte in 'sB' Addr=060025 Addr=0600FA // #686: ; // #687: ; // @094 #688: [read_authentication] 00906 // @094 #688: LOAD(s9,6) ;start address in FLASH 00800 // @095 #689: LOAD(s8,0) 00700 // @096 #690: LOAD(s7,0) // @097 #691: [auth_read_loop] 30101 // @097 #691: CALL(SF_byte_read) ;read byte from FLASH into s0 14710 // @098 #692: COMPARE(s7,16) ;check for bytes/nibbles that contain real information 3549c // @099 #693: JUMP(NZ,auth_check2) 01a00 // @09a #694: LOAD(sA,s0) ;isolate upper order nibble for LS-Byte 0aaf0 // @09b #695: AND(sA,F0) // @09c #696: [auth_check2] 14725 // @09c #696: COMPARE(s7,37) 354a0 // @09d #697: JUMP(NZ,auth_check3) 01b00 // @09e #698: LOAD(sB,s0) ;isolate upper order nibble for MS-Byte 0abf0 // @09f #699: AND(sB,F0) // @0a0 #700: [auth_check3] 1477f // @0a0 #700: COMPARE(s7,127) 354a4 // @0a1 #701: JUMP(NZ,auth_check4) 0a00f // @0a2 #702: AND(s0,15) ;isolate lower order nibble for LS-Byte 0da00 // @0a3 #703: OR(sA,s0) ; and merge with upper order nibble // @0a4 #704: [auth_check4] 147fa // @0a4 #704: COMPARE(s7,FA) 354a8 // @0a5 #705: JUMP(NZ,next_auth_read) 0a00f // @0a6 #706: AND(s0,15) ;isolate lower order nibble for MS-Byte 0db00 // @0a7 #707: OR(sB,s0) ; and merge with upper order nibble // @0a8 #708: [next_auth_read] 18701 // @0a8 #708: ADD(s7,1) ;increment address 2b000 // @0a9 #709: RETURN(Z) ;complete after 256 reads 04004 // @0aa #710: INPUT(s0,random_value_port) ;random delay between reads // @0ab #711: [auth_read_delay] 1c001 // @0ab #711: SUB(s0,1) 354ab // @0ac #712: JUMP(NZ,auth_read_delay) 34097 // @0ad #713: JUMP(auth_read_loop) // #714: ; // #715: ; // #716: ;************************************************************************************** // #717: ; Read 256 bytes (page) of StrataFLASH memory containing the authentication value. // #718: ;************************************************************************************** // #719: ; // #720: ; This routine reads the StrataFLASH memory and displays the contents on the PC display // #721: ; via the UART. The display will be 256 bytes from address range 060000 to 0600FF displayed // #722: ; as 16 lines of 16 bytes with each line commencing with the address of the first byte. // #723: ; // @0ae #724: [send_auth_page] 00906 // @0ae #724: LOAD(s9,6) ;start address in FLASH 00800 // @0af #725: LOAD(s8,0) 00700 // @0b0 #726: LOAD(s7,0) // @0b1 #727: [auth_line_loop] 30154 // @0b1 #727: CALL(send_CR) 30146 // @0b2 #728: CALL(send_hex_3bytes) ;display address 30157 // @0b3 #729: CALL(send_space) // @0b4 #730: [auth_byte_loop] 30157 // @0b4 #730: CALL(send_space) 30101 // @0b5 #731: CALL(SF_byte_read) ;read byte into s0 30140 // @0b6 #732: CALL(send_hex_byte) ;display byte 18701 // @0b7 #733: ADD(s7,1) ;increment FLASH address 1270f // @0b8 #734: TEST(s7,15) ;test for 16 byte boundary 354b4 // @0b9 #735: JUMP(NZ,auth_byte_loop) 127ff // @0ba #736: TEST(s7,FF) ;test for roll over of 256 bytes 354b1 // @0bb #737: JUMP(NZ,auth_line_loop) 30154 // @0bc #738: CALL(send_CR) 2a000 // @0bd #739: RETURN // #740: ; // #741: ; // #742: ; // #743: ; // #744: ;************************************************************************************** // #745: ; Write 256 bytes of StrataFLASH memory including the authentication value. // #746: ;************************************************************************************** // #747: ; // #748: ; This routine writes the authentication value to the StrataFLASH memory. This routine // #749: ; would normally be part of a production programming mechanism and not part of the // #750: ; final design which only reads and confirms authentication. This routine does not // #751: ; require and special measures to confuse an attacker if it is only used in a secure // #752: ; production environment. // #753: ; // #754: ; The 2 bytes forming the actual authentication value are stored as 4-bit nibbles in // #755: ; 4 different locations in the address range 600000 to 6000FF hex (256 bytes) with // #756: ; all remaining locations filled with pseudo random values. // #757: ; // #758: ; The authentication value to be stored in StrataFLASH memory should be provided in // #759: ; the register pair [sE,sD] and will be stored in the following locations. // #760: ; // #761: ; High Order Nibble Low Order Nibble // #762: ; (NNNNxxxx) (xxxxNNNN) // #763: ; // #764: ; LS-Byte in 'sD' Addr=060010 Addr=06007F // #765: ; MS-Byte in 'sE' Addr=060025 Addr=0600FA // #766: ; // #767: ; // @0be #768: [write_authentication] 00906 // @0be #768: LOAD(s9,6) ;start address in FLASH 00800 // @0bf #769: LOAD(s8,0) 00700 // @0c0 #770: LOAD(s7,0) // @0c1 #771: [auth_write_loop] 04004 // @0c1 #771: INPUT(s0,random_value_port) ;Obtain random value 14710 // @0c2 #772: COMPARE(s7,16) ;check for bytes/nibbles that need to be real information 354c8 // @0c3 #773: JUMP(NZ,auth_write_check2) 011d0 // @0c4 #774: LOAD(s1,sD) ;merge upper order nibble for LS-Byte with random 0a1f0 // @0c5 #775: AND(s1,F0) 0a00f // @0c6 #776: AND(s0,15) 0d010 // @0c7 #777: OR(s0,s1) // @0c8 #778: [auth_write_check2] 14725 // @0c8 #778: COMPARE(s7,37) 354ce // @0c9 #779: JUMP(NZ,auth_write_check3) 011e0 // @0ca #780: LOAD(s1,sE) ;merge upper order nibble for MS-Byte with random 0a1f0 // @0cb #781: AND(s1,F0) 0a00f // @0cc #782: AND(s0,15) 0d010 // @0cd #783: OR(s0,s1) // @0ce #784: [auth_write_check3] 1477f // @0ce #784: COMPARE(s7,127) 354d4 // @0cf #785: JUMP(NZ,auth_write_check4) 011d0 // @0d0 #786: LOAD(s1,sD) ;merge lower order nibble for LS-Byte with random 0a10f // @0d1 #787: AND(s1,15) 0a0f0 // @0d2 #788: AND(s0,F0) 0d010 // @0d3 #789: OR(s0,s1) // @0d4 #790: [auth_write_check4] 147fa // @0d4 #790: COMPARE(s7,FA) 354da // @0d5 #791: JUMP(NZ,write_auth) 011e0 // @0d6 #792: LOAD(s1,sE) ;merge lower order nibble for MS-Byte with random 0a10f // @0d7 #793: AND(s1,15) 0a0f0 // @0d8 #794: AND(s0,F0) 0d010 // @0d9 #795: OR(s0,s1) // @0da #796: [write_auth] 300ec // @0da #796: CALL(SF_single_byte_write) ;write byte to FLASH 18701 // @0db #797: ADD(s7,1) ;increment address 2b000 // @0dc #798: RETURN(Z) ;complete after 256 writes 340c1 // @0dd #799: JUMP(auth_write_loop) // #800: ; // #801: ; // #802: ;************************************************************************************** // #803: ; Erase authentication value from StrataFLASH memory. // #804: ;************************************************************************************** // #805: ; // #806: ; Erase block 3 of the StrataFLASH memory which covers the address range 060000 to 07FFFF. // #807: ; This erases the area containing the authentication value and random values which helps // #808: ; to hide it. // #809: ; // @0de #810: [erase_authentication] 00906 // @0de #810: LOAD(s9,6) ;set address to 06xxxx hex which defines block 3 (060000 to 07FFFF) 300e4 // @0df #811: CALL(SF_erase_block) 2a000 // @0e0 #812: RETURN // #813: ; // #814: ; // #815: ;************************************************************************************** // #816: ; Initialise the StrataFlash Memory control signals. // #817: ;************************************************************************************** // #818: ; // #819: ; SF_read = 0 - Output enable off // #820: ; SF_ce = 1 - Deselect StrataFLASH memory // #821: ; SF_we = 1 - Write enable off // #822: ; // #823: ; Register used s0 // #824: ; // @0e1 #825: [SF_init] 00006 // @0e1 #825: LOAD(s0,6) 2c040 // @0e2 #826: OUTPUT(s0,SF_control_port) 2a000 // @0e3 #827: RETURN // #828: ; // #829: ; // #830: ; // #831: ;************************************************************************************** // #832: ; StrataFLASH Block Erase // #833: ;************************************************************************************** // #834: ; // #835: ; This routine will erase one 128k-byte block of the StrataFLASH memory. // #836: ; The block to be erased is specified by the contents of register 's9'. // #837: ; // #838: ; s9=06 erases Block 3 (address range 060000 to 07FFFF) // #839: ; // #840: ; // #841: ; To erase a block the 24-bit address must be set and then the block erase command // #842: ; (20 hex) written to the memory followed by the write confirm command (D0 hex). // #843: ; // #844: ; The act of erasing a block may take up to 1 second to complete. This routine // #845: ; waits for the memory to be ready before restoring the normal read array mode and // #846: ; returning. // #847: ; // #848: ; Registers used s0,s1,s7,s8,s9 // #849: ; // @0e4 #850: [SF_erase_block] 00800 // @0e4 #850: LOAD(s8,0) ;define lower address of block = xx0000 00700 // @0e5 #851: LOAD(s7,0) 00120 // @0e6 #852: LOAD(s1,32) ;block erase command 3010b // @0e7 #853: CALL(SF_byte_write) 001d0 // @0e8 #854: LOAD(s1,D0) ;write confirm command 3010b // @0e9 #855: CALL(SF_byte_write) 30118 // @0ea #856: CALL(wait_SF_ready) ;wait for erase to complete 2a000 // @0eb #857: RETURN // #858: ; // #859: ; // #860: ;************************************************************************************** // #861: ; Write a single byte to StrataFlash Memory // #862: ;************************************************************************************** // #863: ; // #864: ; To write a single byte to StrataFLASH memory the address must be set and the // #865: ; single-word/byte program command (40 hex) sent to the memory. Then the data byte can // #866: ; be written to the memory using the same address. // #867: ; // #868: ; The 24-bit address should be supplied in register set [s9,s8,s7]. // #869: ; Register s0 should contain the byte data to be written to the memory. // #870: ; // #871: ; The act of writing the memory array may take up to 175us to complete. This routine // #872: ; waits for the memory to be ready before restoring the normal read array mode and // #873: ; returning. // #874: ; // #875: ; Registers used s0,s1,s7,s8,s9 (s7,s8,s9 not changed) // #876: ; // #877: ; Registers used s0,s1,s7,s8,s9 // #878: ; // @0ec #879: [SF_single_byte_write] 00140 // @0ec #879: LOAD(s1,64) ;command for single byte program 3010b // @0ed #880: CALL(SF_byte_write) 01100 // @0ee #881: LOAD(s1,s0) ;write data to be programmed 3010b // @0ef #882: CALL(SF_byte_write) 30118 // @0f0 #883: CALL(wait_SF_ready) ;wait for program to complete 2a000 // @0f1 #884: RETURN // #885: ; // #886: ; // #887: ; // #888: ;************************************************************************************** // #889: ; Read the unique 64-bit serial number of the StrataFLASH FLASH memory // #890: ;************************************************************************************** // #891: ; // #892: ; To read the device information the Read device information command (90) // #893: ; must be written to the memory. The information is read back from address 000102 // #894: ; to 000109 (note these are byte access addresses). // #895: ; // #896: ; The serial number is copied to 8 ascending scratch pad memory locations called // #897: ; 'serial_number0' through to 'serial_number7' for future use. // #898: ; // #899: ; After reading the device information the read array command is written to the // #900: ; device to put it back to normal read mode. // #901: ; // #902: ; Registers used s0,s1,s2,s7,s8,s9 // #903: ; // @0f2 #904: [read_SF_serial_number] 00900 // @0f2 #904: LOAD(s9,0) ;StrataFLASH address to read serial number = 000102 00801 // @0f3 #905: LOAD(s8,1) 00702 // @0f4 #906: LOAD(s7,2) 00210 // @0f5 #907: LOAD(s2,serial_number0) ;pointer to scratch pad memory 00190 // @0f6 #908: LOAD(s1,144) ;command to read device information 3010b // @0f7 #909: CALL(SF_byte_write) // @0f8 #910: [read_SN_loop] 30101 // @0f8 #910: CALL(SF_byte_read) ;read serial number value 2f020 // @0f9 #911: STORE(s0,s2) 14217 // @0fa #912: COMPARE(s2,serial_number7) ;check for 8 bytes copied 350ff // @0fb #913: JUMP(Z,end_read_SN) 18701 // @0fc #914: ADD(s7,1) ;increment StrataFLASH address 18201 // @0fd #915: ADD(s2,1) ;increment memory pointer 340f8 // @0fe #916: JUMP(read_SN_loop) // #917: ; // @0ff #918: [end_read_SN] 30115 // @0ff #918: CALL(set_SF_read_array_mode) ;restore normal read array mode 2a000 // @100 #919: RETURN // #920: ; // #921: ; // #922: ; // #923: ;************************************************************************************** // #924: ; Read a byte from StrataFlash Memory // #925: ;************************************************************************************** // #926: ; // #927: ; The 24-bit address should be supplied in register set [s9,s8,s7]. // #928: ; Register s0 will return the byte data retrieved from the memory. // #929: ; // #930: ; To read a byte, the address needs to be set up on the address lines // #931: ; and the controls set as follows // #932: ; SF_read = 1 - disable Spartan data outputs and enable StrataFlash outputs (OE=0) // #933: ; SF_ce = 0 - enable StrataFLASH memory // #934: ; SF_we = 1 - Write enable off // #935: ; // #936: ; The access time of the memory is 75ns. This is equivalent to 3.75 clock cycles at // #937: ; 50MHz. Since each KCPSM3 instruction takes 2 clock cycles to execute, two instructions // #938: ; provides adequate delay for the memory to be accessed. // #939: ; // #940: ; Registers used s0,s1,s7,s8,s9 // #941: ; // @101 #942: [SF_byte_read] 2c983 // @101 #942: OUTPUT(s9,SF_addr_hi_port) ;set 24-bit address 2c882 // @102 #943: OUTPUT(s8,SF_addr_mi_port) 2c781 // @103 #944: OUTPUT(s7,SF_addr_lo_port) 00105 // @104 #945: LOAD(s1,5) ;set controls 2c140 // @105 #946: OUTPUT(s1,SF_control_port) 00106 // @106 #947: LOAD(s1,6) ;>75ns delay 00106 // @107 #948: LOAD(s1,6) ;but do something useful! 04002 // @108 #949: INPUT(s0,SF_data_in_port) ;read data byte 2c140 // @109 #950: OUTPUT(s1,SF_control_port) ;clear controls 2a000 // @10a #951: RETURN // #952: ; // #953: ; // #954: ;************************************************************************************** // #955: ; Write data or command byte to StrataFlash Memory // #956: ;************************************************************************************** // #957: ; // #958: ; The 24-bit address should be supplied in register set [s9,s8,s7]. // #959: ; Register s1 should contain the byte to be written to the memory. // #960: ; // #961: ; To write a byte, the address needs to be set up on the address lines // #962: ; and the controls set as follows // #963: ; SF_read = 0 - enable Spartan data outputs and disable StrataFlash outputs (OE=1) // #964: ; SF_ce = 0 - enable StrataFLASH memory // #965: ; SF_we = 0 - Write enable on // #966: ; // #967: ; The setup time of the memory is 60ns. This is equivalent to 3 clock cycles at // #968: ; 50MHz. Since each KCPSM3 instruction takes 2 clock cycles to execute, two instructions // #969: ; provides adequate delay for the memory. // #970: ; // #971: ; Registers used s1,s7,s8,s9 // #972: ; // @10b #973: [SF_byte_write] 2c983 // @10b #973: OUTPUT(s9,SF_addr_hi_port) ;set 24-bit address 2c882 // @10c #974: OUTPUT(s8,SF_addr_mi_port) 2c781 // @10d #975: OUTPUT(s7,SF_addr_lo_port) 2c180 // @10e #976: OUTPUT(s1,SF_data_out_port) ;set data byte to be written 00100 // @10f #977: LOAD(s1,0) ;set controls 2c140 // @110 #978: OUTPUT(s1,SF_control_port) 00106 // @111 #979: LOAD(s1,6) ;>60ns delay 00106 // @112 #980: LOAD(s1,6) ;but do something useful! 2c140 // @113 #981: OUTPUT(s1,SF_control_port) ;clear controls 2a000 // @114 #982: RETURN // #983: ; // #984: ; // #985: ;************************************************************************************** // #986: ; Set 'Read Array' mode on StrataFLASH // #987: ;************************************************************************************** // #988: ; // #989: ; The read array mode is the default mode of the memory and allows the contents // #990: ; of the memory to be read based on the supplied address. // #991: ; // #992: ; Read array is the default mode of the device, but it must also be placed back // #993: ; into this mode after programming, erasing or reading the status register. // #994: ; // #995: ; The read array command (FF hex) is written to the Strata flash memory. // #996: ; // #997: ; Registers used s1,s7,s8,s9 // #998: ; // @115 #999: [set_SF_read_array_mode] 001ff // @115 #999: LOAD(s1,FF) ;command to read array 3010b // @116 #1000: CALL(SF_byte_write) 2a000 // @117 #1001: RETURN // #1002: ; // #1003: ; // #1004: ;************************************************************************************** // #1005: ; Wait for StrataFLASH to be ready // #1006: ;************************************************************************************** // #1007: ; // #1008: ; This routine will typically be used after instigating a program or erase // #1009: ; command. It continuously reads the StrataFLASH status register and tests the // #1010: ; information provided by bit7 which indicates if the memory is busy(0) or ready(1). // #1011: ; The routine waits for the ready condition before sending a read array command // #1012: ; which puts the memory back to normal read mode. // #1013: ; // #1014: ; // #1015: ; Registers used s0,s1,s7,s8,s9 (s7,s8,s9 not changed) // #1016: ; // #1017: ; // @118 #1018: [wait_SF_ready] 30101 // @118 #1018: CALL(SF_byte_read) ;read status register into s0 12080 // @119 #1019: TEST(s0,128) ;test ready/busy flag 35118 // @11a #1020: JUMP(Z,wait_SF_ready) 30115 // @11b #1021: CALL(set_SF_read_array_mode) ;restore normal read array mode 2a000 // @11c #1022: RETURN // #1023: ; // #1024: ; // #1025: ; // #1026: ; // #1027: ;************************************************************************************** // #1028: ; UART communication routines // #1029: ;************************************************************************************** // #1030: ; // #1031: ; Read one character from the UART // #1032: ; // #1033: ; Character read will be returned in a register called 'UART_data'. // #1034: ; // #1035: ; The routine first tests the receiver FIFO buffer to see if data is present. // #1036: ; If the FIFO is empty, the routine waits until there is a character to read. // #1037: ; As this could take any amount of time the wait loop could include a call to a // #1038: ; subroutine which performs a useful function. // #1039: ; // #1040: ; // #1041: ; Registers used s0 and UART_data // #1042: ; // @11d #1043: [read_from_UART] 04000 // @11d #1043: INPUT(s0,status_port) ;test Rx_FIFO buffer 12004 // @11e #1044: TEST(s0,rx_data_present) ;wait if empty 35521 // @11f #1045: JUMP(NZ,read_character) 3411d // @120 #1046: JUMP(read_from_UART) // @121 #1047: [read_character] 04f01 // @121 #1047: INPUT(UART_data,UART_read_port) ;read from FIFO 2a000 // @122 #1048: RETURN // #1049: ; // #1050: ; // #1051: ; // #1052: ; Transmit one character to the UART // #1053: ; // #1054: ; Character supplied in register called 'UART_data'. // #1055: ; // #1056: ; The routine first tests the transmit FIFO buffer to see if it is full. // #1057: ; If the FIFO is full, then the routine waits until it there is space. // #1058: ; // #1059: ; Registers used s0 // #1060: ; // @123 #1061: [send_to_UART] 04000 // @123 #1061: INPUT(s0,status_port) ;test Tx_FIFO buffer 12002 // @124 #1062: TEST(s0,tx_full) ;wait if full 35127 // @125 #1063: JUMP(Z,UART_write) 34123 // @126 #1064: JUMP(send_to_UART) // @127 #1065: [UART_write] 2cf08 // @127 #1065: OUTPUT(UART_data,UART_write_port) 2a000 // @128 #1066: RETURN // #1067: ; // #1068: ; // #1069: ; // #1070: ;************************************************************************************** // #1071: ;Useful ASCII conversion and handling routines // #1072: ;************************************************************************************** // #1073: ; // #1074: ; // #1075: ; // #1076: ;Convert character to upper case // #1077: ; // #1078: ;The character supplied in register UART_data. // #1079: ;If the character is in the range 'a' to 'z', it is converted // #1080: ;to the equivalent upper case character in the range 'A' to 'Z'. // #1081: ;All other characters remain unchanged. // #1082: ; // #1083: ;Registers used s0. // #1084: ; // @129 #1085: [upper_case] 14f61 // @129 #1085: COMPARE(UART_data,97) ;eliminate character codes below 'a' (61 hex) 2b800 // @12a #1086: RETURN(C) 14f7b // @12b #1087: COMPARE(UART_data,123) ;eliminate character codes above 'z' (7A hex) 2bc00 // @12c #1088: RETURN(NC) 0afdf // @12d #1089: AND(UART_data,DF) ;mask bit5 to convert to upper case 2a000 // @12e #1090: RETURN // #1091: ; // #1092: ; // #1093: ;Convert hexadecimal value provided in register s0 into ASCII characters // #1094: ; // #1095: ;The value provided must can be any value in the range 00 to FF and will be converted into // #1096: ;two ASCII characters. // #1097: ; The upper nibble will be represented by an ASCII character returned in register s2. // #1098: ; The lower nibble will be represented by an ASCII character returned in register s1. // #1099: ; // #1100: ;The ASCII representations of '0' to '9' are 30 to 39 hexadecimal which is simply 30 hex // #1101: ;added to the actual decimal value. The ASCII representations of 'A' to 'F' are 41 to 46 // #1102: ;hexadecimal requiring a further addition of 07 to the 30 already added. // #1103: ; // #1104: ;Registers used s0, s1 and s2. // #1105: ; // @12f #1106: [hex_byte_to_ASCII] 01100 // @12f #1106: LOAD(s1,s0) ;remember value supplied 2000e // @130 #1107: SR0(s0) ;isolate upper nibble 2000e // @131 #1108: SR0(s0) 2000e // @132 #1109: SR0(s0) 2000e // @133 #1110: SR0(s0) 3013b // @134 #1111: CALL(hex_to_ASCII) ;convert 01200 // @135 #1112: LOAD(s2,s0) ;upper nibble value in s2 01010 // @136 #1113: LOAD(s0,s1) ;restore complete value 0a00f // @137 #1114: AND(s0,15) ;isolate lower nibble 3013b // @138 #1115: CALL(hex_to_ASCII) ;convert 01100 // @139 #1116: LOAD(s1,s0) ;lower nibble value in s1 2a000 // @13a #1117: RETURN // #1118: ; // #1119: ;Convert hexadecimal value provided in register s0 into ASCII character // #1120: ; // #1121: ;Register used s0 // #1122: ; // @13b #1123: [hex_to_ASCII] 1c00a // @13b #1123: SUB(s0,10) ;test if value is in range 0 to 9 3593e // @13c #1124: JUMP(C,number_char) 18007 // @13d #1125: ADD(s0,7) ;ASCII char A to F in range 41 to 46 // @13e #1126: [number_char] 1803a // @13e #1126: ADD(s0,58) ;ASCII char 0 to 9 in range 30 to 40 2a000 // @13f #1127: RETURN // #1128: ; // #1129: ; // #1130: ;Send the two character HEX value of the register contents 's0' to the UART // #1131: ; // #1132: ;Registers used s0, s1, s2 // #1133: ; // @140 #1134: [send_hex_byte] 3012f // @140 #1134: CALL(hex_byte_to_ASCII) 01f20 // @141 #1135: LOAD(UART_data,s2) 30123 // @142 #1136: CALL(send_to_UART) 01f10 // @143 #1137: LOAD(UART_data,s1) 30123 // @144 #1138: CALL(send_to_UART) 2a000 // @145 #1139: RETURN // #1140: ; // #1141: ; // #1142: ;Send the six character HEX value of the register contents [s9,s8,s7] to the UART // #1143: ; // #1144: ;Registers used s0, s1, s2 // #1145: ; // @146 #1146: [send_hex_3bytes] 01090 // @146 #1146: LOAD(s0,s9) 30140 // @147 #1147: CALL(send_hex_byte) 01080 // @148 #1148: LOAD(s0,s8) 30140 // @149 #1149: CALL(send_hex_byte) 01070 // @14a #1150: LOAD(s0,s7) 30140 // @14b #1151: CALL(send_hex_byte) 2a000 // @14c #1152: RETURN // #1153: ; // #1154: ; // #1155: ;Display the two character HEX value of the register contents 's0' on the LCD display // #1156: ; // #1157: ;Registers used s0,s1,s2,s3,s4,s5 // #1158: ; // @14d #1159: [disp_hex_byte] 3012f // @14d #1159: CALL(hex_byte_to_ASCII) 01310 // @14e #1160: LOAD(s3,s1) ;remember least significant digit 01520 // @14f #1161: LOAD(s5,s2) 302fe // @150 #1162: CALL(LCD_write_data) ;display most significant digit 01530 // @151 #1163: LOAD(s5,s3) 302fe // @152 #1164: CALL(LCD_write_data) ;display least significant digit 2a000 // @153 #1165: RETURN // #1166: ; // #1167: ; // #1168: ; // #1169: ;************************************************************************************** // #1170: ; UART Text messages // #1171: ;************************************************************************************** // #1172: ; // #1173: ; // #1174: ;Send Carriage Return to the UART // #1175: ; // @154 #1176: [send_CR] 00f0d // @154 #1176: LOAD(UART_data,character_CR) 30123 // @155 #1177: CALL(send_to_UART) 2a000 // @156 #1178: RETURN // #1179: ; // #1180: ;Send a space to the UART // #1181: ; // @157 #1182: [send_space] 00f20 // @157 #1182: LOAD(UART_data,character_space) 30123 // @158 #1183: CALL(send_to_UART) 2a000 // @159 #1184: RETURN // #1185: ; // #1186: ; // #1187: ;Send an equals sign to the UART with a space each side // #1188: ; // @15a #1189: [send_equals] 30157 // @15a #1189: CALL(send_space) 00f3d // @15b #1190: LOAD(UART_data,character_equals) 30123 // @15c #1191: CALL(send_to_UART) 30157 // @15d #1192: CALL(send_space) 2a000 // @15e #1193: RETURN // #1194: ; // #1195: ; // #1196: ; // #1197: ;Send an minus sign (dash) to the UART with a space each side // #1198: ; // @15f #1199: [send_dash] 30157 // @15f #1199: CALL(send_space) 00f2d // @160 #1200: LOAD(UART_data,character_minus) 30123 // @161 #1201: CALL(send_to_UART) 30157 // @162 #1202: CALL(send_space) 2a000 // @163 #1203: RETURN // #1204: ; // #1205: ; // #1206: ;Send 'PicoBlaze Low Cost Design Security v1.00' string to the UART // #1207: ; // @164 #1208: [send_welcome] 30154 // @164 #1208: CALL(send_CR) 30154 // @165 #1209: CALL(send_CR) 00f50 // @166 #1210: LOAD(UART_data,character_P) 30123 // @167 #1211: CALL(send_to_UART) 00f69 // @168 #1212: LOAD(UART_data,character_i) 30123 // @169 #1213: CALL(send_to_UART) 00f63 // @16a #1214: LOAD(UART_data,character_c) 30123 // @16b #1215: CALL(send_to_UART) 00f6f // @16c #1216: LOAD(UART_data,character_o) 30123 // @16d #1217: CALL(send_to_UART) 00f42 // @16e #1218: LOAD(UART_data,character_B) 30123 // @16f #1219: CALL(send_to_UART) 00f6c // @170 #1220: LOAD(UART_data,character_l) 30123 // @171 #1221: CALL(send_to_UART) 00f61 // @172 #1222: LOAD(UART_data,character_a) 30123 // @173 #1223: CALL(send_to_UART) 00f7a // @174 #1224: LOAD(UART_data,character_z) 30123 // @175 #1225: CALL(send_to_UART) 00f65 // @176 #1226: LOAD(UART_data,character_e) 30123 // @177 #1227: CALL(send_to_UART) 30157 // @178 #1228: CALL(send_space) 00f4c // @179 #1229: LOAD(UART_data,character_L) 30123 // @17a #1230: CALL(send_to_UART) 00f6f // @17b #1231: LOAD(UART_data,character_o) 30123 // @17c #1232: CALL(send_to_UART) 00f77 // @17d #1233: LOAD(UART_data,character_w) 30123 // @17e #1234: CALL(send_to_UART) 30157 // @17f #1235: CALL(send_space) 00f43 // @180 #1236: LOAD(UART_data,character_C) 30123 // @181 #1237: CALL(send_to_UART) 00f6f // @182 #1238: LOAD(UART_data,character_o) 30123 // @183 #1239: CALL(send_to_UART) 00f73 // @184 #1240: LOAD(UART_data,character_s) 30123 // @185 #1241: CALL(send_to_UART) 00f74 // @186 #1242: LOAD(UART_data,character_t) 30123 // @187 #1243: CALL(send_to_UART) 30157 // @188 #1244: CALL(send_space) 00f44 // @189 #1245: LOAD(UART_data,character_D) 30123 // @18a #1246: CALL(send_to_UART) 00f65 // @18b #1247: LOAD(UART_data,character_e) 30123 // @18c #1248: CALL(send_to_UART) 00f73 // @18d #1249: LOAD(UART_data,character_s) 30123 // @18e #1250: CALL(send_to_UART) 00f69 // @18f #1251: LOAD(UART_data,character_i) 30123 // @190 #1252: CALL(send_to_UART) 00f67 // @191 #1253: LOAD(UART_data,character_g) 30123 // @192 #1254: CALL(send_to_UART) 00f6e // @193 #1255: LOAD(UART_data,character_n) 30123 // @194 #1256: CALL(send_to_UART) 30157 // @195 #1257: CALL(send_space) 00f53 // @196 #1258: LOAD(UART_data,character_S) 30123 // @197 #1259: CALL(send_to_UART) 00f65 // @198 #1260: LOAD(UART_data,character_e) 30123 // @199 #1261: CALL(send_to_UART) 00f63 // @19a #1262: LOAD(UART_data,character_c) 30123 // @19b #1263: CALL(send_to_UART) 00f75 // @19c #1264: LOAD(UART_data,character_u) 30123 // @19d #1265: CALL(send_to_UART) 00f72 // @19e #1266: LOAD(UART_data,character_r) 30123 // @19f #1267: CALL(send_to_UART) 00f69 // @1a0 #1268: LOAD(UART_data,character_i) 30123 // @1a1 #1269: CALL(send_to_UART) 00f74 // @1a2 #1270: LOAD(UART_data,character_t) 30123 // @1a3 #1271: CALL(send_to_UART) 00f79 // @1a4 #1272: LOAD(UART_data,character_y) 30123 // @1a5 #1273: CALL(send_to_UART) 30157 // @1a6 #1274: CALL(send_space) 00f76 // @1a7 #1275: LOAD(UART_data,character_v) 30123 // @1a8 #1276: CALL(send_to_UART) 00f31 // @1a9 #1277: LOAD(UART_data,character_1) 30123 // @1aa #1278: CALL(send_to_UART) 00f2e // @1ab #1279: LOAD(UART_data,character_fullstop) 30123 // @1ac #1280: CALL(send_to_UART) 00f30 // @1ad #1281: LOAD(UART_data,character_0) 30123 // @1ae #1282: CALL(send_to_UART) 00f30 // @1af #1283: LOAD(UART_data,character_0) 30123 // @1b0 #1284: CALL(send_to_UART) 30154 // @1b1 #1285: CALL(send_CR) 30154 // @1b2 #1286: CALL(send_CR) 2a000 // @1b3 #1287: RETURN // #1288: ; // #1289: ; // #1290: ; // #1291: ;Send 'Copyright Ken Chapman 2006' string to the UART // #1292: ; // #1293: ;This message is significant because it demonstrates that the design // #1294: ;now has a 'watermark'. The ASCII codes for this string will be // #1295: ;stored in the design configuration bit stream somewhere as well as // #1296: ;being played out by the UART. If someone tries to change or delete // #1297: ;this message the contents of the BRAM will change and the hardware // #1298: ;check of the BRAM contents will fail to match the expected value and // #1299: ;the design will again be disabled. // #1300: ; // @1b4 #1301: [send_Copyright] 00f43 // @1b4 #1301: LOAD(UART_data,character_C) 30123 // @1b5 #1302: CALL(send_to_UART) 00f6f // @1b6 #1303: LOAD(UART_data,character_o) 30123 // @1b7 #1304: CALL(send_to_UART) 00f70 // @1b8 #1305: LOAD(UART_data,character_p) 30123 // @1b9 #1306: CALL(send_to_UART) 00f79 // @1ba #1307: LOAD(UART_data,character_y) 30123 // @1bb #1308: CALL(send_to_UART) 00f72 // @1bc #1309: LOAD(UART_data,character_r) 30123 // @1bd #1310: CALL(send_to_UART) 00f69 // @1be #1311: LOAD(UART_data,character_i) 30123 // @1bf #1312: CALL(send_to_UART) 00f67 // @1c0 #1313: LOAD(UART_data,character_g) 30123 // @1c1 #1314: CALL(send_to_UART) 00f68 // @1c2 #1315: LOAD(UART_data,character_h) 30123 // @1c3 #1316: CALL(send_to_UART) 00f74 // @1c4 #1317: LOAD(UART_data,character_t) 30123 // @1c5 #1318: CALL(send_to_UART) 30157 // @1c6 #1319: CALL(send_space) 00f4b // @1c7 #1320: LOAD(UART_data,character_K) 30123 // @1c8 #1321: CALL(send_to_UART) 00f65 // @1c9 #1322: LOAD(UART_data,character_e) 30123 // @1ca #1323: CALL(send_to_UART) 00f6e // @1cb #1324: LOAD(UART_data,character_n) 30123 // @1cc #1325: CALL(send_to_UART) 30157 // @1cd #1326: CALL(send_space) 00f43 // @1ce #1327: LOAD(UART_data,character_C) 30123 // @1cf #1328: CALL(send_to_UART) 00f68 // @1d0 #1329: LOAD(UART_data,character_h) 30123 // @1d1 #1330: CALL(send_to_UART) 00f61 // @1d2 #1331: LOAD(UART_data,character_a) 30123 // @1d3 #1332: CALL(send_to_UART) 00f70 // @1d4 #1333: LOAD(UART_data,character_p) 30123 // @1d5 #1334: CALL(send_to_UART) 00f6d // @1d6 #1335: LOAD(UART_data,character_m) 30123 // @1d7 #1336: CALL(send_to_UART) 00f61 // @1d8 #1337: LOAD(UART_data,character_a) 30123 // @1d9 #1338: CALL(send_to_UART) 00f6e // @1da #1339: LOAD(UART_data,character_n) 30123 // @1db #1340: CALL(send_to_UART) 30157 // @1dc #1341: CALL(send_space) 00f32 // @1dd #1342: LOAD(UART_data,character_2) 30123 // @1de #1343: CALL(send_to_UART) 00f30 // @1df #1344: LOAD(UART_data,character_0) 30123 // @1e0 #1345: CALL(send_to_UART) 30123 // @1e1 #1346: CALL(send_to_UART) 00f36 // @1e2 #1347: LOAD(UART_data,character_6) 30123 // @1e3 #1348: CALL(send_to_UART) 30154 // @1e4 #1349: CALL(send_CR) 30154 // @1e5 #1350: CALL(send_CR) 2a000 // @1e6 #1351: RETURN // #1352: ; // #1353: ; // #1354: ; // #1355: ;Send 'FLASH ' string to the UART // #1356: ; // @1e7 #1357: [send_FLASH] 00f46 // @1e7 #1357: LOAD(UART_data,character_F) 30123 // @1e8 #1358: CALL(send_to_UART) 00f4c // @1e9 #1359: LOAD(UART_data,character_L) 30123 // @1ea #1360: CALL(send_to_UART) 00f41 // @1eb #1361: LOAD(UART_data,character_A) 30123 // @1ec #1362: CALL(send_to_UART) 00f53 // @1ed #1363: LOAD(UART_data,character_S) 30123 // @1ee #1364: CALL(send_to_UART) 00f48 // @1ef #1365: LOAD(UART_data,character_H) 30123 // @1f0 #1366: CALL(send_to_UART) 2a000 // @1f1 #1367: RETURN // #1368: ; // #1369: ; // #1370: ; // #1371: ;Send 'FLASH Serial Number = ' string to the UART // #1372: ; // @1f2 #1373: [send_FLASH_Serial_Number] 301e7 // @1f2 #1373: CALL(send_FLASH) 30157 // @1f3 #1374: CALL(send_space) 00f53 // @1f4 #1375: LOAD(UART_data,character_S) 30123 // @1f5 #1376: CALL(send_to_UART) 00f65 // @1f6 #1377: LOAD(UART_data,character_e) 30123 // @1f7 #1378: CALL(send_to_UART) 00f72 // @1f8 #1379: LOAD(UART_data,character_r) 30123 // @1f9 #1380: CALL(send_to_UART) 00f69 // @1fa #1381: LOAD(UART_data,character_i) 30123 // @1fb #1382: CALL(send_to_UART) 00f61 // @1fc #1383: LOAD(UART_data,character_a) 30123 // @1fd #1384: CALL(send_to_UART) 00f6c // @1fe #1385: LOAD(UART_data,character_l) 30123 // @1ff #1386: CALL(send_to_UART) 30157 // @200 #1387: CALL(send_space) 00f4e // @201 #1388: LOAD(UART_data,character_N) 30123 // @202 #1389: CALL(send_to_UART) 00f75 // @203 #1390: LOAD(UART_data,character_u) 30123 // @204 #1391: CALL(send_to_UART) 00f6d // @205 #1392: LOAD(UART_data,character_m) 30123 // @206 #1393: CALL(send_to_UART) 00f62 // @207 #1394: LOAD(UART_data,character_b) 30123 // @208 #1395: CALL(send_to_UART) 00f65 // @209 #1396: LOAD(UART_data,character_e) 30123 // @20a #1397: CALL(send_to_UART) 00f72 // @20b #1398: LOAD(UART_data,character_r) 30123 // @20c #1399: CALL(send_to_UART) 3015a // @20d #1400: CALL(send_equals) 2a000 // @20e #1401: RETURN // #1402: ; // #1403: ; // #1404: ;Send 'Auth' string to the UART // #1405: ; // @20f #1406: [send_Auth] 00f41 // @20f #1406: LOAD(UART_data,character_A) 30123 // @210 #1407: CALL(send_to_UART) 00f75 // @211 #1408: LOAD(UART_data,character_u) 30123 // @212 #1409: CALL(send_to_UART) 00f74 // @213 #1410: LOAD(UART_data,character_t) 30123 // @214 #1411: CALL(send_to_UART) 00f68 // @215 #1412: LOAD(UART_data,character_h) 30123 // @216 #1413: CALL(send_to_UART) 2a000 // @217 #1414: RETURN // #1415: ; // #1416: ;Send 'Authoris' to the UART // #1417: ; // @218 #1418: [send_Authoris] 3020f // @218 #1418: CALL(send_Auth) 00f6f // @219 #1419: LOAD(UART_data,character_o) 30123 // @21a #1420: CALL(send_to_UART) 00f72 // @21b #1421: LOAD(UART_data,character_r) 30123 // @21c #1422: CALL(send_to_UART) 00f69 // @21d #1423: LOAD(UART_data,character_i) 30123 // @21e #1424: CALL(send_to_UART) 00f73 // @21f #1425: LOAD(UART_data,character_s) 30123 // @220 #1426: CALL(send_to_UART) 2a000 // @221 #1427: RETURN // #1428: ; // #1429: ;Send 'Authorisation' to the UART // #1430: ; // @222 #1431: [send_Authorisation] 30218 // @222 #1431: CALL(send_Authoris) 00f61 // @223 #1432: LOAD(UART_data,character_a) 30123 // @224 #1433: CALL(send_to_UART) 00f74 // @225 #1434: LOAD(UART_data,character_t) 30123 // @226 #1435: CALL(send_to_UART) 00f69 // @227 #1436: LOAD(UART_data,character_i) 30123 // @228 #1437: CALL(send_to_UART) 00f6f // @229 #1438: LOAD(UART_data,character_o) 30123 // @22a #1439: CALL(send_to_UART) 00f6e // @22b #1440: LOAD(UART_data,character_n) 30123 // @22c #1441: CALL(send_to_UART) 2a000 // @22d #1442: RETURN // #1443: ; // #1444: ;Send 'Authorise' to the UART // #1445: ; // @22e #1446: [send_Authorise] 30218 // @22e #1446: CALL(send_Authoris) 00f65 // @22f #1447: LOAD(UART_data,character_e) 30123 // @230 #1448: CALL(send_to_UART) 2a000 // @231 #1449: RETURN // #1450: ; // #1451: ;Send 'Authentication' string to the UART // #1452: ; // @232 #1453: [send_Authentication] 3020f // @232 #1453: CALL(send_Auth) 00f65 // @233 #1454: LOAD(UART_data,character_e) 30123 // @234 #1455: CALL(send_to_UART) 00f6e // @235 #1456: LOAD(UART_data,character_n) 30123 // @236 #1457: CALL(send_to_UART) 00f74 // @237 #1458: LOAD(UART_data,character_t) 30123 // @238 #1459: CALL(send_to_UART) 00f69 // @239 #1460: LOAD(UART_data,character_i) 30123 // @23a #1461: CALL(send_to_UART) 00f63 // @23b #1462: LOAD(UART_data,character_c) 30123 // @23c #1463: CALL(send_to_UART) 00f61 // @23d #1464: LOAD(UART_data,character_a) 30123 // @23e #1465: CALL(send_to_UART) 00f74 // @23f #1466: LOAD(UART_data,character_t) 30123 // @240 #1467: CALL(send_to_UART) 00f69 // @241 #1468: LOAD(UART_data,character_i) 30123 // @242 #1469: CALL(send_to_UART) 00f6f // @243 #1470: LOAD(UART_data,character_o) 30123 // @244 #1471: CALL(send_to_UART) 00f6e // @245 #1472: LOAD(UART_data,character_n) 30123 // @246 #1473: CALL(send_to_UART) 2a000 // @247 #1474: RETURN // #1475: ; // #1476: ; // #1477: ;Send 'FLASH CRC = ' string to the UART // #1478: ; // @248 #1479: [send_FLASH_CRC] 301e7 // @248 #1479: CALL(send_FLASH) // #1480: ; // #1481: ; // #1482: ;Send ' CRC = ' string to the UART // #1483: ; // @249 #1484: [send_CRC] 30157 // @249 #1484: CALL(send_space) 00f43 // @24a #1485: LOAD(UART_data,character_C) 30123 // @24b #1486: CALL(send_to_UART) 00f52 // @24c #1487: LOAD(UART_data,character_R) 30123 // @24d #1488: CALL(send_to_UART) 00f43 // @24e #1489: LOAD(UART_data,character_C) 30123 // @24f #1490: CALL(send_to_UART) 3015a // @250 #1491: CALL(send_equals) 2a000 // @251 #1492: RETURN // #1493: ; // #1494: ; // #1495: ; // #1496: ;Send 'Computed CRC = ' string to the UART // #1497: ; // @252 #1498: [send_Computed_CRC] 00f43 // @252 #1498: LOAD(UART_data,character_C) 30123 // @253 #1499: CALL(send_to_UART) 00f6f // @254 #1500: LOAD(UART_data,character_o) 30123 // @255 #1501: CALL(send_to_UART) 00f6d // @256 #1502: LOAD(UART_data,character_m) 30123 // @257 #1503: CALL(send_to_UART) 00f70 // @258 #1504: LOAD(UART_data,character_p) 30123 // @259 #1505: CALL(send_to_UART) 00f75 // @25a #1506: LOAD(UART_data,character_u) 30123 // @25b #1507: CALL(send_to_UART) 00f74 // @25c #1508: LOAD(UART_data,character_t) 30123 // @25d #1509: CALL(send_to_UART) 00f65 // @25e #1510: LOAD(UART_data,character_e) 30123 // @25f #1511: CALL(send_to_UART) 00f64 // @260 #1512: LOAD(UART_data,character_d) 30123 // @261 #1513: CALL(send_to_UART) 34249 // @262 #1514: JUMP(send_CRC) // #1515: ; // #1516: ; // #1517: ;Send 'Erase ' string to the UART // #1518: ; // @263 #1519: [send_Erase] 00f45 // @263 #1519: LOAD(UART_data,character_E) 30123 // @264 #1520: CALL(send_to_UART) 00f72 // @265 #1521: LOAD(UART_data,character_r) 30123 // @266 #1522: CALL(send_to_UART) 00f61 // @267 #1523: LOAD(UART_data,character_a) 30123 // @268 #1524: CALL(send_to_UART) 00f73 // @269 #1525: LOAD(UART_data,character_s) 30123 // @26a #1526: CALL(send_to_UART) 00f65 // @26b #1527: LOAD(UART_data,character_e) 30123 // @26c #1528: CALL(send_to_UART) 30157 // @26d #1529: CALL(send_space) 2a000 // @26e #1530: RETURN // #1531: ; // #1532: ; // #1533: ;Send 'Erase Authorisation in progress' string to the UART // #1534: ; // @26f #1535: [send_Erase_in_progress] 30154 // @26f #1535: CALL(send_CR) 30263 // @270 #1536: CALL(send_Erase) 30222 // @271 #1537: CALL(send_Authorisation) 30157 // @272 #1538: CALL(send_space) 00f69 // @273 #1539: LOAD(UART_data,character_i) 30123 // @274 #1540: CALL(send_to_UART) 00f6e // @275 #1541: LOAD(UART_data,character_n) 30123 // @276 #1542: CALL(send_to_UART) 30157 // @277 #1543: CALL(send_space) 00f50 // @278 #1544: LOAD(UART_data,character_P) 30123 // @279 #1545: CALL(send_to_UART) 00f72 // @27a #1546: LOAD(UART_data,character_r) 30123 // @27b #1547: CALL(send_to_UART) 00f6f // @27c #1548: LOAD(UART_data,character_o) 30123 // @27d #1549: CALL(send_to_UART) 00f67 // @27e #1550: LOAD(UART_data,character_g) 30123 // @27f #1551: CALL(send_to_UART) 00f72 // @280 #1552: LOAD(UART_data,character_r) 30123 // @281 #1553: CALL(send_to_UART) 00f65 // @282 #1554: LOAD(UART_data,character_e) 30123 // @283 #1555: CALL(send_to_UART) 00f73 // @284 #1556: LOAD(UART_data,character_s) 30123 // @285 #1557: CALL(send_to_UART) 30123 // @286 #1558: CALL(send_to_UART) 30154 // @287 #1559: CALL(send_CR) 2a000 // @288 #1560: RETURN // #1561: ; // #1562: ; // #1563: ;Send 'OK' to the UART // #1564: ; // @289 #1565: [send_OK] 00f4f // @289 #1565: LOAD(UART_data,character_O) 30123 // @28a #1566: CALL(send_to_UART) 00f4b // @28b #1567: LOAD(UART_data,character_K) 30123 // @28c #1568: CALL(send_to_UART) 30154 // @28d #1569: CALL(send_CR) 2a000 // @28e #1570: RETURN // #1571: ; // #1572: ; // #1573: ;Send ' FAILED' to the UART // #1574: ; // @28f #1575: [send_FAILED] 30157 // @28f #1575: CALL(send_space) 00f46 // @290 #1576: LOAD(UART_data,character_F) 30123 // @291 #1577: CALL(send_to_UART) 00f41 // @292 #1578: LOAD(UART_data,character_A) 30123 // @293 #1579: CALL(send_to_UART) 00f49 // @294 #1580: LOAD(UART_data,character_I) 30123 // @295 #1581: CALL(send_to_UART) 00f4c // @296 #1582: LOAD(UART_data,character_L) 30123 // @297 #1583: CALL(send_to_UART) 00f45 // @298 #1584: LOAD(UART_data,character_E) 30123 // @299 #1585: CALL(send_to_UART) 00f44 // @29a #1586: LOAD(UART_data,character_D) 30123 // @29b #1587: CALL(send_to_UART) 2a000 // @29c #1588: RETURN // #1589: ; // #1590: ; // #1591: ;Send ' PASSED' to the UART // #1592: ; // @29d #1593: [send_PASSED] 30157 // @29d #1593: CALL(send_space) 00f50 // @29e #1594: LOAD(UART_data,character_P) 30123 // @29f #1595: CALL(send_to_UART) 00f41 // @2a0 #1596: LOAD(UART_data,character_A) 30123 // @2a1 #1597: CALL(send_to_UART) 00f53 // @2a2 #1598: LOAD(UART_data,character_S) 30123 // @2a3 #1599: CALL(send_to_UART) 30123 // @2a4 #1600: CALL(send_to_UART) 00f45 // @2a5 #1601: LOAD(UART_data,character_E) 30123 // @2a6 #1602: CALL(send_to_UART) 00f44 // @2a7 #1603: LOAD(UART_data,character_D) 30123 // @2a8 #1604: CALL(send_to_UART) 2a000 // @2a9 #1605: RETURN // #1606: ; // #1607: ; // #1608: ; // #1609: ;Send 'Writing Authorisation' to the UART // #1610: ; // @2aa #1611: [send_Writing] 30154 // @2aa #1611: CALL(send_CR) 00f57 // @2ab #1612: LOAD(UART_data,character_W) 30123 // @2ac #1613: CALL(send_to_UART) 00f72 // @2ad #1614: LOAD(UART_data,character_r) 30123 // @2ae #1615: CALL(send_to_UART) 00f69 // @2af #1616: LOAD(UART_data,character_i) 30123 // @2b0 #1617: CALL(send_to_UART) 00f74 // @2b1 #1618: LOAD(UART_data,character_t) 30123 // @2b2 #1619: CALL(send_to_UART) 00f69 // @2b3 #1620: LOAD(UART_data,character_i) 30123 // @2b4 #1621: CALL(send_to_UART) 00f6e // @2b5 #1622: LOAD(UART_data,character_n) 30123 // @2b6 #1623: CALL(send_to_UART) 00f67 // @2b7 #1624: LOAD(UART_data,character_g) 30123 // @2b8 #1625: CALL(send_to_UART) 30157 // @2b9 #1626: CALL(send_space) 30222 // @2ba #1627: CALL(send_Authorisation) 2a000 // @2bb #1628: RETURN // #1629: ; // #1630: ;Send simple menu of options to the UART // #1631: ; // #1632: ; // @2bc #1633: [send_Menu] 30154 // @2bc #1633: CALL(send_CR) 30154 // @2bd #1634: CALL(send_CR) 00f4d // @2be #1635: LOAD(UART_data,character_M) 30123 // @2bf #1636: CALL(send_to_UART) 00f65 // @2c0 #1637: LOAD(UART_data,character_e) 30123 // @2c1 #1638: CALL(send_to_UART) 00f6e // @2c2 #1639: LOAD(UART_data,character_n) 30123 // @2c3 #1640: CALL(send_to_UART) 00f75 // @2c4 #1641: LOAD(UART_data,character_u) 30123 // @2c5 #1642: CALL(send_to_UART) 30154 // @2c6 #1643: CALL(send_CR) 30154 // @2c7 #1644: CALL(send_CR) 00f52 // @2c8 #1645: LOAD(UART_data,character_R) 30123 // @2c9 #1646: CALL(send_to_UART) 3015f // @2ca #1647: CALL(send_dash) 00f52 // @2cb #1648: LOAD(UART_data,character_R) 30123 // @2cc #1649: CALL(send_to_UART) 00f65 // @2cd #1650: LOAD(UART_data,character_e) 30123 // @2ce #1651: CALL(send_to_UART) 00f61 // @2cf #1652: LOAD(UART_data,character_a) 30123 // @2d0 #1653: CALL(send_to_UART) 00f64 // @2d1 #1654: LOAD(UART_data,character_d) 30123 // @2d2 #1655: CALL(send_to_UART) 30157 // @2d3 #1656: CALL(send_space) 30222 // @2d4 #1657: CALL(send_Authorisation) 30154 // @2d5 #1658: CALL(send_CR) 00f45 // @2d6 #1659: LOAD(UART_data,character_E) 30123 // @2d7 #1660: CALL(send_to_UART) 3015f // @2d8 #1661: CALL(send_dash) 30263 // @2d9 #1662: CALL(send_Erase) 30222 // @2da #1663: CALL(send_Authorisation) 30154 // @2db #1664: CALL(send_CR) 00f41 // @2dc #1665: LOAD(UART_data,character_A) 30123 // @2dd #1666: CALL(send_to_UART) 3015f // @2de #1667: CALL(send_dash) 3022e // @2df #1668: CALL(send_Authorise) 30154 // @2e0 #1669: CALL(send_CR) 30154 // @2e1 #1670: CALL(send_CR) 00f3e // @2e2 #1671: LOAD(UART_data,character_greater_than) ;prompt for input 30123 // @2e3 #1672: CALL(send_to_UART) 2a000 // @2e4 #1673: RETURN // #1674: ; // #1675: ;************************************************************************************** // #1676: ;LCD Character Module Routines // #1677: ;************************************************************************************** // #1678: ; // #1679: ;LCD module is a 16 character by 2 line display but all displays are very similar // #1680: ;The 4-wire data interface will be used (DB4 to DB7). // #1681: ; // #1682: ;The LCD modules are relatively slow and software delay loops are used to slow down // #1683: ;KCPSM3 adequately for the LCD to communicate. The delay routines are provided in // #1684: ;a different section (see above in this case). // #1685: ; // #1686: ; // #1687: ;Pulse LCD enable signal 'E' high for greater than 230ns (1us is used). // #1688: ; // #1689: ;Register s4 should define the current state of the LCD output port. // #1690: ; // #1691: ;Registers used s0, s4 // #1692: ; // @2e5 #1693: [LCD_pulse_E] 0e401 // @2e5 #1693: XOR(s4,LCD_E) ;E=1 2c420 // @2e6 #1694: OUTPUT(s4,LCD_output_port) 30348 // @2e7 #1695: CALL(delay_1us) 0e401 // @2e8 #1696: XOR(s4,LCD_E) ;E=0 2c420 // @2e9 #1697: OUTPUT(s4,LCD_output_port) 2a000 // @2ea #1698: RETURN // #1699: ; // #1700: ;Write 4-bit instruction to LCD display. // #1701: ; // #1702: ;The 4-bit instruction should be provided in the upper 4-bits of register s4. // #1703: ;Note that this routine does not release the master enable but as it is only // #1704: ;used during initialisation and as part of the 8-bit instruction write it // #1705: ;should be acceptable. // #1706: ; // #1707: ;Registers used s4 // #1708: ; // @2eb #1709: [LCD_write_inst4] 0a4f8 // @2eb #1709: AND(s4,F8) ;Enable=1 RS=0 Instruction, RW=0 Write, E=0 2c420 // @2ec #1710: OUTPUT(s4,LCD_output_port) ;set up RS and RW >40ns before enable pulse 302e5 // @2ed #1711: CALL(LCD_pulse_E) 2a000 // @2ee #1712: RETURN // #1713: ; // #1714: ; // #1715: ;Write 8-bit instruction to LCD display. // #1716: ; // #1717: ;The 8-bit instruction should be provided in register s5. // #1718: ;Instructions are written using the following sequence // #1719: ; Upper nibble // #1720: ; wait >1us // #1721: ; Lower nibble // #1722: ; wait >40us // #1723: ; // #1724: ;Registers used s0, s1, s4, s5 // #1725: ; // @2ef #1726: [LCD_write_inst8] 01450 // @2ef #1726: LOAD(s4,s5) 0a4f0 // @2f0 #1727: AND(s4,F0) ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 0c408 // @2f1 #1728: OR(s4,LCD_drive) ;Enable=1 302eb // @2f2 #1729: CALL(LCD_write_inst4) ;write upper nibble 30348 // @2f3 #1730: CALL(delay_1us) ;wait >1us 01450 // @2f4 #1731: LOAD(s4,s5) ;select lower nibble with 20407 // @2f5 #1732: SL1(s4) ;Enable=1 20406 // @2f6 #1733: SL0(s4) ;RS=0 Instruction 20406 // @2f7 #1734: SL0(s4) ;RW=0 Write 20406 // @2f8 #1735: SL0(s4) ;E=0 302eb // @2f9 #1736: CALL(LCD_write_inst4) ;write lower nibble 3034c // @2fa #1737: CALL(delay_40us) ;wait >40us 004f0 // @2fb #1738: LOAD(s4,F0) ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 2c420 // @2fc #1739: OUTPUT(s4,LCD_output_port) ;Release master enable 2a000 // @2fd #1740: RETURN // #1741: ; // #1742: ; // #1743: ; // #1744: ;Write 8-bit data to LCD display. // #1745: ; // #1746: ;The 8-bit data should be provided in register s5. // #1747: ;Data bytes are written using the following sequence // #1748: ; Upper nibble // #1749: ; wait >1us // #1750: ; Lower nibble // #1751: ; wait >40us // #1752: ; // #1753: ;Registers used s0, s1, s4, s5 // #1754: ; // @2fe #1755: [LCD_write_data] 01450 // @2fe #1755: LOAD(s4,s5) 0a4f0 // @2ff #1756: AND(s4,F0) ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 0c40c // @300 #1757: OR(s4,12) ;Enable=1 RS=1 Data, RW=0 Write, E=0 2c420 // @301 #1758: OUTPUT(s4,LCD_output_port) ;set up RS and RW >40ns before enable pulse 302e5 // @302 #1759: CALL(LCD_pulse_E) ;write upper nibble 30348 // @303 #1760: CALL(delay_1us) ;wait >1us 01450 // @304 #1761: LOAD(s4,s5) ;select lower nibble with 20407 // @305 #1762: SL1(s4) ;Enable=1 20407 // @306 #1763: SL1(s4) ;RS=1 Data 20406 // @307 #1764: SL0(s4) ;RW=0 Write 20406 // @308 #1765: SL0(s4) ;E=0 2c420 // @309 #1766: OUTPUT(s4,LCD_output_port) ;set up RS and RW >40ns before enable pulse 302e5 // @30a #1767: CALL(LCD_pulse_E) ;write lower nibble 3034c // @30b #1768: CALL(delay_40us) ;wait >40us 004f0 // @30c #1769: LOAD(s4,F0) ;Enable=0 RS=0 Instruction, RW=0 Write, E=0 2c420 // @30d #1770: OUTPUT(s4,LCD_output_port) ;Release master enable 2a000 // @30e #1771: RETURN // #1772: ; // #1773: ; // #1774: ; // #1775: ; // #1776: ;Read 8-bit data from LCD display. // #1777: ; // #1778: ;The 8-bit data will be read from the current LCD memory address // #1779: ;and will be returned in register s5. // #1780: ;It is advisable to set the LCD address (cursor position) before // #1781: ;using the data read for the first time otherwise the display may // #1782: ;generate invalid data on the first read. // #1783: ; // #1784: ;Data bytes are read using the following sequence // #1785: ; Upper nibble // #1786: ; wait >1us // #1787: ; Lower nibble // #1788: ; wait >40us // #1789: ; // #1790: ;Registers used s0, s1, s4, s5 // #1791: ; // @30f #1792: [LCD_read_data8] 0040e // @30f #1792: LOAD(s4,14) ;Enable=1 RS=1 Data, RW=1 Read, E=0 2c420 // @310 #1793: OUTPUT(s4,LCD_output_port) ;set up RS and RW >40ns before enable pulse 0e401 // @311 #1794: XOR(s4,LCD_E) ;E=1 2c420 // @312 #1795: OUTPUT(s4,LCD_output_port) 30348 // @313 #1796: CALL(delay_1us) ;wait >260ns to access data 04503 // @314 #1797: INPUT(s5,LCD_input_port) ;read upper nibble 0e401 // @315 #1798: XOR(s4,LCD_E) ;E=0 2c420 // @316 #1799: OUTPUT(s4,LCD_output_port) 30348 // @317 #1800: CALL(delay_1us) ;wait >1us 0e401 // @318 #1801: XOR(s4,LCD_E) ;E=1 2c420 // @319 #1802: OUTPUT(s4,LCD_output_port) 30348 // @31a #1803: CALL(delay_1us) ;wait >260ns to access data 04003 // @31b #1804: INPUT(s0,LCD_input_port) ;read lower nibble 0e401 // @31c #1805: XOR(s4,LCD_E) ;E=0 2c420 // @31d #1806: OUTPUT(s4,LCD_output_port) 0a5f0 // @31e #1807: AND(s5,F0) ;merge upper and lower nibbles 2000e // @31f #1808: SR0(s0) 2000e // @320 #1809: SR0(s0) 2000e // @321 #1810: SR0(s0) 2000e // @322 #1811: SR0(s0) 0d500 // @323 #1812: OR(s5,s0) 00404 // @324 #1813: LOAD(s4,4) ;Enable=0 RS=1 Data, RW=0 Write, E=0 2c420 // @325 #1814: OUTPUT(s4,LCD_output_port) ;Stop reading 5V device and release master enable 3034c // @326 #1815: CALL(delay_40us) ;wait >40us 2a000 // @327 #1816: RETURN // #1817: ; // #1818: ; // #1819: ;Reset and initialise display to communicate using 4-bit data mode // #1820: ;Includes routine to clear the display. // #1821: ; // #1822: ;Requires the 4-bit instructions 3,3,3,2 to be sent with suitable delays // #1823: ;following by the 8-bit instructions to set up the display. // #1824: ; // #1825: ; 28 = '001' Function set, '0' 4-bit mode, '1' 2-line, '0' 5x7 dot matrix, 'xx' // #1826: ; 06 = '000001' Entry mode, '1' increment, '0' no display shift // #1827: ; 0C = '00001' Display control, '1' display on, '0' cursor off, '0' cursor blink off // #1828: ; 01 = '00000001' Display clear // #1829: ; // #1830: ;Registers used s0, s1, s2, s3, s4 // #1831: ; // @328 #1832: [LCD_reset] 30356 // @328 #1832: CALL(delay_20ms) ;wait more that 15ms for display to be ready 00430 // @329 #1833: LOAD(s4,48) 302eb // @32a #1834: CALL(LCD_write_inst4) ;send '3' 30356 // @32b #1835: CALL(delay_20ms) ;wait >4.1ms 302eb // @32c #1836: CALL(LCD_write_inst4) ;send '3' 30351 // @32d #1837: CALL(delay_1ms) ;wait >100us 302eb // @32e #1838: CALL(LCD_write_inst4) ;send '3' 3034c // @32f #1839: CALL(delay_40us) ;wait >40us 00420 // @330 #1840: LOAD(s4,32) 302eb // @331 #1841: CALL(LCD_write_inst4) ;send '2' 3034c // @332 #1842: CALL(delay_40us) ;wait >40us 00528 // @333 #1843: LOAD(s5,40) ;Function set 302ef // @334 #1844: CALL(LCD_write_inst8) 00506 // @335 #1845: LOAD(s5,6) ;Entry mode 302ef // @336 #1846: CALL(LCD_write_inst8) 0050c // @337 #1847: LOAD(s5,12) ;Display control 302ef // @338 #1848: CALL(LCD_write_inst8) // @339 #1849: [LCD_clear] 00501 // @339 #1849: LOAD(s5,1) ;Display clear 302ef // @33a #1850: CALL(LCD_write_inst8) 30351 // @33b #1851: CALL(delay_1ms) ;wait >1.64ms for display to clear 30351 // @33c #1852: CALL(delay_1ms) 2a000 // @33d #1853: RETURN // #1854: ; // #1855: ;Position the cursor ready for characters to be written. // #1856: ;The display is formed of 2 lines of 16 characters and each // #1857: ;position has a corresponding address as indicated below. // #1858: ; // #1859: ; Character position // #1860: ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // #1861: ; // #1862: ; Line 1 - 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F // #1863: ; Line 2 - C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF // #1864: ; // #1865: ;This routine will set the cursor position using the value provided // #1866: ;in register s5. The upper nibble will define the line and the lower // #1867: ;nibble the character position on the line. // #1868: ; Example s5 = 2B will position the cursor on line 2 position 11 // #1869: ; // #1870: ;Registers used s0, s1, s2, s3, s4 // #1871: ; // @33e #1872: [LCD_cursor] 12510 // @33e #1872: TEST(s5,16) ;test for line 1 35344 // @33f #1873: JUMP(Z,set_line2) 0a50f // @340 #1874: AND(s5,15) ;make address in range 80 to 8F for line 1 0c580 // @341 #1875: OR(s5,128) 302ef // @342 #1876: CALL(LCD_write_inst8) ;instruction write to set cursor 2a000 // @343 #1877: RETURN // @344 #1878: [set_line2] 0a50f // @344 #1878: AND(s5,15) ;make address in range C0 to CF for line 2 0c5c0 // @345 #1879: OR(s5,C0) 302ef // @346 #1880: CALL(LCD_write_inst8) ;instruction write to set cursor 2a000 // @347 #1881: RETURN // #1882: ; // #1883: ;************************************************************************************** // #1884: ;Software delay routines // #1885: ;************************************************************************************** // #1886: ; // #1887: ; // #1888: ; // #1889: ;Delay of 1us. // #1890: ; // #1891: ;Constant value defines reflects the clock applied to KCPSM3. Every instruction // #1892: ;executes in 2 clock cycles making the calculation highly predictable. The '6' in // #1893: ;the following equation even allows for 'CALL delay_1us' instruction in the initiating code. // #1894: ; // #1895: ; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz // #1896: ; // #1897: ;Registers used s0 // #1898: ; // @348 #1899: [delay_1us] 0000b // @348 #1899: LOAD(s0,delay_1us_constant) // @349 #1900: [wait_1us] 1c001 // @349 #1900: SUB(s0,1) 35749 // @34a #1901: JUMP(NZ,wait_1us) 2a000 // @34b #1902: RETURN // #1903: ; // #1904: ;Delay of 40us. // #1905: ; // #1906: ;Registers used s0, s1 // #1907: ; // @34c #1908: [delay_40us] 00128 // @34c #1908: LOAD(s1,40) ;40 x 1us = 40us // @34d #1909: [wait_40us] 30348 // @34d #1909: CALL(delay_1us) 1c101 // @34e #1910: SUB(s1,1) 3574d // @34f #1911: JUMP(NZ,wait_40us) 2a000 // @350 #1912: RETURN // #1913: ; // #1914: ; // #1915: ;Delay of 1ms. // #1916: ; // #1917: ;Registers used s0, s1, s2 // #1918: ; // @351 #1919: [delay_1ms] 00219 // @351 #1919: LOAD(s2,25) ;25 x 40us = 1ms // @352 #1920: [wait_1ms] 3034c // @352 #1920: CALL(delay_40us) 1c201 // @353 #1921: SUB(s2,1) 35752 // @354 #1922: JUMP(NZ,wait_1ms) 2a000 // @355 #1923: RETURN // #1924: ; // #1925: ;Delay of 20ms. // #1926: ; // #1927: ;Delay of 20ms used during initialisation. // #1928: ; // #1929: ;Registers used s0, s1, s2, s3 // #1930: ; // @356 #1931: [delay_20ms] 00314 // @356 #1931: LOAD(s3,20) ;20 x 1ms = 20ms // @357 #1932: [wait_20ms] 30351 // @357 #1932: CALL(delay_1ms) 1c301 // @358 #1933: SUB(s3,1) 35757 // @359 #1934: JUMP(NZ,wait_20ms) 2a000 // @35a #1935: RETURN // #1936: ; // #1937: ;Delay of approximately 1 second. // #1938: ; // #1939: ;Registers used s0, s1, s2, s3, s4 // #1940: ; // @35b #1941: [delay_1s] 00432 // @35b #1941: LOAD(s4,50) ;50 x 20ms = 1000ms // @35c #1942: [wait_1s] 30356 // @35c #1942: CALL(delay_20ms) 1c401 // @35d #1943: SUB(s4,1) 3575c // @35e #1944: JUMP(NZ,wait_1s) 2a000 // @35f #1945: RETURN // #1946: ; // #1947: ; // #1948: ;Delay of approximately N seconds where 'N' is provided in register s5. // #1949: ; // #1950: ;Registers used s0, s1, s2, s3, s4, s5 // #1951: ; // @360 #1952: [delay_Ns] 3035b // @360 #1952: CALL(delay_1s) 1c501 // @361 #1953: SUB(s5,1) 35760 // @362 #1954: JUMP(NZ,delay_Ns) 2a000 // @363 #1955: RETURN // #1956: ; // #1957: ; // #1958: ; // #1959: ;************************************************************************************** // #1960: ;LCD text messages // #1961: ;************************************************************************************** // #1962: ; // #1963: ; // #1964: ; // #1965: ;Display 'PicoBlaze' on LCD at current cursor position // #1966: ; // #1967: ; // @364 #1968: [disp_PicoBlaze] 00550 // @364 #1968: LOAD(s5,character_P) 302fe // @365 #1969: CALL(LCD_write_data) 00569 // @366 #1970: LOAD(s5,character_i) 302fe // @367 #1971: CALL(LCD_write_data) 00563 // @368 #1972: LOAD(s5,character_c) 302fe // @369 #1973: CALL(LCD_write_data) 0056f // @36a #1974: LOAD(s5,character_o) 302fe // @36b #1975: CALL(LCD_write_data) 00542 // @36c #1976: LOAD(s5,character_B) 302fe // @36d #1977: CALL(LCD_write_data) 0056c // @36e #1978: LOAD(s5,character_l) 302fe // @36f #1979: CALL(LCD_write_data) 00561 // @370 #1980: LOAD(s5,character_a) 302fe // @371 #1981: CALL(LCD_write_data) 0057a // @372 #1982: LOAD(s5,character_z) 302fe // @373 #1983: CALL(LCD_write_data) 00565 // @374 #1984: LOAD(s5,character_e) 302fe // @375 #1985: CALL(LCD_write_data) 2a000 // @376 #1986: RETURN // #1987: ; // #1988: ; // #1989: ;Display 'Security' on LCD at current cursor position // #1990: ; // #1991: ; // @377 #1992: [disp_Security] 00553 // @377 #1992: LOAD(s5,character_S) 302fe // @378 #1993: CALL(LCD_write_data) 00565 // @379 #1994: LOAD(s5,character_e) 302fe // @37a #1995: CALL(LCD_write_data) 00563 // @37b #1996: LOAD(s5,character_c) 302fe // @37c #1997: CALL(LCD_write_data) 00575 // @37d #1998: LOAD(s5,character_u) 302fe // @37e #1999: CALL(LCD_write_data) 00572 // @37f #2000: LOAD(s5,character_r) 302fe // @380 #2001: CALL(LCD_write_data) 00569 // @381 #2002: LOAD(s5,character_i) 302fe // @382 #2003: CALL(LCD_write_data) 00574 // @383 #2004: LOAD(s5,character_t) 302fe // @384 #2005: CALL(LCD_write_data) 00579 // @385 #2006: LOAD(s5,character_y) 302fe // @386 #2007: CALL(LCD_write_data) 2a000 // @387 #2008: RETURN // #2009: ; // #2010: ; // #2011: ;Display 'FLASH Serial No.' on LCD at current cursor position // #2012: ; // #2013: ; // @388 #2014: [disp_FLASH_Serial_No] 00546 // @388 #2014: LOAD(s5,character_F) 302fe // @389 #2015: CALL(LCD_write_data) 0054c // @38a #2016: LOAD(s5,character_L) 302fe // @38b #2017: CALL(LCD_write_data) 00541 // @38c #2018: LOAD(s5,character_A) 302fe // @38d #2019: CALL(LCD_write_data) 00553 // @38e #2020: LOAD(s5,character_S) 302fe // @38f #2021: CALL(LCD_write_data) 00548 // @390 #2022: LOAD(s5,character_H) 302fe // @391 #2023: CALL(LCD_write_data) 00520 // @392 #2024: LOAD(s5,character_space) 302fe // @393 #2025: CALL(LCD_write_data) 00553 // @394 #2026: LOAD(s5,character_S) 302fe // @395 #2027: CALL(LCD_write_data) 00565 // @396 #2028: LOAD(s5,character_e) 302fe // @397 #2029: CALL(LCD_write_data) 00572 // @398 #2030: LOAD(s5,character_r) 302fe // @399 #2031: CALL(LCD_write_data) 00569 // @39a #2032: LOAD(s5,character_i) 302fe // @39b #2033: CALL(LCD_write_data) 00561 // @39c #2034: LOAD(s5,character_a) 302fe // @39d #2035: CALL(LCD_write_data) 0056c // @39e #2036: LOAD(s5,character_l) 302fe // @39f #2037: CALL(LCD_write_data) 00520 // @3a0 #2038: LOAD(s5,character_space) 302fe // @3a1 #2039: CALL(LCD_write_data) 0054e // @3a2 #2040: LOAD(s5,character_N) 302fe // @3a3 #2041: CALL(LCD_write_data) 0056f // @3a4 #2042: LOAD(s5,character_o) 302fe // @3a5 #2043: CALL(LCD_write_data) 0052e // @3a6 #2044: LOAD(s5,character_fullstop) 302fe // @3a7 #2045: CALL(LCD_write_data) 2a000 // @3a8 #2046: RETURN // #2047: ; // #2048: ; // #2049: ; // #2050: ;Display 'Authentication' on top line of the LCD // #2051: ; // #2052: ; // @3a9 #2053: [disp_Authentication] 00511 // @3a9 #2053: LOAD(s5,17) ;Line 1 position 1 3033e // @3aa #2054: CALL(LCD_cursor) 00541 // @3ab #2055: LOAD(s5,character_A) 302fe // @3ac #2056: CALL(LCD_write_data) 00575 // @3ad #2057: LOAD(s5,character_u) 302fe // @3ae #2058: CALL(LCD_write_data) 00574 // @3af #2059: LOAD(s5,character_t) 302fe // @3b0 #2060: CALL(LCD_write_data) 00568 // @3b1 #2061: LOAD(s5,character_h) 302fe // @3b2 #2062: CALL(LCD_write_data) 00565 // @3b3 #2063: LOAD(s5,character_e) 302fe // @3b4 #2064: CALL(LCD_write_data) 0056e // @3b5 #2065: LOAD(s5,character_n) 302fe // @3b6 #2066: CALL(LCD_write_data) 00574 // @3b7 #2067: LOAD(s5,character_t) 302fe // @3b8 #2068: CALL(LCD_write_data) 00569 // @3b9 #2069: LOAD(s5,character_i) 302fe // @3ba #2070: CALL(LCD_write_data) 00563 // @3bb #2071: LOAD(s5,character_c) 302fe // @3bc #2072: CALL(LCD_write_data) 00561 // @3bd #2073: LOAD(s5,character_a) 302fe // @3be #2074: CALL(LCD_write_data) 00574 // @3bf #2075: LOAD(s5,character_t) 302fe // @3c0 #2076: CALL(LCD_write_data) 00569 // @3c1 #2077: LOAD(s5,character_i) 302fe // @3c2 #2078: CALL(LCD_write_data) 0056f // @3c3 #2079: LOAD(s5,character_o) 302fe // @3c4 #2080: CALL(LCD_write_data) 0056e // @3c5 #2081: LOAD(s5,character_n) 302fe // @3c6 #2082: CALL(LCD_write_data) 2a000 // @3c7 #2083: RETURN // #2084: ; // #2085: ; // #2086: ; // #2087: ; // #2088: ;Display 'Passed' on lower line of the LCD // #2089: ; // #2090: ; // @3c8 #2091: [disp_Passed] 00525 // @3c8 #2091: LOAD(s5,37) ;Line 2 position 5 3033e // @3c9 #2092: CALL(LCD_cursor) 00550 // @3ca #2093: LOAD(s5,character_P) 302fe // @3cb #2094: CALL(LCD_write_data) 00561 // @3cc #2095: LOAD(s5,character_a) 302fe // @3cd #2096: CALL(LCD_write_data) 00573 // @3ce #2097: LOAD(s5,character_s) 302fe // @3cf #2098: CALL(LCD_write_data) 302fe // @3d0 #2099: CALL(LCD_write_data) 00565 // @3d1 #2100: LOAD(s5,character_e) 302fe // @3d2 #2101: CALL(LCD_write_data) 00564 // @3d3 #2102: LOAD(s5,character_d) 302fe // @3d4 #2103: CALL(LCD_write_data) 2a000 // @3d5 #2104: RETURN // #2105: ; // #2106: ; // #2107: ; // #2108: ; // #2109: ; // #2110: ;Display 'Failed' on lower line of the LCD // #2111: ; // #2112: ; // @3d6 #2113: [disp_Failed] 00525 // @3d6 #2113: LOAD(s5,37) ;Line 2 position 5 3033e // @3d7 #2114: CALL(LCD_cursor) 00546 // @3d8 #2115: LOAD(s5,character_F) 302fe // @3d9 #2116: CALL(LCD_write_data) 00561 // @3da #2117: LOAD(s5,character_a) 302fe // @3db #2118: CALL(LCD_write_data) 00569 // @3dc #2119: LOAD(s5,character_i) 302fe // @3dd #2120: CALL(LCD_write_data) 0056c // @3de #2121: LOAD(s5,character_l) 302fe // @3df #2122: CALL(LCD_write_data) 00565 // @3e0 #2123: LOAD(s5,character_e) 302fe // @3e1 #2124: CALL(LCD_write_data) 00564 // @3e2 #2125: LOAD(s5,character_d) 302fe // @3e3 #2126: CALL(LCD_write_data) 2a000 // @3e4 #2127: RETURN // #2128: ; // #2129: ; // #2130: ;************************************************************************************** // #2131: ; Interrupt Service Routine (ISR) // #2132: ;************************************************************************************** // #2133: ; // #2134: ; Interrupts occur when the application processor is requesting a design authorisation // #2135: ; message. Therefore an interrupt results in a message being sent to the Link FIFO // #2136: ; depending on the authentication status. // #2137: ; // @3e5 #2138: [ISR] 2e000 // @3e5 #2138: STORE(s0,ISR_preserve_s0) ;save register contents // #2139: ; 0601c // @3e6 #2140: FETCH(s0,authentication_status) ;read authentication status 14050 // @3e7 #2141: COMPARE(s0,character_P) ;test for pass 'P' or fail 'F' 353f2 // @3e8 #2142: JUMP(Z,pass_token) // #2143: ; 00046 // @3e9 #2144: LOAD(s0,character_F) ;send FAIL to link FIFO 2c004 // @3ea #2145: OUTPUT(s0,link_FIFO_write_port) 00041 // @3eb #2146: LOAD(s0,character_A) 2c004 // @3ec #2147: OUTPUT(s0,link_FIFO_write_port) 00049 // @3ed #2148: LOAD(s0,character_I) 2c004 // @3ee #2149: OUTPUT(s0,link_FIFO_write_port) 0004c // @3ef #2150: LOAD(s0,character_L) 2c004 // @3f0 #2151: OUTPUT(s0,link_FIFO_write_port) 343f8 // @3f1 #2152: JUMP(end_ISR) // #2153: ; // @3f2 #2154: [pass_token] 2c004 // @3f2 #2154: OUTPUT(s0,link_FIFO_write_port) ;send PASS to link FIFO 00041 // @3f3 #2155: LOAD(s0,character_A) 2c004 // @3f4 #2156: OUTPUT(s0,link_FIFO_write_port) 00053 // @3f5 #2157: LOAD(s0,character_S) 2c004 // @3f6 #2158: OUTPUT(s0,link_FIFO_write_port) 2c004 // @3f7 #2159: OUTPUT(s0,link_FIFO_write_port) // #2160: ; // @3f8 #2161: [end_ISR] 06000 // @3f8 #2161: FETCH(s0,ISR_preserve_s0) ;restore register contents 38001 // @3f9 #2162: RETURNI(ENABLE) // #2163: ; // #2164: ; // #2165: ;************************************************************************************** // #2166: ; Interrupt Vector // #2167: ;************************************************************************************** // #2168: ; @3ff // #2169: ADDRESS(1023) 343e5 // @3ff #2170: JUMP(ISR) // #2171: ; // #2172: ; // #2173: ;************************************************************************************** // #2174: ; End of Program // #2175: ;**************************************************************************************