基于FPGA的I2C读写EEPROM

  I2C在芯片的配置中应用还是很多的,比如摄像头、VGA转HDMI转换芯片,之前博主分享过一篇I2C协议的基础学习IIC协议学习笔记,这篇就使用Verilog来实现EEPROM的读写,进行一个简单的I2C实战应用。

EEPROM

我使用的这个芯片是AT24C32,它手册上还有一种AT24C64,其实操作都是一样的,只是内存大小不同,AT24C32是32k(4096x8)AT24C64是64k(9=8192x8),

SCL设置为频率200Khz

SCL clk posedge data输入EEPROM

SCL clk negedge data输出EEPROM

SDA 双向Pin

A2,A1,A0 Device Addr default all 0,只操作一片可悬空引脚。

WP 接地正常读写,WP接Vcc写操作被禁止

字节寻址地址,是由12(AT24C32)或13bit(AT24C64)的地址组成,需要操作16位字地址高3或4位忽略即可。

Device Address    8’hA0写器件地址,8’hA1读器件地址

写字节操作

随机读字节操作

    我这个芯片是双字节数据地址,所以在写数据地址时要写两次,先是高字节后是低字节。

 

开始结束标志

    这个I2C总线的时序是一致的。

 

EEPROM应答

    输出应答scl的第九个周期给出,低电平应答。如果主机没有收到应答,需要重新配置。

数据传输时序

    sda数据线在scl时钟的下降沿中间变化,可以避免产生误触开始结束标志。

I2C Design

 

    i2c_start为高电平有效,传输完成后会产生一个i2c_done结束标志,表示操作完成。

I2C状态转移图

I2C写操作

(1)产生start位

(2)传送器件地址ID_Address,器件地址的最后一位为数据的传输方向位,R/W,低电平0表示主机往从机写数据(W),1表示主机从从机读数据(R)。这里按照手册给出的操作图,应该是W即低电平。ACK应答,应答是从机发送给主机的应答,这里不用管。

(3)传送写入器件寄存器地址,即数据要写入的位置。同样ACK应答不用管。

(4)传送要写入的数据。ACK应答不用管。

(5)产生stop信号。

I2C读操作

(1)产生start信号

(2)传送器件地址(写ID_Address),这里按照手册给出的操作图,最低位是W即低电平。ACK。

(3)传送字地址(写REG_Address),ACK。

(4)再次产生start信号

(5)再传送一次器件地址,这里根据手册最低位是读R高电平,ACK。

(6)读取一个字节的数据,读数据最后结束前无应答ACK信号。

(7)产生stop信号。

    读写操作的写器件地址和写数据地址操作是一样的,状态转移图中读写操作中这两部分复用了,根据读写标志来判断。

    其他部分没啥好说的根据时序图写就行了,需要注意的一点是我们应该在sclk的高电平的中间采样数据,在sclk低电平的中间改变数据,当sclk为高电平的时候,sda为出现下降沿为start位, sda出现上升沿为stop位,所以在sclk为高电平的时候sda应该保持稳定不能随意乱动。这就又回到了数据传输有效的条件,只有在sclk为低电平期间,才允许数据变化,在高电平期间,不允许数据变化,否则就会出现起始位或结束位。

    EEPROM有个仿真模型,在夏雨闻老师的书里面就有,这个模型默认是200khz的sclk驱动,仿真的时候可以将时间参数改小,我这里也分享出来。

 

仿真模型代码

  1 `timescale 1ns/1ns
  2 `define timeslice 1250
  3 //`define timeslice 300
  4 
  5 module EEPROM_AT24C64(
  6     scl, 
  7     sda
  8 );
  9     input scl;               //串行时钟线
 10     inout sda;               //串行数据线
 11     
 12     reg out_flag;            //SDA数据输出的控制信号
 13     
 14     reg[7:0] memory[8191:0]; //数组模拟存储器
 15     reg[12:0]address;        //地址总线
 16     reg[7:0]memory_buf;      //数据输入输出寄存器
 17     reg[7:0]sda_buf;         //SDA数据输出寄存器
 18     reg[7:0]shift;           //SDA数据输入寄存器
 19     reg[7:0]addr_byte_h;     //EEPROM存储单元地址高字节寄存器
 20     reg[7:0]addr_byte_l;     //EEPROM存储单元地址低字节寄存器
 21     reg[7:0]ctrl_byte;       //控制字寄存器
 22     reg[1:0]State;           //状态寄存器
 23     
 24     integer i;
 25     
 26     //---------------------------
 27     parameter  
 28         r7 = 8'b1010_1111,  w7 = 8'b1010_1110,   //main7
 29         r6 = 8'b1010_1101,  w6 = 8'b1010_1100,   //main6
 30         r5 = 8'b1010_1011,  w5 = 8'b1010_1010,   //main5
 31         r4 = 8'b1010_1001,  w4 = 8'b1010_1000,   //main4
 32         r3 = 8'b1010_0111,  w3 = 8'b1010_0110,   //main3
 33         r2 = 8'b1010_0101,  w2 = 8'b1010_0100,   //main2
 34         r1 = 8'b1010_0011,  w1 = 8'b1010_0010,   //main1
 35         r0 = 8'b1010_0001,  w0 = 8'b1010_0000;   //main0    
 36     //---------------------------
 37     
 38     assign sda = (out_flag == 1) ? sda_buf[7] : 1'bz;
 39     
 40     //------------寄存器和存储器初始化---------------
 41     initial
 42     begin
 43         addr_byte_h    = 0;
 44         addr_byte_l    = 0;
 45         ctrl_byte    = 0;
 46         out_flag     = 0;
 47         sda_buf      = 0;
 48         State        = 2'b00;
 49         memory_buf   = 0;
 50         address      = 0;
 51         shift        = 0;
 52         
 53         for(i=0;i<=8191;i=i+1)
 54             memory[i] = 0;  
 55     end
 56 
 57     //启动信号
 58     always@(negedge sda)
 59     begin
 60         if(scl == 1)
 61         begin
 62             State = State + 1;
 63             if(State == 2'b11)
 64                 disable write_to_eeprom;
 65         end 
 66     end
 67     
 68     //主状态机
 69     always@(posedge sda)
 70     begin
 71         if(scl == 1)                //停止操作
 72             stop_W_R;
 73         else
 74         begin
 75             casex(State)
 76                 2'b01:begin
 77                     read_in;
 78                     if(ctrl_byte == w7 || ctrl_byte == w6 
 79                         || ctrl_byte == w5  || ctrl_byte == w4
 80                         || ctrl_byte == w3  || ctrl_byte == w2
 81                         || ctrl_byte == w1  || ctrl_byte == w0)
 82                     begin
 83                         State = 2'b10;
 84                         write_to_eeprom;    //写操作                 
 85                     end
 86                     else
 87                         State = 2'b00;  
 88                         //State = State;         
 89                 end
 90                 
 91                 2'b11:
 92                     read_from_eeprom;               
 93                 
 94                 default:
 95                     State = 2'b00;          
 96             endcase     
 97         end 
 98     end     //主状态机结束
 99     
100     //操作停止
101     task stop_W_R;
102     begin
103         State        = 2'b00;
104         addr_byte_h  = 0;
105         addr_byte_l  = 0;
106         ctrl_byte    = 0;
107         out_flag     = 0;
108         sda_buf      = 0;   
109     end
110     endtask
111     
112     //读进控制字和存储单元地址
113     task read_in;
114     begin
115         shift_in(ctrl_byte);
116         shift_in(addr_byte_h);
117         shift_in(addr_byte_l);      
118     end 
119     endtask
120     
121     //EEPROM的写操作
122     task write_to_eeprom;
123     begin
124         shift_in(memory_buf);
125         address = {addr_byte_h[4:0], addr_byte_l};
126         memory[address] = memory_buf;       
127         State = 2'b00;
128     end
129     endtask
130     
131     //EEPROM的读操作
132     task read_from_eeprom;
133     begin
134         shift_in(ctrl_byte);
135         if(ctrl_byte == r7 || ctrl_byte == w6 
136             || ctrl_byte == r5  || ctrl_byte == r4
137             || ctrl_byte == r3  || ctrl_byte == r2
138             || ctrl_byte == r1  || ctrl_byte == r0)
139         begin
140             address = {addr_byte_h[4:0], addr_byte_l};
141             sda_buf = memory[address];
142             shift_out;
143             State = 2'b00;
144         end
145     end
146     endtask
147     
148     //SDA数据线上的数据存入寄存器,数据在SCL的高电平有效
149     task shift_in;  
150         output[7:0]shift;
151         begin
152             @(posedge scl) shift[7] = sda;
153             @(posedge scl) shift[6] = sda;
154             @(posedge scl) shift[5] = sda;
155             @(posedge scl) shift[4] = sda;
156             @(posedge scl) shift[3] = sda;
157             @(posedge scl) shift[2] = sda;
158             @(posedge scl) shift[1] = sda;
159             @(posedge scl) shift[0] = sda;
160             
161             @(negedge scl)
162             begin
163                 #`timeslice;
164                 out_flag = 1;     //应答信号输出
165                 sda_buf = 0;
166             end
167             
168             @(negedge scl)
169             begin
170                 #`timeslice;
171                 out_flag = 0;               
172             end         
173         end 
174     endtask
175     
176     //EEPROM存储器中的数据通过SDA数据线输出,数据在SCL低电平时变化
177     task shift_out;
178     begin
179         out_flag = 1;
180         for(i=6; i>=0; i=i-1)
181         begin
182             @(negedge scl);
183             #`timeslice;
184             sda_buf = sda_buf << 1;         
185         end
186         @(negedge scl) #`timeslice sda_buf[7] = 1;    //非应答信号输出
187         @(negedge scl) #`timeslice out_flag = 0;
188     end
189     endtask
190 
191 endmodule 
192 //eeprom.v文件结束

       根据仿真模型仿真的话基本不会有什么问题,需要注意的是操作的完成标志。从仿真上看到输入读写都没问题,但是stop标志没产生好,仿真看到读写操作没问题,但实际还是不行的,需要严格按照EEPROM的手册操作时序进行,差一点就不行。

    I2C的代码我分享出来,我最后使用拨码开关作为读写使能,数码管显示读出来的输出,最后实现了对指定存储地址读写数据。

I2C设计代码点击阅读原文可以查看。

  1 `timescale      1ns/1ps
  2 // *********************************************************************************
  3 // Project Name :       
  4 // Author       : NingHeChuan
  5 // Email        : ninghechuan@foxmail.com
  6 // Blogs        : http://www.cnblogs.com/ninghechuan/
  7 // File Name    : I2C_Ctrl_EEPROM.v
  8 // Module Name  :
  9 // Called By    :
 10 // Abstract     :
 11 //
 12 // CopyRight(c) 2018, NingHeChuan Studio.. 
 13 // All Rights Reserved
 14 //
 15 // *********************************************************************************
 16 // Modification History:
 17 // Date         By              Version                 Change Description
 18 // -----------------------------------------------------------------------
 19 // 2018/8/15    NingHeChuan       1.0                     Original
 20 //  
 21 // *********************************************************************************
 22 
 23 module I2C_Ctrl_EEPROM(
 24     input                   clk,
 25     input                   rst_n,
 26     input           [31:0]  eeprom_config_data,
 27     input                   i2c_start,          //1 valid
 28     inout                   i2c_sdat,
 29     output                  i2c_sclk,
 30     output                  i2c_done,
 31     output      reg [7:0]   i2c_rd_data 
 32 );
 33 
 34 
 35 //-------------------------------------------------------
 36 parameter       I2C_IDLE        =   'd0;
 37 parameter       I2C_START       =   'd1;
 38 parameter       I2C_WR_IDADDR   =   'd2;
 39 parameter       I2C_WR_ACK1     =   'd3;
 40 parameter       I2C_WR_REGADDR1 =   'd4;
 41 parameter       I2C_WR_ACK2     =   'd5;
 42 parameter       I2C_WR_REGADDR2 =   'd6;
 43 parameter       I2C_WR_ACK3     =   'd7;
 44 parameter       I2C_WR_DATA     =   'd8;
 45 parameter       I2C_WR_ACK4     =   'd9;
 46 parameter       I2C_WR_STOP     =   'd10;
 47 //-------------------------------------------------------
 48 parameter       I2C_RD_START    =   'd11;
 49 parameter       I2C_RD_IDADDR   =   'd12;
 50 parameter       I2C_RD_ACK      =   'd13;
 51 parameter       I2C_RD_DATA     =   'd14;
 52 parameter       I2C_RD_NPACK    =   'd15;
 53 parameter       I2C_RD_STOP     =   'd16;
 54 //i2c_sclk freq
 55 parameter       I2C_FREQ      =   250;    //50Mhz/200Khz/2 = 125
 56 parameter       TRANSFER      =   1;
 57 parameter       CAPTURE       =   125;
 58 //parameter       I2C_FREQ        =   60;    //50Mhz/200Khz/2 = 125
 59 //parameter       TRANSFER        =   1;
 60 //parameter       CAPTURE         =   30;
 61 parameter       SEND_BIT        =   8;
 62 
 63 //-------------------------------------------------------
 64 reg     [4:0]   pre_state;
 65 reg     [4:0]   next_state;
 66 //
 67 reg             i2c_sdat_r;
 68 wire            bir_en;
 69 //
 70 wire            transfer_en;
 71 wire            capture_en;
 72 reg             i2c_sclk_r;
 73 reg     [7:0]   sclk_cnt;
 74 //
 75 reg     [3:0]   tran_cnt;
 76 //
 77 wire    [7:0]   wr_device_addr = {eeprom_config_data[31:25], 1'b0};
 78 wire    [7:0]   rd_device_addr = {eeprom_config_data[31:25], 1'b1};
 79 wire            wr_rd_flag  =   eeprom_config_data[24];
 80 wire    [7:0]   reg_addr1   = eeprom_config_data[23:16];
 81 wire    [7:0]   reg_addr2   = eeprom_config_data[15:8];
 82 wire    [7:0]   wr_data     = eeprom_config_data[7:0];
 83 //
 84 reg             wr_ack1;
 85 reg             wr_ack2;
 86 reg             wr_ack3;
 87 reg             wr_ack4;
 88 reg             rd_ack1;
 89 
 90 //-------------------------------------------------------
 91 //i2c_sclk
 92 always @(posedge clk or negedge rst_n)begin
 93     if(rst_n == 1'b0)
 94         sclk_cnt <= 'd1;
 95     else if(sclk_cnt == I2C_FREQ - 1'b1)
 96         sclk_cnt <= 'd0;
 97     else 
 98         sclk_cnt <= sclk_cnt + 1'b1;
 99 end
100 
101 always @(posedge clk or negedge rst_n)begin
102     if(rst_n == 1'b0)
103         i2c_sclk_r <= 1'b0;
104     else if(sclk_cnt >= (I2C_FREQ>>2)*1 && sclk_cnt <= (I2C_FREQ>>2)*3)
105         i2c_sclk_r <= 1'b1;
106     else 
107         i2c_sclk_r <= 1'b0;
108 end
109 //
110 assign  transfer_en = (sclk_cnt == TRANSFER - 1)? 1'b1: 1'b0;
111 assign  capture_en  = (sclk_cnt == CAPTURE - 1)? 1'b1: 1'b0;
112 
113 //-------------------------------------------------------
114 always @(posedge clk or negedge rst_n)begin
115     if(rst_n == 1'b0)
116         tran_cnt <= 'd0;
117     else if(tran_cnt == SEND_BIT && transfer_en == 1'b1)
118         tran_cnt <= 'd0;
119     else if(((next_state == I2C_WR_IDADDR || next_state == I2C_WR_REGADDR1 || 
120         next_state ==I2C_WR_REGADDR2 || next_state == I2C_WR_DATA || 
121         next_state == I2C_RD_IDADDR) && transfer_en == 1'b1) || 
122         (next_state == I2C_RD_DATA && capture_en == 1'b1))
123         tran_cnt <= tran_cnt + 1'b1;
124     else 
125         tran_cnt <= tran_cnt;
126 end
127 
128 //-------------------------------------------------------
129 //FSM step1
130 always @(posedge clk or negedge rst_n)begin
131     if(rst_n == 1'b0)
132         pre_state <= I2C_IDLE;
133     else
134         pre_state <= next_state;
135 end
136 
137 //FSM step2
138 always @(*)begin
139     next_state = I2C_IDLE;
140     case(pre_state)
141     I2C_IDLE:
142         if(i2c_start == 1'b1 && transfer_en == 1'b1)
143             next_state = I2C_START;
144         else 
145             next_state = I2C_IDLE;
146     I2C_START:
147         if(transfer_en == 1'b1)
148             next_state = I2C_WR_IDADDR;
149         else 
150             next_state = I2C_START;
151     I2C_WR_IDADDR:
152         if(transfer_en == 1'b1 && tran_cnt == SEND_BIT)
153             next_state = I2C_WR_ACK1;
154         else
155             next_state = I2C_WR_IDADDR;
156     I2C_WR_ACK1:
157         if(transfer_en == 1'b1 && wr_ack1 == 1'b0)
158             next_state = I2C_WR_REGADDR1;
159         else if(transfer_en == 1'b1)
160             next_state = I2C_IDLE;
161         else 
162             next_state = I2C_WR_ACK1;
163     I2C_WR_REGADDR1:
164         if(transfer_en == 1'b1 && tran_cnt == SEND_BIT)
165             next_state = I2C_WR_ACK2;
166         else
167             next_state = I2C_WR_REGADDR1;
168     I2C_WR_ACK2:
169         if(transfer_en == 1'b1 && wr_ack2 == 1'b0)
170             next_state = I2C_WR_REGADDR2;
171         else if(transfer_en == 1'b1)
172             next_state = I2C_IDLE;
173         else 
174             next_state = I2C_WR_ACK2;
175     I2C_WR_REGADDR2:
176         if(transfer_en == 1'b1 && tran_cnt == SEND_BIT)
177             next_state = I2C_WR_ACK3;
178         else
179             next_state = I2C_WR_REGADDR2;
180     I2C_WR_ACK3:
181         if(transfer_en == 1'b1 && wr_ack3 == 1'b0 && wr_rd_flag == 1'b0)
182             next_state = I2C_WR_DATA;
183         else if(transfer_en == 1'b1 && wr_ack3 == 1'b0 && wr_rd_flag == 1'b1)
184             next_state = I2C_RD_START;
185         else if(transfer_en == 1'b1)
186             next_state = I2C_IDLE;
187         else 
188             next_state = I2C_WR_ACK3;
189     I2C_WR_DATA:
190         if(transfer_en == 1'b1 && tran_cnt == SEND_BIT)
191             next_state = I2C_WR_ACK4;
192         else
193             next_state = I2C_WR_DATA;
194     I2C_WR_ACK4:
195         if(transfer_en == 1'b1 && wr_ack4 == 1'b0)
196             next_state = I2C_WR_STOP;
197         else if(transfer_en == 1'b1)
198             next_state = I2C_IDLE;
199         else 
200             next_state = I2C_WR_ACK4;
201     I2C_WR_STOP:
202         if(transfer_en == 1'b1)
203             next_state = I2C_IDLE;
204         else 
205             next_state = I2C_WR_STOP;
206     I2C_RD_START:
207         if(transfer_en == 1'b1)
208             next_state = I2C_RD_IDADDR;
209         else 
210             next_state = I2C_RD_START;
211     I2C_RD_IDADDR:
212         if(transfer_en == 1'b1 && tran_cnt == SEND_BIT)
213             next_state = I2C_RD_ACK;
214         else
215             next_state = I2C_RD_IDADDR;
216     I2C_RD_ACK:
217         if(transfer_en == 1'b1 && rd_ack1 == 1'b0)
218             next_state = I2C_RD_DATA;
219         else if(transfer_en == 1'b1)
220             next_state = I2C_IDLE;
221         else 
222             next_state = I2C_RD_ACK;
223     I2C_RD_DATA:
224         if(transfer_en == 1'b1 && tran_cnt == SEND_BIT)
225             next_state = I2C_RD_NPACK;
226         else
227             next_state = I2C_RD_DATA;
228     I2C_RD_NPACK:
229         if(transfer_en == 1'b1)
230             next_state = I2C_RD_STOP;
231         else 
232             next_state = I2C_RD_NPACK;
233     I2C_RD_STOP:
234         if(transfer_en == 1'b1)
235             next_state = I2C_IDLE;
236         else 
237             next_state = I2C_RD_STOP;
238     default:next_state = I2C_IDLE;
239     endcase
240 end
241 
242 //FSM step3
243 always @(posedge clk or negedge rst_n)begin
244     if(rst_n == 1'b0)
245         i2c_sdat_r <= 1'b1;
246     else begin
247         case(next_state)
248         I2C_IDLE:   if(capture_en == 1'b1)  i2c_sdat_r <= 1'b1;
249         I2C_START:  if(capture_en == 1'b1)  i2c_sdat_r <= 1'b0;
250         I2C_WR_IDADDR:  if(transfer_en == 1'b1) i2c_sdat_r <= wr_device_addr['d7 - tran_cnt];
251         I2C_WR_REGADDR1:if(transfer_en == 1'b1) i2c_sdat_r <= reg_addr1['d7 - tran_cnt];
252         I2C_WR_REGADDR2:if(transfer_en == 1'b1) i2c_sdat_r <= reg_addr2['d7 - tran_cnt];
253         I2C_WR_DATA:    if(transfer_en == 1'b1) i2c_sdat_r <= wr_data['d7 - tran_cnt];
254         I2C_WR_ACK4:    if(transfer_en == 1'b1) i2c_sdat_r <= 1'b0;
255         I2C_WR_STOP:    if(capture_en == 1'b1) i2c_sdat_r <= 1'b1;
256         I2C_RD_START:   if(capture_en == 1'b1)  i2c_sdat_r <= 1'b0;
257         I2C_RD_IDADDR:  if(transfer_en == 1'b1) i2c_sdat_r <= rd_device_addr['d7 - tran_cnt];
258         I2C_RD_NPACK:   if(transfer_en == 1'b1) i2c_sdat_r <= 1'b0;
259         I2C_RD_STOP:    if(capture_en == 1'b1) i2c_sdat_r <= 1'b1;
260         default:        i2c_sdat_r <= i2c_sdat_r; 
261         endcase
262     end
263 end
264 
265 always @(posedge clk or negedge rst_n)begin
266     if(rst_n == 1'b0)begin
267         i2c_rd_data <= 8'b0;
268         wr_ack1   <= 1'b1;
269         wr_ack2   <= 1'b1;
270         wr_ack3   <= 1'b1;
271         wr_ack4   <= 1'b1;
272         rd_ack1   <= 1'b1;
273     end
274     else if(capture_en == 1'b1)begin
275         case(next_state)
276         I2C_WR_ACK1: wr_ack1 <= i2c_sdat;
277         I2C_WR_ACK2: wr_ack2 <= i2c_sdat;
278         I2C_WR_ACK3: wr_ack3 <= i2c_sdat;
279         I2C_WR_ACK4: wr_ack4 <= i2c_sdat;
280         I2C_WR_STOP: begin
281             wr_ack1   <= 1'b1;
282             wr_ack2   <= 1'b1;
283             wr_ack3   <= 1'b1;
284             wr_ack4   <= 1'b1;
285             rd_ack1   <= 1'b1;
286         end
287         I2C_RD_ACK: rd_ack1 <= i2c_sdat;
288         I2C_RD_DATA: i2c_rd_data['d7 - tran_cnt] <= i2c_sdat;
289         I2C_RD_STOP:begin
290             wr_ack1   <= 1'b1;
291             wr_ack2   <= 1'b1;
292             wr_ack3   <= 1'b1;
293             wr_ack4   <= 1'b1;
294             rd_ack1   <= 1'b1;
295         end
296         default:begin
297             i2c_rd_data <= i2c_rd_data;
298             wr_ack1 <= wr_ack1;
299             wr_ack2 <= wr_ack2;
300             wr_ack3 <= wr_ack3;
301             wr_ack4 <= wr_ack4;
302             rd_ack1 <= rd_ack1;
303         end
304         endcase
305     end
306     else begin
307         i2c_rd_data <= i2c_rd_data;
308         wr_ack1   <= wr_ack1;
309         wr_ack2   <= wr_ack2;
310         wr_ack3   <= wr_ack3;
311         wr_ack4   <= wr_ack4;
312         rd_ack1   <= rd_ack1;
313     end
314 end
315 
316 //-------------------------------------------------------
317 assign  bir_en = (pre_state == I2C_WR_ACK1 || pre_state == I2C_WR_ACK2 || pre_state == I2C_WR_ACK3 ||
318                   pre_state == I2C_WR_ACK4 || pre_state == I2C_RD_ACK || pre_state == I2C_RD_DATA)? 1'b0: 1'b1;
319 
320 assign  i2c_sdat = (bir_en == 1'b1)? i2c_sdat_r: 1'bz;
321 
322 assign  i2c_sclk = i2c_sclk_r;
323 assign  i2c_done = (pre_state == I2C_WR_STOP && next_state == I2C_IDLE ||
324                     pre_state == I2C_RD_STOP && next_state == I2C_IDLE)? 1'b1: 1'b0;
325 
326 endmodule 

 

转载请注明出处:NingHeChuan(宁河川)

个人微信订阅号:开源FPGA

如果你想及时收到个人撰写的博文推送,可以扫描左边二维码(或者长按识别二维码)关注个人微信订阅号

知乎ID:NingHeChuan

微博ID:NingHeChuan

原文地址:https://www.cnblogs.com/ninghechuan/p/9534893.html 

 

posted @ 2018-08-27 21:08  NingHeChuan  阅读(11881)  评论(1编辑  收藏  举报