24LC64_IIC_verilog控制读写
Posted 小白白笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了24LC64_IIC_verilog控制读写相关的知识,希望对你有一定的参考价值。
PS:EEPROM单次写时间比较长,24LC64要5ms,才能进行读操作,否则不会响应地址,示波器观察的。
1‘给出单次写仿真图1;(sda上面的蓝色是主从三态门切换时候,未知态,实测波形,也会有小尖峰出现)
2’给出单次读仿真图2;
3‘给出main代码;(用quartus的issp观察数据的)
4’给出testbench代码;(添加了24LC64的verilog模型,读数据不能显示,显示的高阻态)
图一
图2
main代码
module eeprom_iic ( input sys_clk, input sys_rst_n, output reg iic_sck, inout wire iic_sda ); reg [3:0] current_state; reg [3:0] next_state; reg [7:0] clk_1mhz_cnt; reg flag; reg [7:0] clk_1mhz_bit; reg [11:0] cnt_byte; reg sda; reg write_flag; wire read_flag; reg ack; reg [7:0] rd_data_reg; reg [7:0] rd_data; wire sda_ctrl; wire [7:0] D_ADDR_DATA; wire [7:0] B_ADDR_H_DATA; wire [7:0] B_ADDR_L_DATA; wire [7:0] WR_DATA_DATA; wire [7:0] RD_ADDR_DATA; //~~~~~~~~~~~~~~~~~~~~~~~~~~parameter~~~~~~~~~~~~~~~~~~~~~~ parameter IDLE = 4\'d00; parameter START_1 = 4\'d01; parameter SEND_D_ADDR = 4\'d02; parameter ACK_1 = 4\'d03; parameter SEND_B_ADDR_H = 4\'d04; parameter ACK_2 = 4\'d05; parameter SEND_B_ADDR_L = 4\'d06; parameter ACK_3 = 4\'d07; parameter WR_DATA = 4\'d08; parameter ACK_4 = 4\'d09; parameter START_2 = 4\'d10; parameter SEND_RD_ADDR = 4\'d11; parameter ACK_5 = 4\'d12; parameter RD_DATA = 4\'d13; parameter N_ACK = 4\'d14; parameter STOP = 4\'d15; parameter CNT_1MHZ = 8\'d49; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ assign sda_ctrl = ((current_state == ACK_1)||(current_state == ACK_2)|| (current_state == ACK_3)||(current_state == ACK_4)|| (current_state == ACK_5)||(current_state == RD_DATA) ) ? 1\'b1 :1\'b0; assign iic_sda = (sda_ctrl == 1\'b1) ? 1\'bz : sda ; assign D_ADDR_DATA = 8\'b1010_0000; assign B_ADDR_H_DATA = 8\'b0000_0100; assign B_ADDR_L_DATA = 8\'b0000_0110; // assign WR_DATA_DATA = 8\'b0101_1010; assign RD_ADDR_DATA = 8\'b1010_0001; unnamed u000 ( .source (WR_DATA_DATA), // sources.source .probe (rd_data) // probes.probe ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) clk_1mhz_cnt <= 8\'d0; else if(current_state != IDLE) begin if(clk_1mhz_cnt < CNT_1MHZ ) clk_1mhz_cnt <= clk_1mhz_cnt + 1\'b1; else clk_1mhz_cnt <= 8\'d0 ; end else clk_1mhz_cnt <= 8\'d0; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) write_flag <= 1\'b1; else if(flag == 1\'b1) write_flag <= ~ write_flag; else write_flag <= write_flag; assign read_flag = ~ write_flag; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) flag <= 1\'b0; else if((current_state == STOP)&&(cnt_byte == 8\'d1)&&(clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)) flag <= 1\'b1; else flag <= 1\'b0; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) clk_1mhz_bit <= 8\'d0; else if(current_state != IDLE) begin if(clk_1mhz_cnt == CNT_1MHZ) begin if(clk_1mhz_bit < 8\'d3) clk_1mhz_bit <= clk_1mhz_bit + 1\'b1; else clk_1mhz_bit <= 8\'d0 ; end else clk_1mhz_bit <= clk_1mhz_bit; end else clk_1mhz_bit <= 8\'d0; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) cnt_byte <= 8\'d0; else if((current_state == SEND_D_ADDR)||(current_state == SEND_B_ADDR_H)|| (current_state == SEND_B_ADDR_L)||(current_state == WR_DATA)|| (current_state == SEND_RD_ADDR)||(current_state == RD_DATA) ) begin if(cnt_byte <= 8\'d7) begin if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)) cnt_byte <= cnt_byte + 1\'b1; else cnt_byte <= cnt_byte ; end else cnt_byte <= 8\'d0; end else if(current_state == STOP) begin if(cnt_byte <= 12\'d2000) begin if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)) cnt_byte <= cnt_byte + 1\'b1; else cnt_byte <= cnt_byte ; end else cnt_byte <= 8\'d0; end else cnt_byte <= 8\'d0; //~~~~~~~~~~~~~~~~~~~~~~~~~~fsm~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) current_state <= IDLE ; else current_state <= next_state; always@(*) begin case(current_state) IDLE : if((write_flag == 1\'b1)||(read_flag == 1\'b1)) next_state = START_1; else next_state = IDLE; START_1 : if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3)) next_state = SEND_D_ADDR; else next_state = START_1; SEND_D_ADDR : if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte == 8\'d7)&&(clk_1mhz_bit == 8\'d3)) next_state = ACK_1; else next_state = SEND_D_ADDR; ACK_1 : if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3)&&(ack == 1\'b0)) next_state = SEND_B_ADDR_H; else next_state = ACK_1; SEND_B_ADDR_H: if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte == 8\'d7)&&(clk_1mhz_bit == 8\'d3)) next_state = ACK_2; else next_state = SEND_B_ADDR_H; ACK_2 : if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3)&&(ack == 1\'b0)) next_state = SEND_B_ADDR_L; else next_state = ACK_2; SEND_B_ADDR_L: if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte == 8\'d7)&&(clk_1mhz_bit == 8\'d3)) next_state = ACK_3; else next_state = SEND_B_ADDR_L; ACK_3 : if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3)&&(ack == 1\'b0)) begin if(write_flag == 1\'b1) next_state = WR_DATA; else if((read_flag == 1\'b1)) next_state = START_2; else next_state = ACK_3; end else next_state = ACK_3; WR_DATA : if((clk_1mhz_cnt == CNT_1MHZ )&&(cnt_byte == 8\'d7)&&(clk_1mhz_bit == 8\'d3)) next_state = ACK_4; else next_state = WR_DATA; ACK_4 : if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)&&(ack == 1\'b0)) next_state = STOP; else next_state = ACK_4; START_2 : if((clk_1mhz_cnt == CNT_1MHZ )&&(clk_1mhz_bit == 8\'d3)) next_state = SEND_RD_ADDR; else next_state = START_2; SEND_RD_ADDR: if((clk_1mhz_cnt == CNT_1MHZ)&&(cnt_byte == 8\'d7)&&(clk_1mhz_bit == 8\'d3)) next_state = ACK_5; else next_state = SEND_RD_ADDR; ACK_5 : if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)&&(ack == 1\'b0)) next_state = RD_DATA; else next_state = ACK_5; RD_DATA : if((clk_1mhz_cnt == CNT_1MHZ)&&(cnt_byte == 8\'d7)&&(clk_1mhz_bit == 8\'d3)) next_state = N_ACK; else next_state = RD_DATA; N_ACK : if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)) next_state = STOP; else next_state = N_ACK; STOP : if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)&&(cnt_byte == 12\'d2000)) next_state = IDLE; else next_state = STOP; default : next_state = IDLE; endcase end always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) iic_sck <= 1\'b1; else if(current_state == START_1) begin if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d2)) iic_sck <= 1\'b0; else iic_sck <= iic_sck; end else if(current_state == STOP) begin if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d0)&&(cnt_byte == 8\'d0)) iic_sck <= 1\'b1; else iic_sck <= iic_sck; end else if((current_state != IDLE)&&(current_state != START_1)&&(current_state != STOP)) begin if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d0)) iic_sck <= 1\'b1; else if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d2)) iic_sck <= 1\'b0; else iic_sck <= iic_sck; end else iic_sck <= 1\'b1; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) rd_data_reg <= 8\'d0; else if(current_state == RD_DATA) begin if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit <= 8\'d7)&&(clk_1mhz_bit == 8\'d1)) rd_data_reg <= {rd_data_reg[6:0],iic_sda}; else rd_data_reg <= rd_data_reg; end else rd_data_reg <= 8\'d0; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) rd_data <= 8\'d06; else if(current_state == RD_DATA) begin if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d3)&&(cnt_byte == 8\'d7)) rd_data <= rd_data_reg; else rd_data <= rd_data; end else rd_data <= rd_data; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) ack <= 1\'b1; else if((current_state == ACK_1)||(current_state == ACK_2 )||(current_state == ACK_3 ) ||(current_state == ACK_4 )||(current_state == ACK_5 )) begin if((clk_1mhz_cnt == CNT_1MHZ)&& (clk_1mhz_bit == 8\'d1)) ack <= iic_sda ; else ack <= ack; end else ack <= 1\'b1; always@(posedge sys_clk or negedge sys_rst_n) if(!sys_rst_n) sda <= 1\'b1; else if(current_state == START_1) begin if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d0)) sda <= 1\'b0; else sda <= sda; end else if(current_state == START_2) begin if((clk_1mhz_cnt == 1\'b0)&&(clk_1mhz_bit == 8\'d0)) sda <= 1\'b1; else if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d1)) sda <= 1\'b0; else sda <= sda; end else if(current_state == N_ACK) begin if((clk_1mhz_cnt == 1\'b0)&&(clk_1mhz_bit == 8\'d0)) sda <= 1\'b1; else sda <= sda; end else if(current_state == STOP) begin if((clk_1mhz_cnt == 1\'b0)&&(clk_1mhz_bit == 8\'d0)&&(cnt_byte == 8\'d0)) sda <= 1\'b0; else if((clk_1mhz_cnt == CNT_1MHZ)&&(clk_1mhz_bit == 8\'d2)&&(cnt_byte == 8\'d0)) sda <= 1\'b1; else sda <= sda; end else if(current_state == SEND_D_ADDR) begin if((clk_1mhz_cnt == 1\'b0)&&(clk_1mhz_bit == 8\'d0)) sda <= D_ADDR_DATA[(4\'d7 - cnt_byte)]; else sda <= sda; end else if(current_state == SEND_B_ADDR_H) begin if((clk_1mhz_cnt == 1\'b0)&&(clk_1mhz_bit == 8\'d0)) sda <= B_ADDR_H_DATA[(4\'d7 - cnt_byte)]; else sda <= sda; end else if(current_state == SEND_B_ADDR_L) begin if((clk_1mhz_cnt == 1\'b0)&&(clk_1mhz_bit == 8\'d0)) sda <= B_ADDR_L_DATA[(4\'d7 - cnt_byte)]; else sda <= sda; end else if(current_state == WR_DATA) begin if((clk_1mhz_cnt == 1\'b0)&&(clk_1mhz_bit == 8\'d0)) sda <= WR_DATA_DATA[(4\'d7 - cnt_byte)]; else sda <= sda; end else if(current_state == SEND_RD_ADDR) begin if((clk_1mhz_cnt == 1\'b0)&&(clk_1mhz_bit == 8\'d0)) sda <= RD_ADDR_DATA[(4\'d7 - cnt_byte)]; else sda <= sda; end else sda <= 1\'b1; endmodule
testbench
`timescale 1ns/1ns module eeprom_iic_tb; reg sys_clk; reg sys_rst_n; wire iic_sck; wire iic_sda; /* reg sda_link; reg sda_ack; assign iic_sda = (sda_link == 1\'b1) ? 1\'bz : sda_ack; */ initial begin sys_clk = 1\'b1; sys_rst_n = 1\'b0; # 36000; sys_rst_n = 1\'b1; /* sda_link = 1\'b1; sda_ack <= 1\'b1; # 36000; sys_rst_n = 1\'b1; #36020; sda_link = 1\'b0; //ack1 sda_ack <= 1\'b0; #4000; sda_link = 1\'b1; //ack up sda_ack <= 1\'b1; #32000; sda_link = 1\'b0; //ack2 sda_ack <= 1\'b0; #4000; sda_link = 1\'b1; //ack up sda_ack <= 1\'b1; #32000; sda_link = 1\'b0; sda_ack <= 1\'b0; //ack3 #4000; sda_link = 1\'b1; //ack up sda_ack <= 1\'b1; #32000; sda_link = 1\'b0; sda_ack <= 1\'b0; //ack4 #4000; sda_link = 1\'b1; //ack up sda_ack <= 1\'b1; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #52000; sda_link = 1\'b0; sda_ack <= 1\'b0; //ack1 #4000; sda_link = 1\'b1; //ack up sda_ack <= 1\'b1; #32000; sda_link = 1\'b0; sda_ack <= 1\'b0; //ack2 #4000; sda_link = 1\'b1; //ack up sda_ack <= 1\'b1; #32000;以上是关于24LC64_IIC_verilog控制读写的主要内容,如果未能解决你的问题,请参考以下文章
为啥我在 CREF JavaCard 模拟器的控制台中测试读写 APDU 时收到输入数据长度!= Lc 或 SW1 SW2: 6700?
Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime(代码片