;xilinx bitstream downloader, Paul Stoffregen, Mar 1996 ;beta version 0.2 ;opps, screwed up 4000 series download in version 0.1.. fixed now ;To use this thing, just connect the 8051's uart to your ;serial port (via driver/receiver chip) and attach the ;five necessary lines from port1 to your xilinx chip. ;Just send the binary .bit file directly to the serial ;port (at the right baud rate) and this code will remove ;the .bit file's header and download the data into your ;xilinx chip. There is little to no error checking for ;3000 series parts, so be careful. ; --Paul Stoffregen (paul@ece.orst.edu) ;to do: ; -> add status led outputs -download "started" and "finished" ; -> check for another device (xchecker) starting a download ; and go into high impedance until it's finished ; -> add mode input (shown on schematic) and it master serial ; mode is selected general program pulse in response to ; reset pin but then let the serial prom do the work ; -> better messages to host computer in the unlikely event ; someone is using a terminal program and actually reading it ; -> add jumper and extra line to OE/R pin on serial prom and ; support multiple consecutive configurations in the proms. ; -> check that init signal goes is low before we see it go ; high so the chip-not-connected error can be detected ; instead of just downloading into nowhere and thinking it ; was successful because of pull-up resistors. ;timer reload calculation ; baud_const = 256 - (crystal / (12 * 16 * baud)) baud_const equ 253 ;19200 baud w/ 11.0592 MHz ;.equ baud_const, 250 ;9600 baud w/ 11.0592 MHz PCON DEFINE 087H ;Power down register ;port pins required cclk equ 097h ;cclk = xilinx chip config clock done equ 094h ;done = xilinx chip done signal (D/P on 3000s) din equ 096h ;din = xilinx chip serial data input prog equ 095h ;prog = xilinx chip program request line (reset on 3000s) init equ 093h ;init = xilinx chip init/error signal ;these aren't supported yet ;mode equ 0 ;xilinx mode select (0=ser master, 1=ser slave) ;rst equ 0 ;xilinx reset (begin reprogram if mode=0) ;config equ 0 ;LED driver, low if we're programming ;ok equ 0 ;LED driver, low if the chip is programmed ok ;internal ram memory usage c_3000 equ 020h c_4000 equ 021h pile equ 060h ;reset and interrupt vectors org 0 ljmp poweron ;reset vector org 3 ;ext int0 vector org 11 ;timer0 vector org 19 ;ext int1 vector org 27 ;timer1 vector org 35 ;uart vector org 43 ;timer2 vector (8052) org 48 ;finally we can begin main: mov sp, #pile mov c_3000, #0 mov c_4000, #0 mov dptr, #0 wait_begin: ;waiting for beginning of bit file acall cin mov r2, a mov dptr, #s_3000 mov r0, #c_3000 acall lexer jc begin3000 mov dptr, #s_4000 mov r0, #c_4000 acall lexer jc begin4000 sjmp wait_begin begin3000: ;assume the bit file is arriving... we better ;start the program sequence before the real ;data starts to show up clr prog clr done mov r0, #240 djnz r0, $ setb prog setb done mov dptr, #s_3000 clr a movc a, @a+dptr mov dpl, a mov dph, #0 mov a, #'3' acall cout sjmp waitinit s_3000: db 10 ;length of 3000 series bitstream id header` db 0F0h, 00Fh, 0F0h, 00Fh, 0F0h db 00Fh, 0F0h, 00Fh, 000h, 033h begin4000: ;assume the bit file is arriving... we better ;start the program sequence before the real ;data starts to show up clr done ; RAJOUT le 25/11/00 clr prog mov r0, #240 djnz r0, $ setb done setb prog mov dptr, #s_4000 clr a movc a, @a+dptr mov dpl, a mov dph, #0 mov a, #'4' acall cout sjmp waitinit s_4000: db 13 ;length of 4000 series bitstream id header` db 009h, 00Fh, 0F0h, 00Fh, 0F0h, 00Fh, 0F0h db 00Fh, 0F0h, 000h, 000h, 001h, 061h waitinit: jnb ri, wtinit2 clr ri mov a, sbuf inc dptr wtinit2: jnb init, waitinit wait255: acall cin inc dptr cjne a, #255, wait255 mov r2, #0 sjmp shift next: acall cin inc dptr shift: mov b, r5 mov r4, b mov b, r6 mov r5, b mov b, r7 mov r6, b mov r7, a mov r0, #8 inc r2 sh_loop: rlc a mov din, c clr cclk nop setb cclk djnz r0, sh_loop nop nop nop ; jnb init, error ; MIS EN COMMENTAIRE LE 25/11/00 nop jnb done, next ;now that it says it's done, it needs a few more ;cclk pulses to actually start up... see pg 2-29 ;in 1993 xilinx databook. setb din ;in case a 3000 series .bit file left it low mov r0, #32 ;need more cclk pulses to finish startup startup:clr cclk nop setb cclk djnz r0, startup mov dptr, #msg_done acall pstr acall delay acall delay acall delay ajmp main msg_done: db 'Done signal went high.',13,10,0 ;error: ;if we get here, it means the xilinx chip pulled ;init low to tell us it got a checksum error! ; mov a, #'E' ; acall cout ; mov a, #'r' ; acall cout ; acall cout ; mov a, #'@' ; acall cout ; mov a, dph ;offset in .bit file where error detected ; acall phex ; mov a, dpl ; acall phex ; mov a, #' ' ; acall cout ; mov a, r4 ; acall phex ; mov a, #' ' ; acall cout ; mov a, r5 ; acall phex ; mov a, #' ' ; acall cout ; mov a, r6 ; acall phex ; mov a, #' ' ; acall cout ; mov a, r7 ; acall phex ; mov a, #' ' ; acall cout ; acall cout ; acall cout ; mov a, r2 ; acall phex ; setb c ; jc $ delay: mov r3, #200 delay2: nop mov r2, #228 djnz r2, $ djnz r3, delay2 ret cin: jnb ri, cin jnb ri, cin clr ri mov a, sbuf ret cout: jnb ti, cout ;not ok to change carry bit here! clr ti mov sbuf, a ret newline:push acc mov a, #13 acall cout mov a, #10 acall cout pop acc ret phex: phex8: push acc swap a anl a, #15 add a, #246 jnc phex_b add a, #7 phex_b: add a, #58 acall cout pop acc phex1: push acc anl a, #15 add a, #246 jnc phex_c add a, #7 phex_c: add a, #58 acall cout pop acc ret pstr: ;print string PUSH ACC pstr1: CLR A MOVC A,@A+DPTR JZ pstr2 mov c, acc.7 anl a, #01111111b acall cout Jc pstr2 inc dptr SJMP pstr1 pstr2: POP ACC RET poweron: MOV SP, #pile clr psw.3 clr psw.4 mov th1, #baud_const ORL PCON,#10000000b ; set double baud rate MOV TMOD,#00100001b ; T0=16 bit, T1=8 bit auto reload ; both are timers, software control MOV SCON,#01010010b ; Set Serial for mode 1 & ; Enable reception, ti=1, ri=0 ORL TCON,#01010101b ; Start both timers, both int are ; falling edge trigger mov dptr, #welcome acall pstr ajmp main welcome:db 'Xilinx Bitstream Downloader',13,10 db 'Beta Version 0.2',13,10 db 'Paul Stoffregen, March 1996',13,10,13,10,0 lexer: mov a, @r0 inc a ;don't look at length byte movc a, @a+dptr ;get character from string clr c subb a, r2 jnz lex_nope ;at this point, it matches the string, so now ;the question becomes "are we at the end?" inc @r0 ;advance index clr a movc a, @a+dptr ;get string length clr c subb a, @r0 ;subtract index jz lex_match ;we're not at the end of the string yet clr c ret lex_match: ;we've found all of the string now mov @r0, a ;reset index automatically setb c ret lex_nope: ;the received character doesn't match the string ;so we set the index back to zero, and return with ;carry clear mov @r0, #0 clr c ret end