基于FPGA的IIC协议详解——EEPROM控制器(2)

小结

相信大家读完上一篇博客对IIC协议与eeprom读写已经有了一定的了解,本篇博客将以黑金A7102开发板为例进行验证上结代码的准确性,这里注意之江将上篇文章的代码放在A7102中是不能用的,因为上篇文章的代码是以24LC64为例进行书写的,而A7102中的eeprom芯片是24LC04。这里为了简单起见不再给出修改后的代码,需要的同学可以进群自取。

modelsim仿真测试

在这里插入图片描述
从上图中我们可以看到我们编写的eeprom控制器modelsim仿真通过验证。

上板测试代码

为了上板验证的方便性,我们将添加如下代码:
top_test模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : 
// Module Name  : top_test.v
// Create Time  : 2020-01-14 16:13:00
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module top_test(
    input                   sys_clk_p       ,
    input                   sys_clk_n       ,
    input                   rst_n           ,
    input                   key_wr          ,
    input                   key_rd          ,
    output  wire            iic_sck         ,
    inout                   iic_sda     
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
wire                        wr_req          ;
wire                        rd_req          ;
wire                [ 7:0]  addr            ;
wire                [ 7:0]  wr_data         ;
wire                [ 7:0]  rd_data         ;
wire                        rd_valid        ;
wire                        sclk            ;


 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
clk_wiz_0 clk_wiz_0_inst(
    .clk_out1           (sclk               ), 
    .resetn             (rst_n              ), 
    .clk_in1_p          (sys_clk_p          ), 
    .clk_in1_n          (sys_clk_n          )
);    
key key_inst1(
    .sclk               (sclk               ),
    .rst_n              (rst_n              ),
    .key                (~key_wr            ),
    .key_o              (wr_req             )
);

key key_inst2(
    .sclk               (sclk               ),
    .rst_n              (rst_n              ),
    .key                (~key_rd            ),
    .key_o              (rd_req             )   
);

top top_inst(
    .sclk               (sclk               ),
    .rst_n              (rst_n              ),
    .wr_req             (wr_req             ),
    .rd_req             (rd_req             ),
    .addr               (addr               ),
    .rd_data            (rd_data            ),
    .rd_valid           (rd_valid           ),
    .wr_data            (wr_data            ),
    .busy               (                   ),
    .iic_sck            (iic_sck            ),
    .iic_sda            (iic_sda            )    
);
//========================================================================================\
//*******************************     Debug    **********************************
//========================================================================================/

ila_0 ila_0_inst (
    .clk                (sclk               ), // input wire clk
    .probe0             (rd_data            ), // input wire [7:0]  probe0  
    .probe1             (rd_valid           ) // input wire [0:0]  probe1
);

vio_0 vio_0_inst (
  .clk                  (sclk               ),                // input wire clk
  .probe_out0           (addr               ),  // output wire [7 : 0] probe_out0
  .probe_out1           (wr_data            )  // output wire [7 : 0] probe_out1
);

endmodule

key模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : 
// Module Name  : key.v
// Create Time  : 2020-01-05 13:49:36
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module key(
    input                       sclk            ,
    input                       rst_n           ,
    input                       key             ,
    output  reg                 key_o       
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
parameter       IDLE        =       4'b0001     ;    
parameter       S1          =       4'b0010     ;
parameter       S2          =       4'b0100     ;
parameter       S3          =       4'b1000     ;

reg                 [ 3:0]      state           ;
reg                 [ 9:0]      cnt             ;
reg                             key_r1          ;
reg                             key_r2          ;
reg                             key_r3          ;
reg                             nege_flag       ;
reg                             pose_flag       ;
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk)
    key_r1          <=      key;

always @(posedge sclk)
    key_r2          <=      key_r1;

always @(posedge sclk)
    key_r3          <=      key_r2;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        nege_flag       <=      1'b0;
    else if(key_r3 == 1'b1 && key_r2 == 1'b0)
        nege_flag       <=      1'b1;
    else
        nege_flag       <=      1'b0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        pose_flag       <=      1'b0;
    else if(key_r3 == 1'b0 && key_r2 == 1'b1) 
        pose_flag       <=      1'b1;
    else
        pose_flag       <=      1'b0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        state           <=      IDLE;
    else case(state)
        IDLE    :   if(nege_flag == 1'b1)
                        state           <=      S1;
                    else
                        state           <=      IDLE;                        
        S1      :   if(cnt == 10'd999)
                        state           <=      S2;
                    else if(pose_flag == 1'b1)
                        state           <=      IDLE;
                    else
                        state           <=      S1;                        
        S2      :   if(pose_flag == 1'b1)
                        state           <=      S3;
                    else
                        state           <=      S2;                        
        S3      :   if(cnt == 10'd999)
                        state           <=      IDLE;
                    else if(nege_flag == 1'b1)
                        state           <=      S2;
                    else
                        state           <=      S3;
                        
        default :   state           <=      IDLE;
    endcase

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt             <=      10'd0;
    else if(state != S1 && state != S3)
        cnt             <=      10'd0;
    else
        cnt             <=      cnt + 1'b1;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        key_o           <=      1'b0;
    else if(state == S1 && cnt == 10'd999) 
        key_o           <=      1'b1;
    else
        key_o           <=      1'b0;

endmodule

从代码中可以看出我们使用了ila与vio在线调试工具,这在vivado中非常常见。

上班调试

我们首先通过按键与ila向地址8’h15写入aa,再向地址8‘h51写入55,最后读出数据通过ila显示在图形化界面中验证我们控制器的正确性。
在这里插入图片描述
在这里插入图片描述
从上面的图中可以验证我们eeprom控制器代码的正确性。

结束语

创作不易,认为文章有帮助的同学们可以收藏点赞支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

发布了14 篇原创文章 · 获赞 4 · 访问量 587

猜你喜欢

转载自blog.csdn.net/zhangningning1996/article/details/103992689