Menu Close

I2C 应用层 Verilog程序组装

在完成iic_cmd 层设计后,就需要上层应用程序发送操作给cmd层。在结构化设计中, 我们需要将iic_cmd,iic_phy,scl_en 等模块封装一起,称为iic_engine 模块,这样iic_engine 模块就可以独立使用了, 应用层有多种多样,但都是可以调用iic_engine 。本文中使用iic_app 模块作为i2c 的应用层。在iic_app 中,只有数据包的发送和接收, 再没有和i2c phy相关的具体操作了,完全是数据的传输。在结构化设计中,结构框图如下:

 

图1

从图1中可以看出, iic_app层与数据相关,只是安装接口协议写入或者读取相应的数据到iic_engine,不负责i2c 的具体操作。 iic_engine 负责i2c 的具体操作,但是命令是由上层(iic_app)来提供的。

1 iic_app 层代码:

 

图2

状态0:初始化, 等待65535 个时钟周期,主要用于仿真,方便观察,跳转到状态1

状态1:读取二维数值中的数据,如果数组不为0, 表示当前命令有效,发送数据到cmd 层,跳转到状态2

状态2:等待cmd 层返回pkg_din_ack 信号, 发送下一笔数据,直到发送的数据个数等于 pkg_len,跳转到状态3

状态3:等待cmd 层返回pkg_end, 指针指向下一条命令, 跳转到状态1。

`timescale 1ns / 1ps


module iic_app
(
    input        sys_clk,

    output reg [7:0] pkg_din = 0,
    output reg   pkg_din_vld = 0,
    input        pkg_din_ack,
    input        pkg_end,

    input  [7:0] pkg_dout,
    input        pkg_dout_vld,

    input        rst
);

localparam CMD_LEN = 12;
reg [CMD_LEN*8 - 1: 0] cmd_list[9:0];
initial
begin
    //            length delay  addr  data/rd leng            data 
    cmd_list[0] = {8'h0c,8'h05,8'ha0, 8'h00,       8'h00,8'h01,8'h02,8'h03,8'h04,8'h05,8'h06,8'h07};
    cmd_list[1] = {8'h0b,8'h05,8'ha0, 8'h08,       8'h08,8'h09,8'h0a,8'h0b,8'h0c,8'h0d,8'h0e,8'h0f};
    cmd_list[2] = {8'h05,8'h01,8'ha1, 8'h03,       8'h06,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
    cmd_list[3] = {8'h04,8'h01,8'ha1, 8'h02,       8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
    cmd_list[4] = {8'h04,8'h01,8'ha1, 8'h00,       8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
    cmd_list[5] = {8'h05,8'h01,8'ha1, 8'h0b,       8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
    cmd_list[6] = 0;
end

reg [7:0] pkg_len = 0;
reg [3:0] app_st;
reg [15:0] cnt;
reg [4:0] cmd_idx = 0;
always@(posedge sys_clk or posedge rst)
if(rst)
begin
    pkg_din_vld <= 0;
    cmd_idx <= 0;
    
    cnt <= 1;
    app_st <= 0;
end
else
case(app_st)
0:
begin
    cmd_idx <= 0;
    pkg_din_vld <= 0;

    cnt <= cnt + 1;
    
    if(&cnt[15:0])
    begin
        cnt <= 1;
        app_st <= 1;
    end
end
1:
begin
    cnt <= 1;
    if(cmd_list[cmd_idx] != 0)
    begin
        pkg_din_vld <= 1;
        pkg_len <= cmd_list[cmd_idx][CMD_LEN*8-1 -:8];
        pkg_din <= cmd_list[cmd_idx][CMD_LEN*8-1 -:8];
        app_st <= 2;
    end
    else $stop;
end
2:
begin
    if(pkg_len == cnt)
        app_st <= 3;
    else
    begin
        if(pkg_din_ack)
        begin
            pkg_din <= cmd_list[cmd_idx][(CMD_LEN - cnt)*8-1 -:8];
            cnt <= cnt + 1;
        end
    end
    
end
3:
begin
    if(pkg_end)
    begin
        pkg_din_vld <= 0;
        cmd_idx <= cmd_idx + 1;
        #50000;
        app_st <= 1;
    end
end
default:app_st <= 0;
endcase

endmodule

 

仿真

图3

 

 

Posted in FPGA, FPGA 教材教案, Verilog, 教材与教案

发表回复

相关链接