From CraigJacks@auslig.gov.au Sun Oct 8 15:27 PDT 1995 Received: from mailhost.auslig.gov.au by ECE.ORST.EDU with SMTP (1.38.193.4/16.2) id AA29883; Sun, 8 Oct 1995 15:27:53 -0700 Return-Path: Received: from mailgate (mailgate.auslig.gov.au) by mailhost.auslig.gov.au with SMTP id AA26522 (5.65c/IDA-1.4.4 for ); Mon, 9 Oct 1995 08:27:32 +1000 Received: by mailgate with Microsoft Mail id <30793F59@mailgate>; Mon, 09 Oct 95 08:27:21 PDT From: "Jackson, Craig" To: Paul Stoffregen Subject: 8XC51 xilinx programming. Date: Sun, 08 Oct 95 15:22:00 PDT Message-Id: <30793F59@mailgate> Encoding: 267 TEXT X-Mailer: Microsoft Mail V3.0 Status: RO Paul, I noticed when wandering around your 8751 home page, that you are working on some download code for Xilinx parts using an 8751. I've already done this, so you may be interested in the following code. It's written to do download and continual readback for an XC3090. The software expects to see a valid download stream (binary format) at 0x0000 in external data space, followed by a mask stream at 0x2000, which is generated by the makebits program (part of XACT) and tells which bits in the readback stream are important, and which ones are dynamic. In any case, the program, upon reset, asserts reset and prog\ on the xilinx, and then programs the chip. This takes a hundred milliseconds or so for a 8751 at 12 MHz. It then does a continual readback to ensure the thing keeps working. If the readback fails, it kicks the machine up the arse and starts again. The code is written in Franklin C, btw, and programs the xilinx in slave serial mode, so it consumes only half a dozen pins or so. Email me if you have any queries. Cheers, Craig Jackson, Technical Officer, Orroral Geodetic Observatory. -------------------------------------------- /* DOWNLOAD SOFTWARE FOR 3090/3190 CHIP. Author: Craig Jackson Revision: 1.0. Date: 26 Jul 1993 Output States: Initialise Programming Readback rst_out (P1.0) 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 clk_out (P1.1) 1 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1 prg_out (P1.2) 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 rtrig (P1.3) 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 rdata (P1.4) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 dat_out (P1.5) 1 1 1 1 D1 D1 D2 D2 D3 D3 1 1 1 1 1 1 init_in (P1.6) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ #include /* register map for 8751 */ #define mask_start 0x2000 /* program and mask starts */ #define num_frames 373 /* modify for different */ #define bits_frame 172 /* xilinx chip (set for 3090) */ xdata unsigned char buffer [0x4000]; sbit rst_out = P1 ^ 5; /* xilinx reset input */ sbit clk_out = P1 ^ 0; /* xilinx cclk input */ sbit prg_out = P1 ^ 1; /* xilinx done/prog* input */ sbit rtrig = P1 ^ 6; /* xilinx M0/rtrig input */ sbit rdata = P1 ^ 7; /* xilinx M1/rdata input */ sbit dat_out = P1 ^ 2; /* xilinx din input */ sbit init_in = P1 ^ 4; /* xilinx init output */ sbit data_0 = ACC ^ 0; sbit data_1 = ACC ^ 1; sbit data_2 = ACC ^ 2; sbit data_3 = ACC ^ 3; sbit data_4 = ACC ^ 4; sbit data_5 = ACC ^ 5; sbit data_6 = ACC ^ 6; sbit data_7 = ACC ^ 7; void initialise_chip (); unsigned char mirror (unsigned char); unsigned int get_length (); void program_chip (unsigned int); bit readback (unsigned int, unsigned int, unsigned int); void initialise_chip () /* initiates the xilinx initialisation and programming sequence */ { unsigned int i; rtrig = 1; /* select slave serial mode */ rdata = 1; prg_out = 0; /* assert !prog */ for (i = 0; i < 3; i++); prg_out = 1; /* de-assert !prog */ rst_out = 0; /* assert !reset */ for (i = 0; i < 3; i++); rst_out= 1; /* de-assert !reset */ } unsigned char mirror (input_char) /* mirrors all bits in input_char */ unsigned char input_char; { unsigned char temp; temp = 0; if (input_char & 0x80) temp += 0x01; if (input_char & 0x40) temp += 0x02; if (input_char & 0x20) temp += 0x04; if (input_char & 0x10) temp += 0x08; if (input_char & 0x08) temp += 0x10; if (input_char & 0x04) temp += 0x20; if (input_char & 0x02) temp += 0x40; if (input_char & 0x01) temp += 0x80; return (temp); } unsigned int get_length () /* finds program length from program lengthcount in xilinx program */ { unsigned int p_pointer, length; p_pointer = 0; /* start at program beginning */ while (buffer [p_pointer] == 0xff) /* find end of preamble */ p_pointer++; length = ((mirror (buffer [++p_pointer])) * 256 + (mirror (buffer [++p_pointer]))) * 2 + 1; /* get length */ if (buffer [++p_pointer] & 0x01) length ++; return (length); } void program_chip (p_length) /* programs the xilinx chip from the data stored in the buffer */ unsigned int p_length; { unsigned int p_pointer, i; for (p_pointer = 0; p_pointer < p_length; p_pointer++) { ACC = buffer [p_pointer]; /* read program data */ dat_out = data_0; /* shift out bit 0 */ clk_out = 0; clk_out = 1; dat_out = data_1; /* shift out bit 1 */ clk_out = 0; clk_out = 1; dat_out = data_2; /* shift out bit 2 */ clk_out = 0; clk_out = 1; dat_out = data_3; /* shift out bit 3 */ clk_out = 0; clk_out = 1; dat_out = data_4; /* shift out bit 4 */ clk_out = 0; clk_out = 1; dat_out = data_5; /* shift out bit 5 */ clk_out = 0; clk_out = 1; dat_out = data_6; /* shift out bit 6 */ clk_out = 0; clk_out = 1; dat_out = data_7; /* shift out bit 7 */ clk_out = 0; clk_out = 1; } for (i=0; i < 25; i++) { /* send 25 extra clocks */ clk_out = 0; clk_out = 1; } } bit read_back (m_start, frames, frame_len) /* performs a readback operation on the xilinx chip, and returns true if there is a configuration error. */ unsigned int m_start, frames, frame_len; { unsigned int i, j, p_pointer; unsigned char k, p_data, m_data; bit error, p_dat_bit, m_dat_bit; rtrig = 0; /* pulse M0 low to initiate */ rtrig = 1; /* readback. */ clk_out = 0; /* pulse CCLK low twice to */ clk_out = 1; /* discard dummy start bits */ clk_out = 0; clk_out = 1; p_pointer = 5; /* skip program/mask preamble */ k = 7; /* initialise current bit */ for (i = 0; i < frames; i++) { /* for all frames in chip */ for (j = 0; j < frame_len-2; j++) { /* for all bits in each frame */ k++; /* next bit */ if (k == 8) { /* time for a byte read ? */ k = 0; /* yes, reset bit counter */ m_data = buffer [p_pointer + m_start]; /* read in next mask byte */ p_data = buffer [p_pointer++]; /* read in next program byte */ } p_dat_bit = (p_data & 0x01); /* get next bits from bytes */ m_dat_bit = (m_data & 0x01); clk_out = 0; /* clock the xilinx chip */ clk_out = 1; error = ((~(rdata ^ p_dat_bit)) & m_dat_bit); /* have we an error */ if (error) return (error); /* bomb if we do */ p_data /= 2; /* shift the bytes */ m_data /= 2; } for (j = 0; j < 2; j++) { /* adjust program and mask */ k++; /* to account for different */ if (k == 8) { /* numbers of stop bits in */ k = 0; /* program and readback. */ m_data = buffer [p_pointer + m_start]; p_data = buffer [p_pointer++]; } p_data /= 2; /* get next bit from bytes */ m_data /= 2; } } for (i = 0; i < 25; i++) { /* send an extra 25 clocks */ clk_out = 0; /* to ensure all data is */ clk_out = 1; /* out. */ } return (error); } void main () { unsigned int length; for (;;) { /* repeat continually */ length = get_length (); initialise_chip (); while (!init_in) {}; /* wait for init to rise */ program_chip (length); while (!read_back (mask_start, num_frames, bits_frame)); /* wait for a readback error */ } /* yes - reprogram. */ }