I2C
- module I2C(clk,cmd,rst,contr_b,addr_h_b,addr_l_b,data_in,sclk,sda,data_out); //草稿
- input clk,rst;
- input [7:0] contr_b;
- input [7:0] addr_h_b;
- input [7:0] addr_l_b;
- input [7:0] data_in;
- input cmd; // write: cmd=1, read: cmd=0
- output sclk;
- output [7:0] data_out;
- inout sda;
- wire sda_w,sda_r;
- wire sclk_w,sclk_r;
- assign sda=cmd?sda_w:sda_r;
- assign sclk=cmd?sclk_w:sclk_r;
- I2C_w I2C_w(
- .clk(clk),
- .rst(rst),
- .contr_b(contr_b),
- .addr_h_b(addr_h_b),
- .addr_l_b(addr_l_b),
- .data(data_in),
- .sclk(sclk_w),
- .sda(sda_w)
- );
- I2C_r I2C_r(
- .clk(clk),
- .rst(rst),
- .contr_b(contr_b),
- .addr_h_b(addr_h_b),
- .addr_l_b(addr_l_b),
- .sclk(sclk_r),
- .data(data_out),
- .sda(sda_r)
- );
- endmodule
- module I2C_r(clk,rst,sda,contr_b,addr_h_b,addr_l_b,sclk,data);
- input clk,rst;
- input [7:0] contr_b;
- input [7:0] addr_h_b;
- input [7:0] addr_l_b;
- output sclk;
- output [7:0] data;
- inout sda;
- reg sclk;
- reg [6:0] cnt1;
- reg [3:0] cnt2;
- reg en;
- reg en2;
- reg sda_reg;
- reg [7:0] d_reg;
- reg [7:0] data_in;
- reg sda_en;
- reg [7:0] data;
- wire Q;
- parameter [15:0] contr1 = 16'b0000_0000_0000_0001;
- parameter [15:0] start = 16'b0000_0000_0000_0010;
- parameter [15:0] start1 = 16'b0000_0000_0000_0100;
- parameter [15:0] contr = 16'b0000_0000_0000_1000;
- parameter [15:0] ack1 = 16'b0000_0000_0001_0000;
- parameter [15:0] addr_h = 16'b0000_0000_0010_0000;
- parameter [15:0] ack2 = 16'b0000_0000_0100_0000;
- parameter [15:0] addr_l = 16'b0000_0000_1000_0000;
- parameter [15:0] start2 = 16'b0000_0001_0000_0000;
- parameter [15:0] start3 = 16'b0000_0010_0000_0000;
- parameter [15:0] ack4 = 16'b0000_0100_0000_0000;
- parameter [15:0] data_t = 16'b0000_1000_0000_0000;
- parameter [15:0] no_ack = 16'b0001_0000_0000_0000;
- parameter [15:0] stop = 16'b0010_0000_0000_0000;
- parameter [15:0] stop1 = 16'b0100_0000_0000_0000;
- parameter [15:0] ack3 = 16'b1000_0000_0000_0000;
- reg [15:0] present_state, next_state;
- always@(posedge clk or negedge rst)
- begin
- if(!rst) present_state <= start;
- else present_state <= next_state;
- end
- always@(present_state or cnt1 or cnt2)
- begin
- case(present_state)
- start: if(cnt1 == 7'd62)
- next_state = start1;
- else
- next_state = start;
- start1:if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = contr;
- else
- next_state = start1;
- contr: if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = ack1;
- else
- next_state = contr;
- ack1: if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = addr_h;
- else
- next_state = ack1;
- addr_h:if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = ack2;
- else
- next_state = addr_h;
- ack2: if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = addr_l;
- else
- next_state = ack2;
- addr_l:if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = ack3;
- else
- next_state = addr_l;
- ack3: if(cnt1 == 7'd124)
- next_state = start2;
- else
- next_state = ack3;
- start2:if(cnt1 == 7'd62 && cnt2 == 4'd0)
- next_state = start3;
- else
- next_state = start2;
- start3:if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = contr1;
- else
- next_state = start3;
- contr1:if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = ack4;
- else
- next_state = contr1;
- ack4: if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = data_t;
- else
- next_state = ack4;
- data_t:if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = no_ack;
- else
- next_state = data_t;
- no_ack:if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = stop;
- else
- next_state = no_ack;
- stop: if(cnt1 == 7'd62 && cnt2 == 4'd0)
- next_state = stop1;
- else
- next_state = stop;
- stop1: next_state = stop1;
- default: next_state = start;
- endcase
- end
- always@(posedge clk)
- begin
- case(present_state)
- start : begin
- en<=1;
- en2<=0;
- sda_reg<=1;
- end
- start1: begin
- en<=1;
- en2<=0;
- sda_reg<=0;
- end
- contr : begin
- en<=1;
- en2<=1;
- sda_reg<=d_reg[7];
- data_in<=contr_b;
- end
- ack1 : begin
- en<=1;
- en2<=1;
- sda_reg<=0;
- end
- addr_h: begin
- en<=1;
- en2<=1;
- sda_reg<=d_reg[7];
- data_in<=addr_h_b;
- end
- ack2 : begin
- en<=1;
- en2<=1;
- sda_reg<=0;
- end
- addr_l: begin
- en<=1;
- en2<=1;
- sda_reg<=d_reg[7];
- data_in<=addr_l_b;
- end
- ack3 : begin
- en=1;
- en2<=0;
- sda_reg<=0;
- end
- start2: begin
- en=1;
- en2<=1;
- sda_reg<=1;
- end
- start3: begin
- en=1;
- en2<=1;
- sda_reg<=0;
- end
- contr1: begin
- en=1;
- en2<=1;
- sda_reg<=d_reg[7];
- data_in<=contr_b;
- end
- ack4 : begin
- en=1;
- en2<=1;
- sda_reg<=0;
- end
- data_t: begin
- en=1;
- en2<=1;
- end
- no_ack: begin
- en<=1;
- en2<=0;
- sda_reg<=1;
- end
- stop : begin
- en<=1;
- en2<=1;
- sda_reg<=0;
- end
- stop1 : begin
- en<=0;
- en2<=0;
- sda_reg<=1;
- end
- default:;
- endcase
- end
- // 分頻計數器----------------------------------------------------------------
- always@(posedge clk or negedge rst)
- begin
- if(!rst) cnt1 <= 7'd0;
- else if(en)
- begin
- if(cnt1 == 7'd124) cnt1 <= 7'd0;
- else cnt1 <= cnt1 + 7'd1;
- end
- else cnt1 <= cnt1;
- end
- always@(posedge clk or negedge rst)
- begin
- if(!rst) cnt2 <= 4'd0;
- else if(en2)
- begin
- if(cnt1 == 7'd124)
- begin
- if(cnt2 == 4'd8) cnt2 <= 4'd0;
- else cnt2 <= cnt2 + 4'd1;
- end
- end
- else cnt2 <= cnt2;
- end
- // 移位暫存器---------------------------------------------------------------------------
- always@(posedge clk or negedge rst)
- begin
- if(!rst)
- d_reg <= 8'b00000000;
- else if(cnt2 == 4'd1)
- d_reg <= data_in;
- else if(cnt1 == 7'd1)
- begin
- d_reg[7:1] <= d_reg[6:0];
- d_reg[0] <= 0;
- end
- else
- d_reg <= d_reg;
- end
- //-------------------------------------------------------
- assign sda = sda_en ? sda_reg : 1'bz;
- assign Q = sda;
- always@(posedge clk or negedge rst)
- begin
- if(!rst)
- sda_en<=1;
- else if((present_state == ack1 && cnt1==7'd1) || (present_state == ack2 && cnt1==7'd1) || (present_state == ack3 && cnt1==7'd1) || (present_state == ack4 && cnt1==7'd1) || present_state == data_t)
- sda_en<=0;
- else
- sda_en<=1;
- end
- // sclk-----------------------------------------------------------------------------
- always@(posedge clk)
- begin
- if(present_state==start || present_state==start1 || present_state==stop || present_state==stop1 || present_state==start2 || present_state==start3)
- sclk<=1;
- else if(present_state==contr || present_state==ack1 || present_state==ack2 || present_state==ack3 || present_state==ack4 || present_state==data_t || present_state==addr_l || present_state==addr_h || present_state==contr1 || present_state==no_ack)
- begin
- if(cnt1 == 7'd0)
- sclk<=0;
- else if(cnt1 == 7'd31)
- sclk<=1;
- else if(cnt1 == 7'd93)
- sclk<=0;
- else
- sclk<=sclk;
- end
- else
- sclk<=sclk;
- end
- //present_state==data_t--------------------------------------------------
- always@(posedge clk)
- begin
- if(present_state == data_t && cnt2 == 4'd1 && cnt1==7'd1)
- data[7] <= Q;
- else if(present_state == data_t && cnt2 == 4'd2 && cnt1==7'd1)
- data[6] <= Q;
- else if(present_state == data_t && cnt2 == 4'd3 && cnt1==7'd1 )
- data[5] <= Q;
- else if(present_state == data_t && cnt2 == 4'd4 && cnt1==7'd1 )
- data[4] <= Q;
- else if(present_state == data_t && cnt2 == 4'd5 && cnt1==7'd1 )
- data[3] <= Q;
- else if(present_state == data_t && cnt2 == 4'd6 && cnt1==7'd1 )
- data[2] <= Q;
- else if(present_state == data_t && cnt2 == 4'd7 && cnt1==7'd1 )
- data[1] <= Q;
- else if(present_state == data_t && cnt2 == 4'd8 && cnt1==7'd1 )
- data[0] <= Q;
- else
- data <= data;
- end
- endmodule
- module I2C_w(clk,rst,contr_b,addr_h_b,addr_l_b,data,sclk,sda);
- input clk,rst;
- input [7:0] contr_b;
- input [7:0] addr_h_b;
- input [7:0] addr_l_b;
- input [7:0] data;
- output sclk;
- output sda;
- reg sclk;
- reg [6:0] cnt1;
- reg [3:0] cnt2;
- reg en;
- reg en2;
- reg sda_reg;
- reg [7:0] d_reg;
- reg [7:0] data_in;
- reg sda_en;
- // FSM狀態機-------------------------------------------------------------------------------------
- parameter [11:0] start = 12'b000000000001,
- contr = 12'b000000000010,
- ack1 = 12'b000000000100,
- addr_h = 12'b000000001000,
- ack2 = 12'b000000010000,
- addr_l = 12'b000000100000,
- ack3 = 12'b000001000000,
- data_t = 12'b000010000000,
- ack4 = 12'b000100000000,
- stop = 12'b001000000000,
- start1 = 12'b010000000000,
- stop1 = 12'b100000000000;
- reg [11:0] present_state, next_state;
- always@(posedge clk or negedge rst)
- begin
- if(!rst) present_state <= start;
- else present_state <= next_state;
- end
- always@(present_state or cnt1 or cnt2)
- begin
- case(present_state)
- start: if(cnt1 == 7'd62)
- next_state = start1;
- else
- next_state = start;
- start1: if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = contr;
- else
- next_state = start1;
- contr: if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = ack1;
- else
- next_state = contr;
- ack1: if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = addr_h;
- else
- next_state = ack1;
- addr_h:if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = ack2;
- else
- next_state = addr_h;
- ack2: if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = addr_l;
- else
- next_state = ack2;
- addr_l:if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = ack3;
- else
- next_state = addr_l;
- ack3: if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = data_t;
- else
- next_state = ack3;
- data_t:if(cnt1 == 7'd124 && cnt2 == 4'd8)
- next_state = ack4;
- else
- next_state = data_t;
- ack4: if(cnt1 == 7'd124 && cnt2 == 4'd0)
- next_state = stop;
- else
- next_state = ack4;
- stop: if(cnt1 == 7'd62 && cnt2 == 4'd0)
- next_state = stop1;
- else
- next_state = stop;
- stop1: next_state = stop1;
- default: next_state = start;
- endcase
- end
- always@(posedge clk)
- begin
- case(present_state)
- start : begin
- en<=1;
- en2<=0;
- sda_reg<=1;
- end
- start1: begin
- en<=1;
- en2<=0;
- sda_reg<=0;
- end
- contr : begin
- en<=1;
- en2<=1;
- sda_reg<=d_reg[7];
- data_in<=contr_b;
- end
- ack1 : begin
- en<=1;
- en2<=1;
- sda_reg<=0;
- end
- addr_h: begin
- en<=1;
- en2<=1;
- sda_reg<=d_reg[7];
- data_in<=addr_h_b;
- end
- ack2 : begin
- en<=1;
- en2<=1;
- sda_reg<=0;
- end
- addr_l: begin
- en<=1;
- en2<=1;
- sda_reg<=d_reg[7];
- data_in<=addr_l_b;
- end
- ack3 : begin
- en=1;
- en2<=1;
- sda_reg<=0;
- end
- data_t: begin
- en<=1;
- en2<=1;
- sda_reg<=d_reg[7];
- data_in<=data;
- end
- ack4 : begin
- en<=1;
- en2<=0;
- sda_reg<=0;
- end
- stop : begin
- en<=1;
- en2<=1;
- sda_reg<=0;
- end
- stop1 : begin
- en<=0;
- en2<=0;
- sda_reg<=1;
- end
- default:;
- endcase
- end
- // 分頻計數器----------------------------------------------------------------
- always@(posedge clk or negedge rst)
- begin
- if(!rst) cnt1 <= 7'd0;
- else if(en)
- begin
- if(cnt1 == 7'd124) cnt1 <= 7'd0;
- else cnt1 <= cnt1 + 7'd1;
- end
- else cnt1 <= cnt1;
- end
- always@(posedge clk or negedge rst)
- begin
- if(!rst) cnt2 <= 4'd0;
- else if(en2)
- begin
- if(cnt1 == 7'd124)
- begin
- if(cnt2 == 4'd8) cnt2 <= 4'd0;
- else cnt2 <= cnt2 + 4'd1;
- end
- end
- else cnt2 <= cnt2;
- end
- // sclk-----------------------------------------------------------------------------
- always@(posedge clk)
- begin
- if(present_state==start || present_state==start1 || present_state==stop || present_state==stop1)
- sclk<=1;
- else if(present_state==contr || present_state==ack1 || present_state==ack2 || present_state==ack3 || present_state==ack4 || present_state==data_t || present_state==addr_l || present_state==addr_h)
- begin
- if(cnt1 == 7'd0)
- sclk<=0;
- else if(cnt1 == 7'd31)
- sclk<=1;
- else if(cnt1 == 7'd93)
- sclk<=0;
- else
- sclk<=sclk;
- end
- else
- sclk<=sclk;
- end
- // 移位暫存器---------------------------------------------------------------------------
- always@(posedge clk or negedge rst)
- begin
- if(!rst)
- d_reg <= 8'b00000000;
- else if(cnt2 == 4'd1)
- d_reg <= data_in;
- else if(cnt1 == 7'd1)
- begin
- d_reg[7:1] <= d_reg[6:0];
- d_reg[0] <= 0;
- end
- else
- d_reg <= d_reg;
- end
- //-------------------------------------------------------------------
- assign sda = sda_en ? sda_reg : 1'bz;
- always@(posedge clk or negedge rst)
- begin
- if(!rst)
- sda_en<=1;
- else if((present_state == ack1 && cnt1==7'd1) || (present_state == ack2 && cnt1==7'd1) || (present_state == ack3 && cnt1==7'd1) || (present_state == ack4 && cnt1==7'd1))
- sda_en<=0;
- else
- sda_en<=1;
- end
- endmodule
相關文章
- I2C匯流排 | I2C匯流排介紹
- I2C 匯流排
- I2C系統框架(1)框架
- I2C 波形讀取方法
- i2c除錯工具分享除錯
- 【esp32 專案】使用I2C第一篇——I2C的科普
- UART,I2C,SPI 介面總結
- I2C子系統框架二框架
- uboot i2c 操作函式記錄boot函式
- 13. I2C通訊協議協議
- 【esp32 專案】使用I2C
- AP316C I2C驅動示例
- 【linux】i2c使用分析&原始碼實戰Linux原始碼
- 核心下gpio模擬i2c驅動修改
- FPGA對EEPROM驅動控制(I2C協議)FPGA協議
- I2C裝置地址 TargetAddress 24LC04
- 【.NET 與樹莓派】i2c(IIC)通訊樹莓派
- 如何debug通訊協議 I2C 子系統協議
- stm32的HAL庫i2c從機實現
- STM8S I2C Slave模式錯誤解決模式
- FRDM-MCXN947開發板之i2c應用
- 框架-裝置與驅動的拆分及實現-I2C框架
- MicroPython 硬體 I2C 驅動 MPU6050 - RaspberryPi Pico 示例Python
- 必看版指南:BTB擴充套件介面——LCD、Camera、UART、I2C…套件
- Linux驅動之I2C匯流排裝置以及驅動Linux
- STM32 HAL 庫硬體 I2C 驅動 MPU6050
- 5.7.2 ARM微控制器外設:I2C的通訊協議協議
- STM32基於I2C的AHT20溫溼度採集
- 【北京迅為】i.MX6ULL終結者I2C操作原理分析
- [RK3399][Android7.1]Linux核心I2C子系統框架圖解AndroidLinux框架圖解
- STM32 I2C鉗住SCL強行拉低的解決方法
- STM32基於I2C協議的AHT20溫溼度測量協議
- 張高興的 .NET Core IoT 入門指南:(三)使用 I2C 進行通訊
- 微控制器學習(十一)I2C匯流排和AT24C02的使用
- U8g2圖形庫與STM32移植(I2C,軟體與硬體)
- EV20S & EV01S 5G無線音訊模組I2C介面與STM音訊
- 菜鳥入門9,在I2C通訊協議的基礎上完成的溫溼度採集協議
- VK16K33 I2C匯流排介面 128點陣適用於高階家電車用裝置等LED顯示器/皮膚的控制及驅動