前言
??在前面的教程中呢,小編帶領(lǐng)各位讀者完成了對所有寄存器的配置,本章教程只需要完成對手勢數(shù)據(jù)寄存器里面的數(shù)據(jù)讀出即可,因為我們只檢測上、下、左、右揮手數(shù)據(jù),因此用四個led燈作為揮手數(shù)據(jù)結(jié)果指示即可。本章教程是基于FPGA的PAJ7620U2手勢識別的最后一章教程,具體實現(xiàn)方法請繼續(xù)往下瀏覽。
一、如何讀取手勢數(shù)據(jù)寄存器數(shù)據(jù)?
??在上一章教程中,我們采用的是突發(fā)讀操作的時序圖來對模塊進行配置的,但是本章教程我們采用單次讀操作對模塊進行配置,單次讀操作與突發(fā)讀操作在前半段配置方式都是一樣的,都是要指定讀取的寄存器:
??但是在后半段,連續(xù)讀操作是從DATA狀態(tài),跳轉(zhuǎn)到主機返回ACK響應(yīng),再從ACK響應(yīng)跳轉(zhuǎn)到DATA狀態(tài),結(jié)合官方數(shù)據(jù)手冊:
??我們發(fā)現(xiàn),不管是采用哪種讀方式,讀取到數(shù)據(jù)后,都不會自動停下,這時候結(jié)合前面的數(shù)據(jù)手冊,需要我們設(shè)置“中斷”,當(dāng)讀取到的8位數(shù)據(jù)不為全0時,則中斷讀操作。但是呢,我們采用的是FPGA來配置這個模塊,對數(shù)據(jù)的處理就簡單得多,因此只需要檢測出該模塊數(shù)據(jù)變化,將變化的數(shù)據(jù)作為LED燈亮起的觸發(fā)信號,觸發(fā)以后LED燈在下次觸發(fā)信號到來時,一直保持亮起即可。
??這里呢,我們采用單次讀操作,因為后續(xù)利用Singal Tap II觸發(fā)波形信號的時候,可以觀測到從IDLE到STOP一整個的執(zhí)行周期,因為整個執(zhí)行周期是非常短暫的,遠遠小于我們手勢變化的時間,因此在這里使用單次讀操作是完全可以采集到手勢數(shù)據(jù)的變化情況。
二、配置步驟
1.模塊狀態(tài)轉(zhuǎn)移圖繪制
??從圖中可以看出,讀取0x43寄存器數(shù)值狀態(tài)轉(zhuǎn)移圖與讀取0x00寄存器狀態(tài)轉(zhuǎn)移圖繪制方式一樣,因此各位讀者如果學(xué)會了讀取0x00寄存器數(shù)值操作后,本章教程對大家應(yīng)該沒有難度。
2.模塊波形圖繪制
??從波形圖可以看出,除了跳轉(zhuǎn)信號外,我們還需要引入兩路信號,一路是po_data_reg,這個信號主要是在DATA狀態(tài)下寄存拼接的數(shù)據(jù)。第二路信號是po_data,這個信號是在po_data_reg信號拼接完成后,讀取DATA狀態(tài)末尾拼接完成的數(shù)據(jù)。我們?nèi)o_data信號低四位,這低四位數(shù)據(jù),某位由0變化為1后,則代表上、下、左、右揮手動作被檢測出來,我們利用這個變化來驅(qū)動LED燈亮起。因為驅(qū)動LED燈亮起非常簡單,我們可以在頂層文件直接編寫代碼,就不再進行波形圖的繪制。
3.上板驗證
??設(shè)置skip_en_6信號為觸發(fā)條件:
??使用連續(xù)觸發(fā),抓取到的信號波形如圖所示:
??我們發(fā)現(xiàn),在DATA狀態(tài)下,一直沒有采集到數(shù)據(jù),并且4個LED燈也一直保持高電平,即熄滅狀態(tài)。我們向左揮手,抓取到的信號波形如下:
??可以看到,LED燈已經(jīng)發(fā)生了變化,第二位已經(jīng)由高電平變?yōu)榈碗娖剑兞亮?。但是為什么DATA狀態(tài)下,SDA還是為低電平呢?因為我們使用的是連續(xù)觸發(fā),觸發(fā)時間非常短暫,po_data采集到數(shù)據(jù)以后,馬上讓LED燈點亮,在下次采集數(shù)據(jù)時,po_data已經(jīng)歸零了,但是LED燈還維持在點亮狀態(tài)沒有改變。接下來,我們分別朝右、上、下?lián)]手,抓取到的信號波形如下:
??LED燈低三位數(shù)值都有變化,因此我們代碼驗證通過,且上板現(xiàn)象與預(yù)期一致(具體的實驗現(xiàn)象各位讀者可自行綁定引腳測試,在這里小編就不做演示了),整個工程驗證通過。文章來源:http://www.zghlxwxcb.cn/news/detail-443262.html
4.參考代碼(i2c_ctrl和paj7620_top)
module i2c_ctrl
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [23:0] cfg_data ,
input wire i2c_start ,
input wire [5:0] cfg_num ,
output wire scl ,
output reg cfg_start ,
output reg i2c_clk ,
output reg [2:0] mode ,
output reg [7:0] po_data ,
inout wire sda
);
localparam CNT_CLK_MAX = 5'd25 ;
localparam CNT_WAIT_MAX = 10'd1000;
localparam CNT_DELAY_MAX = 10'd1000;
localparam SLAVE_ID = 7'h73 ;
localparam SENSOR_ADDR = 8'hEF ;
localparam DATA_ADDR = 8'h43 ;
localparam IDLE = 4'd0 ,
START = 4'd1 ,
SLAVE_ADDR = 4'd2 ,
WAIT = 4'd3 ,
STOP = 4'd4 ,
ACK_1 = 4'd5 ,
DEVICE_ADDR = 4'd6 ,
ACK_2 = 4'd7 ,
DATA = 4'd8 ,
ACK_3 = 4'd9 ,
NACK = 4'd10 ;
reg [4:0] cnt_clk ; //分頻計數(shù)器
reg [9:0] cnt_wait ; //開始狀態(tài)等待1000us計數(shù)器
reg skip_en_0 ; //喚醒狀態(tài)跳轉(zhuǎn)信號
reg skip_en_1 ; //激活bank0跳轉(zhuǎn)信號
reg skip_en_2 ; //配置0x00寄存器狀態(tài)跳轉(zhuǎn)信號
reg skip_en_3 ; //讀取0x00寄存器狀態(tài)跳轉(zhuǎn)信號
reg skip_en_4 ; //配置51個操作寄存器
reg skip_en_5 ; //配置0x43寄存器狀態(tài)跳轉(zhuǎn)信號
reg skip_en_6 ; //讀取0x43寄存器狀態(tài)跳轉(zhuǎn)信號
reg error_en ; //讀取出來的值不是0x20,錯誤信號
reg [3:0] n_state ; //次態(tài)
reg [3:0] c_state ; //現(xiàn)態(tài)
reg [1:0] cnt_i2c_clk ; //對i2c_clk分頻時鐘個數(shù)計數(shù)
reg [2:0] cnt_bit ; //對傳輸?shù)?bit數(shù)據(jù)進行計數(shù)
reg i2c_scl ; //就是SCL
reg i2c_sda ; //SDA賦值給i2c_sda
reg [9:0] cnt_delay ; //發(fā)送完指令后等待1000us計數(shù)器
reg i2c_end ; //i2c結(jié)束信號
reg [7:0] po_data_reg ; //采集數(shù)據(jù),拼接完成后賦值給po_data
reg [7:0] slave_addr ; //不同模式下7'h73+1'bx
reg [7:0] device_addr ; //不同模式下寄存器地址變化
reg [7:0] wr_data ; //向地址寫入的數(shù)據(jù)
reg [7:0] rec_data ; //喚醒操作讀取0x00寄存器數(shù)據(jù)寄存
reg ack ;
wire sda_in ;
wire sda_en ;
assign scl = i2c_scl ;
assign sda_in = sda ; //從設(shè)備發(fā)送到主機的數(shù)據(jù)
assign sda_en = ((c_state == ACK_1)||(c_state == ACK_2)||(c_state == ACK_3)||((c_state == DATA)&&(mode == 3'd3))||((c_state == DATA)&&(mode == 3'd6))) ? 1'b0 : 1'b1 ; //主機控制sda有效
assign sda = (sda_en == 1'b1) ? i2c_sda : 1'bz ;
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cfg_start <= 1'b0 ;
else
cfg_start <= i2c_end ;
always@(*)
case(mode)
3'd0 :slave_addr = {SLAVE_ID,1'b0} ;
3'd1 :begin
slave_addr = {SLAVE_ID,1'b0} ;
device_addr = SENSOR_ADDR ;
wr_data = 8'h00 ;
end
3'd2 :begin
slave_addr = {SLAVE_ID,1'b0} ;
device_addr = 8'h00 ;
end
3'd3 :slave_addr = {SLAVE_ID,1'b1} ;
3'd4 :begin
slave_addr <= cfg_data[23:16] ;
device_addr <= cfg_data[15:8] ;
wr_data <= cfg_data[7:0] ;
end
3'd5 :begin
slave_addr <= {SLAVE_ID,1'b0} ;
device_addr <= DATA_ADDR ;
end
3'd6 :slave_addr = {SLAVE_ID,1'b1} ;
default :begin
slave_addr <= 8'd0 ;
device_addr <= 8'd0 ;
wr_data <= 8'd0 ;
end
endcase
//
//分頻計數(shù)器進行計數(shù)
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk <= 5'd0 ;
else if(cnt_clk == CNT_CLK_MAX - 1'b1)
cnt_clk <= 5'd0 ;
else
cnt_clk <= cnt_clk + 1'b1 ;
//產(chǎn)生i2c驅(qū)動時鐘
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
i2c_clk <= 1'b0 ;
else if(cnt_clk == CNT_CLK_MAX - 1'b1)
i2c_clk <= ~i2c_clk ;
else
i2c_clk <= i2c_clk ;
//
//狀態(tài)機第一段
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
c_state <= IDLE ;
else
c_state <= n_state ;
//狀態(tài)機第二段
always@(*)
case(c_state)
IDLE : if((skip_en_0 == 1'b1)||(skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_3 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1)||(skip_en_6 == 1'b1))
n_state = START ;
else
n_state = IDLE ;
START : if((skip_en_0 == 1'b1)||(skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_3 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1)||(skip_en_6 == 1'b1))
n_state = SLAVE_ADDR ;
else
n_state = START ;
SLAVE_ADDR : if(skip_en_0 == 1'b1)
n_state = WAIT ;
else if((skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_3 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1)||(skip_en_6 == 1'b1))
n_state = ACK_1 ;
else
n_state = SLAVE_ADDR ;
ACK_1 : if((skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1))
n_state = DEVICE_ADDR ;
else if((skip_en_3 == 1'b1)||(skip_en_6 == 1'b1))
n_state = DATA ;
else
n_state = ACK_1 ;
DEVICE_ADDR : if((skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1))
n_state = ACK_2 ;
else
n_state = DEVICE_ADDR ;
ACK_2 : if((skip_en_1 == 1'b1)||(skip_en_4 == 1'b1))
n_state = DATA ;
else if((skip_en_2 == 1'b1)||(skip_en_5 == 1'b1))
n_state = STOP ;
else
n_state = ACK_2 ;
DATA : if((skip_en_1 == 1'b1)||(skip_en_4 == 1'b1))
n_state = ACK_3 ;
else if((skip_en_3 == 1'b1)||(skip_en_6 == 1'b1))
n_state = NACK ;
else if(error_en == 1'b1)
n_state = IDLE ;
else
n_state = DATA ;
ACK_3 : if((skip_en_1 == 1'b1)||(skip_en_4 == 1'b1))
n_state = STOP ;
else
n_state = ACK_3 ;
WAIT : if(skip_en_0 == 1'b1)
n_state = STOP ;
else
n_state = WAIT ;
NACK : if((skip_en_3 == 1'b1)||(skip_en_6 == 1'b1))
n_state = STOP ;
else
n_state = NACK ;
STOP : if((skip_en_0 == 1'b1)||(skip_en_1 == 1'b1)||(skip_en_2 == 1'b1)||(skip_en_3 == 1'b1)||(skip_en_4 == 1'b1)||(skip_en_5 == 1'b1)||(skip_en_6 == 1'b1))
n_state = IDLE ;
else
n_state = STOP ;
default : n_state = IDLE ;
endcase
//狀態(tài)機第三段
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
cnt_wait <= 10'd0 ;
skip_en_0 <= 1'b0 ;
skip_en_1 <= 1'b0 ;
skip_en_2 <= 1'b0 ;
skip_en_3 <= 1'b0 ;
skip_en_4 <= 1'b0 ;
skip_en_5 <= 1'b0 ;
skip_en_6 <= 1'b0 ;
error_en <= 1'b0 ;
cnt_i2c_clk <= 2'd0 ;
cnt_bit <= 3'd0 ;
cnt_delay <= 10'd0 ;
mode <= 3'd0 ;
i2c_end <= 1'b0 ;
end
else
case(c_state)
IDLE :begin
cnt_wait <= cnt_wait + 1'b1 ;
if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd0))
skip_en_0 <= 1'b1 ;
else
skip_en_0 <= 1'b0 ;
if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd2))
skip_en_2 <= 1'b1 ;
else
skip_en_2 <= 1'b0 ;
if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd3))
skip_en_3 <= 1'b1 ;
else
skip_en_3 <= 1'b0 ;
if((i2c_start == 1'b1)&&(mode == 3'd4))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd5))
skip_en_5 <= 1'b1 ;
else
skip_en_5 <= 1'b0 ;
if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd6))
skip_en_6 <= 1'b1 ;
else
skip_en_6 <= 1'b0 ;
end
START :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))
skip_en_0 <= 1'b1 ;
else
skip_en_0 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2))
skip_en_2 <= 1'b1 ;
else
skip_en_2 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3))
skip_en_3 <= 1'b1 ;
else
skip_en_3 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5))
skip_en_5 <= 1'b1 ;
else
skip_en_5 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6))
skip_en_6 <= 1'b1 ;
else
skip_en_6 <= 1'b0 ;
end
SLAVE_ADDR :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if(cnt_i2c_clk == 2'd3)
cnt_bit <= cnt_bit + 1'b1 ;
else
cnt_bit <= cnt_bit ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd0))
skip_en_0 <= 1'b1 ;
else
skip_en_0 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd2))
skip_en_2 <= 1'b1 ;
else
skip_en_2 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3))
skip_en_3 <= 1'b1 ;
else
skip_en_3 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd5))
skip_en_5 <= 1'b1 ;
else
skip_en_5 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd6))
skip_en_6 <= 1'b1 ;
else
skip_en_6 <= 1'b0 ;
end
ACK_1 :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2)&&(ack == 1'b1))
skip_en_2 <= 1'b1 ;
else
skip_en_2 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3)&&(ack == 1'b1))
skip_en_3 <= 1'b1 ;
else
skip_en_3 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5)&&(ack == 1'b1))
skip_en_5 <= 1'b1 ;
else
skip_en_5 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6)&&(ack == 1'b1))
skip_en_6 <= 1'b1 ;
else
skip_en_6 <= 1'b0 ;
end
DEVICE_ADDR :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if(cnt_i2c_clk == 2'd3)
cnt_bit <= cnt_bit + 1'b1 ;
else
cnt_bit <= cnt_bit ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd2))
skip_en_2 <= 1'b1 ;
else
skip_en_2 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd5))
skip_en_5 <= 1'b1 ;
else
skip_en_5 <= 1'b0 ;
end
ACK_2 :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2)&&(ack == 1'b1))
skip_en_2 <= 1'b1 ;
else
skip_en_2 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5)&&(ack == 1'b1))
skip_en_5 <= 1'b1 ;
else
skip_en_5 <= 1'b0 ;
end
DATA :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if(cnt_i2c_clk == 2'd3)
cnt_bit <= cnt_bit + 1'b1 ;
else
cnt_bit <= cnt_bit ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3)&&(rec_data == 8'h20))
skip_en_3 <= 1'b1 ;
else
skip_en_3 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd6))
skip_en_6 <= 1'b1 ;
else
skip_en_6 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3)&&(rec_data != 8'h20))
begin
error_en <= 1'b1 ;
mode <= 3'd0 ;
end
else
begin
error_en <= 1'b0 ;
mode <= mode ;
end
end
ACK_3 :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
end
WAIT :begin
if((cnt_delay == CNT_DELAY_MAX - 2'd2)&&(mode == 3'd0))
skip_en_0 <= 1'b1 ;
else
skip_en_0 <= 1'b0 ;
cnt_delay <= cnt_delay + 1'b1 ;
end
NACK :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3)&&(ack == 1'b1))
skip_en_3 <= 1'b1 ;
else
skip_en_3 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6)&&(ack == 1'b1))
skip_en_6 <= 1'b1 ;
else
skip_en_6 <= 1'b0 ;
end
STOP :begin
cnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))
skip_en_0 <= 1'b1 ;
else
skip_en_0 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))
skip_en_1 <= 1'b1 ;
else
skip_en_1 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2))
skip_en_2 <= 1'b1 ;
else
skip_en_2 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3))
skip_en_3 <= 1'b1 ;
else
skip_en_3 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4))
skip_en_4 <= 1'b1 ;
else
skip_en_4 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5))
skip_en_5 <= 1'b1 ;
else
skip_en_5 <= 1'b0 ;
if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6))
skip_en_6 <= 1'b1 ;
else
skip_en_6 <= 1'b0 ;
if(cnt_i2c_clk == 2'd2)
i2c_end <= 1'b1 ;
else
i2c_end <= 1'b0 ;
if((i2c_end == 1'b1)&&(mode <= 3'd3))
mode <= mode + 1'b1 ;
else if((mode == 3'd4)&&(i2c_end == 1'b1)&&(cfg_num == 6'd51))
mode <= mode + 1'b1 ;
else if((i2c_end == 1'b1)&&(mode == 3'd5))
mode <= mode + 1'b1 ;
else
mode <= mode ;
end
default :begin
cnt_wait <= 10'd0 ;
skip_en_0 <= 1'b0 ;
skip_en_1 <= 1'b0 ;
skip_en_2 <= 1'b0 ;
skip_en_3 <= 1'b0 ;
skip_en_4 <= 1'b0 ;
skip_en_5 <= 1'b0 ;
skip_en_6 <= 1'b0 ;
error_en <= 1'b0 ;
cnt_i2c_clk <= 2'd0 ;
cnt_bit <= 3'd0 ;
cnt_delay <= 10'd0 ;
mode <= mode ;
i2c_end <= 1'b0 ;
end
endcase
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rec_data <= 8'd0 ;
else
case(c_state)
DATA : if((mode == 3'd3)&&(cnt_i2c_clk == 2'd1))
rec_data <= {rec_data[6:0],sda_in} ;
else
rec_data <= rec_data ;
default : rec_data <= 8'd0 ;
endcase
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
po_data_reg <= 8'd0 ;
else
case(c_state)
DATA : if((mode == 3'd6)&&(cnt_i2c_clk == 2'd1))
po_data_reg <= {po_data_reg[6:0],sda_in} ;
else
po_data_reg <= po_data_reg ;
default : po_data_reg <= po_data_reg ;
endcase
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
po_data <= 8'd0 ;
else if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd6))
po_data <= po_data_reg ;
else
po_data <= po_data ;
always@(*)
case(c_state)
ACK_1,ACK_2,ACK_3 : ack = ~sda_in ;
NACK : ack = i2c_sda ;
default : ack = 1'b0 ;
endcase
always@(*)
case(c_state)
IDLE : i2c_scl = 1'b1 ;
START : if(cnt_i2c_clk == 2'd3)
i2c_scl = 1'b0 ;
else
i2c_scl = 1'b1 ;
SLAVE_ADDR,ACK_1,DEVICE_ADDR,ACK_2,DATA,ACK_3,NACK
: if((cnt_i2c_clk == 2'd0)||(cnt_i2c_clk == 2'd3))
i2c_scl = 1'b0 ;
else
i2c_scl = 1'b1 ;
WAIT : i2c_scl = 1'b0 ;
STOP : if(cnt_i2c_clk == 2'd0)
i2c_scl = 1'b0 ;
else
i2c_scl = 1'b1 ;
default : i2c_scl = 1'b1 ;
endcase
always@(*)
case(c_state)
IDLE : i2c_sda = 1'b1 ;
START : if(cnt_i2c_clk == 2'd0)
i2c_sda = 1'b1 ;
else
i2c_sda = 1'b0 ;
SLAVE_ADDR : i2c_sda = slave_addr[7 - cnt_bit] ;
ACK_1,ACK_2,ACK_3,
: i2c_sda = 1'b0 ;
NACK : i2c_sda = 1'b1 ;
DEVICE_ADDR : i2c_sda = device_addr[7 - cnt_bit] ;
DATA : i2c_sda = wr_data[7 - cnt_bit] ;
WAIT : i2c_sda = 1'b0 ;
STOP : if((cnt_i2c_clk == 2'd0)||(cnt_i2c_clk == 2'd1))
i2c_sda <= 1'b0 ;
else
i2c_sda <= 1'b1 ;
default : i2c_sda <= 1'b1 ;
endcase
endmodule
module paj7620_top
(
input wire sys_clk ,
input wire sys_rst_n ,
output wire scl ,
output reg [3:0] led ,
inout wire sda
);
wire [23:0] cfg_data ;
wire i2c_start ;
wire [5:0] cfg_num ;
wire i2c_clk ;
wire [2:0] mode ;
wire cfg_start ;
wire [7:0] po_data ;
always@(posedge i2c_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
led <= 4'b1111 ;
else if(po_data[3:0] == 4'b0001)
led <= 4'b1110 ;
else if(po_data[3:0] == 4'b0010)
led <= 4'b1101 ;
else if(po_data[3:0] == 4'b0100)
led <= 4'b1011 ;
else if(po_data[3:0] == 4'b1000)
led <= 4'b0111 ;
else
led <= led ;
i2c_ctrl i2c_ctrl_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ) ,
.cfg_data (cfg_data ) ,
.i2c_start (i2c_start ) ,
.cfg_num (cfg_num ) ,
.scl (scl ) ,
.i2c_clk (i2c_clk ) ,
.mode (mode ) ,
.cfg_start (cfg_start ) ,
.po_data (po_data ) ,
.sda (sda )
);
paj7620_cfg paj7620_cfg_inst
(
.i2c_clk (i2c_clk ),
.sys_rst_n (sys_rst_n ),
.cfg_start (cfg_start ),
.mode (mode ),
.cfg_data (cfg_data ),
.cfg_num (cfg_num ),
.i2c_start (i2c_start )
);
endmodule
總結(jié)
??小編在這里用了7章的教程,帶領(lǐng)各位讀者完成了對paj7620手勢識別模塊上、下、左、右的識別配置,感謝各位讀者的支持,后續(xù)將為大家?guī)?x4矩陣鍵盤密碼鎖工程的實現(xiàn),敬請期待。文章來源地址http://www.zghlxwxcb.cn/news/detail-443262.html
到了這里,關(guān)于PAJ7620U2手勢識別——讀取手勢數(shù)據(jù)寄存器數(shù)據(jù)與LED顯示(完)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!