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
相关推荐
2202_754421544 分钟前
一个计算频率的模块
驱动开发·fpga开发
小灰灰的FPGA1 小时前
低速接口项目之串口Uart开发(七)——如何在FPGA项目中实现自适应波特率串口功能
fpga开发
网易独家音乐人Mike Zhou13 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
fei_sun20 小时前
【Verilog】第一章作业
fpga开发·verilog
深圳市雷龙发展有限公司longsto21 小时前
基于FPGA(现场可编程门阵列)的SD NAND图片显示系统是一个复杂的项目,它涉及硬件设计、FPGA编程、SD卡接口、NAND闪存控制以及图像显示等多个方面
fpga开发
9527华安1 天前
FPGA实现PCIE3.0视频采集转10G万兆UDP网络输出,基于XDMA+GTH架构,提供工程源码和技术支持
网络·fpga开发·udp·音视频·xdma·pcie3.0·万兆网
able陈1 天前
为什么verilog中递归函数需要定义为automatic?
fpga开发
fei_sun1 天前
【Verilog】第二章作业
fpga开发·verilog
碎碎思1 天前
如何使用 Vivado 从源码构建 Infinite-ISP FPGA 项目
fpga开发·接口隔离原则
江山如画,佳人北望1 天前
fpga-状态机的设计及应用
fpga开发