PAJ7620U2手势识别——读取手势数据寄存器数据与LED指示(完)
文章目录 总结
前言
在前面的教程中呢,小编带领各位读者完成了对所有寄存器的配置,本章教程只需要完成对手势数据寄存器里面的数据读出即可,因为我们只检测上、下、左、右挥手数据,因此用四个led灯作为挥手数据结果指示即可。本章教程是基于FPGA的手势识别的最后一章教程,具体实现方法请继续往下浏览。
一、如何读取手势数据寄存器数据?
在上一章教程中,我们采用的是突发读操作的时序图来对模块进行配置的,但是本章教程我们采用单次读操作对模块进行配置,单次读操作与突发读操作在前半段配置方式都是一样的,都是要指定读取的寄存器:
但是在后半段,连续读操作是从DATA状态,跳转到主机返回ACK响应,再从ACK响应跳转到DATA状态,结合官方数据手册:
我们发现,不管是采用哪种读方式,读取到数据后,都不会自动停下,这时候结合前面的数据手册,需要我们设置“中断”,当读取到的8位数据不为全0时,则中断读操作。但是呢,我们采用的是FPGA来配置这个模块,对数据的处理就简单得多,因此只需要检测出该模块数据变化,将变化的数据作为LED灯亮起的触发信号,触发以后LED灯在下次触发信号到来时,一直保持亮起即可。
这里呢,我们采用单次读操作,因为后续利用 Tap II触发波形信号的时候,可以观测到从IDLE到STOP一整个的执行周期,因为整个执行周期是非常短暂的,远远小于我们手势变化的时间,因此在这里使用单次读操作是完全可以采集到手势数据的变化情况。
二、配置步骤 1.模块状态转移图绘制
从图中可以看出,读取0x43寄存器数值状态转移图与读取0x00寄存器状态转移图绘制方式一样,因此各位读者如果学会了读取0x00寄存器数值操作后,本章教程对大家应该没有难度。
2.模块波形图绘制
从波形图可以看出,除了跳转信号外,我们还需要引入两路信号,一路是,这个信号主要是在DATA状态下寄存拼接的数据。第二路信号是,这个信号是在信号拼接完成后,读取DATA状态末尾拼接完成的数据。我们取信号低四位,这低四位数据,某位由0变化为1后,则代表上、下、左、右挥手动作被检测出来,我们利用这个变化来驱动LED灯亮起。因为驱动LED灯亮起非常简单,我们可以在顶层文件直接编写代码,就不再进行波形图的绘制。
3.上板验证
设置信号为触发条件:
使用连续触发,抓取到的信号波形如图所示:
我们发现,在DATA状态下,一直没有采集到数据,并且4个LED灯也一直保持高电平,即熄灭状态。我们向左挥手,抓取到的信号波形如下:
可以看到,LED灯已经发生了变化,第二位已经由高电平变为低电平,变亮了。但是为什么DATA状态下,SDA还是为低电平呢?因为我们使用的是连续触发,触发时间非常短暂,采集到数据以后,马上让LED灯点亮,在下次采集数据时,已经归零了,但是LED灯还维持在点亮状态没有改变。接下来,我们分别朝右、上、下挥手,抓取到的信号波形如下:
LED灯低三位数值都有变化,因此我们代码验证通过,且上板现象与预期一致(具体的实验现象各位读者可自行绑定引脚测试,在这里小编就不做演示了),整个工程验证通过。
4.参考代码(和)
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 ; //分频计数器
reg [9:0] cnt_wait ; //开始状态等待1000us计数器
reg skip_en_0 ; //唤醒状态跳转信号
reg skip_en_1 ; //激活bank0跳转信号
reg skip_en_2 ; //配置0x00寄存器状态跳转信号
reg skip_en_3 ; //读取0x00寄存器状态跳转信号
reg skip_en_4 ; //配置51个操作寄存器
reg skip_en_5 ; //配置0x43寄存器状态跳转信号
reg skip_en_6 ; //读取0x43寄存器状态跳转信号
reg error_en ; //读取出来的值不是0x20,错误信号
reg [3:0] n_state ; //次态
reg [3:0] c_state ; //现态
reg [1:0] cnt_i2c_clk ; //对i2c_clk分频时钟个数计数
reg [2:0] cnt_bit ; //对传输的8bit数据进行计数
reg i2c_scl ; //就是SCL
reg i2c_sda ; //SDA赋值给i2c_sda
reg [9:0] cnt_delay ; //发送完指令后等待1000us计数器
reg i2c_end ; //i2c结束信号
reg [7:0] po_data_reg ; //采集数据,拼接完成后赋值给po_data
reg [7:0] slave_addr ; //不同模式下7'h73+1'bx
reg [7:0] device_addr ; //不同模式下寄存器地址变化
reg [7:0] wr_data ; //向地址写入的数据
reg [7:0] rec_data ; //唤醒操作读取0x00寄存器数据寄存
reg ack ;
wire sda_in ;
wire sda_en ;assign scl = i2c_scl ;
assign sda_in = sda ; //从设备发送到主机的数据
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 ;elsecfg_start <= i2c_end ;always@(*)case(mode)3'd0 :slave_addr = {SLAVE_ID,1'b0} ;3'd1 :beginslave_addr = {SLAVE_ID,1'b0} ;device_addr = SENSOR_ADDR ;wr_data = 8'h00 ;end3'd2 :beginslave_addr = {SLAVE_ID,1'b0} ;device_addr = 8'h00 ; end3'd3 :slave_addr = {SLAVE_ID,1'b1} ;3'd4 :beginslave_addr <= cfg_data[23:16] ;device_addr <= cfg_data[15:8] ;wr_data <= cfg_data[7:0] ;end3'd5 :begin slave_addr <= {SLAVE_ID,1'b0} ;device_addr <= DATA_ADDR ;end3'd6 :slave_addr = {SLAVE_ID,1'b1} ;default :beginslave_addr <= 8'd0 ;device_addr <= 8'd0 ;wr_data <= 8'd0 ; endendcase//
//分频计数器进行计数
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 ;elsecnt_clk <= cnt_clk + 1'b1 ;//产生i2c驱动时钟
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 ;elsei2c_clk <= i2c_clk ;
////状态机第一段
always@(posedge i2c_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)c_state <= IDLE ;elsec_state <= n_state ;//状态机第二段
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 ;elsen_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 ;elsen_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 ;elsen_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 ;elsen_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 ;elsen_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 ;elsen_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 ;elsen_state = DATA ;ACK_3 : if((skip_en_1 == 1'b1)||(skip_en_4 == 1'b1))n_state = STOP ;elsen_state = ACK_3 ;WAIT : if(skip_en_0 == 1'b1)n_state = STOP ;elsen_state = WAIT ;NACK : if((skip_en_3 == 1'b1)||(skip_en_6 == 1'b1))n_state = STOP ;elsen_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 ;elsen_state = STOP ;default : n_state = IDLE ;endcase//状态机第三段
always@(posedge i2c_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)begincnt_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 ;endelsecase(c_state)IDLE :begincnt_wait <= cnt_wait + 1'b1 ;if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd0))skip_en_0 <= 1'b1 ;elseskip_en_0 <= 1'b0 ;if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd1))skip_en_1 <= 1'b1 ;elseskip_en_1 <= 1'b0 ; if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd2))skip_en_2 <= 1'b1 ;elseskip_en_2 <= 1'b0 ; if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd3))skip_en_3 <= 1'b1 ;elseskip_en_3 <= 1'b0 ; if((i2c_start == 1'b1)&&(mode == 3'd4))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ; if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd5))skip_en_5 <= 1'b1 ;elseskip_en_5 <= 1'b0 ;if((cnt_wait == CNT_WAIT_MAX - 2'd2)&&(mode == 3'd6))skip_en_6 <= 1'b1 ;elseskip_en_6 <= 1'b0 ; endSTART :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))skip_en_0 <= 1'b1 ;elseskip_en_0 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))skip_en_1 <= 1'b1 ;elseskip_en_1 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2))skip_en_2 <= 1'b1 ;elseskip_en_2 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3))skip_en_3 <= 1'b1 ;elseskip_en_3 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5))skip_en_5 <= 1'b1 ;elseskip_en_5 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6))skip_en_6 <= 1'b1 ;elseskip_en_6 <= 1'b0 ; endSLAVE_ADDR :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;if(cnt_i2c_clk == 2'd3)cnt_bit <= cnt_bit + 1'b1 ;elsecnt_bit <= cnt_bit ; if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd0))skip_en_0 <= 1'b1 ;elseskip_en_0 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))skip_en_1 <= 1'b1 ;elseskip_en_1 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd2))skip_en_2 <= 1'b1 ;elseskip_en_2 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3))skip_en_3 <= 1'b1 ;elseskip_en_3 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd5))skip_en_5 <= 1'b1 ;elseskip_en_5 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd6))skip_en_6 <= 1'b1 ;elseskip_en_6 <= 1'b0 ; endACK_1 :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))skip_en_1 <= 1'b1 ;elseskip_en_1 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2)&&(ack == 1'b1))skip_en_2 <= 1'b1 ;elseskip_en_2 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3)&&(ack == 1'b1))skip_en_3 <= 1'b1 ;elseskip_en_3 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5)&&(ack == 1'b1))skip_en_5 <= 1'b1 ;elseskip_en_5 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6)&&(ack == 1'b1))skip_en_6 <= 1'b1 ;elseskip_en_6 <= 1'b0 ; endDEVICE_ADDR :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;if(cnt_i2c_clk == 2'd3)cnt_bit <= cnt_bit + 1'b1 ;elsecnt_bit <= cnt_bit ; if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))skip_en_1 <= 1'b1 ;elseskip_en_1 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd2))skip_en_2 <= 1'b1 ;elseskip_en_2 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd5))skip_en_5 <= 1'b1 ;elseskip_en_5 <= 1'b0 ; endACK_2 :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))skip_en_1 <= 1'b1 ;elseskip_en_1 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2)&&(ack == 1'b1))skip_en_2 <= 1'b1 ;elseskip_en_2 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5)&&(ack == 1'b1))skip_en_5 <= 1'b1 ;elseskip_en_5 <= 1'b0 ; endDATA :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;if(cnt_i2c_clk == 2'd3)cnt_bit <= cnt_bit + 1'b1 ;elsecnt_bit <= cnt_bit ; if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd1))skip_en_1 <= 1'b1 ;elseskip_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 ;elseskip_en_3 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd4))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd6))skip_en_6 <= 1'b1 ;elseskip_en_6 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(cnt_bit == 3'd7)&&(mode == 3'd3)&&(rec_data != 8'h20))beginerror_en <= 1'b1 ;mode <= 3'd0 ;endelsebeginerror_en <= 1'b0 ;mode <= mode ;end endACK_3 :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1)&&(ack == 1'b1))skip_en_1 <= 1'b1 ;elseskip_en_1 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4)&&(ack == 1'b1))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ; end WAIT :beginif((cnt_delay == CNT_DELAY_MAX - 2'd2)&&(mode == 3'd0))skip_en_0 <= 1'b1 ;elseskip_en_0 <= 1'b0 ;cnt_delay <= cnt_delay + 1'b1 ;endNACK :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3)&&(ack == 1'b1))skip_en_3 <= 1'b1 ;elseskip_en_3 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6)&&(ack == 1'b1))skip_en_6 <= 1'b1 ;elseskip_en_6 <= 1'b0 ; endSTOP :begincnt_i2c_clk <= cnt_i2c_clk + 1'b1 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd0))skip_en_0 <= 1'b1 ;elseskip_en_0 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd1))skip_en_1 <= 1'b1 ;elseskip_en_1 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd2))skip_en_2 <= 1'b1 ;elseskip_en_2 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd3))skip_en_3 <= 1'b1 ;elseskip_en_3 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd4))skip_en_4 <= 1'b1 ;elseskip_en_4 <= 1'b0 ;if((cnt_i2c_clk == 2'd2)&&(mode == 3'd5))skip_en_5 <= 1'b1 ;elseskip_en_5 <= 1'b0 ; if((cnt_i2c_clk == 2'd2)&&(mode == 3'd6))skip_en_6 <= 1'b1 ;elseskip_en_6 <= 1'b0 ; if(cnt_i2c_clk == 2'd2)i2c_end <= 1'b1 ;elsei2c_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 ;elsemode <= mode ;enddefault :begincnt_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 ;endendcasealways@(posedge i2c_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)rec_data <= 8'd0 ;elsecase(c_state)DATA : if((mode == 3'd3)&&(cnt_i2c_clk == 2'd1))rec_data <= {rec_data[6:0],sda_in} ;elserec_data <= rec_data ;default : rec_data <= 8'd0 ;endcasealways@(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} ;elsepo_data_reg <= po_data_reg ;default : po_data_reg <= po_data_reg ;endcasealways@(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 ;elsepo_data <= po_data ;always@(*)case(c_state)ACK_1,ACK_2,ACK_3 : ack = ~sda_in ;NACK : ack = i2c_sda ;default : ack = 1'b0 ;endcasealways@(*)case(c_state)IDLE : i2c_scl = 1'b1 ;START : if(cnt_i2c_clk == 2'd3)i2c_scl = 1'b0 ;elsei2c_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 ;elsei2c_scl = 1'b1 ;WAIT : i2c_scl = 1'b0 ;STOP : if(cnt_i2c_clk == 2'd0)i2c_scl = 1'b0 ;elsei2c_scl = 1'b1 ;default : i2c_scl = 1'b1 ;endcasealways@(*)case(c_state)IDLE : i2c_sda = 1'b1 ;START : if(cnt_i2c_clk == 2'd0)i2c_sda = 1'b1 ;elsei2c_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 ;elsei2c_sda <= 1'b1 ;default : i2c_sda <= 1'b1 ;endcaseendmodule
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 ;elseled <= 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
总结
小编在这里用了7章的教程,带领各位读者完成了对手势识别模块上、下、左、右的识别配置,感谢各位读者的支持,后续将为大家带来4x4矩阵键盘密码锁工程的实现,敬请期待。