【代码更新】IIC时序——读写EEPROM
整体代码:
1 //---->50MHz --->20ns 100KHz ---->10000ns 2 `timescale 1ns / 1ps 3 module eeprom_i2c#(parameter SCL_CYC = 1000)//100KHz 4 ( 5 input clk, 6 input rst_n, 7 8 input write_en, 9 input read_en , 10 input [7:0]share_addr, 11 input [7:0] wri_data, 12 13 //仿真接口 14 output reg sda_en, 15 output reg [13:0] state_c, 16 17 //EEPROM接口 18 output reg scl, //时钟 19 inout sda 20 ); 21 // 22 reg busy ;//总线忙信号 23 reg [7:0] rd_data;//读回数据 24 reg rd_data_vld ; 25 // reg [13:0] state_c; 26 // 27 wire sda_in; 28 // reg sda_en; 29 reg sda_reg; 30 // 31 assign sda = sda_en ? sda_reg : 1'bz; 32 assign sda_in = sda; 33 // 34 reg [11:0] div_cnt; 35 reg high_middle; 36 reg [3:0] bit_cnt; 37 reg [3:0] N; 38 39 reg [13:0] state_n; 40 41 reg rd_flag; 42 reg [7:0] rd_buf; 43 44 45 wire add_bit_cnt,end_bit_cnt; 46 wire add_div_cnt,end_div_cnt; 47 wire idle2start,start2wri_ctrl,wri_ctrl2ack1,ack12addr,addr2ack2,ack22wri_data; 48 wire wri_data2ack3,ack32stop,ack22re_start,re_start2rd_ctrl,rd_ctrl2ack4; 49 wire ack42rd_data,rd_data2nack,nack2stop,stop2idle,ack2idle; 50 reg ack_valid,ack_invalid; 51 wire [2:0] cs; 52 53 wire [7:0] device_addr_rd,device_addr_wr; 54 wire [7:0] word_addr; 55 wire ack_state; 56 57 //状态编码 58 localparam IDLE = 14'b00_0000_0000_0001,//1 59 START = 14'b00_0000_0000_0010,//2 60 WRI_CTRL = 14'b00_0000_0000_0100,//4 61 ACK1 = 14'b00_0000_0000_1000,//8 62 ADDR = 14'b00_0000_0001_0000,//10 63 ACK2 = 14'b00_0000_0010_0000,//20 64 WRI_DATA = 14'b00_0000_0100_0000,//40 65 ACK3 = 14'b00_0000_1000_0000,//80 66 RE_START = 14'b00_0001_0000_0000,//100 67 RD_CTRL = 14'b00_0010_0000_0000,//200 68 ACK4 = 14'b00_0100_0000_0000,//400 69 RD_DATA = 14'b00_1000_0000_0000,//800 70 NACK = 14'b01_0000_0000_0000,//1000 71 STOP = 14'b10_0000_0000_0000;//2000 72 73 //分频计数器 在响应操作直到完成或退出到IDLE中间都计数 74 always@(posedge clk or negedge rst_n)begin 75 if(!rst_n) 76 div_cnt <= 0; 77 else if(add_div_cnt)begin 78 if(end_div_cnt) 79 div_cnt <= 0; 80 else 81 div_cnt <= div_cnt + 1'b1; 82 end 83 else 84 div_cnt <= 0; 85 end 86 87 assign add_div_cnt = busy == 1; 88 assign end_div_cnt = add_div_cnt && div_cnt == SCL_CYC - 1; 89 90 //比特计数器 91 always@(posedge clk or negedge rst_n)begin 92 if(!rst_n) 93 bit_cnt <= 0; 94 else if(add_bit_cnt)begin 95 if(end_bit_cnt) 96 bit_cnt <= 0; 97 else 98 bit_cnt <= bit_cnt + 1'b1; 99 end 100 end 101 102 assign add_bit_cnt = end_div_cnt; 103 assign end_bit_cnt = add_bit_cnt && bit_cnt == N - 1; 104 105 always@(*)begin 106 case(state_c) 107 WRI_CTRL:N = 8; 108 ADDR:N = 8; 109 WRI_DATA:N = 8; 110 RD_CTRL:N = 8; 111 RD_DATA:N = 8; 112 default:N = 1; 113 endcase 114 end 115 116 //---------------------iic时序四段式状态机部分------------------------- 117 118 //时序逻辑描述状态转移 119 always@(posedge clk or negedge rst_n)begin 120 if(!rst_n) 121 state_c <= IDLE; 122 else 123 state_c <= state_n; 124 end 125 126 //组合逻辑描述状态转移条件 127 always@(*)begin 128 case(state_c) 129 IDLE:begin //空闲状态 130 if(idle2start) 131 state_n = START; 132 else 133 state_n = state_c; 134 end 135 136 START:begin //产生开始条件 即SCL高电平期间SDA拉低 137 if(start2wri_ctrl) 138 state_n = WRI_CTRL; 139 else 140 state_n = state_c; 141 end 142 143 WRI_CTRL:begin //写器件地址和写标志位 144 if(wri_ctrl2ack1) 145 state_n = ACK1; 146 else 147 state_n = state_c; 148 end 149 150 ACK1:begin //等待响应 151 if(ack12addr) 152 state_n = ADDR; 153 else if(ack2idle) 154 state_n = IDLE; 155 else 156 state_n = state_c; 157 end 158 159 ADDR:begin //写存储单元地址 160 if(addr2ack2) 161 state_n = ACK2; 162 else 163 state_n = state_c; 164 end 165 166 ACK2:begin //等待响应2 167 if(ack22wri_data) //写操作 168 state_n = WRI_DATA; 169 else if(ack22re_start)//读操作 170 state_n = RE_START; 171 else if(ack2idle) 172 state_n = IDLE; 173 else 174 state_n = state_c; 175 end 176 177 WRI_DATA:begin //写数据 8bit 178 if(wri_data2ack3) 179 state_n = ACK3; 180 else 181 state_n = state_c; 182 end 183 184 ACK3:begin //等待响应3 185 if(ack32stop) 186 state_n = STOP; 187 else if(ack2idle) 188 state_n = IDLE; 189 else 190 state_n = state_c; 191 end 192 193 RE_START:begin //若为读操作在响应2后再次构造开始条件 194 if(re_start2rd_ctrl) 195 state_n = RD_CTRL; 196 else 197 state_n = state_c; 198 end 199 200 RD_CTRL:begin //写入存储单元地址和读标志位 201 if(rd_ctrl2ack4) 202 state_n = ACK4; 203 else 204 state_n = state_c; 205 end 206 207 ACK4:begin //等待响应4 208 if(ack42rd_data) 209 state_n = RD_DATA; 210 else if(ack2idle) 211 state_n = IDLE; 212 else 213 state_n = state_c; 214 end 215 216 RD_DATA:begin //读数据 8bit 217 if(rd_data2nack) 218 state_n = NACK; 219 else 220 state_n = state_c; 221 end 222 223 NACK:begin //不响应 无操作即可 224 if(nack2stop) 225 state_n = STOP; 226 else 227 state_n = state_c; 228 end 229 230 STOP:begin //构造停止条件 231 if(stop2idle) 232 state_n = IDLE; 233 else 234 state_n = state_c; 235 end 236 237 default: 238 state_n = IDLE; 239 endcase 240 end 241 242 //连续赋值语句定义状态转移条件 243 assign idle2start = state_c == IDLE && (write_en || read_en); 244 assign start2wri_ctrl = state_c == START && end_bit_cnt; 245 assign wri_ctrl2ack1 = state_c == WRI_CTRL && end_bit_cnt; 246 assign ack12addr = state_c == ACK1 && ack_valid && end_bit_cnt; 247 assign addr2ack2 = state_c == ADDR && end_bit_cnt; 248 assign ack22wri_data = state_c == ACK2 && ack_valid && !rd_flag && end_bit_cnt; 249 assign wri_data2ack3 = state_c == WRI_DATA && end_bit_cnt; 250 assign ack32stop = state_c == ACK3 && ack_valid && end_bit_cnt; 251 assign ack22re_start = state_c == ACK2 && ack_valid && rd_flag && end_bit_cnt; 252 assign re_start2rd_ctrl = state_c == RE_START && end_bit_cnt; 253 assign rd_ctrl2ack4 = state_c == RD_CTRL && end_bit_cnt; 254 assign ack42rd_data = state_c == ACK4 && ack_valid && end_bit_cnt; 255 assign rd_data2nack = state_c == RD_DATA && end_bit_cnt; 256 assign nack2stop = state_c == NACK && end_bit_cnt; 257 assign stop2idle = state_c == STOP && end_bit_cnt; 258 assign ack2idle = ack_state && ack_invalid; 259 260 261 262 always@(posedge clk or negedge rst_n)begin 263 if(!rst_n) 264 ack_valid <= 0; 265 else if(ack12addr || ack22wri_data || ack32stop || ack22re_start || ack42rd_data || ack2idle) 266 ack_valid <= 0; 267 else if(ack_state && high_middle && !sda_en && !sda_in) 268 ack_valid <= 1; 269 end 270 271 assign ack_state = state_c == ACK1 || state_c == ACK2 || state_c == ACK3 || state_c == ACK4; 272 273 always@(posedge clk or negedge rst_n)begin 274 if(!rst_n) 275 ack_invalid <= 0; 276 else if(state_c == NACK && high_middle && !sda_en && sda_in) 277 ack_invalid <= 1; 278 else if(end_bit_cnt) 279 ack_invalid <= 0; 280 end 281 282 //时序逻辑描述状态输出 283 284 //scl时钟信号 285 always@(posedge clk or negedge rst_n)begin 286 if(!rst_n) 287 scl <= 0; 288 else if(add_div_cnt && div_cnt == SCL_CYC/4 - 1) 289 scl <= 1; 290 else if(add_div_cnt && div_cnt == SCL_CYC/4 + SCL_CYC/2 - 1) 291 scl <= 0; 292 end 293 294 //找到scl高低电平中间点 295 always@(posedge clk or negedge rst_n)begin 296 if(!rst_n) 297 high_middle <= 0; 298 else if(add_div_cnt && div_cnt == SCL_CYC/2 - 1) 299 high_middle <= 1; 300 else 301 high_middle <= 0; 302 end 303 304 //三态门输出使能 305 always@(posedge clk or negedge rst_n)begin 306 if(!rst_n) 307 sda_en <= 1; 308 else if(idle2start || ack12addr || ack22wri_data || ack32stop || ack22re_start || nack2stop|| rd_data2nack) 309 sda_en <= 1; 310 else if(wri_ctrl2ack1 || addr2ack2 || wri_data2ack3 || rd_ctrl2ack4 || ack2idle || stop2idle) 311 sda_en <= 0; 312 end 313 314 //数据总线输出寄存器 315 always@(posedge clk or negedge rst_n)begin 316 if(!rst_n) 317 sda_reg <= 1; 318 else if(idle2start) 319 sda_reg <= 1; 320 else if((state_c == START || state_c == RE_START) && high_middle) 321 sda_reg <= 0; 322 else if(state_c == WRI_CTRL) 323 sda_reg <= device_addr_wr[7-bit_cnt]; 324 else if(state_c == ADDR) 325 sda_reg <= word_addr[7 - bit_cnt]; 326 else if(state_c == WRI_DATA) 327 sda_reg <= wri_data[7 - bit_cnt]; 328 else if(state_c == STOP && high_middle) 329 sda_reg <= 1; 330 else if(ack22re_start) 331 sda_reg <= 1; 332 else if(state_c == RE_START && high_middle) 333 sda_reg <= 0; 334 else if(state_c == RD_CTRL) 335 sda_reg <= device_addr_rd[7- bit_cnt]; 336 else if(ack_state) 337 sda_reg <= 0; 338 else if(rd_data2nack) 339 sda_reg <= 1; 340 else if(nack2stop) 341 sda_reg <= 0; 342 end 343 344 assign device_addr_wr = {4'b1010,cs,1'b0}; 345 assign cs = 3'b000; 346 assign word_addr = share_addr; 347 assign device_addr_rd = {4'b1010,cs,1'b1}; 348 349 //读取数据缓存 350 always@(posedge clk or negedge rst_n)begin 351 if(!rst_n) 352 rd_buf <= 0; 353 else if(state_c == RD_DATA && high_middle) 354 rd_buf <= {rd_buf[6:0],sda_in}; 355 end 356 357 //读数据有效指示 358 always@(posedge clk or negedge rst_n)begin 359 if(!rst_n) 360 rd_data_vld <= 0; 361 else if(rd_data2nack) 362 rd_data_vld <= 1; 363 else 364 rd_data_vld <= 0; 365 end 366 367 //读数据输出 368 always@(posedge clk or negedge rst_n)begin 369 if(!rst_n) 370 rd_data <= 0; 371 else 372 rd_data <= rd_buf; 373 end 374 375 //读标志位 376 always@(posedge clk or negedge rst_n)begin 377 if(!rst_n) 378 rd_flag <= 0; 379 else if(read_en) 380 rd_flag <= 1; 381 else if(rd_flag && (stop2idle || state_c == IDLE)) 382 rd_flag <= 0; 383 end 384 385 //总线忙信号 386 always@(posedge clk or negedge rst_n)begin 387 if(!rst_n) 388 busy <= 0; 389 else if(write_en || read_en) 390 busy <= 1; 391 else if(busy == 1 &&(stop2idle || state_c == IDLE)) 392 busy <= 0; 393 end 394 395 endmoduleeeprom_i2c
1 `timescale 1ns / 1ps 2 module tb_eeprom_i2c; 3 4 reg clk; 5 reg rst_n; 6 wire scl; 7 wire sda; 8 wire sda_en;//高电平时待测试文件为输出 9 10 reg sda_tb_out; 11 wire [13:0] state_c; 12 13 reg read,write; 14 15 16 eeprom_i2c #(.SCL_CYC(100)) 17 eeprom_i2c_inst( 18 .clk(clk), 19 .rst_n(rst_n), 20 21 //用户侧接口 22 .write_en(write), //写指令 23 .read_en(read), //读指令 24 .share_addr(8'h15),//读写复用地址 25 .wri_data(8'h32), //待写入数据 26 27 //仿真接口 28 .sda_en(sda_en), 29 .state_c(state_c), 30 //eeprom侧接口 31 .scl(scl), 32 .sda(sda) 33 ); 34 35 36 37 assign sda = (!sda_en) ? sda_tb_out : 1'bz; 38 39 parameter CYC = 5, 40 RST_TIME = 2; 41 42 localparam IDLE = 14'b00_0000_0000_0001, 43 START = 14'b00_0000_0000_0010, 44 WRI_CTRL = 14'b00_0000_0000_0100, 45 ACK1 = 14'b00_0000_0000_1000, 46 ADDR = 14'b00_0000_0001_0000, 47 ACK2 = 14'b00_0000_0010_0000, 48 WRI_DATA = 14'b00_0000_0100_0000, 49 ACK3 = 14'b00_0000_1000_0000, 50 RE_START = 14'b00_0001_0000_0000, 51 RD_CTRL = 14'b00_0010_0000_0000, 52 ACK4 = 14'b00_0100_0000_0000, 53 RD_DATA = 14'b00_1000_0000_0000, 54 NACK = 14'b01_0000_0000_0000, 55 STOP = 14'b10_0000_0000_0000; 56 57 initial begin 58 clk = 0; 59 forever #(CYC/2) clk = ~clk; 60 end 61 62 initial begin 63 rst_n = 1; 64 #1; 65 rst_n = 0; 66 #(CYC*RST_TIME); 67 rst_n = 1; 68 end 69 70 initial begin 71 write = 1'b0; 72 #1; 73 write = 1'b1; 74 read = 1'b0; 75 76 // #(CYC*RST_TIME); 77 // #(CYC*10); 78 #11664; 79 write = 1'b0; 80 read = 1'b1; 81 #10000; 82 write = 1'b0; 83 read = 1'b0; 84 $stop; 85 end 86 87 //构造响应条件 88 always@(*)begin 89 if(state_c == ACK1 || state_c == ACK2 || state_c == ACK3 || state_c == ACK4) 90 sda_tb_out <= 0; 91 else 92 sda_tb_out <= 1; 93 end 94 95 endmoduletb_eeprom_i2c
参考文献链接:
1.https://www.cnblogs.com/moluoqishi/p/7434902.html
2.https://www.cnblogs.com/liujinggang/p/9656358.html
标签:wire,0000,14,读写,b00,sda,IIC,reg,EEPROM From: https://www.cnblogs.com/taylorrrrrrrrrrr/p/18051633