⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iic_master.v

📁 IIC总线的Master代码
💻 V
字号:
/*I2C_Master.v - Verilog source for I2C moduleFeatures:- I2C Baud of 100Kbps or 400kbps- ACK or NACK during READ is controlled via LSB of in_data- SCL handshake (slave pulls SCL low to suspend master)Limitations:- Only supports master mode- no IRQ support but has a busy bit that can be polled to assure module is not busyThis program is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program.  If not, see <http://www.gnu.org/licenses/>.*/`define BAUD400K  25`define BAUD100K  100`define IDLE      0`define START     1`define STOP      2`define READ      3`define WRITE     4module i2c_master(addr, in_data, out_data, sda, scl, cs, rd, wr, clk, iic_busy);output iic_busy;input wire [2:0] addr;input wire [7:0] in_data;output reg [7:0] out_data;inout            sda;inout            scl;input wire       cs;input wire       rd;input wire       wr;input wire       clk;reg out_sda           = 1'b0;reg out_scl           = 1'b0;reg [7:0] in_buffer   = 8'b0;reg [7:0] buffer      = 8'b0;reg ack               = 1'b0;reg speed             = 1'b0;reg i2c_clk           = 1'b0;reg [6:0] clk_count   = 7'b0;reg [2:0] state	    = 3'b0;reg [2:0] nextstate   = 3'b0;reg [5:0] state_count = 6'b0;reg [2:0] bit_count   = 3'b0;

reg [2:0] state_control = 3'b0;////
reg wr_rd_bit = 0;////wire busy;wire held;// I2C Clockalways@(posedge clk)begin	clk_count = clk_count + 1;		if(1)	begin		if(clk_count >= `BAUD400K)		begin			clk_count = 0;		end				// ~50/50 duty cycle		if(clk_count > (`BAUD400K / 2))		begin			i2c_clk <= 1'b0;		end		else		begin			i2c_clk <= 1'b1;		end	end	else	begin		if(clk_count >= `BAUD100K)		begin			clk_count = 0;		end		// ~50/50 duty cycle		if(clk_count > (`BAUD100K / 2))		begin			i2c_clk <= 1'b0;		end		else		begin			i2c_clk <= 1'b1;		end	endend// Output Blockalways@(addr or cs or rd or buffer or speed or ack or held or busy)begin    out_data = 8'bz;        if(cs && rd)    begin        case(addr)         // Data (read)         3'b011:         begin            out_data = buffer;         end	// Status         3'b100:         begin            out_data = {4'b0, speed, ack, held, busy};         end      endcase   endend// Input Blockalways@(posedge clk)begin    nextstate <= nextstate;    case(state)        `IDLE:        begin            if(!busy)/*cs && wr && !busy*/            begin                case(state_control)		                    // Start                    3'b000:                    begin                        nextstate <= `START;
								if(wr_rd_bit) state_control <=3'b010;
								else state_control <=3'b011;                    end                    // Stop                    3'b001:                    begin                        nextstate <= `STOP;                    end			                    // Read                    3'b010:                    begin                        in_buffer = {7'b0, in_data[0]};                        nextstate <= `READ;                    end			                     // Data (write)                    3'b011:                    begin                        in_buffer = 8'b00110011;//in_data;                        nextstate <= `WRITE;
								state_control <=3'b001;                    end			                    // Speed                    3'b100:                    begin                        speed = in_data[0];                        nextstate <= `IDLE;                    end
						  
						  default: nextstate <= `IDLE;
						                  endcase            end        end                `START:        begin            if(state_count >= 6)            begin                nextstate <= `IDLE;            end        end                `STOP:        begin            if(state_count >= 6)            begin                nextstate <= `IDLE;            end        end                `READ:        begin            if(state_count >= 44)            begin                nextstate <= `IDLE;            end        end                `WRITE:        begin            if(state_count >= 44)            begin                nextstate <= `IDLE;            end        end    endcaseend// state_count and bit_countalways@(posedge i2c_clk)begin   state <= nextstate;      case(state)       `START:       begin           if(state_count >= 6)           begin               state_count <= 0;           end           else           begin               state_count <= state_count + 1;           end       end       `STOP:       begin           if(state_count >= 6)           begin               state_count <= 0;           end           else           begin               state_count <= state_count + 1;           end       end       `READ:       begin           if(state_count >= 44)           begin               state_count <= 0;           end           else           begin               if(out_scl == scl)               begin                   state_count <= state_count + 1;               end                          end                      if(bit_count >= 4)           begin               bit_count <= 0;           end           else           begin               if(out_scl == scl)               begin                   bit_count <= bit_count + 1;               end           end       end       `WRITE:       begin           if(state_count >= 44)           begin               state_count <= 0;           end           else           begin               if(out_scl == scl)               begin                   state_count <= state_count + 1;               end           end           if(bit_count >= 4)           begin               bit_count <= 0;           end           else           begin               if(out_scl == scl)               begin                   bit_count <= bit_count + 1;               end           end       end   endcase        end// SDA and SCLalways@(posedge i2c_clk)begin   out_sda = out_sda;   out_scl = out_scl;       case(state)       `START:       begin           case(state_count)               0:               begin                   out_sda = 1'b1;                   out_scl = 1'b1;               end               1:               begin                   out_sda = 1'b1;                   out_scl = 1'b1;               end               2:               begin                   out_sda = 1'b1;                   out_scl = 1'b1;               end                              3:               begin                   out_sda = 1'b0;                   out_scl = 1'b1;               end                              4:               begin                   out_sda = 1'b0;                   out_scl = 1'b1;               end                              5:               begin                   out_sda = 1'b0;                   out_scl = 1'b0;               end                              6:               begin                   out_sda = 1'b0;                   out_scl = 1'b0;               end           endcase       end       `STOP:       begin           case(state_count)               0:               begin                   out_sda = 1'b0;                   out_scl = 1'b0;               end                              1:               begin                   out_sda = 1'b0;                   out_scl = 1'b1;               end                              2:               begin                   out_sda = 1'b0;                   out_scl = 1'b1;               end                              3:               begin                   out_sda = 1'b1;                   out_scl = 1'b1;               end                              4:               begin                   out_sda = 1'b1;                   out_scl = 1'b1;               end                              5:               begin                   out_sda = 1'b1;                   out_scl = 1'b1;               end                              6:               begin                   out_sda = 1'b1;                   out_scl = 1'b1;               end           endcase       end       `READ:       begin           if(state_count >= 40)           begin               case(bit_count)                                      0:                   begin                       out_sda = ~in_buffer[0];                       out_scl = 1'b0;                   end                                      1:                   begin                       out_sda = ~in_buffer[0];                       out_scl = 1'b0;                   end                                      2:                   begin                       out_sda = ~in_buffer[0];                       out_scl = 1'b1;                   end                                      3:                   begin                       out_sda = ~in_buffer[0];                       out_scl = 1'b1;                   end                                      4:                   begin                       out_sda = ~in_buffer[0];                       out_scl = 1'b0;                   end               endcase           end           else           begin               case(bit_count)                                      0:                   begin                       out_sda = 1'b1;                       out_scl = 1'b0;                                              buffer = buffer << 1;                   end                                      1:                   begin                       out_sda = 1'b1;                       out_scl = 1'b0;                   end                                      2:                   begin                       out_sda = 1'b1;                       out_scl = 1'b1;                   end                                      3:                   begin                       out_sda = 1'b1;                       out_scl = 1'b1;                                              buffer[0] = sda;                   end                                      4:                   begin                       out_sda = 1'b1;                       out_scl = 1'b0;                   end                                  endcase           end       end              `WRITE:       begin           if(state_count == 0)           begin               buffer = in_buffer;           end                      if(state_count >= 40)           begin               case(bit_count)                                      0:                   begin                       out_sda = 1'b1;                       out_scl = 1'b0;                   end                                      1:                   begin                       out_sda = 1'b1;                       out_scl = 1'b0;                   end                                      2:                   begin                       out_sda = 1'b1;                       out_scl = 1'b1;                   end                                      3:                   begin                       out_sda = 1'b1;                       out_scl = 1'b1;                                              ack = sda;                   end                                      4:                   begin                       out_sda = 1'b1;                       out_scl = 1'b0;                   end                                  endcase           end           else           begin               case(bit_count)                                      0:                   begin                       out_sda = buffer[7];                       out_scl = 1'b0;                   end                                      1:                   begin                       out_sda = buffer[7];                       out_scl = 1'b0;                   end                                      2:                   begin                       out_sda = buffer[7];                       out_scl = 1'b1;                   end                                      3:                   begin                       out_sda = buffer[7];                       out_scl = 1'b1;                   end                                      4:                   begin                       out_sda = buffer[7];                       out_scl = 1'b0;                                              buffer = buffer << 1;                   end                                  endcase           end       end   endcaseendassign sda = out_sda ? 1'bz : 1'b0;assign scl = out_scl ? 1'bz : 1'b0;assign busy = (state != `IDLE || nextstate != `IDLE) ? 1 : 0;assign iic_busy = (state != `IDLE || nextstate != `IDLE) ? 1 : 0;assign held = out_scl != scl;endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -