当前位置:   article > 正文

FPGA模块——IIC接口设计

FPGA模块——IIC接口设计

FPGA模块——IIC接口设计

IIC协议

在这里插入图片描述
在这里插入图片描述

IIC接口代码


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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372

应用IIC接口的代码

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/599787
推荐阅读
相关标签
  

闽ICP备14008679号