📄 adc_spi_controller.v
字号:
// --------------------------------------------------------------------
// Copyright (c) 2005 by Terasic Technologies Inc.
// --------------------------------------------------------------------
//
// Permission:
//
// Terasic grants permission to use and modify this code for use
// in synthesis for all Terasic Development Boards and Altera Development
// Kits made by Terasic. Other use of this code, including the selling
// ,duplication, or modification of any portion is strictly prohibited.
//
// Disclaimer:
//
// This VHDL/Verilog or C/C++ source code is intended as a design reference
// which illustrates how these types of functions can be implemented.
// It is the user's responsibility to verify their design for
// consistency and functionality through the use of formal
// verification methods. Terasic provides no warranty regarding the use
// or functionality of this code.
//
// --------------------------------------------------------------------
//
// Terasic Technologies Inc
// 356 Fu-Shin E. Rd Sec. 1. JhuBei City,
// HsinChu County, Taiwan
// 302
//
// web: http://www.terasic.com/
// email: support@terasic.com
//
// --------------------------------------------------------------------
//
// Major Functions: This funtion will config and read Touch Screen Digitizer
// X an Y coordinate form LTM
// --------------------------------------------------------------------
//
// Revision History :
// --------------------------------------------------------------------
// Ver :| Author :| Mod. Date :| Changes Made:
// V1.0 :| Johnny Fan :| 06/03/23 :| Initial Revision
// --------------------------------------------------------------------
module adc_spi_controller (
iCLK,
iRST_n,
oADC_DIN,
oADC_DCLK,
oADC_CS,
iADC_DOUT,
iADC_BUSY,
iADC_PENIRQ_n,
oX_COORD,
oY_COORD,
oNEW_COORD,
);
//============================================================================
// PARAMETER declarations
//============================================================================
parameter SYSCLK_FRQ = 50000000;
parameter ADC_DCLK_FRQ = 1000;
parameter ADC_DCLK_CNT = SYSCLK_FRQ/(ADC_DCLK_FRQ*2);
//===========================================================================
// PORT declarations
//===========================================================================
input iCLK;
input iRST_n;
input iADC_DOUT;
input iADC_PENIRQ_n;
input iADC_BUSY;
output oADC_DIN;
output oADC_DCLK;
output oADC_CS;
output [11:0] oX_COORD;
output [11:0] oY_COORD;
output oNEW_COORD;
//=============================================================================
// REG/WIRE declarations
//=============================================================================
reg d1_PENIRQ_n;
reg d2_PENIRQ_n;
wire touch_irq;
reg [15:0] dclk_cnt;
wire dclk;
reg transmit_en;
reg [6:0] spi_ctrl_cnt;
wire oADC_CS;
reg mcs;
reg mdclk;
wire [7:0] x_config_reg;
wire [7:0] y_config_reg;
wire [7:0] ctrl_reg;
reg [7:0] mdata_in;
reg y_coordinate_config;
wire eof_transmition;
reg [5:0] bit_cnt;
reg madc_out;
reg [11:0] mx_coordinate;
reg [11:0] my_coordinate;
reg [11:0] oX_COORD;
reg [11:0] oY_COORD;
wire rd_coord_strob;
reg oNEW_COORD;
reg [5:0] irq_cnt;
reg [15:0] clk_cnt;
//=============================================================================
// Structural coding
//=============================================================================
assign x_config_reg = 8'h92;
assign y_config_reg = 8'hd2;
always@(posedge iCLK or negedge iRST_n)
begin
if (!iRST_n)
madc_out <= 0;
else
madc_out <= iADC_DOUT;
end
/////////////// pen irq detect ////////
always@(posedge iCLK or negedge iRST_n)
begin
if (!iRST_n)
begin
d1_PENIRQ_n <= 0;
d2_PENIRQ_n <= 0;
end
else
begin
d1_PENIRQ_n <= iADC_PENIRQ_n;
d2_PENIRQ_n <= d1_PENIRQ_n;
end
end
// if iADC_PENIRQ_n form high to low , touch_irq goes high
assign touch_irq = d2_PENIRQ_n & ~d1_PENIRQ_n;
// if touch_irq goes high , starting transmit procedure ,transmit_en goes high
// if end of transmition and no penirq , transmit procedure stop.
always@(posedge iCLK or negedge iRST_n)
begin
if (!iRST_n)
transmit_en <= 0;
else if (eof_transmition&&iADC_PENIRQ_n)
transmit_en <= 0;
else if (touch_irq)
transmit_en <= 1;
end
always@(posedge iCLK or negedge iRST_n)
begin
if (!iRST_n)
dclk_cnt <= 0;
else if (transmit_en)
begin
if (dclk_cnt == ADC_DCLK_CNT)
dclk_cnt <= 0;
else
dclk_cnt <= dclk_cnt + 1;
end
else
dclk_cnt <= 0;
end
assign dclk = (dclk_cnt == ADC_DCLK_CNT)? 1 : 0;
always@(posedge iCLK or negedge iRST_n)
begin
if (!iRST_n)
spi_ctrl_cnt <= 0;
else if (dclk)
begin
if (spi_ctrl_cnt == 49)
spi_ctrl_cnt <= 0;
else
spi_ctrl_cnt <= spi_ctrl_cnt + 1;
end
end
always@(posedge iCLK or negedge iRST_n)
begin
if (!iRST_n)
begin
mcs <= 1;
mdclk <= 0;
mdata_in <= 0;
y_coordinate_config <= 0;
mx_coordinate <= 0;
my_coordinate <= 0;
end
else if (transmit_en)
begin
if (dclk)
begin
if (spi_ctrl_cnt == 0)
begin
mcs <= 0;
mdata_in <= ctrl_reg;
end
else if (spi_ctrl_cnt == 49)
begin
mdclk <= 0;
y_coordinate_config <= ~y_coordinate_config;
if (y_coordinate_config)
mcs <= 1;
else
mcs <= 0;
end
else if (spi_ctrl_cnt != 0)
mdclk <= ~mdclk;
if (mdclk)
mdata_in <= {mdata_in[6:0],1'b0};
if (!mdclk)
begin
if(rd_coord_strob)
begin
if(y_coordinate_config)
my_coordinate <= {my_coordinate[10:0],madc_out};
else
mx_coordinate <= {mx_coordinate[10:0],madc_out};
end
end
end
end
end
assign oADC_CS = mcs;
assign oADC_DIN = mdata_in[7];
assign oADC_DCLK = mdclk;
assign ctrl_reg = y_coordinate_config ? y_config_reg : x_config_reg;
assign eof_transmition = (y_coordinate_config & (spi_ctrl_cnt == 49) & dclk);
assign rd_coord_strob = ((spi_ctrl_cnt>=19)&&(spi_ctrl_cnt<=41)) ? 1 : 0;
always@(posedge iCLK or negedge iRST_n)
begin
if (!iRST_n)
begin
oX_COORD <= 0;
oY_COORD <= 0;
end
else if (eof_transmition&&(my_coordinate!=0))
begin
oX_COORD <= mx_coordinate;
oY_COORD <= my_coordinate;
end
end
always@(posedge iCLK or negedge iRST_n)
begin
if (!iRST_n)
oNEW_COORD <= 0;
else if (eof_transmition&&(my_coordinate!=0))
oNEW_COORD <= 1;
else
oNEW_COORD <= 0;
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -