/*============================================================================
  • *
  • *  LOGIC CORE:          I2C控制器顶层文件
  • *  MODULE NAME:         i2c_control()
  • *  COMPANY:             武汉芯路恒科技有限公司
  • *                       http://xiaomeige.taobao.com
  • *  author:                                小梅哥
  • *  Website:                                www.corecourse.cn
  • *  REVISION HISTORY:  
  • *
  • *  Revision:                         1.0  04/10/2019     
  • *  Description:                 Initial Release.
  • *
  • *  FUNCTIONAL DESCRIPTION:
  • ===========================================================================*/
  • module i2c_control(
  •         Clk,
  •         Rst_n,
  •        
  •         wrreg_req,
  •         rdreg_req,
  •         addr,
  •         addr_mode,
  •         wrdata,
  •         rddata,
  •         device_id,
  •         RW_Done,
  •        
  •         ack,
  •        
  •         i2c_sclk,
  •         i2c_sdat
  • );
  •         input Clk;
  •         input Rst_n;
  •        
  •         input wrreg_req;
  •         input rdreg_req;
  •         input [15:0]addr;
  •         input addr_mode;
  •         input [7:0]wrdata;
  •         output reg[7:0]rddata;
  •         input [7:0]device_id;
  •         output reg RW_Done;
  •        
  •         output reg ack;
  •         output i2c_sclk;
  •         inout i2c_sdat;
  •        
  •         reg [5:0]Cmd;
  •         reg [7:0]Tx_DATA;
  •         wire Trans_Done;
  •         wire ack_o;
  •         reg Go;
  •         wire [15:0] reg_addr;
  •        
  •         assign reg_addr = addr_mode?addr:{addr[7:0],addr[15:8]};
  •        
  •         wire [7:0]Rx_DATA;
  •        
  •         localparam
  •                 WR   = 6'b000001,   //写请求
  •                 STA  = 6'b000010,   //起始位请求
  •                 RD   = 6'b000100,   //读请求
  •                 STO  = 6'b001000,   //停止位请求
  •                 ACK  = 6'b010000,   //应答位请求
  •                 NACK = 6'b100000;   //无应答请求
  •        
  •         i2c_bit_shift i2c_bit_shift(
  •                 .Clk(Clk),
  •                 .Rst_n(Rst_n),
  •                 .Cmd(Cmd),
  •                 .Go(Go),
  •                 .Rx_DATA(Rx_DATA),
  •                 .Tx_DATA(Tx_DATA),
  •                 .Trans_Done(Trans_Done),
  •                 .ack_o(ack_o),
  •                 .i2c_sclk(i2c_sclk),
  •                 .i2c_sdat(i2c_sdat)
  •         );
  •        
  •         reg [6:0]state;
  •         reg [7:0]cnt;
  •        
  •         localparam
  •                 IDLE         = 7'b0000001,
  •                 WR_REG       = 7'b0000010,
  •                 WAIT_WR_DONE = 7'b0000100,
  •                 WR_REG_DONE  = 7'b0001000,
  •                 RD_REG       = 7'b0010000,
  •                 WAIT_RD_DONE = 7'b0100000,
  •                 RD_REG_DONE  = 7'b1000000;
  •        
  •         always@(posedge Clk or negedge Rst_n)
  •         if(!Rst_n)begin
  •                 Cmd <= 6'd0;
  •                 Tx_DATA <= 8'd0;
  •                 Go <= 1'b0;
  •                 rddata <= 0;
  •                 state <= IDLE;
  •                 ack <= 0;
  •         end
  •         else begin
  •                 case(state)
  •                         IDLE:
  •                                 begin
  •                                         cnt <= 0;
  •                                         ack <= 0;
  •                                         RW_Done <= 1'b0;                                       
  •                                         if(wrreg_req)
  •                                                 state <= WR_REG;
  •                                         else if(rdreg_req)
  •                                                 state <= RD_REG;
  •                                         else
  •                                                 state <= IDLE;
  •                                 end
  •                        
  •                         WR_REG:
  •                                 begin
  •                                         state <= WAIT_WR_DONE;
  •                                         case(cnt)
  •                                                 0:write_byte(WR | STA, device_id);
  •                                                 1:write_byte(WR, reg_addr[15:8]);
  •                                                 2:write_byte(WR, reg_addr[7:0]);
  •                                                 3:write_byte(WR | STO, wrdata);
  •                                                 default:;
  •                                         endcase
  •                                 end
  •                        
  •                         WAIT_WR_DONE:
  •                                 begin
  •                                         Go <= 1'b0;
  •                                         if(Trans_Done)begin
  •                                                 ack <= ack | ack_o;
  •                                                 case(cnt)
  •                                                         0: begin cnt <= 1; state <= WR_REG;end
  •                                                         1:
  •                                                                 begin
  •                                                                         state <= WR_REG;
  •                                                                         if(addr_mode)
  •                                                                                 cnt <= 2;
  •                                                                         else
  •                                                                                 cnt <= 3;
  •                                                                 end
  •                                                                        
  •                                                         2: begin
  •                                                                         cnt <= 3;
  •                                                                         state <= WR_REG;
  •                                                                 end
  •                                                         3:state <= WR_REG_DONE;
  •                                                         default:state <= IDLE;
  •                                                 endcase
  •                                         end
  •                                 end
  •                        
  •                         WR_REG_DONE:
  •                                 begin
  •                                         RW_Done <= 1'b1;
  •                                         state <= IDLE;
  •                                 end
  •                                
  •                         RD_REG:
  •                                 begin
  •                                         state <= WAIT_RD_DONE;
  •                                         case(cnt)
  •                                                 0:write_byte(WR | STA, device_id);
  •                                                 1:if(addr_mode)
  •                                                                 write_byte(WR, reg_addr[15:8]);
  •                                                         else
  •                                                                 write_byte(WR | STO, reg_addr[15:8]);
  •                                                 2:write_byte(WR | STO, reg_addr[7:0]);
  •                                                 3:write_byte(WR | STA, device_id | 8'd1);
  •                                                 4:read_byte(RD | ACK | STO);
  •                                                 default:;
  •                                         endcase
  •                                 end
  •                                
  •                         WAIT_RD_DONE:
  •                                 begin
  •                                         Go <= 1'b0;
  •                                         if(Trans_Done)begin
  •                                                 if(cnt <= 3)
  •                                                         ack <= ack | ack_o;
  •                                                 case(cnt)
  •                                                         0: begin cnt <= 1; state <= RD_REG;end
  •                                                         1:
  •                                                                 begin
  •                                                                         state <= RD_REG;
  •                                                                         if(addr_mode)
  •                                                                                 cnt <= 2;
  •                                                                         else
  •                                                                                 cnt <= 3;
  •                                                                 end
  •                                                                        
  •                                                         2: begin
  •                                                                         cnt <= 3;
  •                                                                         state <= RD_REG;
  •                                                                 end
  •                                                         3:begin
  •                                                                         cnt <= 4;
  •                                                                         state <= RD_REG;
  •                                                                 end
  •                                                         4:state <= RD_REG_DONE;
  •                                                         default:state <= IDLE;
  •                                                 endcase
  •                                         end
  •                                 end
  •                                
  •                         RD_REG_DONE:
  •                                 begin
  •                                         RW_Done <= 1'b1;
  •                                         rddata <= Rx_DATA;
  •                                         state <= IDLE;                               
  •                                 end
  •                         default:state <= IDLE;
  •                 endcase
  •         end
  •        
  •         task read_byte;
  •                 input [5:0]Ctrl_Cmd;
  •                 begin
  •                         Cmd <= Ctrl_Cmd;
  •                         Go <= 1'b1;
  •                 end
  •         endtask
  •        
  •         task write_byte;
  •                 input [5:0]Ctrl_Cmd;
  •                 input [7:0]Wr_Byte_Data;
  •                 begin
  •                         Cmd <= Ctrl_Cmd;
  •                         Tx_DATA <= Wr_Byte_Data;
  •                         Go <= 1'b1;
  •                 end
  •         endtask
  • endmodule
  • 复制代码