FPGA With Touch Screen
FPGA With Touch Screen
FPGA With Touch Screen
WITH FPGA
SUBMITTED TO:
SUBMITTED BY:
AEISHWARYA BAVISKAR
ELECTRICAL AND ELECTRONICS ENGINEERING, VNIT NAGPUR
JENIL SAVLA
ELECTRICAL AND ELECTRONICS ENGINEERING, VNIT NAGPUR
ACKNOWLEDGEMENT:
1. INTRODUCTION
2. WHAT IS FPGA?
3. DE2I-150 BOARD
4. QUARTUS II
5. GETTING STARTED WITH FPGA
6. EXPERIMENTAL SETUP
7. TOUCH SCREEN
8. SPI SERIAL INTERFACE
9. CODE
INTRODUCTION
FPGA SPECIFICATIONS:
FEATURED DEVICES
Cyclone IV EP4CGX150DF31 device
720 M9K memory blocks
6,480 Kbits embedded memory
FPGA CONFIGURATION
JTAG and AS mode configuration
EPCS64 serial configuration device
On-board USB Blaster circuitry
MEMORY DEVICES
128MB (32Mx32bit) SDRAM
4MB (1Mx32) SSRAM
64MB (4Mx16) Flash with 16-bit mode
CONNECTORS
Ethernet 10/100/1000 Mbps ports
High Speed Mezzanine Card (HSMC)
40-pin expansion port
VGA-out connector
VGA DAC (high speed triple DACs)
DB9 serial connector for RS-232 port with flow control
CLOCK
Three 50MHz oscillator clock inputs
DISPLAY
16x2 LCD module
18 slide switches and 4 push-buttons switches
18 red and 9 green LEDs
Eight 7-segment displays
QUARTUS II
Quartus II is a software tool produced by Altera for analysis and synthesis of HDL designs, which
enables the developer to compile their designs, perform timing analysis, examine RTL diagrams,
simulate a design's reaction to different stimuli, and configure the target device with the programmer.
You can start with some basic codes once a project is made in quartus.
http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&No=529
A block diagram file is an easy way to get started. Various logic gates and simple ICs such as encoders, multiplexers
are available ready to use in the library. Here is an implementation of NAND gate:
https://www.youtube.com/watch?v=auQ7wpVH-0Q
There are 18 red and 7 green leds mounted on the board along with four push buttons and 18 slider switches. Here
is a code to access some of the leds and push buttons.
module countertest(KEY,LEDR);
input[1:0] KEY;
output[7:0] LEDR;
counter counter1(KEY[0],KEY[1],LEDR[7:0]);
endmodule
module counter (C,CLR,Q);
input C,CLR;
output [7:0] Q;
reg[7:0] tmp;
always @(posedge C or posedge CLR)
begin
if(CLR)
tmp = 8'b00000000;
else
tmp = tmp + 8'b00000001;
end
assign Q = tmp;
endmodule
module andgate(input_1,input_2,GPIO);
input input_1;
input input_2;
output [0:0]GPIO;
wire and_temp;
assign and_temp = input_1 & input_2;
assign GPIO[0] = and_temp;
endmodule
module async_receiver(
input clk,
input RxD,
output reg RxD_data_ready = 0,
output reg [7:0] RxD_data = 0,
// data received, valid only (for one clock cycle) when RxD_data_ready is asserted
// We also detect if a gap occurs in the received stream of characters
// That can be useful if multiple characters are sent in burst
// so that multiple characters can be treated as a "packet"output RxD_idle,
// asserted when no data has been received for a while output reg RxD_endofpacket = 0
// asserted for one clock cycle when a packet has been detected (i.e. RxD_idle is going high)
);
parameter ClkFrequency = 25000000; // 25MHz
parameter Baud = 115200;
parameter Oversampling = 8; // needs to be a power of 2
// we oversample the RxD line at a fixed rate to capture each RxD data bit at the "right" time
// 8 times oversampling by default, use 16 for higher quality reception generate
if(ClkFrequency<Baud*Oversampling) ASSERTION_ERROR PARAMETER_OUT_OF_RANGE("Frequency too
low for current Baud rate and oversampling");
if(Oversampling<8 || ((Oversampling & (Oversampling-1))!=0)) ASSERTION_ERROR
PARAMETER_OUT_OF_RANGE("Invalid oversampling value");
endgenerate
reg [3:0] RxD_state = 0;
`ifdef SIMULATION
wire RxD_bit = RxD;
wire sampleNow = 1'b1; // receive one bit per clock cycle
`else
wire OversamplingTick;
BaudTickGen #(ClkFrequency, Baud, Oversampling) tickgen(.clk(clk), .enable(1'b1), .tick(OversamplingTick));
// synchronize RxD to our clk domain
reg [1:0] RxD_sync = 2'b11;
always @(posedge clk) if(OversamplingTick) RxD_sync <= {RxD_sync[0], RxD};
// and filter it
reg [1:0] Filter_cnt = 2'b11;
reg RxD_bit = 1'b1;
always @(posedge clk)
if(OversamplingTick)
begin
if(RxD_sync[1]==1'b1 && Filter_cnt!=2'b11) Filter_cnt <= Filter_cnt + 1'd1;
else
if(RxD_sync[1]==1'b0 && Filter_cnt!=2'b00) Filter_cnt <= Filter_cnt - 1'd1;
if(Filter_cnt==2'b11) RxD_bit <= 1'b1;
else
if(Filter_cnt==2'b00) RxD_bit <= 1'b0;
end
// and decide when is the good time to sample the RxD line
function integer log2(input integer v); begin log2=0; while(v>>log2) log2=log2+1; end endfunction
localparam l2o = log2(Oversampling);
reg [l2o-2:0] OversamplingCnt = 0;
always @(posedge clk) if(OversamplingTick) OversamplingCnt <= (RxD_state==0) ? 1'd0 : OversamplingCnt + 1'd1;
wire sampleNow = OversamplingTick && (OversamplingCnt==Oversampling/2-1);
`endif
// now we can accumulate the RxD bits in a shift-register
always @(posedge clk)
case(RxD_state)
4'b0000: if(~RxD_bit) RxD_state <= `ifdef SIMULATION 4'b1000 `else 4'b0001 `endif; // start bit found?
4'b0001: if(sampleNow) RxD_state <= 4'b1000; // sync start bit to sampleNow
4'b1000: if(sampleNow) RxD_state <= 4'b1001; // bit 0
4'b1001: if(sampleNow) RxD_state <= 4'b1010; // bit 1
4'b1010: if(sampleNow) RxD_state <= 4'b1011; // bit 2
4'b1011: if(sampleNow) RxD_state <= 4'b1100; // bit 3
4'b1100: if(sampleNow) RxD_state <= 4'b1101; // bit 4
4'b1101: if(sampleNow) RxD_state <= 4'b1110; // bit 5
4'b1110: if(sampleNow) RxD_state <= 4'b1111; // bit 6
4'b1111: if(sampleNow) RxD_state <= 4'b0010; // bit 7
4'b0010: if(sampleNow) RxD_state <= 4'b0000; // stop bit
default: RxD_state <= 4'b0000;
endcase
always @(posedge clk)
if(sampleNow && RxD_state[3]) RxD_data <= {RxD_bit, RxD_data[7:1]};
//reg RxD_data_error = 0;
always @(posedge clk)
begin
RxD_data_ready <= (sampleNow && RxD_state==4'b0010 && RxD_bit); // make sure a stop bit is
received
//RxD_data_error <= (sampleNow && RxD_state==4'b0010 && ~RxD_bit); // error if a stop bit is not
received
end
reg [l2o+1:0] GapCnt = 0;
always @(posedge clk) if (RxD_state!=0) GapCnt<=0; else if(OversamplingTick & ~GapCnt[log2(Oversampling)+1])
GapCnt <= GapCnt + 1'h1;
assign RxD_idle = GapCnt[l2o+1];
always @(posedge clk) RxD_endofpacket <= OversamplingTick & ~GapCnt[l2o+1] &&GapCnt[l2o:0];
endmodule
module BaudTickGen(input clk, enable,output tick ); // generate a tick at the specified baud rate * oversampling
parameter ClkFrequency = 25000000;
parameter Baud = 115200;
parameter Oversampling = 1;
function integer log2(input integer v); begin log2=0; while(v>>log2) log2=log2+1; end endfunction
localparam AccWidth = log2(ClkFrequency/Baud)+8; // +/- 2% max timing error over a byte
reg [AccWidth:0] Acc = 0;
localparam ShiftLimiter = log2(Baud*Oversampling >> (31-AccWidth)); // this makes sure Inc calculation doesn't
overflow
localparam Inc = ((Baud*Oversampling << (AccWidth-
ShiftLimiter))+(ClkFrequency>>(ShiftLimiter+1)))/(ClkFrequency>>ShiftLimiter);
always @(posedge clk) if(enable) Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0]; else Acc <= Inc[AccWidth:0];
assign tick = Acc[AccWidth];
endmodule
The above three modules are basic modules for serial communication. Then you can write your own code to
perform serial communication as you want. For example for swapping the given stream of serial bytes, below is a
code:
integer ioCount;
reg[7:0] data[0:LENMAX];
integer state;
initial begin
txStart = 0;
state = READ;
end
SOLVING: begin
integer i;
for (i = 0; i < LEN/2; i = i + 1) begin
reg[7:0] swap;
swap = data[i];
data[i] = data[LENMAX-i];
data[LENMAX-i] = swap;
end
state = WRITE1;
end
WRITE1: begin
if (!txBusy) begin
txData = data[ioCount];
txStart = 1;
state = WRITE2;
end
end
WRITE2: begin
txStart = 0;
if (ioCount != LENMAX) begin
ioCount = ioCount + 1;
state = WRITE1;
end else begin
ioCount = 0;
state = READ;
end
end
endcase
end
endmodule
- http://www.fpga4fun.com/SerialInterface.html
- http://www.sparxeng.com/blog/software/talking-rs-232-with-cyclone-ii-fpga-part-1
- http://www.sparxeng.com/blog/software/talking-rs-232-with-cyclone-ii-fpga-part-2
- http://www.sparxeng.com/blog/software/communicating-with-your-cyclone-ii-fpga-over-serial-port-part-3-number-
crunching
EXPERIMENTAL SETUP
When the PET film is pressed down, the two resistive surfaces meet. The position of this meeting
(a touch) can be read by a touch screen controller circuit
TOUCH SCREEN CONTROLLER (ADS7843):
FPGA is a digital device hence it can process only digital input and gives digital output. The output
of a Resistive touchscreen is analog. Hence to convert the analog output to digital an analog to
digital converter touch screen controller is used. Texas instrument’s ADS7843 touch screen
controller is used for this.
SPECIFICATION:
●4-WIRE TOUCH SCREEN INTERFACE
● RATIOMETRIC CONVERSION
● SINGLE SUPPLY: 2.7V to 5V
● UP TO 125kHz CONVERSION RATE
● SERIAL INTERFACE
● PROGRAMMABLE 8- OR 12-BIT RESOLUTION
● 2 AUXILIARY ANALOG INPUTS
● FULL POWER-DOWN CONTROL
module spi(
CLK, RSTn,
TOUCH_CS,
TOUCH_IRQ,
TOUCH_BY,
TOUCH_CLK,
TOUCH_MISO,
TOUCH_MOSI,
test
);
input CLK; //50 Mhz
input RSTn; //assign switch
input TOUCH_BY;
output TOUCH_CS ; //make gnd
// input TOUCH_IRQ;
inout TOUCH_IRQ; //penirq
output TOUCH_CLK; // ads clock
input TOUCH_MISO; //from ads data
output TOUCH_MOSI; // to ads control register
// ****** **************************************************
`define touch_clk_pos 8'd2
`define touch_clk_neg T500ns / 2
`define High 1'b1
`define low 1'b0
// ******************* *******************************************
end
else
begin
state_touch <= 8'd3;
count_2us_flag <= `count_2us_open;
spi_clk_flag <= `spi_clk_close;
end
end
else if (count_500ns == `touch_clk_neg)
begin
state_touch <= 8'd2; // to run the loop till all the control bits are transfered
TOUCH_CLKr <= `High;
end
else
state_touch <= 8'd3;
8'd4: // Read Data
if (count_500ns == `touch_clk_neg) // wait negedge clk
begin
state_touch <= 8'd5;
TOUCH_CLKr <= `High;
touch_x1data [count_dat_bit-1'b1] <= TOUCH_MISO;
end
else
state_touch <= 8'd4;
8'd5:
begin
state_touch <= 8'd6;
count_dat_bit <= count_dat_bit - 1'b1;
end
8'd6:
if (count_dat_bit == 8'D0)
begin
state_touch <= 8'd7;
TOUCH_CLKr <= `low;
end
else if (count_500ns == `touch_clk_pos)
begin
TOUCH_CLKr <= `low;
state_touch <= 8'd4;
end
else
state_touch <= 8'd6;
8'd7:
begin
state_touch <= 8'd8;
spi_clk_flag <= `spi_clk_close; // Close the spi Clock
TOUCH_CSr <= `High;
end
8'd8:
if (count_2us == 8'd99)
begin
state_touch <= 8'd9;
count_2us_flag <= `count_2us_close;
end
else
begin
state_touch <= 8'd8;
count_2us_flag <= `count_2us_open;
end
8'd9:
begin
state_touch <= 8'd10;
spi_clk_flag <= `spi_clk_open; //start spi clk 50ns or 2Mhz frequency
TOUCH_CSr <= `low;
count_cmd_bit <= 8'd9; //to count MOSI control register bits
count_dat_bit <= 8'd12;
end
8'd10 : // Write control bits
if (count_500ns == `touch_clk_pos) // wait posedge clk
begin
state_touch <= 8'd11;
TOUCH_CLKr <= `low;
TOUCH_MOSIr <= touch_cmd_y [count_cmd_bit-2'b10];
count_cmd_bit <= count_cmd_bit-1'b1;
end
else
state_touch <= 8'd10;
8'd11:
if (count_cmd_bit == 8'D0) // count cmd bit =0 indicates that all the control bits are transfered now
conversion can be achievec
begin
TOUCH_MOSIr <= 1'd0;
TOUCH_CLKr <= `low;
if (count_2us == 8'd99)
begin
state_touch <= 8'd12;
count_2us_flag <= `count_2us_close;
count_dat_bit <= 8'd12;
spi_clk_flag <=`spi_clk_open;
end
else
begin
state_touch <= 8'd11;
count_2us_flag <= `count_2us_open;
spi_clk_flag <= `spi_clk_close;
end
end
else if (count_500ns == `touch_clk_neg)
begin
state_touch <= 8'd10; // to run the loop till all the control bits are transfered
TOUCH_CLKr <= `High;
end
else state_touch <= 8'd11;
8'd12: // Read Data
if (count_500ns == `touch_clk_neg) // wait negedge clk
begin
state_touch <= 8'd13;
TOUCH_CLKr <= `High;
touch_x2data [count_dat_bit-1'b1] <= TOUCH_MISO;
end
else
state_touch <= 8'd12;
8'd13:
begin
state_touch <= 8'd14;
count_dat_bit <= count_dat_bit - 1'b1;
end
8'd14:
if (count_dat_bit == 8'D0)
begin
state_touch <= 8'd15;
TOUCH_CLKr <= `low;
end
else if (count_500ns == `touch_clk_pos)
begin
TOUCH_CLKr <= `low;
state_touch <= 8'd12;
end
else
state_touch <= 8'd14;
8'd15:
begin
state_touch <= 8'd16;
spi_clk_flag <= `spi_clk_close; // Close the spi Clock
TOUCH_CSr <= `High;
end
8'd16:
if (count_2us == 8'd99)
begin
state_touch <= 8'd0;
count_2us_flag <= `count_2us_close;
end
else
begin
state_touch <= 8'd16;
count_2us_flag <= `count_2us_open;
end
endcase
assign TOUCH_CLK = TOUCH_CLKr;
assign TOUCH_CS = TOUCH_CSr;
assign TOUCH_MOSI = TOUCH_MOSIr;
assign test = touch_x1data [ 3 : 0 ]; // display the data collected fourth place
endmodule
FUTURE IMPROVEMENTS
The touch screen can be mounted on a LCD module. Thus, the LCD Touch screen module can be used
to develop further applications such as drawing pad.