📄 i2c_slave.v
字号:
//***********************************//i2c_slave.v v1.0 2007-05-27//initial//***********************************//v1.1 2007-05-28// Add neg_counter[9:0],cycle,scl_mid_pulse. neg_counter counts numbers when SCL=0; the result stored to cycle register;// scl_mid_pulse is the pulse between one negedge SCL and one posedge SCL. that is the midddle time from last negedge SCL to//next posedge SCL.//***********************************//v2.0 2007-05-30//Can be write or read in burst mode;//2.2 2007-06-01 15:00//Can read data from "input_data.dat" file and send to I2C master//Can receive data from I2C master ,then save them to the "receive_data.dat" file//Modify define to parameter mode//*************************************module i2c_slave(clk,SCL,reset,SDAI,SDAO);input clk,SCL,reset,SDAI;output SDAO;////`include "i2c_slave_userconf.v"parameter input_data= "input_data.dat";parameter receive_data= "receive_data.dat";parameter IDLE= 3'b000; //state machine parameter START= 3'b001;parameter ADDRESS= 3'b010;parameter ACK= 3'b011;parameter DATA= 3'b100; parameter DATA_ACK= 3'b101;parameter CONT_END= 4'b1000; parameter SLAVE_ADDRESS= 7'b0000001; //define this I2C_SLAVE ip own address parameter MEMLEN= 10; //memory array length, can modify if u need//wire scl;assign scl = SCL;//wire SDAI;reg SDAO; //reg [2:0] state;//reg sda_reg; reg sda_reg_delayed;reg scl_reg=0;reg scl_reg_delayed=0;//reg [7:0] out_reg=0;reg [7:0] in_reg;//reg r_w_bit; //read or write bit//reg ack_flag=0;reg start_pulse;reg start_detect;//reg stop_pulse;reg stop_detect;//reg scl_pulse;reg scl_neg_pulse;//reg out_en=0; //output enablereg sda_out;//reg in_reg_enable;//reg [3:0] bit_counter; //bit counterreg [7:0] word_w_address; //the data input i2c_slave will be stored in word_w_address register//reg [7:0] WORD_R_ADDRESS;//reg [9:0] neg_counter;reg [9:0] cycle;reg scl_mid_pulse; //sign the middle time when SCL is low//reg [7:0] memory[0:MEMLEN - 1]; //stored reading data from files//integer N=0;integer M; //if the number of reading data is above 16, //integer rev;////initialbegin $readmemh (input_data, memory); //read data into memory rev=$fopen(receive_data); $fdisplay(rev,"Data received from I2C master as following:\n");end//output to receive_data.dat filealways @(posedge clk)if (N<MEMLEN+2)begin if (out_en & scl_pulse) begin if (N>0) begin $fdisplay(rev,"BYTE%h=%h",N,word_w_address); N<=N+1; end else N<=N+1; endendelse $fclose(rev); //sda_samplealways @(posedge clk) if(~reset) begin sda_reg <= 1; sda_reg_delayed <= 1; end else begin sda_reg <= SDAI; sda_reg_delayed <= sda_reg; end//start_pulsealways @(posedge clk) if (~reset) start_pulse <= 0; else if (~sda_reg & sda_reg_delayed & SCL) start_pulse <= 1; else start_pulse <= 0;//start_detectalways @(posedge clk) if (~reset) start_detect <= 0; else if (start_pulse) start_detect <= 1; else if (~SCL) start_detect <= 0; else start_detect <= start_detect;//stop_pulsealways @(posedge clk) if (~reset) stop_pulse <= 0; else if (sda_reg & ~sda_reg_delayed & SCL) stop_pulse <= 1; else stop_pulse <= 0;//stop_detectalways @(posedge clk) if (~reset) stop_detect <= 0; else if (stop_pulse) stop_detect<=1; else if (~SCL) stop_detect<=0; else stop_detect<=stop_detect;//scl_samplealways @(posedge clk) if (~reset) begin scl_reg<=1; scl_reg_delayed<=1; end else begin scl_reg<=scl; scl_reg_delayed<=scl_reg; end //scl_posedgealways @(posedge clk) if (~reset) scl_pulse<=0; else if (scl_reg & ~scl_reg_delayed ) scl_pulse <=1; else scl_pulse <=0; //scl_neg_posedgealways @(posedge clk) if (~reset) scl_neg_pulse<=0; else if (~scl_reg & scl_reg_delayed ) scl_neg_pulse<=1; else scl_neg_pulse<=0;//neg_counteralways @(posedge clk) if (~reset) neg_counter<=0; else if (~scl) neg_counter<=neg_counter+1; else if (scl_pulse) begin neg_counter<=0; cycle<=neg_counter; end//scl_mid_pulsealways @(posedge clk) if (~reset) scl_mid_pulse <=0; else if (~scl & (neg_counter==cycle/2) & (neg_counter>0)) scl_mid_pulse <=1; else scl_mid_pulse<=0; //moorealways @(posedge clk )if (~reset) state<=IDLE;elsebegin////statecase (state)//////IDLE IDLE: begin if (start_detect & scl) state <= START; else begin state <=IDLE; in_reg_enable <= 0; end end//////START START: begin if (start_detect & scl ) state <= START; else if (stop_detect & scl) state <= IDLE; else if (scl_mid_pulse) ////scl begin bit_counter <=0; in_reg_enable <=1; end else if (in_reg_enable) begin in_reg_enable <=0; bit_counter =bit_counter+1; ack_flag<=0; state<=ADDRESS; end end//////ADDRESS ADDRESS: begin if (start_detect & scl) state <=START; else if (stop_detect & scl) state<=IDLE; else if (scl_pulse & (bit_counter<=CONT_END)) in_reg_enable<=1; else if (in_reg_enable) begin in_reg_enable<=0; bit_counter<=bit_counter+1; state <=ADDRESS; end else if (bit_counter==CONT_END) begin if (in_reg[7:1]==SLAVE_ADDRESS ) //slave address begin r_w_bit<=in_reg[0]; M<=0; ack_flag<=0; state<=ACK; end else begin sda_out<=1; state <=IDLE; end end end//////ACK ACK: begin if (start_detect & scl) state<=START; else if (stop_detect & scl) state<=IDLE; else if (~ack_flag & scl_neg_pulse) ////////////neg begin out_en <=1; ack_flag <=1; end else if (ack_flag & scl_neg_pulse) ////////////neg begin out_en <=0; ack_flag<=0; sda_out<=1; bit_counter<=0; state<=DATA; end else begin sda_out<=0; bit_counter<=0; state<=ACK; end end//////DATA DATA: begin if (start_detect & scl) state <=START; else if (stop_detect & scl) state<=IDLE; else if (~r_w_bit & (bit_counter==4'b0000) & scl_mid_pulse ) ///////////pos begin in_reg_enable<=1; // bit_counter <=bit_counter+1; end else if (in_reg_enable & scl_pulse & (bit_counter<CONT_END)) begin // in_reg_enable <=0; bit_counter <=bit_counter+1; state <=DATA; end else if (~r_w_bit & (bit_counter==CONT_END)) begin in_reg_enable <=0; ack_flag <=0; word_w_address <= in_reg; //save data from I2C master state <= DATA_ACK; end else if (r_w_bit & (bit_counter==4'b0000) ) begin out_en<=1; bit_counter <=bit_counter+1; out_reg<=memory[M]; //send memory data to I2C master end else if (r_w_bit & (bit_counter<CONT_END) & scl_neg_pulse) ///////////neg bit_counter <=bit_counter+1; else if (r_w_bit & (bit_counter ==CONT_END) & scl_neg_pulse) //////////neg begin if (M<MEMLEN) M<=M+1; else M<=0; bit_counter<=0; ack_flag <=0; state <= DATA_ACK; end end //////DATA_ACK DATA_ACK: begin if (start_detect & scl) state <=START; else if (stop_detect & scl) state<=IDLE; else if (~r_w_bit & scl_neg_pulse & ~ack_flag) /////////neg begin out_en <=1; sda_out <=0; ack_flag <=1; end else if (r_w_bit & scl_neg_pulse & ~ack_flag) ////////////neg begin ack_flag<=0; sda_out <=1; ///add 5-29 if (~SDAI & (M<MEMLEN)) begin out_en<=1; ///0 bit_counter<=0; ack_flag <=0; state <= DATA; ///IDLE end else begin out_en <=0; state <= IDLE; ///IDLE M<=0; end end ////add 5-29 else if (~r_w_bit & scl_neg_pulse) ////////////neg begin if (~SDAI) begin out_en<=0; ///0 bit_counter<=0; ack_flag <=0; state <= DATA; ///IDLE end end enddefault: state <= state; endcaseend//moore end//cou_oalways @(posedge clk)case(bit_counter) 4'b0001: sda_out<= out_reg[7]; 4'b0010: sda_out<= out_reg[6]; 4'b0011: sda_out<= out_reg[5]; 4'b0100: sda_out<= out_reg[4]; 4'b0101: sda_out<= out_reg[3]; 4'b0110: sda_out<= out_reg[2]; 4'b0111: sda_out<= out_reg[1]; 4'b1000: sda_out<= out_reg[0]; default: sda_out<= sda_out;endcase//cou_ialways @(posedge clk)if (in_reg_enable) begin case(bit_counter) 4'b0000: in_reg[7] <= sda_reg; 4'b0001: in_reg[6] <= sda_reg; 4'b0010: in_reg[5] <= sda_reg; 4'b0011: in_reg[4] <= sda_reg; 4'b0100: in_reg[3] <= sda_reg; 4'b0101: in_reg[2] <= sda_reg; 4'b0110: in_reg[1] <= sda_reg; 4'b0111: in_reg[0] <= sda_reg; default: in_reg <= in_reg; endcase end//Palways @(posedge clk) if (ack_flag) SDAO<=0; else if (out_en) SDAO <= sda_out; else SDAO <= 1;endmodule//END......
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -