FPGA模块——IIC接口设计

FPGA模块------IIC接口设计

IIC协议


IIC接口代码

c 复制代码
module iic_drive#(
    parameter           P_ADDR_WIDTH = 16                      
)(              
    input               i_clk                   ,//模块输入时钟
    input               i_rst                   ,//模块输入复位-高有效

    /*--------用户接口--------*/
    input  [6 :0]       i_drive                 ,//用户输入设备地址
    input  [15:0]       i_operation_addr        ,//用户输入存储地址
    input  [7 :0]       i_operation_len         ,//用户输入读写长度
    input  [1 :0]       i_operation_type        ,//用户输入操作类型
    input               i_opeartion_valid       ,//用户输入有效信号
    output              o_operation_ready       ,//用户输出准备信号

    input  [7 :0]       i_write_data            ,//用户输入写数据
    output              o_write_req             ,//用户写数据请求信号

    output [7 :0]       o_read_data             ,//输出IIC读到的数据
    output              o_read_valid            ,//输出IIC读数据有效

    /*--------IIC接口--------*/
    output              o_iic_scl               ,//IIC的时钟
    inout               io_iic_sda               //IIC的双向数据项
);

/***************function**************/

/***************parameter*************/
parameter               P_ST_IDLE   = 0         ,//状态机-空闲
                        P_ST_START  = 1         ,//状态机-起始
                        P_ST_UADDR  = 2         ,//状态机-设备地址
                        P_ST_DADDR1 = 3         ,//状态机-存储地址高位
                        P_ST_DADDR2 = 4         ,//状态机-存储地址地位
                        P_ST_WRITE  = 5         ,//状态机-写数据
                        P_ST_RESTART= 6         ,
                        P_ST_READ   = 7         ,//状态机-读数据
                        P_ST_WAIT   = 8         ,
                        P_ST_STOP   = 9         ,//状态机-停止
                        P_ST_EMPTY  = 10        ;

localparam              P_W =   1               ,//2'b01
                        P_R =   2               ;//2'b10
                        

/***************port******************/             

/***************mechine***************/
reg  [7 :0]             r_st_current            ;//当前状态机
reg  [7 :0]             r_st_next               ;//下一个状态机
reg  [7 :0]             r_st_cnt                ;//状态机计数器


/***************reg*******************/
reg                     ro_operation_ready      ;//操作准备信号
reg                     ro_write_req            ;//写数据请求
reg                     ro_write_valid          ;//写数据有效
reg  [7 :0]             ro_read_data            ;//读数据
reg                     ro_read_valid           ;//读数据有效
reg                     ro_iic_scl              ;//IIC的SCL输出寄存器
reg  [7 :0]             ri_drive                ;//输入的设备地址
reg  [15:0]             ri_operation_addr       ;//输入的存储地址
reg  [7 :0]             ri_operation_len        ;//输入的读写长度
reg  [1 :0]             ri_operation_type       ;//输入读写类型
reg  [7 :0]             ri_write_data           ;//输入的写数据
reg                     r_iic_st                ;//iic时钟状态
reg                     r_iic_sda_ctrl          ;//iic数据三态门控制信号
reg                     ro_iic_sda              ;//iic数据信号
reg  [7 :0]             r_wr_cnt                ;//读写数据bit计数器
reg                     r_slave_ack             ;//iic操作里的从机应答
reg                     r_ack_valid             ;//应答有效
reg                     r_st_restart            ;
reg                     r_ack_lock              ;
reg  [7 :0]             r_read_drive            ;

/***************wire******************/
wire                    w_operation_active      ;//操作激活信号
wire                    w_st_trun               ;//状态机跳转信号
wire                    w_iic_sda               ;//iic数据线输入信号

/***************component*************/

/***************assign****************/
assign o_operation_ready    = ro_operation_ready    ;//准备信号
assign o_write_req          = ro_write_req          ;//写数据请求信号
assign o_read_data          = ro_read_data          ;//读数据
assign o_read_valid         = ro_read_valid         ;//读数据有效
assign o_iic_scl            = ro_iic_scl            ;//iic的scl
assign w_operation_active   = i_opeartion_valid & o_operation_ready ;//激活信号
assign w_st_trun            = r_st_cnt == 8 && r_iic_st             ;//状态机跳转条件
//三态门使用
assign io_iic_sda           = r_iic_sda_ctrl  ? ro_iic_sda : 1'bz   ;//三态门输出
assign w_iic_sda            = !r_iic_sda_ctrl ? io_iic_sda : 1'b0   ;//三态门输入

// IOBUF #(
//    .DRIVE           (12                 ),
//    .IBUF_LOW_PWR    ("TRUE"             ),
//    .IOSTANDARD      ("DEFAULT"          ),
//    .SLEW            ("SLOW"             ) 
// ) 
// IOBUF_u0 
// (      
//    .O               (ro_iic_sda         ),  
//    .IO              (io_iic_sda         ),  
//    .I               (w_iic_sda          ),  
//    .T               (!r_iic_sda_ctrl    )   
// );

/***************always****************/
//第一段状态
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_st_current <= P_ST_IDLE;
    else 
        r_st_current <= r_st_next;
end

//状态机跳转
always@(*)
begin
    case(r_st_current)
        P_ST_IDLE   : r_st_next <= w_operation_active   ? P_ST_START    : P_ST_IDLE     ;//空闲,操作激活时跳转到起始状态
        P_ST_START  : r_st_next <= P_ST_UADDR;                                           //起始状态,跳转设备地址
        P_ST_UADDR  : r_st_next <= w_st_trun            ? 
                                   r_st_restart ? P_ST_READ : P_ST_DADDR1                //判断是否时重启,重启转入读状态,不是重启转入写存储地址状态
                                   : P_ST_UADDR    ;                                     //写设备地址,写完跳转存储地址
        P_ST_DADDR1 : r_st_next <= r_slave_ack          ? P_ST_STOP     :                //存储地址,先等待应答,应答后操作结束跳转存储地址低位
                                   w_st_trun            ? P_ST_DADDR2   : P_ST_DADDR1   ;
        P_ST_DADDR2 : r_st_next <= w_st_trun & ri_operation_type == P_W ? P_ST_WRITE    ://存储地址低位,判断读写,读跳转读状态,写跳转写状态 
                                   w_st_trun & ri_operation_type == P_R ? P_ST_RESTART  :
                                   P_ST_DADDR2   ;
        P_ST_WRITE  : r_st_next <= w_st_trun & r_wr_cnt == ri_operation_len - 1  
                                                        ? P_ST_WAIT     : P_ST_WRITE    ;//写数据状态,写完目标长度跳转结束
        P_ST_RESTART: r_st_next <= P_ST_STOP;                                            //读数据时,重启总线状态
        P_ST_READ   : r_st_next <= w_st_trun ? P_ST_WAIT     : P_ST_READ     ;//读数据状态,写完目标长度跳转结束
        P_ST_WAIT   : r_st_next <= P_ST_STOP    ;
        P_ST_STOP   : r_st_next <= r_st_cnt == 1? P_ST_EMPTY : P_ST_STOP;
        P_ST_EMPTY  : r_st_next <= r_st_restart | r_ack_lock ? P_ST_START : P_ST_IDLE;   //空状态,等待IIC成功停止,判断是否重启,重启转入START,不重启转入IDLE
        default     : r_st_next <= P_ST_IDLE;
    endcase
end

//iic应答状态,1为没应答
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_ack_lock <= 'd0;
    else if(r_ack_valid && !w_iic_sda && r_st_current == P_ST_DADDR1)
        r_ack_lock <= 'd0;
    else if(r_ack_valid && w_iic_sda && r_st_current == P_ST_DADDR1)
        r_ack_lock <= 'd1;
    else 
        r_ack_lock <= r_ack_lock;
end

//读数据时,假写操作后重启信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_st_restart <= 'd0;
    else if(r_st_current == P_ST_READ)
        r_st_restart <= 'd0;
    else if(r_st_current == P_ST_RESTART)
        r_st_restart <= 'd1;
    else 
        r_st_restart <= r_st_restart;
end

//操作准备信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_operation_ready <= 'd1;
    else if(w_operation_active)
        ro_operation_ready <= 'd0;
    else if(r_st_current == P_ST_IDLE)
        ro_operation_ready <= 'd1;
    else 
        ro_operation_ready <= ro_operation_ready;
end

//寄存操作数据
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        ri_drive          <= 'd0;
        ri_operation_addr <= 'd0;
        ri_operation_len  <= 'd0;
        ri_operation_type <= 'd0;
    end else if(w_operation_active) begin
        ri_drive          <= {i_drive,1'b0};
        ri_operation_addr <= i_operation_addr   ;
        ri_operation_len  <= i_operation_len    ;
        ri_operation_type <= i_operation_type   ;
    end else begin
        ri_drive          <= ri_drive           ;
        ri_operation_addr <= ri_operation_addr  ;
        ri_operation_len  <= ri_operation_len   ;
        ri_operation_type <= ri_operation_type  ;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_read_drive <= 'd0;
    else if(w_operation_active)
        r_read_drive <= {i_drive,1'b1};
    else 
        r_read_drive <= r_read_drive;
end

//状态计数器
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_st_cnt <= 'd0;
    else if(r_st_current != r_st_next || ro_write_valid || ro_read_valid)//状态跳转、写完8bit数、读写8bit数
        r_st_cnt <= 'd0;
    else if(r_st_current == P_ST_STOP)
        r_st_cnt <= r_st_cnt + 1;
    else if(r_iic_st)
        r_st_cnt <= r_st_cnt + 1;
    else
        r_st_cnt <= r_st_cnt;
end

//iic时钟
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_iic_scl <= 'd1;
    else if(r_st_current >= P_ST_UADDR && r_st_current <= P_ST_WAIT)
        ro_iic_scl <= ~ro_iic_scl;
    else
        ro_iic_scl <= 'd1;
end

//iic时钟状态
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_iic_st <= 'd0;
    else if(r_st_current >= P_ST_UADDR && r_st_current <= P_ST_WAIT)
        r_iic_st <= ~r_iic_st;
    else
        r_iic_st <= 'd0;
end

//iic数据线三态门控制
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_iic_sda_ctrl <= 'd0;
    else if(r_st_cnt == 8 || r_st_next == P_ST_IDLE)
        r_iic_sda_ctrl <= 'd0;
    else if(r_st_current >= P_ST_START && r_st_current <= P_ST_WRITE || r_st_current == P_ST_STOP)
        r_iic_sda_ctrl <= 'd1;
    else
        r_iic_sda_ctrl <= r_iic_sda_ctrl;
end
 
//iic数据线写数据
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_iic_sda <= 'd0;
    else if(r_st_current == P_ST_START)
        ro_iic_sda <= 'd0;
    else if(r_st_current == P_ST_UADDR)
        ro_iic_sda <= r_st_restart ? r_read_drive[7 - r_st_cnt] :  ri_drive[7 - r_st_cnt];
    else if(r_st_current == P_ST_DADDR1)
        ro_iic_sda <= ri_operation_addr[15 - r_st_cnt];
    else if(r_st_current == P_ST_DADDR2)
        ro_iic_sda <= ri_operation_addr[7  - r_st_cnt];
    else if(r_st_current == P_ST_WRITE)
        ro_iic_sda <= ri_write_data[7  - r_st_cnt];
    else if(r_st_current == P_ST_STOP && r_st_cnt == 1)
        ro_iic_sda <= 'd1;
    else
        ro_iic_sda <= 'd0;
end

//写请求
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_write_req <= 'd0;
    else if(r_st_current == P_ST_DADDR2 && ri_operation_type == P_W && r_st_cnt == 7 && r_iic_st)
        ro_write_req <= 'd1;
    else if(r_st_current >= P_ST_DADDR2 && ri_operation_type == P_W && r_st_cnt == 7 && r_iic_st)
        ro_write_req <= r_wr_cnt < ri_operation_len - 1 ? 1'b1 : 1'b0;
    else
        ro_write_req <= 'd0;
end

//写有效
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_write_valid <= 'd0;
    else 
        ro_write_valid <= ro_write_req;
end

//写数据
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ri_write_data <= 'd0;
    else if(ro_write_valid)
        ri_write_data <= i_write_data;
    else        
        ri_write_data <= ri_write_data;
end

//读写计数器
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_wr_cnt <= 'd0;
    else if(r_st_current == P_ST_IDLE)
        r_wr_cnt <= 'd0;
    else if((r_st_current == P_ST_WRITE || r_st_current == P_ST_READ) && w_st_trun)
        r_wr_cnt <= r_wr_cnt + 1;
    else 
        r_wr_cnt <= r_wr_cnt;
end

//读出数据
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_read_data <= 'd0;
    else if(r_st_current == P_ST_READ && r_st_cnt >= 1 && r_st_cnt <= 8 && !r_iic_st)       
        ro_read_data <= {ro_read_data[6:0],w_iic_sda};
    else 
        ro_read_data <= ro_read_data;
end

//读出数据有效
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_read_valid <= 'd0;
    else if(r_st_current == P_ST_READ && r_st_cnt == 8 && !r_iic_st)
        ro_read_valid <= 'd1;
    else 
        ro_read_valid <= 'd0;
end

//从机应答信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_slave_ack <= 'd0;
    else if(r_ack_valid)
        r_slave_ack <= w_iic_sda;
    else 
        r_slave_ack <= 'd0;
end

//指示应答有效信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_ack_valid <= 'd0;
    else 
        r_ack_valid <= w_st_trun;
end
endmodule

应用IIC接口的代码

c 复制代码
module my_ctrl(
    input               i_clk                   ,
    input               i_rst                   ,

    input  [2 :0]       i_ctrl_eeprom_addr      ,
    input  [15:0]       i_ctrl_operation_addr   ,
    input  [1 :0]       i_ctrl_operation_type   ,
    input  [7 :0]       i_ctrl_operation_len    ,
    input               i_ctrl_opeartion_valid  ,
    output              o_ctrl_operation_ready  ,

    input  [7 :0]       i_ctrl_write_data       ,
    input               i_ctrl_write_sop        ,
    input               i_ctrl_write_eop        ,
    input               i_ctrl_write_valid      ,

    output [7 :0]       o_ctrl_read_data        ,
    output              o_ctrl_read_valid       ,

    /*--------iic dirve--------*/
    output [6 :0]       o_drive                 ,//用户输入设备地址
    output [15:0]       o_operation_addr        ,//用户输入存储地址
    output [7 :0]       o_operation_len         ,//用户输入读写长度
    output [1 :0]       o_operation_type        ,//用户输入操作类型
    output              o_opeartion_valid       ,//用户输入有效信号
    input               i_operation_ready       ,//用户输出准备信号

    output [7 :0]       o_write_data            ,//用户输入写数据
    input               i_write_req             ,//用户写数据请求信号

    input  [7 :0]       i_read_data             ,//输出IIC读到的数据
    input               i_read_valid             //输出IIC读数据有效
);

/***************function**************/

/***************parameter*************/
localparam              P_ST_IDLE       =   0               ,
                        P_ST_WRITE      =   1               ,
                        P_ST_WAIT       =   2               ,
                        P_ST_READ       =   3               ,
                        P_ST_REREAD     =   4               ,
                        P_ST_OREAD      =   5               ;

/***************port******************/             

/***************mechine***************/
reg  [7 :0]             r_st_current                        ;
reg  [7 :0]             r_st_next                           ;

/***************reg*******************/
reg                     ro_ctrl_operation_ready             ;
reg  [7 :0]             ro_ctrl_read_data                   ;
reg                     ro_ctrl_read_valid                  ;
reg  [7 :0]             ri_ctrl_write_data                  ;
reg                     ri_ctrl_write_sop                   ;
reg                     ri_ctrl_write_eop                   ;
reg                     ri_ctrl_write_valid                 ;
reg  [2 :0]             ri_ctrl_eeprom_addr                 ;
reg  [15:0]             ri_ctrl_operation_addr              ;
reg  [1 :0]             ri_ctrl_operation_type              ;
reg  [7 :0]             ri_ctrl_operation_len               ;
reg                     ri_operation_ready                  ;
reg  [7 :0]             ri_read_data                        ;
reg                     ri_read_valid                       ;
reg  [6 :0]             ro_drive                            ;
reg  [15:0]             ro_operation_addr                   ;
reg  [7 :0]             ro_operation_len                    ;
reg  [1 :0]             ro_operation_type                   ;
reg                     ro_opeartion_valid                  ;
reg                     r_fifo_read_en                      ;
reg  [7 :0]             r_read_cnt                          ;
reg  [15:0]             r_read_addr                         ;
reg                     r_read_vld_1d                       ;

/***************wire******************/     
wire                    w_ctrl_active                       ;
wire                    w_drive_end                         ;
wire                    w_drive_act                         ;
wire [7 :0]             w_fifo_read_data                    ;
wire                    w_fifo_empty                        ;


/***************component*************/


    FIFO_8X1024 FIFO_8X1024_WRITE_U0 (
    .clk                  (i_clk                  ),
    .srst                 (i_rst                  ),
    .din                  (ri_ctrl_write_data     ),
    .wr_en                (ri_ctrl_write_valid    ),
    .rd_en                (i_write_req            ),
    .dout                 (o_write_data           ),
    .full                 (),
    .empty                () 
    );

    FIFO_8X1024 FIFO_8X1024_READ_U0 (
    .clk                  (i_clk                  ),
    .srst                 (i_rst                  ),
    .din                  (ri_read_data           ),
    .wr_en                (ri_read_valid          ),
    .rd_en                (r_fifo_read_en         ),
    .dout                 (w_fifo_read_data       ),
    .full                 (),
    .empty                (w_fifo_empty           ) 
    );


/***************assign****************/
assign o_ctrl_operation_ready   = ro_ctrl_operation_ready   ;
assign o_ctrl_read_data         = ro_ctrl_read_data         ;
assign o_ctrl_read_valid        = r_read_vld_1d             ;
assign w_ctrl_active            = i_ctrl_opeartion_valid&o_ctrl_operation_ready;
assign w_drive_end              = i_operation_ready & !ri_operation_ready;
assign w_drive_act              = o_opeartion_valid & i_operation_ready;
assign o_drive                  = ro_drive          ;
assign o_operation_addr         = ro_operation_addr ;
assign o_operation_len          = ro_operation_len  ;
assign o_operation_type         = ro_operation_type ;
assign o_opeartion_valid        = ro_opeartion_valid;
/***************always****************/
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_st_current <= P_ST_IDLE;
    else
        r_st_current <= r_st_next;
end

always@(*)
begin
    case(r_st_current)
        P_ST_IDLE   :r_st_next = w_ctrl_active && i_ctrl_operation_type == 1 ? P_ST_WRITE : 
                                 w_ctrl_active && i_ctrl_operation_type == 2 ? P_ST_WAIT  :
                                 P_ST_IDLE; 
        P_ST_WRITE  :r_st_next = w_drive_end ? P_ST_IDLE : P_ST_WRITE; 
        P_ST_WAIT   :r_st_next = P_ST_READ;
        P_ST_READ   :r_st_next = w_drive_end ? 
                                 r_read_cnt == ri_ctrl_operation_len - 1  ? P_ST_OREAD : P_ST_REREAD 
                                 : P_ST_READ; 
        P_ST_REREAD :r_st_next = P_ST_READ;
        P_ST_OREAD  :r_st_next = w_fifo_empty ? P_ST_IDLE : P_ST_OREAD;
        default     :r_st_next = P_ST_IDLE;
    endcase
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_fifo_read_en <= 'd0;
    else if(w_fifo_empty)
        r_fifo_read_en <= 'd0;
    else if(r_st_current != P_ST_OREAD && r_st_next == P_ST_OREAD)
        r_fifo_read_en <= 'd1;
    else 
        r_fifo_read_en <= r_fifo_read_en;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        ro_ctrl_read_data <= 'd0;
    else 
        ro_ctrl_read_data <= w_fifo_read_data;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        ro_ctrl_read_valid <= 'd0;
    else if(w_fifo_empty)
        ro_ctrl_read_valid <= 'd0;
    else if(r_fifo_read_en)
        ro_ctrl_read_valid <= 'd1;
    else 
        ro_ctrl_read_valid <= ro_ctrl_read_valid;
end


always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_read_vld_1d <= 'd0;
    else 
        r_read_vld_1d <= ro_ctrl_read_valid;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        ri_ctrl_eeprom_addr    <= 'd0;
        ri_ctrl_operation_addr <= 'd0;
        ri_ctrl_operation_type <= 'd0;
        ri_ctrl_operation_len  <= 'd0;
    end else if(w_ctrl_active) begin
        ri_ctrl_eeprom_addr    <= i_ctrl_eeprom_addr    ;
        ri_ctrl_operation_addr <= i_ctrl_operation_addr;
        ri_ctrl_operation_type <= i_ctrl_operation_type;
        ri_ctrl_operation_len  <= i_ctrl_operation_len;
    end else begin
        ri_ctrl_eeprom_addr    <= ri_ctrl_eeprom_addr   ;
        ri_ctrl_operation_addr <= ri_ctrl_operation_addr;
        ri_ctrl_operation_type <= ri_ctrl_operation_type;
        ri_ctrl_operation_len  <= ri_ctrl_operation_len;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        ri_ctrl_write_data  <= 'd0;
        ri_ctrl_write_sop   <= 'd0;
        ri_ctrl_write_eop   <= 'd0;
        ri_ctrl_write_valid <= 'd0;
    end else begin
        ri_ctrl_write_data  <= i_ctrl_write_data    ;
        ri_ctrl_write_sop   <= i_ctrl_write_sop     ;
        ri_ctrl_write_eop   <= i_ctrl_write_eop     ;
        ri_ctrl_write_valid <= i_ctrl_write_valid   ;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_ctrl_operation_ready <= 'd1;
    else if(w_ctrl_active)
        ro_ctrl_operation_ready <= 'd0;
    else if(r_st_current == P_ST_IDLE)
        ro_ctrl_operation_ready <= 'd1;
    else
        ro_ctrl_operation_ready <= ro_ctrl_operation_ready; 
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ri_operation_ready <= 'd0;
    else
        ri_operation_ready <= i_operation_ready;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        ri_read_data  <= 'd0;
        ri_read_valid <= 'd0;
    end else begin
        ri_read_data  <= i_read_data ;
        ri_read_valid <= i_read_valid;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        ro_drive           <= 'd0;
        ro_operation_addr  <= 'd0;
        ro_operation_len   <= 'd0;
        ro_operation_type  <= 'd0;
        ro_opeartion_valid <= 'd0;
    end else if(w_drive_act) begin
        ro_drive           <= 'd0;
        ro_operation_addr  <= 'd0;
        ro_operation_len   <= 'd0;
        ro_operation_type  <= 'd0;
        ro_opeartion_valid <= 'd0;
    end else if(ri_ctrl_write_eop) begin
        ro_drive           <= {4'b1010,ri_ctrl_eeprom_addr};
        ro_operation_addr  <= ri_ctrl_operation_addr;
        ro_operation_len   <= ri_ctrl_operation_len;
        ro_operation_type  <= ri_ctrl_operation_type;
        ro_opeartion_valid <= 'd1;
    end else if(r_st_next == P_ST_READ && r_st_current != P_ST_READ) begin
        ro_drive           <= {4'b1010,ri_ctrl_eeprom_addr};
        ro_operation_addr  <= r_read_addr;
        ro_operation_len   <= 1;
        ro_operation_type  <= ri_ctrl_operation_type;
        ro_opeartion_valid <= 'd1;
    end else begin
        ro_drive           <= ro_drive          ;
        ro_operation_addr  <= ro_operation_addr ;
        ro_operation_len   <= ro_operation_len  ;
        ro_operation_type  <= ro_operation_type ;
        ro_opeartion_valid <= ro_opeartion_valid;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_read_addr <= 'd0;
    else if(w_ctrl_active)
        r_read_addr <= i_ctrl_operation_addr;
    else if(r_st_current == P_ST_READ && w_drive_end)
        r_read_addr <= r_read_addr + 1 ;
    else
        r_read_addr <= r_read_addr;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_read_cnt <= 'd0;
    else if(r_st_current == P_ST_IDLE)
        r_read_cnt <= 'd0;
    else if(r_st_current == P_ST_READ && w_drive_end)
        r_read_cnt <= r_read_cnt  +1;
    else
        r_read_cnt <= r_read_cnt;
end

endmodule
相关推荐
DS小龙哥1 小时前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
上理考研周导师11 小时前
第二章 虚拟仪器及其构成原理
fpga开发
jjyangyou11 小时前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
FPGA技术实战12 小时前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
bigbig猩猩1 天前
FPGA(现场可编程门阵列)的时序分析
fpga开发
憧憬一下1 天前
Pinctrl子系统中Pincontroller和client驱动程序的编写
arm开发·嵌入式·c/c++·linux驱动开发
蓝天居士1 天前
ES8388 —— 带耳机放大器的低功耗立体声音频编解码器(4)
嵌入式·音频·es8388
Terasic友晶科技1 天前
第2篇 使用Intel FPGA Monitor Program创建基于ARM处理器的汇编或C语言工程<二>
fpga开发·汇编语言和c语言
码农阿豪1 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡