• 状态机练习 基于EEPROM的I2C 随机读、写


    I2C完整的随机读写时序前面已经贴出来了,这里直接贴状态机图:

    设计思路同之前的方法,有了前面的随机读、 写的实验,这里将读、写融合在一个状态机里面,很快就整合完了,验证也是非常的OK。

    注意区分在写状态时的ack_flag 和 读状态时的ack_flag,同时加上wr_vld 和 rd_vld 来区分ack 将跳转下一个状态。

    完整的代码:

      1 module i2c_eeprom_w_r(
      2                         clk,
      3                         rst_n,
      4                         wr_en,
      5                         rd_en,
      6                         
      7                         scl,
      8                         sda,
      9                         rec_buf
     10 );
     11 
     12 parameter        D_W             = 8     ;
     13 parameter        SCL_100K         = 500;
     14 parameter         IDLE              = 0     ;
     15 parameter         START             = 1     ;
     16 parameter         SLAVE_ADD         = 2     ;
     17 parameter         ACK               = 3     ; 
     18 parameter         REG_ADD              = 4     ;
     19 parameter         REG_DAT              = 5     ;
     20 parameter         REC_DAT              = 6     ;
     21 parameter         NOACK              = 7     ;
     22 parameter         STOP              = 8     ;
     23 
     24 parameter        slave_address   = 8'b1010_0000;
     25 parameter        reg_address     = 8'h0f;
     26 parameter        reg_data        = 8'h88;
     27 
     28 input            clk         ;
     29 input            rst_n    ;
     30 input            wr_en    ;
     31 input            rd_en    ;
     32 output            scl        ;
     33 inout            sda        ;
     34 output[D_W-1:0] rec_buf    ;
     35 
     36 wire [D_W-1:0]  slave_address_r;
     37 
     38 assign             slave_address_r = slave_address | 1'b1;    
     39 
     40 wire            IDLE2START        ;
     41 wire            START2SLAVE_ADD    ;
     42 wire            SLAVE_ADD2ACK    ;
     43 wire            ACK2REG_ADD        ;
     44 wire            ACK2REG_DAT        ;
     45 wire            ACK2REC_DAT        ;
     46 wire            ACK2START        ;
     47 wire            ACK2STOP        ;
     48 wire            REG_ADD2ACK        ;
     49 wire            REG_DAT2ACK        ;
     50 wire            REC_DAT2NOACK    ;
     51 wire            NOACK2STOP        ;
     52 wire            STOP2IDLE        ;
     53 
     54 wire            SCL_H2L          ;
     55 wire            SCL_L2H          ;
     56 wire            SCL_H_MIDDLE     ;
     57 wire             add_cnt0         ;
     58 wire             end_cnt0         ;
     59 wire             add_cnt1         ;
     60 wire             end_cnt1         ;
     61 
     62 reg[D_W-1:0]    rec_buf    ;
     63 reg                scl        ;
     64 reg              link    ;
     65 reg             sda_temp;
     66 reg             ack_err ;
     67 reg[4-1:0]        state_c /* synthesis keep*/;
     68 reg[4-1:0]        state_n /* synthesis keep*/;
     69 reg[4-1:0]        x        ;
     70 reg                wr_vld    ;
     71 reg                rd_vld    ;
     72 reg[2-1:0]         ack_flag; 
     73 
     74 reg[9-1:0]    cnt0;
     75 reg[4-1:0]    cnt1;
     76 
     77 //写使能信号
     78 always @(posedge clk or negedge rst_n)begin
     79     if(!rst_n)begin
     80         wr_vld <= 0;
     81     end
     82     else if(wr_en)begin
     83         wr_vld <= 1;
     84     end
     85     else if(state_c == STOP && end_cnt1)begin
     86         wr_vld <= 0;
     87     end
     88 end
     89 
     90 //读使能信号
     91 always @(posedge clk or negedge rst_n)begin
     92     if(!rst_n)begin
     93         rd_vld <= 0;
     94     end
     95     else if(rd_en)begin
     96         rd_vld <= 1;
     97     end
     98     else if(state_c == STOP && end_cnt1)begin
     99         rd_vld <= 0;
    100     end
    101 end
    102 
    103 //计数器cnt0,用于产生scl时钟
    104 always @(posedge clk or negedge rst_n)begin
    105     if(!rst_n)begin
    106         cnt0 <= 0;
    107     end
    108     else if(add_cnt0)begin
    109         if(end_cnt0)begin
    110             cnt0 <= 0;
    111         end
    112         else begin
    113             cnt0 <= cnt0 + 1;
    114         end
    115     end
    116 end
    117 
    118 assign add_cnt0 = wr_vld || rd_vld;
    119 assign end_cnt0 = add_cnt0 && cnt0 == SCL_100K - 1;
    120 
    121 //计数器cnt1,用于scl时钟周期数量计数
    122 always @(posedge clk or negedge rst_n)begin
    123     if(!rst_n)begin
    124         cnt1 <= 0;
    125     end
    126     else if(add_cnt1)begin
    127         if(end_cnt1)begin
    128             cnt1 <= 0;
    129         end
    130         else begin
    131             cnt1 <= cnt1 + 1;
    132         end
    133     end
    134 end
    135 
    136 assign add_cnt1 = end_cnt0;
    137 assign end_cnt1 = add_cnt1 && cnt1 == x - 1;
    138 
    139 //每个状态下的scl时钟周期数量个数
    140 always @(*)begin
    141     if(state_c == START || state_c == ACK || state_c == NOACK || state_c == STOP)begin
    142         x = 1;
    143     end
    144     else begin
    145         x = 8;
    146     end
    147 end
    148 
    149 
    150 //scl时钟周期  _--_
    151 always @(posedge clk or negedge rst_n)begin
    152     if(!rst_n)begin
    153         scl <= 1;
    154     end
    155     else if(add_cnt0 && cnt0 == ((SCL_100K>>1)+ (SCL_100K>>2)) -1 && state_c != STOP)begin
    156         scl <= 0;
    157     end
    158     else if(add_cnt0 && cnt0 == (SCL_100K>>2) -1)begin
    159         scl <= 1;
    160     end
    161 end
    162 
    163 assign SCL_H2L         = add_cnt0 && cnt0 == ((SCL_100K>>1)+ (SCL_100K>>2)) -1; //下降沿
    164 assign SCL_L2H         = add_cnt0 && cnt0 == (SCL_100K>>2) -1;    //上升沿
    165 assign SCL_H_MIDDLE = add_cnt0 && cnt0 == (SCL_100K>>1) -1;    //高电平中间
    166 
    167 
    168 //第一段
    169 always @(posedge clk or negedge rst_n)begin
    170     if(!rst_n)begin
    171         state_c <= IDLE;
    172     end
    173     else begin
    174         state_c <= state_n;
    175     end
    176 end
    177 
    178 //第二段
    179 always @(*)begin
    180     case(state_c)
    181     
    182     IDLE:begin
    183         if(IDLE2START)begin
    184             state_n = START;
    185         end
    186         else begin
    187             state_n = state_c;
    188         end
    189     end
    190     
    191     START:begin
    192         if(START2SLAVE_ADD)begin
    193             state_n = SLAVE_ADD;
    194         end
    195         else begin
    196             state_n = state_c;
    197         end
    198     end
    199     
    200     SLAVE_ADD:begin
    201         if(SLAVE_ADD2ACK)begin
    202             state_n = ACK;
    203         end
    204         else begin
    205             state_n = state_c;
    206         end
    207     end
    208     
    209     ACK:begin
    210         if(ACK2REG_ADD)begin
    211             state_n = REG_ADD;
    212         end
    213         else if(ACK2REG_DAT)begin
    214             state_n = REG_DAT;
    215         end
    216         else if(ACK2REC_DAT)begin
    217             state_n = REC_DAT;
    218         end
    219         else if(ACK2START)begin
    220             state_n = START;
    221         end
    222         else if(ACK2STOP)begin
    223             state_n = STOP;
    224         end
    225         else begin
    226             state_n = state_c;
    227         end
    228     end
    229     
    230     REG_ADD:begin
    231         if(REG_ADD2ACK)begin
    232             state_n = ACK;
    233         end
    234         else begin
    235             state_n = state_c;
    236         end
    237     end
    238     
    239     REG_DAT:begin
    240         if(REG_DAT2ACK)begin
    241             state_n = ACK;
    242         end
    243         else begin
    244             state_n = state_c;
    245         end
    246     end
    247     
    248     REC_DAT:begin
    249         if(REC_DAT2NOACK)begin
    250             state_n = NOACK;
    251         end
    252         else begin
    253             state_n = state_c;
    254         end
    255     end
    256     
    257     NOACK:begin
    258         if(NOACK2STOP)begin
    259             state_n = STOP;
    260         end
    261         else begin
    262             state_n = state_c;
    263         end
    264     end
    265     
    266     STOP:begin
    267         if(STOP2IDLE)begin
    268             state_n = IDLE;
    269         end
    270         else begin
    271             state_n = state_c;
    272         end
    273     end
    274     
    275     default:begin
    276         state_n = IDLE;
    277     end
    278     
    279     endcase
    280 end
    281 
    282 //第三段,条件转移
    283 assign IDLE2START             = state_c == IDLE          && (wr_vld || rd_vld);
    284 assign START2SLAVE_ADD        = state_c == START         && end_cnt1;
    285 assign SLAVE_ADD2ACK        = state_c == SLAVE_ADD     && end_cnt1;
    286 assign ACK2REG_ADD            = state_c == ACK            && end_cnt1 && ack_flag == 0;
    287 assign ACK2REG_DAT            = state_c == ACK           && end_cnt1 && ack_flag == 1 && wr_vld;
    288 assign ACK2REC_DAT            = state_c == ACK           && end_cnt1 && ack_flag == 2 && rd_vld;
    289 assign ACK2START            = state_c == ACK           && end_cnt1 && ack_flag == 1 && rd_vld;
    290 assign ACK2STOP                = state_c == ACK        && end_cnt1 && ack_flag == 2 && wr_vld;
    291 assign REG_ADD2ACK            = state_c == REG_ADD    && end_cnt1;
    292 assign REG_DAT2ACK            = state_c == REG_DAT    && end_cnt1;
    293 assign REC_DAT2NOACK        = state_c == REC_DAT    && end_cnt1;
    294 assign NOACK2STOP            = state_c == NOACK        && end_cnt1;
    295 assign STOP2IDLE            = state_c == STOP        && end_cnt1;
    296 
    297 always @(posedge clk or negedge rst_n)begin
    298     if(!rst_n)begin
    299         ack_flag <= 0;
    300     end
    301     else if(wr_vld)begin
    302         if(state_c == REG_ADD)begin
    303             ack_flag <= 1; //代表是发送完寄存器地址后面的ACK
    304         end
    305         else if(state_c == REG_DAT)begin
    306             ack_flag <= 2; //代表是发送完寄存器数据后面的ACK
    307         end
    308         else if(state_c == STOP && end_cnt1)begin
    309             ack_flag <= 0;
    310         end
    311     end
    312     else if(rd_vld)begin
    313         if(state_c == SLAVE_ADD && ack_flag == 0)begin
    314             ack_flag <= 0;
    315         end
    316         else if(state_c == REG_ADD)begin
    317             ack_flag <= 1; //代表是发送完寄存器地址后面的ACK
    318         end
    319         else if(state_c == SLAVE_ADD && ack_flag == 1)begin
    320             ack_flag <= 2; 
    321         end
    322         else if(state_c == STOP && end_cnt1)begin
    323             ack_flag <= 0;
    324         end
    325     end
    326 end
    327 
    328 //sda的方向控制
    329 always @(posedge clk or negedge rst_n)begin
    330     if(!rst_n)begin
    331         link <= 1;
    332     end
    333     else if((state_c ==  ACK && add_cnt0 && cnt0 >= 0 && cnt0 <((SCL_100K>>1)+ (SCL_100K>>2)))  || state_c == REC_DAT)begin
    334         link <= 0;    //释放sda,准备接收数据 ,注意在接收数据期间是要一直释放的
    335     end
    336     else begin
    337         link <= 1;
    338     end
    339 end
    340 
    341 //sda要发出的数据
    342 always @(posedge clk or negedge rst_n)begin
    343     if(!rst_n)begin
    344         sda_temp <= 1;
    345     end
    346     else if(state_c == START && SCL_H_MIDDLE)begin //在高电平中间拉低sda 
    347         sda_temp <= 0; //产生start信号 
    348     end
    349     else if(state_c == ACK && end_cnt1 && ack_flag == 0 && rd_vld)begin
    350         sda_temp <= 1; //拉高SDA,准备再次产生start信号
    351     end
    352     else if(state_c == SLAVE_ADD && ack_flag == 0)begin
    353         sda_temp <= slave_address[7-cnt1];  //写设备地址,写操作
    354     end
    355     else if(state_c == REG_ADD)begin
    356         sda_temp <= reg_address[7-cnt1];    //写寄存器地址
    357     end
    358     else if(state_c == SLAVE_ADD && ack_flag == 2 && rd_vld)begin
    359         sda_temp <= slave_address_r[7-cnt1]; //写设备地址,读操作
    360     end
    361     else if(state_c == REG_DAT)begin
    362         sda_temp <= reg_data[7-cnt1];    //写数据
    363     end
    364     else if(state_c == ACK && end_cnt0 && ack_flag == 2 && wr_vld)begin
    365         sda_temp <= 0;    //在产生stop之前,先将sda信号拉低
    366     end
    367     else if(state_c == NOACK)begin
    368         sda_temp <= 0;    //在产生stop之前,先将sda信号拉低
    369     end
    370     else if(state_c == STOP && SCL_H_MIDDLE)begin
    371         sda_temp <= 1;
    372     end
    373 end
    374 
    375 //接收读取的数据
    376 always @(posedge clk or negedge rst_n)begin
    377     if(!rst_n)begin
    378         rec_buf <= 0;
    379     end
    380     else if(state_c == REC_DAT && SCL_H_MIDDLE)begin
    381         rec_buf <= {rec_buf[6:0],sda};
    382     end
    383 end
    384 
    385 //sda接收数据 ,主要是判断是否接收到有效的ack
    386 always @(posedge clk or negedge rst_n)begin
    387     if(!rst_n)begin
    388         ack_err <= 0;
    389     end
    390     else if(state_c == ACK && SCL_H_MIDDLE)begin
    391         ack_err <= sda;
    392     end
    393 end
    394 
    395 assign sda = link? sda_temp : 1'bz;
    396 
    397 endmodule

    在随机写状态时的仿真波形:主要看start 、ACK 、stop 几个状态是否正确

     在随机读状态时的仿真波形

     

     通过检查波形,产生的时序是正确的,接下来用 Quartus 的逻辑分析在抓取硬件的回应:

    (1)、抓取的写时序,主要看ACK

    (2)、主要看接收的数据

     OK 整个I2C 读写实验基本全都完成了,完成之后,感觉轻松多了,之前写了很多的版本,感觉都不怎么好,代码繁琐,且很麻烦,不够精简。

    贴出几个其他的版本,功能都能实现:

    第一个版本,写的特别长,每个bit都当做一个状态机,虽然好理解,但觉得很幼稚

      1 module AT24C02(
      2                 clk,
      3                 rst_n,
      4                     
      5                 led,
      6                 scl,
      7                 sda
      8                 );
      9                 
     10 parameter     IDLE = 2'd0,
     11             WRITE_TASK = 2'd1,
     12             READ_TASK = 2'd2;
     13             
     14 parameter    INIT             = 6'd0,
     15             GEN_START         = 6'd1,
     16             DEV_ADDR_D7     = 6'd2,
     17             DEV_ADDR_D6     = 6'd3,
     18             DEV_ADDR_D5     = 6'd4,
     19             DEV_ADDR_D4     = 6'd5,
     20             DEV_ADDR_D3     = 6'd6,
     21             DEV_ADDR_D2     = 6'd7,
     22             DEV_ADDR_D1     = 6'd8,
     23             DEV_ADDR_D0     = 6'd9,
     24             DEV_RELEASE_SDA = 6'd10,
     25             DEV_READ_ACK    = 6'd11,
     26             DEV_CHECK_ACK     = 6'd12,
     27             
     28             REG_ADDR_D7     = 6'd13,
     29             REG_ADDR_D6     = 6'd14,
     30             REG_ADDR_D5     = 6'd15,
     31             REG_ADDR_D4     = 6'd16,
     32             REG_ADDR_D3     = 6'd17,
     33             REG_ADDR_D2     = 6'd18,
     34             REG_ADDR_D1     = 6'd19,
     35             REG_ADDR_D0     = 6'd20,
     36             REG_RELEASE_SDA = 6'd21,
     37             REG_READ_ACK    = 6'd22,
     38             REG_CHECK_ACK     = 6'd23,
     39             
     40             
     41             SEND_D7         = 6'd24,
     42             SEND_D6         = 6'd25,
     43             SEND_D5         = 6'd26,
     44             SEND_D4         = 6'd27,
     45             SEND_D3         = 6'd28,
     46             SEND_D2         = 6'd29,
     47             SEND_D1         = 6'd30,
     48             SEND_D0         = 6'd31,
     49             DAT_RELEASE_SDA = 6'd32,
     50             DAT_READ_ACK    = 6'd33,
     51             DAT_CHECK_ACK     = 6'd34,
     52             STOP            = 6'd35,
     53             WR_FINISH        = 6'd36,
     54             
     55             RD_DATA_7        = 6'd37,
     56             RD_DATA_6        = 6'd38,
     57             RD_DATA_5        = 6'd39,
     58             RD_DATA_4        = 6'd40,
     59             RD_DATA_3        = 6'd41,
     60             RD_DATA_2        = 6'd42,
     61             RD_DATA_1        = 6'd43,
     62             RD_DATA_0        = 6'd44,
     63             NO_ACK            = 6'd45,
     64             RD_FINISH        = 6'd46;
     65             
     66             
     67             
     68 parameter     device_addr     = 8'b1010_0000;
     69 parameter     reg_addr         = 8'h02;
     70 parameter    data            = 8'h10;
     71 
     72 input     clk        ;
     73 input     rst_n    ;
     74 
     75 output     led;
     76 output    scl        ;
     77 inout    sda        ;
     78 
     79 wire    sda        ;
     80 wire      led        ;
     81 
     82 reg        wr_req    ;
     83 reg     rd_req    ;
     84 
     85 wire     add_cnt0;
     86 wire     end_cnt0;
     87 
     88 reg        link;
     89 reg     sda_temp;
     90 
     91 
     92 
     93 //濞存籂鍛櫢SCL闁哄啫鐖奸幐
     94 reg [8:0] cnt0;
     95 always @(posedge clk or negedge rst_n)begin
     96     if(!rst_n)begin
     97         cnt0 <= 0;
     98     end
     99     else if(add_cnt0)begin
    100         if(end_cnt0)begin
    101             cnt0 <= 0;
    102         end
    103         else begin
    104             cnt0 <= cnt0 + 1;
    105         end
    106     end
    107 end
    108 
    109 assign add_cnt0 = 1;
    110 assign end_cnt0 = add_cnt0 && cnt0 == 500 - 1;  // SCL 100Khz
    111 
    112 
    113 reg    scl;
    114 always @(posedge clk or negedge rst_n)begin
    115     if(!rst_n)begin
    116         scl <= 1;
    117     end
    118     else if(add_cnt0 && cnt0 >= 250 && cnt0 < 500)begin
    119         scl <= 0;
    120     end
    121     else if(add_cnt0 && cnt0 >= 0 && cnt0 < 250)begin
    122         scl <= 1;
    123     end
    124 end
    125 
    126 reg scl_pos;
    127 reg scl_neg;
    128 reg scl_h_center;
    129 reg scl_l_center;
    130 always @(posedge clk or negedge rst_n)begin
    131     if(!rst_n)begin
    132         scl_pos <= 0;
    133     end
    134     else if(end_cnt0)begin
    135         scl_pos <= 1;
    136     end
    137     else begin
    138         scl_pos <= 0;
    139     end
    140 end
    141 
    142 always @(posedge clk or negedge rst_n)begin
    143     if(!rst_n)begin
    144         scl_h_center <= 0;
    145     end
    146     else if(add_cnt0 && cnt0 == 125-1)begin
    147         scl_h_center <= 1;
    148     end
    149     else begin
    150         scl_h_center <= 0;
    151     end
    152 end
    153 
    154 always @(posedge clk or negedge rst_n)begin
    155     if(!rst_n)begin
    156         scl_neg <= 0;
    157     end
    158     else if(add_cnt0 && cnt0 == 250-1)begin
    159         scl_neg <= 1;
    160     end
    161     else begin
    162         scl_neg <= 0;
    163     end
    164 end
    165 
    166 always @(posedge clk or negedge rst_n)begin
    167     if(!rst_n)begin
    168         scl_l_center <= 0;
    169     end
    170     else if(add_cnt0 && cnt0 == 375-1)begin
    171         scl_l_center <= 1;
    172     end
    173     else begin
    174         scl_l_center <= 0;
    175     end
    176 end
    177 
    178 reg rd_flag;
    179 reg wr_done;
    180 reg rd_done;
    181 reg [1:0] main_state;
    182 reg [5:0] inner_state;
    183 reg [7:0] rd_buf;
    184 always @(posedge clk or negedge rst_n)begin
    185     if(!rst_n)begin
    186         main_state <= IDLE;
    187         inner_state <= INIT;
    188         wr_done <= 0;
    189         rd_done <= 0;
    190         link <= 1;
    191         sda_temp <= 1;
    192         
    193         rd_req <= 0;
    194         wr_req <= 1;
    195         
    196         rd_flag <= 0;
    197         rd_buf = 8'h00;
    198     end
    199     else    
    200     case(main_state)
    201         IDLE: begin
    202             if(wr_req)begin
    203                 wr_req <= 0;
    204                 main_state <= WRITE_TASK;
    205             end
    206             else if(rd_req)begin
    207                 rd_req <= 0;
    208                 main_state <= READ_TASK;
    209             end
    210             rd_done <= 0;
    211             wr_done <= 0;
    212             link <= 1;
    213             sda_temp <= 1;
    214             rd_flag <= 0;
    215         end
    216         
    217         WRITE_TASK:
    218             case(inner_state)
    219                 INIT     :    
    220                     inner_state <= GEN_START;
    221                     
    222                 GEN_START:    
    223                     if(scl_h_center)begin
    224                         link  <= 1;
    225                         sda_temp <= 0;
    226                         inner_state <= DEV_ADDR_D7;
    227                     end
    228                     else begin
    229                         inner_state <= GEN_START;
    230                     end
    231                 
    232                 DEV_ADDR_D7:
    233                     if(scl_l_center)begin
    234                         link  <= 1;
    235                         sda_temp <= device_addr[7];
    236                         inner_state <= DEV_ADDR_D6;
    237                     end
    238                     else begin
    239                         inner_state <= DEV_ADDR_D7;
    240                     end
    241                 
    242                 DEV_ADDR_D6:
    243                     if(scl_l_center)begin
    244                         link  <= 1;
    245                         sda_temp <= device_addr[6];
    246                         inner_state <= DEV_ADDR_D5;
    247                     end
    248                     else begin
    249                         inner_state <= DEV_ADDR_D6;
    250                     end
    251                     
    252                 DEV_ADDR_D5:
    253                     if(scl_l_center)begin
    254                         link  <= 1;
    255                         sda_temp <= device_addr[5];
    256                         inner_state <= DEV_ADDR_D4;
    257                     end
    258                     else begin
    259                         inner_state <= DEV_ADDR_D5;
    260                     end
    261                 
    262                 DEV_ADDR_D4:
    263                     if(scl_l_center)begin
    264                         link  <= 1;
    265                         sda_temp <= device_addr[4];
    266                         inner_state <= DEV_ADDR_D3;
    267                     end
    268                     else begin
    269                         inner_state <= DEV_ADDR_D4;
    270                     end
    271                 
    272                 DEV_ADDR_D3:
    273                     if(scl_l_center)begin
    274                         link  <= 1;
    275                         sda_temp <= device_addr[3];
    276                         inner_state <= DEV_ADDR_D2;
    277                     end
    278                     else begin
    279                         inner_state <= DEV_ADDR_D3;
    280                     end
    281                 
    282                 DEV_ADDR_D2:
    283                     if(scl_l_center)begin
    284                         link  <= 1;
    285                         sda_temp <= device_addr[2];
    286                         inner_state <= DEV_ADDR_D1;
    287                     end
    288                     else begin
    289                         inner_state <= DEV_ADDR_D2;
    290                     end
    291                 
    292                 DEV_ADDR_D1:
    293                     if(scl_l_center)begin
    294                         link  <= 1;
    295                         sda_temp <= device_addr[1];
    296                         inner_state <= DEV_ADDR_D0;
    297                     end
    298                     else begin
    299                         inner_state <= DEV_ADDR_D1;
    300                     end
    301                 
    302                 DEV_ADDR_D0:
    303                     if(scl_l_center)begin
    304                         link  <= 1;
    305                         sda_temp <= device_addr[0];
    306                         inner_state <= DEV_RELEASE_SDA;
    307                     end
    308                     else begin
    309                         inner_state <= DEV_ADDR_D0;
    310                     end
    311                 
    312                 DEV_RELEASE_SDA:
    313                     if(scl_l_center)begin
    314                         link <= 0; //闂佹彃锕ラ弬涓糄A
    315                         inner_state <= DEV_READ_ACK;
    316                     end
    317                     else begin
    318                         inner_state <= DEV_RELEASE_SDA;
    319                     end
    320                     
    321                 DEV_READ_ACK: 
    322                     if(scl_h_center)begin
    323                         link <= 0; //闂佹彃锕ラ弬涓糄A
    324                         sda_temp <= sda;
    325                         inner_state <= DEV_CHECK_ACK;
    326                     end
    327                     else begin
    328                         inner_state <= DEV_READ_ACK;
    329                     end
    330                 
    331                 DEV_CHECK_ACK: 
    332                     if(scl_neg)begin
    333                         link <= 1;
    334                         inner_state <= REG_ADDR_D7;
    335                     end
    336                     else if(!sda_temp)begin 
    337                         link <= 0; //闂佹彃锕ラ弬涓糄A
    338                         inner_state <= DEV_CHECK_ACK;
    339                     end
    340                     else if(sda_temp)begin
    341                         main_state <= IDLE;      //ACK濠㈡儼绮剧憴锕傛儍閸曨喚妯堥柨娑樼焸閸f悂寮幏宀€绠婚柛蹇fDLE
    342                         inner_state <= INIT;    //ACK濠㈡儼绮剧憴锕傛儍閸曨喚妯堥柨娑樼焸閸f悂寮幏宀€绠婚柛蹇fNIT
    343                     end
    344 
    345                 //闁告瑦鍨块埀顑跨閻﹀海鈧稒锚濞呮帡宕烽弶鎸庣祷                
    346                 REG_ADDR_D7:
    347                     if(scl_l_center)begin
    348                         link  <= 1;
    349                         sda_temp <= reg_addr[7];
    350                         inner_state <= REG_ADDR_D6;
    351                     end
    352                     else begin
    353                         inner_state <= REG_ADDR_D7;
    354                     end
    355                 
    356                 REG_ADDR_D6:
    357                     if(scl_l_center)begin
    358                         link  <= 1;
    359                         sda_temp <= reg_addr[6];
    360                         inner_state <= REG_ADDR_D5;
    361                     end
    362                     else begin
    363                         inner_state <= REG_ADDR_D6;
    364                     end
    365                     
    366                 REG_ADDR_D5:
    367                     if(scl_l_center)begin
    368                         link  <= 1;
    369                         sda_temp <= reg_addr[5];
    370                         inner_state <= REG_ADDR_D4;
    371                     end
    372                     else begin
    373                         inner_state <= REG_ADDR_D5;
    374                     end
    375                 
    376                 REG_ADDR_D4:
    377                     if(scl_l_center)begin
    378                         link  <= 1;
    379                         sda_temp <= reg_addr[4];
    380                         inner_state <= REG_ADDR_D3;
    381                     end
    382                     else begin
    383                         inner_state <= REG_ADDR_D4;
    384                     end
    385                 
    386                 REG_ADDR_D3:
    387                     if(scl_l_center)begin
    388                         link  <= 1;
    389                         sda_temp <= reg_addr[3];
    390                         inner_state <= REG_ADDR_D2;
    391                     end
    392                     else begin
    393                         inner_state <= REG_ADDR_D3;
    394                     end
    395                 
    396                 REG_ADDR_D2:
    397                     if(scl_l_center)begin
    398                         link  <= 1;
    399                         sda_temp <= reg_addr[2];
    400                         inner_state <= REG_ADDR_D1;
    401                     end
    402                     else begin
    403                         inner_state <= REG_ADDR_D2;
    404                     end
    405                 
    406                 REG_ADDR_D1:
    407                     if(scl_l_center)begin
    408                         link  <= 1;
    409                         sda_temp <= reg_addr[1];
    410                         inner_state <= REG_ADDR_D0;
    411                     end
    412                     else begin
    413                         inner_state <= REG_ADDR_D1;
    414                     end
    415                 
    416                 REG_ADDR_D0:
    417                     if(scl_l_center)begin
    418                         link  <= 1;
    419                         sda_temp <= reg_addr[0];
    420                         inner_state <= REG_RELEASE_SDA;
    421                     end
    422                     else begin
    423                         inner_state <= REG_ADDR_D0;
    424                     end
    425                 
    426                 REG_RELEASE_SDA:
    427                     if(scl_l_center)begin
    428                         link <= 0; //闂佹彃锕ラ弬涓糄A
    429                         inner_state <= REG_READ_ACK;
    430                     end
    431                     else begin
    432                         inner_state <= REG_RELEASE_SDA;
    433                     end
    434                     
    435                 REG_READ_ACK: 
    436                     if(scl_h_center)begin
    437                         link <= 0; //闂佹彃锕ラ弬涓糄A
    438                         sda_temp <= sda;
    439                         inner_state <= REG_CHECK_ACK;
    440                     end
    441                     else begin
    442                         inner_state <= REG_READ_ACK;
    443                     end
    444                 
    445                 REG_CHECK_ACK: 
    446                     if(scl_neg)begin
    447                             link <= 1;
    448                             inner_state <= SEND_D7;
    449                     end
    450                     else if(!sda_temp)begin 
    451                             inner_state <= REG_CHECK_ACK;
    452                     end
    453                     else if(sda_temp)begin
    454                         main_state <= IDLE;
    455                         inner_state <= INIT;
    456                     end
    457                 
    458                 //閺夆晜绋戦崣鍡涘矗閹达腹鍋撴担瑙勬闁            
    459                 SEND_D7:
    460                     if(scl_l_center)begin
    461                         link  <= 1;
    462                         sda_temp <= data[7];
    463                         inner_state <= SEND_D6;
    464                     end
    465                     else begin
    466                         inner_state <= SEND_D7;
    467                     end
    468                 
    469                 SEND_D6:
    470                     if(scl_l_center)begin
    471                         link  <= 1;
    472                         sda_temp <= data[6];
    473                         inner_state <= SEND_D5;
    474                     end
    475                     else begin
    476                         inner_state <= SEND_D6;
    477                     end
    478                     
    479                 SEND_D5:
    480                     if(scl_l_center)begin
    481                         link  <= 1;
    482                         sda_temp <= data[5];
    483                         inner_state <= SEND_D4;
    484                     end
    485                     else begin
    486                         inner_state <= SEND_D5;
    487                     end
    488                 
    489                 SEND_D4:
    490                     if(scl_l_center)begin
    491                         link  <= 1;
    492                         sda_temp <= data[4];
    493                         inner_state <= SEND_D3;
    494                     end
    495                     else begin
    496                         inner_state <= SEND_D4;
    497                     end
    498                 
    499                 SEND_D3:
    500                     if(scl_l_center)begin
    501                         link  <= 1;
    502                         sda_temp <= data[3];
    503                         inner_state <= SEND_D2;
    504                     end
    505                     else begin
    506                         inner_state <= SEND_D3;
    507                     end
    508                 
    509                 SEND_D2:
    510                     if(scl_l_center)begin
    511                         link  <= 1;
    512                         sda_temp <= data[2];
    513                         inner_state <= SEND_D1;
    514                     end
    515                     else begin
    516                         inner_state <= SEND_D2;
    517                     end
    518                 
    519                 SEND_D1:
    520                     if(scl_l_center)begin
    521                         link  <= 1;
    522                         sda_temp <= data[1];
    523                         inner_state <= SEND_D0;
    524                     end
    525                     else begin
    526                         inner_state <= SEND_D1;
    527                     end
    528                 
    529                 SEND_D0:
    530                     if(scl_l_center)begin
    531                         link  <= 1;
    532                         sda_temp <= data[0];
    533                         inner_state <= DAT_RELEASE_SDA;
    534                     end
    535                     else begin
    536                         inner_state <= SEND_D0;
    537                     end
    538                 
    539                 DAT_RELEASE_SDA:
    540                     if(scl_l_center)begin
    541                         link <= 0; //闂佹彃锕ラ弬涓糄A
    542                         inner_state <= DAT_READ_ACK;
    543                     end
    544                     else begin
    545                         inner_state <= DAT_RELEASE_SDA;
    546                     end
    547                     
    548                 DAT_READ_ACK: 
    549                     if(scl_h_center)begin
    550                         link <= 0; //闂佹彃锕ラ弬涓糄A
    551                         sda_temp <= sda;
    552                         inner_state <= DAT_CHECK_ACK;
    553                     end
    554                     else begin
    555                         inner_state <= DAT_READ_ACK;
    556                     end
    557                 
    558                 DAT_CHECK_ACK:
    559                     if(scl_neg)begin
    560                             link <= 1;
    561                             inner_state <= STOP;
    562                     end
    563                     else if(!sda_temp)begin 
    564                             link <= 0; //闂佹彃锕ラ弬涓糄A
    565                             inner_state <= DAT_CHECK_ACK;
    566                     end
    567                     else if(sda_temp)begin
    568                         main_state <= IDLE;
    569                         inner_state <= INIT;
    570                     end
    571                 
    572                 STOP:
    573                     if(scl_l_center)begin
    574                         link <= 1;
    575                         sda_temp <= 0;
    576                         inner_state <= STOP;
    577                     end
    578                     else if(scl_h_center)begin
    579                         link <= 1;
    580                         sda_temp <= 1;
    581                         inner_state <= WR_FINISH;
    582                     end
    583                     else begin
    584                         inner_state <= STOP;
    585                     end
    586                 
    587                 WR_FINISH:
    588                     begin
    589                         link <= 1;
    590 //                        inner_state <= WR_FINISH;
    591                         main_state <= IDLE;
    592                         wr_done <= 1;
    593                         rd_req <= 1;
    594                         wr_req <= 0;
    595                     end    
    596                     
    597                 default: inner_state <= INIT;
    598             endcase
    599                         
    600         READ_TASK:    
    601         case(inner_state)
    602                 INIT     :    
    603                     inner_state <= GEN_START;
    604                     
    605                 GEN_START:    
    606                     if(scl_h_center)begin
    607                         link  <= 1;
    608                         sda_temp <= 0;
    609                         inner_state <= DEV_ADDR_D7;
    610                     end
    611                     else begin
    612                         inner_state <= GEN_START;
    613                     end
    614                 
    615                 DEV_ADDR_D7:
    616                     if(scl_l_center)begin
    617                         link  <= 1;
    618                         sda_temp <= device_addr[7];
    619                         inner_state <= DEV_ADDR_D6;
    620                     end
    621                     else begin
    622                         inner_state <= DEV_ADDR_D7;
    623                     end
    624                 
    625                 DEV_ADDR_D6:
    626                     if(scl_l_center)begin
    627                         link  <= 1;
    628                         sda_temp <= device_addr[6];
    629                         inner_state <= DEV_ADDR_D5;
    630                     end
    631                     else begin
    632                         inner_state <= DEV_ADDR_D6;
    633                     end
    634                     
    635                 DEV_ADDR_D5:
    636                     if(scl_l_center)begin
    637                         link  <= 1;
    638                         sda_temp <= device_addr[5];
    639                         inner_state <= DEV_ADDR_D4;
    640                     end
    641                     else begin
    642                         inner_state <= DEV_ADDR_D5;
    643                     end
    644                 
    645                 DEV_ADDR_D4:
    646                     if(scl_l_center)begin
    647                         link  <= 1;
    648                         sda_temp <= device_addr[4];
    649                         inner_state <= DEV_ADDR_D3;
    650                     end
    651                     else begin
    652                         inner_state <= DEV_ADDR_D4;
    653                     end
    654                 
    655                 DEV_ADDR_D3:
    656                     if(scl_l_center)begin
    657                         link  <= 1;
    658                         sda_temp <= device_addr[3];
    659                         inner_state <= DEV_ADDR_D2;
    660                     end
    661                     else begin
    662                         inner_state <= DEV_ADDR_D3;
    663                     end
    664                 
    665                 DEV_ADDR_D2:
    666                     if(scl_l_center)begin
    667                         link  <= 1;
    668                         sda_temp <= device_addr[2];
    669                         inner_state <= DEV_ADDR_D1;
    670                     end
    671                     else begin
    672                         inner_state <= DEV_ADDR_D2;
    673                     end
    674                 
    675                 DEV_ADDR_D1:
    676                     if(scl_l_center)begin
    677                         link  <= 1;
    678                         sda_temp <= device_addr[1];
    679                         inner_state <= DEV_ADDR_D0;
    680                     end
    681                     else begin
    682                         inner_state <= DEV_ADDR_D1;
    683                     end
    684                 
    685                 DEV_ADDR_D0:
    686                     if(scl_l_center)begin
    687                         link  <= 1;
    688                         if(!rd_flag)begin
    689                             sda_temp <= device_addr[0];  //
    690                         end
    691                         else if(rd_flag)begin
    692                             sda_temp <= device_addr[0] | 1'b1; //鐠                    
    693                         end
    694                         inner_state <= DEV_RELEASE_SDA;
    695                     end
    696                     else begin
    697                         inner_state <= DEV_ADDR_D0;
    698                     end
    699                 
    700                 DEV_RELEASE_SDA:
    701                     if(scl_l_center)begin
    702                         link <= 0; 
    703                         inner_state <= DEV_READ_ACK;
    704                     end
    705                     else begin
    706                         inner_state <= DEV_RELEASE_SDA;
    707                     end
    708                     
    709                 DEV_READ_ACK: 
    710                     if(scl_h_center)begin
    711                         link <= 0;
    712                         sda_temp <= sda;
    713                         inner_state <= DEV_CHECK_ACK;
    714                     end
    715                     else begin
    716                         inner_state <= DEV_READ_ACK;
    717                     end
    718                 
    719                 DEV_CHECK_ACK: 
    720                     if(scl_neg)begin
    721                         if(!rd_flag)begin
    722                             link <= 1;
    723                             inner_state <= REG_ADDR_D7;
    724                         end
    725                         else if(rd_flag)begin
    726                             link <= 0; 
    727                             inner_state <= RD_DATA_7;
    728                         end
    729                     end
    730                     else if(!sda_temp)begin 
    731                         link <= 0; //闂佹彃锕ラ弬涓糄A
    732                         inner_state <= DEV_CHECK_ACK;
    733                     end
    734                     else if(sda_temp)begin
    735                         main_state <= IDLE;      //ACK濠㈡儼绮剧憴锕傛儍閸曨喚妯堥柨娑樼焸閸f悂寮幏宀€绠婚柛蹇fDLE
    736                         inner_state <= INIT;    //ACK濠㈡儼绮剧憴锕傛儍閸曨喚妯堥柨娑樼焸閸f悂寮幏宀€绠婚柛蹇fNIT
    737                     end
    738 
    739                 //闁告瑦鍨块埀顑跨閻﹀海鈧稒锚濞呮帡宕烽弶鎸庣祷                
    740                 REG_ADDR_D7:
    741                     if(scl_l_center)begin
    742                         link  <= 1;
    743                         sda_temp <= reg_addr[7];
    744                         inner_state <= REG_ADDR_D6;
    745                     end
    746                     else begin
    747                         inner_state <= REG_ADDR_D7;
    748                     end
    749                 
    750                 REG_ADDR_D6:
    751                     if(scl_l_center)begin
    752                         link  <= 1;
    753                         sda_temp <= reg_addr[6];
    754                         inner_state <= REG_ADDR_D5;
    755                     end
    756                     else begin
    757                         inner_state <= REG_ADDR_D6;
    758                     end
    759                     
    760                 REG_ADDR_D5:
    761                     if(scl_l_center)begin
    762                         link  <= 1;
    763                         sda_temp <= reg_addr[5];
    764                         inner_state <= REG_ADDR_D4;
    765                     end
    766                     else begin
    767                         inner_state <= REG_ADDR_D5;
    768                     end
    769                 
    770                 REG_ADDR_D4:
    771                     if(scl_l_center)begin
    772                         link  <= 1;
    773                         sda_temp <= reg_addr[4];
    774                         inner_state <= REG_ADDR_D3;
    775                     end
    776                     else begin
    777                         inner_state <= REG_ADDR_D4;
    778                     end
    779                 
    780                 REG_ADDR_D3:
    781                     if(scl_l_center)begin
    782                         link  <= 1;
    783                         sda_temp <= reg_addr[3];
    784                         inner_state <= REG_ADDR_D2;
    785                     end
    786                     else begin
    787                         inner_state <= REG_ADDR_D3;
    788                     end
    789                 
    790                 REG_ADDR_D2:
    791                     if(scl_l_center)begin
    792                         link  <= 1;
    793                         sda_temp <= reg_addr[2];
    794                         inner_state <= REG_ADDR_D1;
    795                     end
    796                     else begin
    797                         inner_state <= REG_ADDR_D2;
    798                     end
    799                 
    800                 REG_ADDR_D1:
    801                     if(scl_l_center)begin
    802                         link  <= 1;
    803                         sda_temp <= reg_addr[1];
    804                         inner_state <= REG_ADDR_D0;
    805                     end
    806                     else begin
    807                         inner_state <= REG_ADDR_D1;
    808                     end
    809                 
    810                 REG_ADDR_D0:
    811                     if(scl_l_center)begin
    812                         link  <= 1;
    813                         sda_temp <= reg_addr[0];
    814                         inner_state <= REG_RELEASE_SDA;
    815                     end
    816                     else begin
    817                         inner_state <= REG_ADDR_D0;
    818                     end
    819                 
    820                 REG_RELEASE_SDA:
    821                     if(scl_l_center)begin
    822                         link <= 0; //闂佹彃锕ラ弬涓糄A
    823                         inner_state <= REG_READ_ACK;
    824                     end
    825                     else begin
    826                         inner_state <= REG_RELEASE_SDA;
    827                     end
    828                     
    829                 REG_READ_ACK: 
    830                     if(scl_h_center)begin
    831                         link <= 0; //闂佹彃锕ラ弬涓糄A
    832                         sda_temp <= sda;
    833                         inner_state <= REG_CHECK_ACK;
    834                     end
    835                     else begin
    836                         inner_state <= REG_READ_ACK;
    837                     end
    838                 
    839                 REG_CHECK_ACK: 
    840                     if(scl_l_center)begin
    841                         rd_flag <= 1;
    842                         link <= 1;
    843                         sda_temp <= 1;
    844                         inner_state <= GEN_START;
    845                     end
    846                     else if(scl_neg)begin
    847                         rd_flag <= 1;
    848                         link <= 1;
    849                         inner_state <= REG_CHECK_ACK;
    850                     end
    851                     else if(!sda_temp)begin 
    852                             inner_state <= REG_CHECK_ACK;
    853                     end
    854                     else if(sda_temp)begin
    855                         main_state <= IDLE;
    856                         inner_state <= INIT;
    857                     end
    858         
    859                 
    860                 //閺夆晜绋戦崣鍡欐嫚缂佹ɑ娈堕柟                
    861                 RD_DATA_7:
    862                     if(scl_h_center)begin
    863                         link  <= 0;
    864                         rd_buf[7] <= sda;
    865                         inner_state <= RD_DATA_6;
    866                     end
    867                     else begin
    868                         inner_state <= RD_DATA_7;
    869                     end
    870                 
    871                 RD_DATA_6:
    872                     if(scl_h_center)begin
    873                         link  <= 0;
    874                         rd_buf[6] <= sda;
    875                         inner_state <= RD_DATA_5;
    876                     end
    877                     else begin
    878                         inner_state <= RD_DATA_6;
    879                     end
    880                     
    881                 RD_DATA_5:
    882                     if(scl_h_center)begin
    883                         link  <= 0;
    884                         rd_buf[5] <= sda;
    885                         inner_state <= RD_DATA_4;
    886                     end
    887                     else begin
    888                         inner_state <= RD_DATA_5;
    889                     end
    890                 
    891                 RD_DATA_4:
    892                     if(scl_h_center)begin
    893                         link  <= 0;
    894                         rd_buf[4] <= sda;
    895                         inner_state <= RD_DATA_3;
    896                     end
    897                     else begin
    898                         inner_state <= RD_DATA_4;
    899                     end
    900                 
    901                 RD_DATA_3:
    902                     if(scl_h_center)begin
    903                         link  <= 0;
    904                         rd_buf[3] <= sda;
    905                         inner_state <= RD_DATA_2;
    906                     end
    907                     else begin
    908                         inner_state <= RD_DATA_3;
    909                     end
    910                 
    911                 RD_DATA_2:
    912                     if(scl_h_center)begin
    913                         link  <= 0;
    914                         rd_buf[2] <= sda;
    915                         inner_state <= RD_DATA_1;
    916                     end
    917                     else begin
    918                         inner_state <= RD_DATA_2;
    919                     end
    920                 
    921                 RD_DATA_1:
    922                     if(scl_h_center)begin
    923                         link  <= 0;
    924                         rd_buf[1] <= sda;
    925                         inner_state <= RD_DATA_0;
    926                     end
    927                     else begin
    928                         inner_state <= RD_DATA_1;
    929                     end
    930                 
    931                 RD_DATA_0:
    932                     if(scl_h_center)begin
    933                         link  <= 0;
    934                         rd_buf[0] <= sda;
    935                         inner_state <= NO_ACK;
    936                     end
    937                     else begin
    938                         inner_state <= RD_DATA_0;
    939                     end
    940                 
    941                 NO_ACK:
    942                     if(scl_l_center)begin
    943                         link <= 1;
    944                         sda_temp <= 0;
    945                         inner_state <= STOP;
    946                     end
    947                     else if(scl_neg)begin
    948                         link <= 1;
    949                         inner_state <= NO_ACK;
    950                     end
    951         
    952                 STOP:
    953                     if(scl_h_center)begin
    954                         link <= 1;
    955                         sda_temp <= 1;
    956                         inner_state <= RD_FINISH;
    957                     end
    958                     else begin
    959                         inner_state <= STOP;
    960                     end
    961                 
    962                 RD_FINISH:
    963                     begin
    964                         link <= 1;
    965                         inner_state <= RD_FINISH;
    966                         rd_done <= 1;
    967                         rd_flag <= 0;
    968                         sda_temp <= 1;
    969                     end    
    970                 default: inner_state <= INIT;
    971             endcase
    972         default : main_state <= IDLE;
    973     
    974     endcase
    975 end
    976 
    977 reg led_temp;
    978 always @(posedge clk or negedge rst_n)begin
    979     if(!rst_n)begin
    980         led_temp <= 0;
    981     end
    982     else if(rd_buf == data)begin
    983         led_temp <= 1;
    984     end
    985     else begin
    986         led_temp <= 0;
    987     end
    988 end
    989 assign sda = link ? sda_temp : 1'bz;
    990 
    991 assign led = led_temp;
    992 
    993 endmodule
    View Code

    第二个版本,只写了随机写,但感觉状态机是多余的,完全是按照计数器实现的,没体现状态机的优势

      1 module eeprom_wr(
      2                     clk,
      3                     rst_n,
      4                     wr_en,
      5                     slave_address,
      6                     reg_address,
      7                     reg_data,
      8                     scl,
      9                     sda
     10 );
     11 
     12 parameter       IDLE          = 0;
     13 parameter       START         = 1;
     14 parameter       SLAVE_ADD     = 2;
     15 parameter       ACK            = 3;
     16 parameter       REG_ADD       = 4;
     17 parameter       REG_DAT       = 5;
     18 parameter       STOP        = 6;
     19 
     20 parameter       SCL_100K      = 500;
     21 parameter        D_W            = 8;
     22 
     23 input            clk                ;
     24 input            rst_n            ;
     25 input            wr_en            ;
     26 input[D_W-1:0]    slave_address    ;
     27 input[D_W-1:0]    reg_address        ;
     28 input[D_W-1:0]    reg_data        ;
     29 
     30 output            scl;
     31 inout            sda;
     32         
     33 reg                scl        ;
     34 reg                sda_temp;
     35 reg             wr_vld    ;
     36 wire            link    ;
     37 
     38 reg[3-1:0]        state_c;
     39 reg[3-1:0]        state_n;        
     40 
     41 reg[9-1:0]         cnt0;
     42 reg[5-1:0]         cnt1;
     43 
     44 wire             scl_l_middle;
     45 wire            scl_h_middle;
     46 wire            add_cnt0    ;
     47 wire             end_cnt0    ;
     48 wire            add_cnt1    ;
     49 wire            end_cnt1    ;
     50 
     51 wire             idle2start         ;
     52 wire             start2slave_add ;
     53 wire             slave_add2ack     ;
     54 wire             ack2reg_add        ;
     55 wire             ack2reg_dat     ;
     56 wire             ack2stop         ;
     57 wire             reg_add2ack     ;
     58 wire             reg_dat2ack     ;
     59 wire             stop2idle       ;
     60 
     61 //产生 “写" 有效保持信号
     62 always @(posedge clk or negedge rst_n)begin
     63     if(!rst_n)begin
     64         wr_vld <= 0; 
     65     end
     66     else if(wr_en)begin
     67         wr_vld <= 1; 
     68     end
     69     else if(end_cnt1)begin
     70         wr_vld <= 0; 
     71     end
     72 end
     73 
     74 //计数cnt0,用于产生scl
     75 always @(posedge clk or negedge rst_n)begin
     76     if(!rst_n)begin
     77         cnt0 <= 0;
     78     end
     79     else if(add_cnt0)begin
     80         if(end_cnt0)begin
     81             cnt0 <= 0;
     82         end
     83         else begin
     84             cnt0 <= cnt0 + 1;
     85         end
     86     end
     87 end
     88 
     89 assign add_cnt0 = wr_vld;
     90 assign end_cnt0 = add_cnt0 && cnt0 == SCL_100K -1; // SCL_100K = 500;
     91 
     92 //计数器cnt1,写数据时,需要产生scl的数量
     93 always @(posedge clk or negedge rst_n)begin
     94     if(!rst_n)begin
     95         cnt1 <= 0;
     96     end
     97     else if(add_cnt1)begin
     98         if(end_cnt1)begin
     99             cnt1 <= 0;
    100         end
    101         else begin
    102             cnt1 <= cnt1 + 1;
    103         end
    104     end
    105 end
    106 
    107 assign add_cnt1 = end_cnt0;
    108 assign end_cnt1 = add_cnt1 && cnt1 == 29 -1;
    109 
    110 //产生scl
    111 always @(posedge clk or negedge rst_n)begin
    112     if(!rst_n)begin
    113         scl <= 1;
    114     end
    115     else if(add_cnt0 && cnt0 == 250 - 1 && cnt1 != 1-1)begin // 在第一个时钟时, scl不拉低
    116         scl <= 1;
    117     end
    118     else if(end_cnt0)begin
    119         scl <= 0;
    120     end
    121 end
    122 
    123 //第一段,状态跳转
    124 always @(posedge clk or negedge rst_n)begin
    125     if(!rst_n)begin
    126         state_c <= IDLE;
    127     end
    128     else begin
    129         state_c <= state_n;
    130     end
    131 end
    132 
    133 
    134 //写数据:idle -> start -> send slave_address -> wait ack -> send reg address -> wait ack -> 写数据 -> wait ack -> stop
    135 //第二段,罗列出所有条件跳转
    136 always @(*)begin
    137     case(state_c)
    138         IDLE:begin
    139             if(idle2start)begin
    140                 state_n = START;
    141             end
    142             else begin
    143                 state_n = state_c;
    144             end
    145         end
    146         
    147         START:begin
    148             if(start2slave_add)begin
    149                 state_n = SLAVE_ADD;
    150             end
    151             else begin
    152                 state_n = state_c;
    153             end
    154         end
    155         
    156         SLAVE_ADD:begin
    157             if(slave_add2ack)begin
    158                 state_n = ACK;
    159             end
    160             else begin
    161                 state_n = state_c;
    162             end
    163         end
    164         
    165         ACK:begin
    166             if(ack2reg_add)begin
    167                 state_n = REG_ADD;
    168             end
    169             else if(ack2reg_dat)begin
    170                 state_n = REG_DAT;
    171             end
    172             else if(ack2stop)begin
    173                 state_n = STOP;
    174             end
    175             else begin
    176                 state_n = state_c;
    177             end
    178         end
    179         
    180         REG_ADD:begin
    181             if(reg_add2ack)begin
    182                 state_n = ACK;
    183             end
    184             else begin
    185                 state_n = state_c;
    186             end
    187         end
    188         
    189         REG_DAT:begin
    190             if(reg_dat2ack)begin
    191                 state_n = ACK;
    192             end
    193             else begin
    194                 state_n = state_c;
    195             end
    196         end
    197         
    198         STOP:begin
    199             if(stop2idle)begin
    200                 state_n = IDLE;
    201             end
    202             else begin
    203                 state_n = state_c;
    204             end
    205         end
    206         
    207         default:begin
    208             state_n = IDLE;
    209         end
    210         
    211     endcase 
    212 end
    213 
    214 assign scl_h_middle =  add_cnt0 && cnt0 == 375-1;
    215 assign scl_l_middle =  add_cnt0 && cnt0 == 125-1;
    216 //assign scl_h_2_l    =  end_cnt0;
    217 assign scl_l_2_h    =  add_cnt0 && cnt0 == 250-1;
    218 
    219 //第三段,设计跳转条件
    220 assign idle2start         = state_c == IDLE         && wr_vld && scl_l_middle && (cnt1 == 1  - 1);
    221 assign start2slave_add  = state_c == START        && end_cnt0;
    222 assign slave_add2ack     = state_c == SLAVE_ADD && scl_l_middle && (cnt1 == 10 - 1);
    223 assign ack2reg_add        = state_c == ACK       && end_cnt0        && (cnt1 == 10 - 1);
    224 assign ack2reg_dat         = state_c == ACK       && end_cnt0       && (cnt1 == 19 - 1);
    225 assign ack2stop         = state_c == ACK       && end_cnt0       && (cnt1 == 28 - 1);
    226 assign reg_add2ack         = state_c == REG_ADD   && scl_l_middle && (cnt1 == 19 - 1);
    227 assign reg_dat2ack      = state_c == REG_DAT   && scl_l_middle && (cnt1 == 28 - 1);
    228 assign stop2idle        = state_c == STOP       && end_cnt1;
    229 
    230 //sda 
    231 always @(posedge clk or negedge rst_n)begin
    232     if(!rst_n)begin
    233         sda_temp <= 1;
    234     end
    235     else if(state_c == IDLE)begin
    236         sda_temp <= 1;
    237     end
    238     else if(state_c == START && scl_l_2_h)begin
    239         sda_temp <= 0;
    240     end
    241     else if(scl_l_middle && cnt1 >= 2-1 && cnt1 < 9)begin     //&& state_c == SLAVE_ADD
    242         sda_temp <= slave_address[8-cnt1];
    243     end
    244     else if(scl_l_middle && cnt1 >= 11-1 && cnt1 < 18)begin //&& state_c == REG_ADD
    245         sda_temp <= reg_address[17-cnt1];
    246     end
    247     else if(scl_l_middle && cnt1 >= 20-1 && cnt1 < 27)begin //&& state_c == REG_DAT
    248         sda_temp <= reg_data[26-cnt1]; 
    249     end
    250 //    else if(end_cnt0 && cnt1 == 28-1)begin
    251 //        sda_temp <= 1;
    252 //    end
    253     else if(state_c == STOP && scl_l_middle)begin
    254         sda_temp <= 0;
    255     end
    256     else if(state_c == STOP && scl_h_middle)begin
    257         sda_temp <= 1;
    258     end
    259 end
    260 
    261 //sda方向控制, 等待ack时 sda需要释放,还有接收数据时,也需要释放
    262 assign link = state_c == ACK ? 1'b0 : 1'b1;
    263 
    264 reg rd_ack;
    265 always @(posedge clk or negedge rst_n)begin
    266     if(!rst_n)begin
    267         rd_ack <= 1;
    268     end
    269     else if(state_c == ACK && scl_h_middle)begin // 在高电平中间读ack
    270         rd_ack <= sda;
    271     end
    272 end
    273 
    274 reg ack_err;
    275 always @(posedge clk or negedge rst_n)begin
    276     if(!rst_n)begin
    277         ack_err <= 0;
    278     end
    279     else if(!rd_ack)begin
    280         ack_err <= 1;    //说明读的ACK不是0
    281     end
    282     else begin
    283         ack_err <= 0;
    284     end
    285 end
    286 
    287 assign sda = link ? sda_temp : 1'bz;
    288 
    289 endmodule
    View Code

    以上两个版本计数器都是按照常规的思路,scl的拉高 和拉低 都比较传统,就是cnt0 = 0时 ,scl拉高,在end_cnt0时拉低,这样就导致了后面的条件转移设计及sda发送的数据比较麻烦,因为sda是在scl的低电平中间发送,而这个时候的cnt1是跨在

    两个状态机之间,比如cnt1 = 1时,状态机可能是在start状态或是slave_add状态下,就没法对齐,边界分的不清楚,导致后面的sda_temp 加的条件判断特别麻烦。

    总结:  在设计状态机时,思路要明确,尤其是跳转条件,分析的透彻之后,写起来就比较爽快,一个always里面就写一个信号,一次就考虑一个信号,考虑该信号  变高点变低点 ,逐个完善每个信号。不要一锅端

  • 相关阅读:
    一文搞懂 ThreadLocal 原理
    听说用 Lombok 可以早点下班?
    原来 CPU 为程序性能优化做了这么多
    如何优雅地中止线程?
    线程数,射多少更舒适?
    Elasticsearch 之聚合分析入门
    Go语言之旅:基本类型
    Go语言之旅:包
    网络七层协议之数据链路层
    网络七层协议之物理层
  • 原文地址:https://www.cnblogs.com/wen2376/p/16147457.html
Copyright © 2020-2023  润新知