Kirjoitusalusta.fi
Koko ruutu

Server Notice:

hide

Julkinen työtila Latest text of pad hacklab-kurssit-fpga Tallennettu Toukokuu 24, 2012

 
     
dEEP FPGA -kurssia Helsinki Hacklabillä
 
Suovulan muistipointteja kirjasta Real World FPGA Design with Verilog:
 
 
Latches vs. Flipflops
  • generally both will sample the input signal at clock egde, but latch is transparent when clock signal is low
  • Transparent Latch
  • Reset Set Latch, RTL: LATRS
  • Verilog:
  • always @ (data_in or clock)
  • if (!clock) begin
  • data_out <= data_in;
  • end
  • D Flipflop
  • Data Flip-flop with Reset and Set, RTL: DFFERS
  • Verilog:
  • always @ (posedge clock)
  • begin
  • data_out <= data_in;
  • end
  • VHDL:
  • begin dff: process (D, CLK)
  • begin
  • if (rising_edge(CLK)) then
  • Q <= D;
  • end if;
  • end process dff;
 
 
Synchronization
  • s.59 "Each FPGA input should drive one and exactly one flipflop."
  • s.4 "Always synchronize inputs that are not phase related to the system clock."
  • s.4 "Use double-synchronizing flipflops for external signals to minimize metastability problems."
  • Verilog:
  • always @ (posedge clock)
  • begin
  • button_sync1 <= button_in;
  • button_sync2 <= button_sync1;
  • end
 
 
  • Onko ylläolevat järkeviä päätelmiä?
  • Karttu antaa hyväksyntänsä!
 
 
                                                                                                      
                                                                                                      
 
CPLD-ohjelmointi JTAGWhisperer-ohjelmalla
 
Esimerkit Windowsiin, mutta kaikki ohjelmat ovat saatavilla myös muihin käyttöjärjestelmiin.
 
1. JTAGWhisperer-ohjelma Arduinoon
 
 
  • pura zip-paketti Arduinon libraries-hakemistoon
  • purkaantuu oletuksena hakemistoon sowbug-JTAGWhisperer-0200a39, hakemiston nimi pitää muuttaa pelkäksi JTAGWhisperer:ksi
      
  • Arduino IDE:ssä pitäisi nyt näkyä File->Examples->JTAGWhisperer->JTAGWhisperer
  • avaa tämä, käännä ja uploadaa Arduinoon
 
 
2. Python-ympäristön asennus
 
  • Lataa ja asenna Python 2.7 (ei 3.x !) sivulta 
        http://www.python.org/download/ (python-2.7.2.msi)
        
  • Lataa ja asenna Pythonin sarjaporttikirjasto pyserial sivulta
         http://sourceforge.net/projects/pyserial/ (pyserial-2.5.win32.exe)
        
 
3. Python-skriptin ja Arduinon yhteistyön testaus
 
  • Windowsin command promptiin
 
  • Siirry JTAGWhisperer-kirjaston hakemistoon
         C:\Users\Jari\Documents\Arduino\libraries\JTAGWhisperer
    
  • Anna komento (COM8 = Arduinon sarjaportin numero)
        c:\python27\python send_xsvf -p COM8 xsvf\XC9572XL\DeviceID.xsvf
    
  • Homma epäonnistuu, koska ei ole CPLD:tä perässä, mutta pitäisi tulostua suunnilleen:
 
        Ready to send file of size 90 bytes.
        Device is ready.
        Sent:       64 bytes,       26 remaining
        IMPORTANT: SDR check failed.
        IMPORTANT: Failure at instruction #7
        IMPORTANT: Processed 7 instructions.
        IMPORTANT: Checksum 6c2/21.
        Received device quit: Exiting!
        Expected checksum: 10c1/5a.
        Elapsed time: 0.04 seconds.
 
  • Osa näistä tulosteista tulee Arduinon ohjelmalta, joten Python-skripti ja Arduino keskustelevat.
 
 
4. CPLD:n kytkeminen Arduinoon
 
  • Kytke piuhat Arduinosta CPLD:hen JTAGWhispererin readme.md-tiedostossa kuvatun mukaisesti:
 
        Arduino pin  8 = TMS
        Arduino pin  9 = TDI
        Arduino pin 10 = TDO
        Arduino pin 11 = TCK
 
  • Myös CPLD:n ja Arduinon maat pitää kytkeä yhteen.
    
   
5. CPLD:n ohjelmointi
 
  • Tee iMPACTilla XSVF-muotoinen ohjelmointitiedosto
  • Ohjelmoi se sisään samalla komennolla kuin kohdassa 3
  • Tuloste pitäisi olla tämän tapainen:
 
        Ready to send file of size 103964 bytes.
        Device is ready.
        Sent:   103964 bytes,        0 remaining
        IMPORTANT: XCOMPLETE
        IMPORTANT: Processed 11582 instructions.
        IMPORTANT: Checksum 6e06ac/1961c.
        Received device quit: Exiting!
        Expected checksum: 6e06ac/1961c.
        Elapsed time: 43.77 seconds.
 
  • Rivi "IMPORTANT: XCOMPLETE" on merkki siitä, että ohjelmointi meni loppuun saakka.
 
--------8<----------------8<----------------8<----------------8<----------------8<--------
 
 
enum { BufferSize = 1*1024 };
uint8_t    buffer[BufferSize];
 
enum {
  SERIAL_DATA       = 3,
  SERIAL_CLK        = 4,
  SERIAL_ENABLE     = 12,
  SERIAL_DELAY      = 10,
};
 
const uint8_t IntelHEXStartCode = ':';
 
void HALT(uint8_t) {
   // Kääk -> HALT
   while (true) {
     digitalWrite(13, LOW);
     delay(500);
     digitalWrite(13, HIGH);
     delay(500);
   }  
}
 
 
void setup() {                
  
  pinMode(13, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(SERIAL_DATA, OUTPUT);
  pinMode(SERIAL_CLK, OUTPUT);
  pinMode(SERIAL_ENABLE, OUTPUT);
 
  
  digitalWrite(13, LOW);
  
  // Test static allocation
  for (size_t i = 0; i < BufferSize; ++i) {
    buffer[i] = 0;
  }
 
  
  
  Serial.begin(9600);
  Serial.flush();      // ??
  while (Serial.available()) Serial.read();   // Clear input
  
  // All Ok
  Serial.print("OK");  
  Serial.println();  
  digitalWrite(13, HIGH);
  
  
  digitalWrite(11, LOW);
  delayMicroseconds(1);
  digitalWrite(11, HIGH);
  
  
 
}
 
size_t     bytesReceived = 0;
 
uint32_t   lastPrintTime = 0;
bool       dirty = false;
 
 
uint8_t readHex8() {
  while (Serial.available() < 2) { }; 
  int h1 = Serial.read();
  int h2 = Serial.read();
 
  uint8_t val = 0;
  if (h1 >= '0' && h1 <= '9') val |= (h1 - '0') << 4;
  if (h1 >= 'a' && h1 <= 'f') val |= (h1 - 'a' + 10) << 4;
  if (h1 >= 'A' && h1 <= 'F') val |= (h1 - 'A' + 10) << 4;
  if (h2 >= '0' && h2 <= '9') val |= (h2 - '0') << 0;
  if (h2 >= 'a' && h2 <= 'f') val |= (h2 - 'a' + 10) << 0;
  if (h2 >= 'A' && h2 <= 'F') val |= (h2 - 'A' + 10) << 0;
  
  return val;
}
 
uint16_t readHex16BE() {
  uint16_t  b1 = readHex8();
  uint16_t  b2 = readHex8();
 
  return (b1 << 8) + b2;
}
 
uint32_t readHex32BE() {
  uint32_t  b1 = readHex8();
  uint32_t  b2 = readHex8();
  uint32_t  b3 = readHex8();
  uint32_t  b4 = readHex8();
 
  return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
}
 
 
 
 
uint8_t send_serial_out(uint32_t val, size_t bits) {
  uint8_t even_parity = 0;
  
  digitalWrite(SERIAL_CLK, LOW);
  digitalWrite(SERIAL_ENABLE, HIGH);
  
  for(size_t i = 0; i < bits; i++) { 
    bool bit = (val >> (bits - i - 1)) & 0x1;
    digitalWrite(SERIAL_DATA, bit);  // siirretään taulukko vasemmalta oikealle 
    digitalWrite(SERIAL_CLK, HIGH);
    //delay(SERIAL_DELAY); 
    digitalWrite(SERIAL_CLK, LOW);
    //delay(SERIAL_DELAY); 
    
    even_parity = (even_parity ^ bit) & 0x01;
  }
  digitalWrite(SERIAL_ENABLE, LOW);
  digitalWrite(SERIAL_CLK, LOW);
  
  return even_parity;
}
 
 
        // uint8_t send_serial_out(uint8_t table[], size_t tablesize) {
 
 
 
void loop() {
  
  int c = 0;
  
  if (Serial.available()) {
    c = Serial.read();
    if (c == IntelHEXStartCode) {
      uint8_t     byteCount = readHex8();
      uint16_t    address = readHex16BE();
      uint8_t     recordType = readHex8();
 
       
      if (recordType == 00) {
        
        Serial.print("byteCount = ");  
        Serial.print(byteCount);  
        Serial.print(" address = ");  
        Serial.print(address);  
        Serial.print(" recordType = ");  
        Serial.print(recordType);  
        
        // Data
        for (size_t i = 0; i < byteCount; ++i) {
          buffer[i] = readHex8();
        }
 
        // Tässä näin..
        for (size_t i = 0; i < byteCount; ++i) {
          send_serial_out((uint32_t(address + i) << 8) | buffer[i], 15+8);
        }
       
        Serial.print(" <> ");  
        
        
        bytesReceived += byteCount;
        
      } else if (recordType == 01) {
        // End Of File
        Serial.println("<EOF>");  
        for (size_t i = 0; i < byteCount; ++i) readHex8();
        
        dirty = true;
      } else {
        //Serial.print("Unknown record");  
        for (size_t i = 0; i < byteCount; ++i) readHex8();
      }
 
      uint8_t    checksum = readHex8();
 
      /*
      Serial.print(" checksum = ");  
      Serial.print(int(checksum));  
      Serial.println();  
      */
    } else {
      // Skip  
      //Serial.print("unknown char = ");  
      //Serial.print(int(c));  
      //Serial.println();  
    }
  }
  
  if (dirty && (millis() - lastPrintTime) > 5000) {
    Serial.print("OK ");  
    Serial.print(bytesReceived);  
    Serial.print(" bytes received");  
    Serial.println();  
    
    lastPrintTime = millis();
    dirty = false;
    
  }
 
  
  
}