In this tutorial, we are going to develop a platform where FPGA DueProLogic communicates with Arduino Due.
Four tasks will be demonstrated.
(A) PC remotes FPGA DueProLogic
(B) FPGA DueProLogic controls the LED-13 on Arduino Due
(C) Arduino Due sends ultrasonic sensor data to FPGA DueProLogic
(D) FPGA DueProLogic transmits data to PC
Step 1: Build the electronic circuit
When you buy FPGA DueProLogic, you should receive a DVD. After you open "Projects_HDL", you should see verilog code
Step 3: Compile verilog code
Press "Start Compilation" in Quartus, no error message should be generated. If you receive error message about multiple pins. Go to Assignments -> Device -> Device and Pin Options -> Dual-Purpose Pins -> change the value of the appropriate pin to "Use as regular I/O".
After compilation, you should get pof output file directly. If you get sof output file only, click "File" in Quartus -> "convert programming files". Change the settings which are marked by red boxes.
Press "Programmer" in Quartus, update the pof file and then click "Start"
Step 4: Upload Arduino code
#define COMMANDDELAY 10 // ms to wait for the filling of Serial buffer
#define COMBUFFERSIZE 3 // Size of buffer for incoming numbers
int startStopBit = 0;
int count = 0;
int echoPin = 2; // Echo
int trigPin = 3; // Trigger
long duration, cm, inches;
int inPin11 = 11; //Input
int ledPin = 13; //Due Output
int LEDExt = 15; //Output
int C_Enable = 17; //Output
int new_value = 0x00000000;
int data_top_2bits = 0;
int data_bottom_6bits = 0;
int data_to_DPL = 0;
int newP = 500;
char commandBuffer[COMBUFFERSIZE+1];
// Fills the given buffer with bufferSize chars from a Serial object
void fillBuffer( \
char *buffer, \
byte bufferSize, \
HardwareSerial* serial = &Serial );
void setup()
{
int k ;
//Set pins D33-D41 as outputs
for( k = 33 ; k <= 41 ; k++ )
pinMode( k, OUTPUT ) ; // Sets Port C2-C9 to output pins
// Set the output pins in the Output Write Enable Register
REG_PIOC_OWER = 0x0000037E ;
// Disable writing to all other pins on the same port-
REG_PIOC_OWDR = 0xFFFFFC81 ;
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(C_Enable, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(LEDExt, OUTPUT);
pinMode(inPin11, INPUT);
pinMode(motorPin, OUTPUT);
//randomSeed(analogRead(1));
Serial.begin(115200);
}
void loop ()
{
int i ;
//Sample the Start/Stop switch
//from the EPT-4CE6-AF
startStopBit = digitalRead(inPin11);
Serial.println(startStopBit);
delay(newP); //Delay in ms
if(startStopBit==0)
{
digitalWrite(ledPin, LOW);
delay(1000);
}
if(startStopBit==1)
{
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = (duration/2) / 29.1; // Divide by 29.1 or multiply by 0.0343, this is physics
new_value = cm;
delay(1000);
//Map the the transfer byte to pins available on the DueProLogic
data_top_2bits = (new_value & 0x000000c0)<<2;
data_bottom_6bits = (new_value & 0x0000003F)<<1;
//Or the re-mapped bits together and use the ODSR register to transmit the bits
data_to_DPL = data_top_2bits | data_bottom_6bits;
REG_PIOC_ODSR = data_to_DPL;
//Set the Write Enable Pin High
digitalWrite(C_Enable, HIGH);
//Set the LED Pin High
digitalWrite(LEDExt, HIGH);
delay(newP); //Delay in ms
//Set the LED Pin Low
digitalWrite(LEDExt, LOW);
//Set the Write Enable Pin Low
digitalWrite(C_Enable, LOW);
}
if ( Serial.available() > 0 )
{
// Read the incoming byte
char theChar = Serial.read();
// Parse character
switch (theChar) {
case 's': // 's' for setting time between samples
// Wait for COMMANDDELAY ms to be sure that the Serial buffer is filled
delay(COMMANDDELAY);
fillBuffer( commandBuffer, COMBUFFERSIZE );
// Convert buffer to integer
//commandBuffer = "32";
newP = atoi( commandBuffer );
// Display moving status indicator
Serial.print("Setting the EPT prescaler to: ");
Serial.println(newP);
//Call set timing with newP
//setIntervalTiming(newP);
break;
default:
// Display error message
Serial.print("ERROR: Command not found, it was: ");
Serial.println(theChar);
break;
}
}
}
//-----------------------------------------------------------------------------
// fillBuffer
//-----------------------------------------------------------------------------
// Fills the given buffer with bufferSize chars from a Serial object
void fillBuffer( char *buffer, byte bufferSize, HardwareSerial* serial )
{
// Clean buffer
memset( (void *)buffer, '\0', sizeof(char) * bufferSize );
byte limit = ( bufferSize < serial->available() ) ? bufferSize : serial->available();
// Fill buffer
for ( byte i = 0; i < limit; i++ ) {
buffer[i] = serial->read();
}
}
Step 5: Connect FPGA to PC
You have to Install Visual Studio C#. Then open the C# file in Active_Host (DVD).
Create ON and OFF buttons in GUI interface with help of C# Toolbox.
//On button:
private void btnWriteByte_Click(object sender, EventArgs e)
{
int address_to_device;
address_to_device = Convert.ToInt32(tbAddress.Text);
EPT_AH_SendTransferControlByte((char)2, (char)1);
}
//OFF button
private void btnTransferReset_Click(object sender, EventArgs e)
{
int address_to_device;
address_to_device = Convert.ToInt32(tbAddress.Text);
EPT_AH_SendTransferControlByte((char)address_to_device, (char)0);
}
The char 0 and 1 determine the status of "start_stop_cntrl" in FPGA
When you compile and build the C# projects, exe file will be generated in C:\Visual Studio 2019\Data_collector\bin\x64\Release.
When you click "On", your PC sends signals to the FGPA to light up LED-13 on Arduino Due. Meanwhile the ultrasonic sensor transfers the data to the FPGA and then the data will be appeared on your PC.
Four tasks will be demonstrated.
(A) PC remotes FPGA DueProLogic
(B) FPGA DueProLogic controls the LED-13 on Arduino Due
(C) Arduino Due sends ultrasonic sensor data to FPGA DueProLogic
(D) FPGA DueProLogic transmits data to PC
Step 1: Build the electronic circuit
Step 2: Edit Verilog code as follow
//Arduino Connections
assign LEDExt = XIO_5[5]; //XIO_5 -- UB59 -- D15
assign XIO_1[3] = start_stop_cntrl; //XIO_1 -- UB3 -- D11
assign c_enable = XIO_5[2]; //XIO_5 -- UB57 -- D17
assign data_from_arduino[7] = XIO_6[18]; //XIO_6 -- UB40 -- D40
assign data_from_arduino[6] = XIO_6[17]; //XIO_6 -- UB39 -- D39
assign data_from_arduino[5] = XIO_6[16]; //XIO_6 -- UB38 -- D38
assign data_from_arduino[4] = XIO_6[15]; //XIO_6 -- UB37 -- D37
assign data_from_arduino[3] = XIO_6[14]; //XIO_6 -- UB36 -- D36
assign data_from_arduino[2] = XIO_6[13]; //XIO_6 -- UB35 -- D35
assign data_from_arduino[1] = XIO_6[12]; //XIO_6 -- UB34 -- D34
assign data_from_arduino[0] = XIO_6[11]; //XIO_6 -- UB33 -- D33
Step 3: Compile verilog code
Press "Start Compilation" in Quartus, no error message should be generated. If you receive error message about multiple pins. Go to Assignments -> Device -> Device and Pin Options -> Dual-Purpose Pins -> change the value of the appropriate pin to "Use as regular I/O".
After compilation, you should get pof output file directly. If you get sof output file only, click "File" in Quartus -> "convert programming files". Change the settings which are marked by red boxes.
Press "Programmer" in Quartus, update the pof file and then click "Start"
Step 4: Upload Arduino code
#define COMMANDDELAY 10 // ms to wait for the filling of Serial buffer
#define COMBUFFERSIZE 3 // Size of buffer for incoming numbers
int startStopBit = 0;
int count = 0;
int echoPin = 2; // Echo
int trigPin = 3; // Trigger
long duration, cm, inches;
int inPin11 = 11; //Input
int ledPin = 13; //Due Output
int LEDExt = 15; //Output
int C_Enable = 17; //Output
int new_value = 0x00000000;
int data_top_2bits = 0;
int data_bottom_6bits = 0;
int data_to_DPL = 0;
int newP = 500;
char commandBuffer[COMBUFFERSIZE+1];
// Fills the given buffer with bufferSize chars from a Serial object
void fillBuffer( \
char *buffer, \
byte bufferSize, \
HardwareSerial* serial = &Serial );
void setup()
{
int k ;
//Set pins D33-D41 as outputs
for( k = 33 ; k <= 41 ; k++ )
pinMode( k, OUTPUT ) ; // Sets Port C2-C9 to output pins
// Set the output pins in the Output Write Enable Register
REG_PIOC_OWER = 0x0000037E ;
// Disable writing to all other pins on the same port-
REG_PIOC_OWDR = 0xFFFFFC81 ;
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(C_Enable, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(LEDExt, OUTPUT);
pinMode(inPin11, INPUT);
pinMode(motorPin, OUTPUT);
//randomSeed(analogRead(1));
Serial.begin(115200);
}
void loop ()
{
int i ;
//Sample the Start/Stop switch
//from the EPT-4CE6-AF
startStopBit = digitalRead(inPin11);
Serial.println(startStopBit);
delay(newP); //Delay in ms
if(startStopBit==0)
{
digitalWrite(ledPin, LOW);
delay(1000);
}
if(startStopBit==1)
{
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = (duration/2) / 29.1; // Divide by 29.1 or multiply by 0.0343, this is physics
new_value = cm;
delay(1000);
//Map the the transfer byte to pins available on the DueProLogic
data_top_2bits = (new_value & 0x000000c0)<<2;
data_bottom_6bits = (new_value & 0x0000003F)<<1;
//Or the re-mapped bits together and use the ODSR register to transmit the bits
data_to_DPL = data_top_2bits | data_bottom_6bits;
REG_PIOC_ODSR = data_to_DPL;
//Set the Write Enable Pin High
digitalWrite(C_Enable, HIGH);
//Set the LED Pin High
digitalWrite(LEDExt, HIGH);
delay(newP); //Delay in ms
//Set the LED Pin Low
digitalWrite(LEDExt, LOW);
//Set the Write Enable Pin Low
digitalWrite(C_Enable, LOW);
}
if ( Serial.available() > 0 )
{
// Read the incoming byte
char theChar = Serial.read();
// Parse character
switch (theChar) {
case 's': // 's' for setting time between samples
// Wait for COMMANDDELAY ms to be sure that the Serial buffer is filled
delay(COMMANDDELAY);
fillBuffer( commandBuffer, COMBUFFERSIZE );
// Convert buffer to integer
//commandBuffer = "32";
newP = atoi( commandBuffer );
// Display moving status indicator
Serial.print("Setting the EPT prescaler to: ");
Serial.println(newP);
//Call set timing with newP
//setIntervalTiming(newP);
break;
default:
// Display error message
Serial.print("ERROR: Command not found, it was: ");
Serial.println(theChar);
break;
}
}
}
//-----------------------------------------------------------------------------
// fillBuffer
//-----------------------------------------------------------------------------
// Fills the given buffer with bufferSize chars from a Serial object
void fillBuffer( char *buffer, byte bufferSize, HardwareSerial* serial )
{
// Clean buffer
memset( (void *)buffer, '\0', sizeof(char) * bufferSize );
byte limit = ( bufferSize < serial->available() ) ? bufferSize : serial->available();
// Fill buffer
for ( byte i = 0; i < limit; i++ ) {
buffer[i] = serial->read();
}
}
Step 5: Connect FPGA to PC
You have to Install Visual Studio C#. Then open the C# file in Active_Host (DVD).
Create ON and OFF buttons in GUI interface with help of C# Toolbox.
//On button:
private void btnWriteByte_Click(object sender, EventArgs e)
{
int address_to_device;
address_to_device = Convert.ToInt32(tbAddress.Text);
EPT_AH_SendTransferControlByte((char)2, (char)1);
}
//OFF button
private void btnTransferReset_Click(object sender, EventArgs e)
{
int address_to_device;
address_to_device = Convert.ToInt32(tbAddress.Text);
EPT_AH_SendTransferControlByte((char)address_to_device, (char)0);
}
The char 0 and 1 determine the status of "start_stop_cntrl" in FPGA
When you compile and build the C# projects, exe file will be generated in C:\Visual Studio 2019\Data_collector\bin\x64\Release.
When you click "On", your PC sends signals to the FGPA to light up LED-13 on Arduino Due. Meanwhile the ultrasonic sensor transfers the data to the FPGA and then the data will be appeared on your PC.
Demo
Comments
Post a Comment